Categories

# Access Triangulation Elements and draw Postscript – Example2

This article has two goals: First, it shows how you can access the elements of a triangulation. Second, it shows how you can draw them. Because development is much easier when you can visualize your work.

## Preparing a triangulation

Let’s prepare and draw a simple triangulation for this demo:

```int example2_main()
{
std::cout<<"\nexample2: Access elements of a triangulation\n";
// * 1 *   Create points on a circle
std::vector<Point2> vPoints;
int numPoints(6);
vPoints.push_back(Point2(centerX,centerY)); // Add the center point

// * 2 *   Optional step: You can add custom indices to relate
//         the points to your own data structures. But you do
//         not need to use this feature.
int myStartIndex(77); // An arbitrary value
for(size_t i=0;i<vPoints.size();++i)
{
vPoints[i].setCustomIndex(myStartIndex++);
}

// * 3 *   Insert the vertices
Fade_2D dt; // The Delaunay triangulation
std::vector<Point2*> vVertexHandles; // Pointers to the vertices inside Fade
dt.insert(vPoints,vVertexHandles); // Fastest method: insert all points at once
// * 4 *   Draw the triangulation
dt.show("triangulation.ps");
...
}```
1. In Step 1 we fill the vector `vPoints` with 6 points on a circle plus the center point. Hint: Fade provides generators for circles and for random points, segments, polygons and surfaces).
2. Step 2 assigns indices to the points. These are thought to let you link Fade points with your own datastructures. This is of course completely optional.
3. Step 3 inserts the points. Internally, Fade keeps a copy of the points and returns pointers to them (in the same order) in `vVertexHandles`. Inserting all points at once is most efficient. But there is also a method to insert the points one by one.
4. The fourth step draws the triangulation using `Fade_2D::show("triangulation.ps")`

## Accessing Elements

Access to elements in a triangulation is often required. For example, you may want to access the neighboring triangles of a particular triangle. Or you may want to create a custom visualization instead of the ready-made visualization. So let’s discuss the below `manualDraw()` function:

```void manualDraw(Fade_2D& dt)
{
// * 1 *   Create a postscript visualizer and define some colors
Visualizer2 vis("manualDraw.ps");
Color cBlack(CBLACK);
Color cBlue(CBLUE);
Color cRed(CRED);
Color cPurple(CPURPLE);

// * 2 *   Get and draw the vertices with their custom index
std::vector<Point2*> vAllPoints;
dt.getVertexPointers(vAllPoints);
std::cout<<"vAllPoints.size()="<<vAllPoints.size()<<std::endl;
for(std::vector<Point2*>::iterator it(vAllPoints.begin());it!=vAllPoints.end();++it)
{
Point2* currentPoint(*it);
int customIndex(currentPoint->getCustomIndex());
std::string text(toString(customIndex));
}
// * 3 *   Get and draw the triangles
std::vector<Triangle2*> vAllDelaunayTriangles;
dt.getTrianglePointers(vAllDelaunayTriangles);
for(std::vector<Triangle2*>::iterator it=vAllDelaunayTriangles.begin();it!=vAllDelaunayTriangles.end();++it)
{
Triangle2* pT(*it);
}
// * 4 *   Choose one triangle and color it green
Triangle2* pT(vAllDelaunayTriangles);
Color cGreenFill(CPALEGREEN,0.001f,true);
// * 5 *   The corners of pT can be accessed through the so called intra-
// triangle-indices 0,1,2. They are counterclockwise oriented (CCW).
// Let's write intra-triangle-index labels beside the corners.
for(int intraTriangleIndex=0;intraTriangleIndex<3;++intraTriangleIndex)
{
Point2* pCorner(pT->getCorner(intraTriangleIndex));
std::string text("\nidx="+toString(intraTriangleIndex));
}
// * 6 *   Each triangle has three neighbor triangles (or NULL
// pointers at border edges). They are accessed through the
// intra-triangle-indices. The i'th opposite triangle of pT is
// the one that is opposite to the i'th vertex. Let's draw that:
Label label_pT(pT->getBarycenter()," pT",true,15);
for(int intraTriangleIndex=0;intraTriangleIndex<3;++intraTriangleIndex)
{
Triangle2* pNeigT(pT->getOppositeTriangle(intraTriangleIndex));
if(pNeigT==NULL) continue; // No adjacent triangle at this edge
// Compute the barycenter and write a label there
Point2 barycenter(pNeigT->getBarycenter());
std::string text(" =pT->getOppositeTriangle("+toString(intraTriangleIndex)+")");
Label neigLabel(barycenter,text.c_str(),true,15);
}
// Write the postscript file to disk
vis.writeFile();
}```
1. Step 1 creates a `Visualizer2` object with the postscript-filename “manualDraw.ps”. Next it defines a few colors and then it adds labels to the visualizer.
2. The second step retrieves pointers to all triangulation vertices. It draws them along with the custom indices set before.
3. The third step fetches all triangle pointers and then adds them them to the visualizer.
4. Step 4 chooses an arbitrary triangle `pT` and fills it with green color
5. Step 5 shows how to access the corners of `pT` through the so called intra-triangle-indices {0,1,2}. These are always counterclockwise. We write the intra-triangle-indices in blue color.
6. Each triangle `pT` has three pointers to its neighboring triangles (or `NULL` in case of border edges): The i-th neighbor triangle is always the one opposite the vertex with intra-triangle-index i. Step 6 draws red labels at the barycenters of the neighbor triangles.
7. The `writeFile()` method is called to finalize the postscript drawing.

## More Visualization

It is unlikely that you will need it soon, but for completeness, the demo ex2_access_draw.cpp also includes the `moreDraw()` function, which demonstrates additional functions of the Visualizer2 class. It’s source code below is certainly self-explanatory.

```void moreDraw()
{
// * 1 *   Defining color
// Define red by values (red,green,blue,linewidth,bFill)
Color cRed(1,0,0,0.001,false);
// Or simply use a color name and the defaults linewidth=0.001 and bFill=false
Color cBlue(CBLUE);
Color cGreen(CGREEN);
Color cPurple(CPURPLE);
// Specify a bolt green color (linewidth=1.0) and another one with
// bFill=true to fill the area of an object which is drawn using
// that color. In case that a segment is drawn with bFill=true,
// marks for its endpoints are added.
Color cGreenBolt(CGREEN,1.0,false);
Color cGreenFill(CGREEN,.001f,true);
// Postscript writer
Visualizer2 vis("moreDraw.ps");
// Create a label and add it to the Visualizer
false,			// Don't write an x-mark
30);			// Font size
// Add a row of points
for(int x=0;x<100;x+=5)
{
Point2 p(x,50);
}
// Draw a segment with cGreen
Point2 p0(0,0);
Point2 p1(100,0);
Segment2 seg0(p0,p1);
// Draw a segment with cGreenFill (with marks at the endpoints)
Point2 p2(0,10);
Point2 p3(100,10);
Segment2 seg1(p2,p3);
// Draw a segment with cGreenBolt
Point2 p4(0,20);
Point2 p5(100,20);
Segment2 seg2(p4,p5);
// Draw labels
Label lab0(Point2(20,2),"Segment in cGreen",false,15);
Label lab1(Point2(20,12),"Segment in cGreenFill",false,15);
Label lab2(Point2(20,22),"Segment in cGreenBolt",false,15);