Commit 1d6a6bed authored by Julien Michel's avatar Julien Michel
Browse files

ENH: (Visu Refactoring) Finilazing the VectorDataGlComponent

parent 7da549e5
......@@ -61,6 +61,7 @@ GluPolygonDrawingHelper::GluPolygonDrawingHelper()
// Instantiation of the tesselator object
m_PointVector.clear();
m_GluTesselator = gluNewTess();
// Color
m_Color[0]=0;
m_Color[1]=0;
......
......@@ -126,6 +126,7 @@ private:
GLUtesselator * m_GluTesselator;
/** Color of the polygon */
GLdouble m_Color[4];
};
} // end namespace otb
#endif
......@@ -21,6 +21,23 @@
#include "otbGlComponent.h"
#include "itkPreOrderTreeIterator.h"
# ifdef __APPLE__
# include <OpenGL/glu.h>
# else
# include <GL/glu.h>
# endif
// There are function prototype conflits under cygwin between standard w32 API
// and standard C ones
#ifndef CALLBACK
#if defined(__CYGWIN__)
#define CALLBACK __stdcall
#else
#define CALLBACK
#endif
#endif
namespace otb
{
/** \class VectorDataGlComponent
......@@ -81,28 +98,56 @@ public:
itkSetObjectMacro(VectorData,VectorDataType);
itkGetObjectMacro(VectorData,VectorDataType);
/** Set/Get the color */
itkSetMacro(Color,ColorType);
itkGetConstReferenceMacro(Color,ColorType);
protected:
/** Constructor */
VectorDataGlComponent();
/** Destructor */
virtual ~VectorDataGlComponent(){}
virtual ~VectorDataGlComponent();
/** Printself method */
void PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os,indent);
}
// Render a point
/// Render a point
void RenderPoint(const PointType & p, const RegionType & extent, const AffineTransformType * transform);
// Render a polyline
/// Render a polyline
void RenderLine(const LineType * l, const RegionType & extent, const AffineTransformType * transform);
// Render a complex polygon (with holes)
void RenderPolygon(const PolygonType * extRing, const PolygonListType * intRings, const RegionType & extent, const AffineTransformType * transform);
/// Frame a given point using the frame width and color (point
/// should be in gl screen coordinates)
void FramePoint(const PointType & p);
private:
VectorDataGlComponent(const Self&); // purposely not implemented
void operator=(const Self&); // purposely not implemented
// Function pointer typedef
typedef void (CALLBACK * FunctionPointerType)();
// Static Combine callback for tesselation
static void TesselationCombineCallback(GLdouble coords[2],GLdouble * data[4], GLfloat weights[4],GLdouble **dataOut)
{
GLdouble * vertex = new GLdouble[2];
vertex[0] = coords[0];
vertex[1] = coords[1];
*dataOut = vertex;
}
// Static error callback fir tesselation
static void TesselationErrorCallback(GLenum errorCode)
{
const GLubyte * estring = gluErrorString(errorCode);
itkGenericExceptionMacro(<<"Glu Tesselation error: "<<estring);
}
/// Pointer to the vector data to render
VectorDataPointerType m_VectorData;
......@@ -112,6 +157,12 @@ private:
/// Origin of the image
PointType m_Origin;
/// The GluTesselator object to render complex polygons
GLUtesselator * m_GluTesselator;
/// Color of the vector layer
ColorType m_Color;
}; // end class
} // end namespace otb
......
......@@ -20,14 +20,44 @@
#include "otbVectorDataGlComponent.h"
// We need this include to get NodeType enum right.
#include "otbDataNode.h"
namespace otb
{
template <class TVectorData>
VectorDataGlComponent<TVectorData>
::VectorDataGlComponent() : m_VectorData(),m_Spacing(), m_Origin()
::VectorDataGlComponent() : m_VectorData(),m_Spacing(), m_Origin(), m_GluTesselator(), m_Color()
{
// Default color is red
m_Color.Fill(0);
m_Color[0]=1.;
m_Color[3]=0.75;
// Intialize origin and spacing
m_Origin.Fill(0.);
m_Spacing.Fill(1.);
// Create the tesselator
m_GluTesselator = gluNewTess();
// Set the winding rule
// gluTessProperty(m_GluTesselator,GLU_TESS_WINDING_RULE,GLU_TESS_WINDING_ODD);
// Setting up the tesselator callbacks
gluTessCallback(m_GluTesselator,GLU_TESS_BEGIN, (FunctionPointerType) glBegin);
gluTessCallback(m_GluTesselator,GLU_TESS_END, (FunctionPointerType) glEnd);
gluTessCallback(m_GluTesselator,GLU_TESS_ERROR, (FunctionPointerType) VectorDataGlComponent<TVectorData>::TesselationErrorCallback);
gluTessCallback(m_GluTesselator,GLU_TESS_VERTEX, (FunctionPointerType) glVertex2dv);
gluTessCallback(m_GluTesselator,GLU_TESS_COMBINE,(FunctionPointerType) VectorDataGlComponent<TVectorData>::TesselationCombineCallback);
}
template <class TVectorData>
VectorDataGlComponent<TVectorData>
::~VectorDataGlComponent()
{
// Delete the tesselator
m_GluTesselator = gluNewTess();
}
template <class TVectorData>
......@@ -41,9 +71,18 @@ VectorDataGlComponent<TVectorData>
return;
}
// Set up blending and color
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4d(m_Color[0],m_Color[1],m_Color[2],m_Color[3]);
glLineWidth(2);
// Enabling line antialiasing
glEnable(GL_LINE_SMOOTH);
// Iterate on the data tree
TreeIteratorType it(m_VectorData->GetDataTree());
it.GoToBegin();
while(!it.IsAtEnd())
......@@ -77,14 +116,31 @@ VectorDataGlComponent<TVectorData>
}
++it;
}
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
}
template <class TVectorData>
void
VectorDataGlComponent<TVectorData>
::RenderPoint(const PointType & p, const RegionType & extent, const AffineTransformType * transform)
{
// Take into account pixel spacing and origin
PointType spacePoint = p;
spacePoint[0]*= m_Spacing[0];
spacePoint[1]*= m_Spacing[1];
spacePoint[0]-= m_Origin[0];
spacePoint[1]-=m_Origin[1];
// Transform to a screen point
PointType screenPoint = transform->TransformPoint(spacePoint);
glBegin(GL_LINES);
// Draw a cross
glVertex2d(screenPoint[0]-10,screenPoint[1]);
glVertex2d(screenPoint[0]+10,screenPoint[1]);
glVertex2d(screenPoint[0],screenPoint[1]-10);
glVertex2d(screenPoint[0],screenPoint[1]+10);
glEnd();
}
template <class TVectorData>
......@@ -92,8 +148,28 @@ void
VectorDataGlComponent<TVectorData>
::RenderLine(const LineType * l, const RegionType & extent, const AffineTransformType * transform)
{
// Iterate on the line
typename LineType::VertexListType::ConstIterator vIt = l->GetVertexList()->Begin();
glBegin(GL_LINE_STRIP);
while(vIt != l->GetVertexList()->End())
{
// Take into account pixel spacing and origin
PointType spacePoint = vIt.Value();
spacePoint[0]*= m_Spacing[0];
spacePoint[1]*= m_Spacing[1];
spacePoint[0]-= m_Origin[0];
spacePoint[1]-= m_Origin[1];
// Transform to a screen point
PointType screenPoint = transform->TransformPoint(spacePoint);
// Add a point to the rendered line
glVertex2d(screenPoint[0],screenPoint[1]);
++vIt;
}
glEnd();
}
template <class TVectorData>
......@@ -101,10 +177,116 @@ void
VectorDataGlComponent<TVectorData>
::RenderPolygon(const PolygonType * extRing, const PolygonListType * intRings, const RegionType & extent, const AffineTransformType * transform)
{
typedef std::vector<GLdouble * > VertexVectorType;
// A buffer to hold vertex until they are rendered
VertexVectorType vertexBuffer;
// Begin a new polygon
gluTessBeginPolygon(m_GluTesselator,NULL);
// Render the outer boundary
gluTessBeginContour(m_GluTesselator);
// Iterate on the polygon
typename PolygonType::VertexListType::ConstIterator vIt = extRing->GetVertexList()->Begin();
while(vIt!= extRing->GetVertexList()->End())
{
// Take into account pixel spacing and origin
PointType spacePoint = vIt.Value();
spacePoint[0]*= m_Spacing[0];
spacePoint[1]*= m_Spacing[1];
spacePoint[0]-= m_Origin[0];
spacePoint[1]-= m_Origin[1];
// Transform to a screen point
PointType screenPoint = transform->TransformPoint(spacePoint);
// Convert to double array
GLdouble * glp = new GLdouble[2];
glp[0]=screenPoint[0];
glp[1]=screenPoint[1];
vertexBuffer.push_back(glp);
// Add a point to the outer boundary
gluTessVertex(m_GluTesselator,glp,glp);
++vIt;
}
// End the outer boundary contour
gluTessEndContour(m_GluTesselator);
// Render remaining inner boundaries
typename PolygonListType::ConstIterator pIt = intRings->Begin();
// For each inner boundary
while(pIt != intRings->End())
{
vIt = pIt.Get()->GetVertexList()->Begin();
// Begin a new contour
gluTessBeginContour(m_GluTesselator);
// Render each of its vertex
while(vIt!= pIt.Get()->GetVertexList()->End())
{
// Take into account pixel spacing and origin
PointType spacePoint = vIt.Value();
spacePoint[0]*= m_Spacing[0];
spacePoint[1]*= m_Spacing[1];
spacePoint[0]-= m_Origin[0];
spacePoint[1]-= m_Origin[1];
// Transform to a screen point
PointType screenPoint = transform->TransformPoint(spacePoint);
// Convert to double array
GLdouble * glp = new GLdouble[2];
glp[0]=screenPoint[0];
glp[1]=screenPoint[1];
vertexBuffer.push_back(glp);
// Add a point to the outer boundary
gluTessVertex(m_GluTesselator,glp,glp);
++vIt;
}
// End the contour
gluTessEndContour(m_GluTesselator);
++pIt;
}
// End the polygon
gluTessEndPolygon(m_GluTesselator);
// Do not forget to free all the vertex
for(typename VertexVectorType::iterator it = vertexBuffer.begin();
it!=vertexBuffer.end();++it)
{
delete [] (*it);
}
}
template <class TVectorData>
void
VectorDataGlComponent<TVectorData>
::FramePoint(const PointType & point)
{
// Set the frame color
glColor4d(0,0,1,1);
glBegin(GL_LINE_LOOP);
glVertex2d(point[0]-5,point[1]-5);
glVertex2d(point[0]-5,point[1]+5);
glVertex2d(point[0]+5,point[1]+5);
glVertex2d(point[0]+5,point[1]-5);
glEnd();
// Set back the drawing color
glColor4d(m_Color[0],m_Color[1],m_Color[2],m_Color[3]);
}
}
#endif
......
......@@ -255,6 +255,11 @@ ADD_TEST(vrTuVectorDataGlComponentNew ${VISUREFAC_TESTS1}
otbVectorDataGlComponentNew
)
ADD_TEST(vrTvImageWidgetWithVectorDataGlComponent ${VISUREFAC_TESTS1}
otbImageWidgetWithVectorDataGlComponent
${INPUTDATA}/poupees.png 0
)
# Testing srcs
SET(VisuRefac_SRCS1
......@@ -291,6 +296,7 @@ otbCurves2DWidget.cxx
otbHistogramCurveNew.cxx
otbCurves2DWidgetWithHistogram.cxx
otbVectorDataGlComponentNew.cxx
otbImageWidgetWithVectorDataGlComponent.cxx
)
# Building testing executables
......
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#define OTB_DISABLE_GL_USE_ACCEL
#include "otbImageWidget.h"
#include "otbImageFileReader.h"
#include "otbVectorDataGlComponent.h"
#include "otbVectorData.h"
#include <FL/Fl.H>
int otbImageWidgetWithVectorDataGlComponent( int argc, char * argv[] )
{
const char * infname = argv[1];
const bool useAccel = atoi(argv[2]);
// Widget typedefs
typedef otb::ImageWidget<> WidgetType;
typedef WidgetType::InputImageType ImageType;
typedef otb::ImageFileReader<ImageType> ReaderType;
// VectorData component typedef
typedef otb::VectorData<double,2> VectorDataType;
typedef otb::VectorDataGlComponent<VectorDataType> VectorDataGlComponentType;
typedef VectorDataType::DataNodeType DataNodeType;
typedef DataNodeType::PointType PointType;
typedef DataNodeType::LineType LineType;
typedef DataNodeType::PolygonType PolygonType;
// Reading the input image
ReaderType::Pointer reader = ReaderType::New();
reader->SetFileName(infname);
reader->Update();
ImageType::RegionType region = reader->GetOutput()->GetLargestPossibleRegion();
// Create a VectorData
VectorDataType::Pointer data = VectorDataType::New();
DataNodeType::Pointer document = DataNodeType::New();
DataNodeType::Pointer folder = DataNodeType::New();
DataNodeType::Pointer point = DataNodeType::New();
DataNodeType::Pointer line = DataNodeType::New();
DataNodeType::Pointer polygon = DataNodeType::New();
document->SetNodeId("DOCUMENT");
folder->SetNodeId("FOLDER");
point->SetNodeId("FEATURE_POINT");
line->SetNodeId("FEATURE_LINE");
polygon->SetNodeId("FEATURE_POLYGON");
// Create a point on the first quarter of the image
PointType p;
p[0] = region.GetIndex()[0]+region.GetSize()[0]/4;
p[1] = region.GetIndex()[1]+region.GetSize()[1]/4;
point->SetPoint(p);
// Create a line on the second quarter of the image
LineType::Pointer l = LineType::New();
LineType::ContinuousIndexType cindex;
cindex[0] = region.GetIndex()[0]+region.GetSize()[0]/2;
cindex[1] = region.GetIndex()[1];
l->AddVertex(cindex);
cindex[0] = region.GetIndex()[0]+region.GetSize()[0];
cindex[1] = region.GetIndex()[1]+region.GetSize()[1]/2;
l->AddVertex(cindex);
line->SetLine(l);
// Create a complex polygon shape on the remaning of the image
// Outer ring
PolygonType::Pointer outer = PolygonType::New();
cindex[0] = region.GetIndex()[0]+region.GetSize()[0]/16;
cindex[1] = region.GetIndex()[1]+9*region.GetSize()[1]/16;
outer->AddVertex(cindex);
cindex[0] = region.GetIndex()[0]+15*region.GetSize()[0]/16;
cindex[1] = region.GetIndex()[1]+9*region.GetSize()[1]/16;
outer->AddVertex(cindex);
cindex[0] = region.GetIndex()[0]+15*region.GetSize()[0]/16;
cindex[1] = region.GetIndex()[1]+15*region.GetSize()[1]/16;
outer->AddVertex(cindex);
cindex[0] = region.GetIndex()[0]+region.GetSize()[0]/16;
cindex[1] = region.GetIndex()[1]+15*region.GetSize()[1]/16;
outer->AddVertex(cindex);
polygon->SetPolygonExteriorRing(outer);
// Inner ring
PolygonType::Pointer inner = PolygonType::New();
cindex[0] = region.GetIndex()[0]+2*region.GetSize()[0]/16;
cindex[1] = region.GetIndex()[1]+10*region.GetSize()[1]/16;
inner->AddVertex(cindex);
cindex[0] = region.GetIndex()[0]+14*region.GetSize()[0]/16;
cindex[1] = region.GetIndex()[1]+10*region.GetSize()[1]/16;
inner->AddVertex(cindex);
cindex[0] = region.GetIndex()[0]+14*region.GetSize()[0]/16;
cindex[1] = region.GetIndex()[1]+14*region.GetSize()[1]/16;
inner->AddVertex(cindex);
cindex[0] = region.GetIndex()[0]+2*region.GetSize()[0]/16;
cindex[1] = region.GetIndex()[1]+14*region.GetSize()[1]/16;
inner->AddVertex(cindex);
polygon->GetPolygonInteriorRings()->PushBack(inner);
DataNodeType::Pointer root = data->GetDataTree()->GetRoot()->Get();
data->GetDataTree()->Add(document,root);
data->GetDataTree()->Add(folder,document);
data->GetDataTree()->Add(point,folder);
data->GetDataTree()->Add(line,folder);
data->GetDataTree()->Add(polygon,folder);
// Create a widget
WidgetType::Pointer widget = WidgetType::New();
// Set the acceleration mode
widget->SetUseGlAcceleration(useAccel);
// Resize it
widget->resize(0,0,region.GetSize()[0],region.GetSize()[1]);
// Show it
widget->show();
// Refresh display
Fl::check();
// Read the OpenGl buffer
widget->ReadBuffer(reader->GetOutput(),region);
// Redraw it
widget->redraw();
// Refresh display
Fl::check();
// Create the VectorDataGlComponent
VectorDataGlComponentType::Pointer vdgl = VectorDataGlComponentType::New();
vdgl->SetVectorData(data);
widget->AddGlComponent(vdgl);
widget->redraw();
Fl::check();
return EXIT_SUCCESS;
}
......@@ -59,4 +59,5 @@ void RegisterTests()
REGISTER_TEST(otbCurves2DWidget);
REGISTER_TEST(otbCurves2DWidgetWithHistogram);
REGISTER_TEST(otbVectorDataGlComponentNew);
REGISTER_TEST(otbImageWidgetWithVectorDataGlComponent);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment