

In my crossplatform c++ framework ( www.amanith.org ) i've implemented a fast sweepline tesselator that can handle non simple polygons with holes , and some common degenerations.
For every questions abuot this, email me at: mfabbri@amanith.org





You had implemented it?
My god! Your code is too similiar to SGI/libtess.
Such functions as "sweepevent", "TessellateMonotoneRegion" ..., are almost the same to SGI/libtess.
I suggest you add " Thanks to SGI/libtess " in the header.
Hey, kavenger,
you should not always call "AddContourPoint",
If you had research the struct of Mesh carefully,you can add all your vertex once together. This can make you function 100% faster.
============================
Gods know that I really love you from the bottom of my heart,but I forget to tell you that...





Hey Liu,
I have read all libtess sources/docs, and got inspired during the writing of my tessellator, as weel as for another good paper, that explain the sweepline algorithm in details ( http://www.cs.ucsb.edu/~suri/cs235/Triangulation.pdf ).So, yes, i'll follow your suggestion adding the greetings to SGI.
My decision to rewite a tesselator instead of using the libtess ones is due to the fact that i had a try to be more robust and support more degeneration cases, without to introduce overheads of any kind.
Anyway, now, i'm oriented in a direction to use OpenGL drawing tecniques that don't need of the tesselation step, beacuse this step is too expensive, and it needs a too high robustness level.
Just for curiosity,
Are you using Amanith? Do u use the tessellation for drawing purposes or for something other?
( my mail is: mfabbri ]at[ amanith ]dot[ org )





Change the line:
for( register int i=0 , j=1 ; j < nPoints ; i++ , j++ ){
to:
for( register int i=0 , j=1 ; i < nPoints ; i++ , j++, j=j%nPoints ){
and normal of the polygon will be calculated correctly.
Torsten





It could be better for performance issue to exclude the case of last j from the for loop, in order not to compute the modulo each time.
I would do :
normal[0]=normal[1]=normal[2]=0.0f;
for( register int i=0 , j=1 ; j < nPoints ; i++ , j++ ){
normal[0]+= ( points[i][1]  points[j][1] ) * ( points[i][2] + points[j][2] ) ;
normal[1]+= ( points[i][2]  points[j][2] ) * ( points[i][0] + points[j][0] ) ;
normal[2]+= ( points[i][0]  points[j][0] ) * ( points[i][1] + points[j][1] ) ;
}
// last case :
normal[0]+= ( points[i][1]  points[0][1] ) * ( points[i][2] + points[0][2] ) ;
normal[1]+= ( points[i][2]  points[0][2] ) * ( points[i][0] + points[0][0] ) ;
normal[2]+= ( points[i][0]  points[0][0] ) * ( points[i][1] + points[0][1] ) ;

It would also be a good idea to delete Vector3F array in CPolyTryView::OnDraw(CDC* pDC) after call to triangulate() to avoid memory leaks !





Area computation is bugged :
you should add in CPolyTriView::OnDraw()
existing :
//
for( int i=0 ; i < m_nPoints ; i++ ){
points[i][0] = m_points[i].x;
points[i][1] = m_points[i].y;
if( i ) Area+= ( m_points[i].x * m_points[i1].y  m_points[i1].x * m_points[i].y) * 0.5f;
}
//
// added after for loop :
Area += ( m_points[0].x * m_points[i1].y  m_points[i1].x * m_points[0].y) * 0.5f;
Also, if area computation is only used for normal deduction, you can avoid *0.5f as it will not change area sign.





Thanks for the code.
Martin





Thank you very much for this example!
It's the simple and best tesselation
algorithm I found over the internet!
I found a special case that popup an
index range error (very hard to find!!! )
in the Triangulate function.
The "k" index missed 2 hits because it
starts at k=2... So I did a little patch!
New loop:
for( int i=0 , j=1 , k=2 ; k < nVertex+3 ; )
New indexes:
int ib = i % nVertex;
int jb = j % nVertex;
int kb = k % nVertex;
Here is the modified function:
// BEGIN
int nTriangle= 0;
int nVertex = nCount;
//
AllocIndex(nCount);
//
bool bNoErrors = true;
//
while( nVertex > 3 && bNoErrors )
{
//
// tri to remove one vertex...
//
bNoErrors = false;
//
for( int i=0 , j=1 , k=2 ; k < nVertex+3 ; )
{
if( nVertex == 0 )
break;
int ib = i % nVertex;
int jb = j % nVertex;
int kb = k % nVertex;
//
switch( TriangleArea(points,
m_nIndex[ib],
m_nIndex[jb],
m_nIndex[kb],
normal) )
{
//
// ok. flush face && remove vertex j
//
case convex :
//
// Testing containement
//
if( IsAnyPointInside(points,ib,jb,kb,nVertex) ){
//
// go ahead..
//
i = j;
j = k;
k++;
}
else
{
nTriangle++;
AddFace(points,m_nIndex[ib],m_nIndex[jb],m_nIndex[kb]);
//
// remove vertex j
//
nVertex = RemoveVertex(jb, nVertex);
bNoErrors= true;
}
break;
case concave :
//
// go ahead..
//
i = j;
j = k;
k++;
break;
case degenerate :
//
// remove vertex j
//
nVertex = RemoveVertex(jb, nVertex);
bNoErrors= true;
break;
}
}
}
return nTriangle;
// END
TruePyroman





Another litle improvement:
Use previus code and change the line
while( nVertex > 3 && bNoErrors )
with the line
while( nVertex >= 3 && bNoErrors )
Also to solve the problem with degenerate points (alligned or suballigned) replace the test in function Triangle Area (that work fine for planar 2D polygon's)
//
// j is alligned from i to k ?
//
if( (FLT_EPSILON) < m_A && m_A < FLT_EPSILON )
return degenerate;
with:
//
// j is alligned from i to k ?
//
if( (FLT_EPSILON) < m_A && m_A < FLT_EPSILON &&
(FLT_EPSILON) < m_N[0] && m_N[0] < FLT_EPSILON &&
(FLT_EPSILON) < m_N[1] && m_N[1] < FLT_EPSILON &&
(FLT_EPSILON) < m_N[2] && m_N[2] < FLT_EPSILON )
return degenerate;
Last (but not least) if some consecutive triangles as the same origin vertex you can optimizing opengl drawing code collecting the common side (from two consecutive triangles) and using triangle fan (example triangle vertex 0,1,2 && 0,2,3 etc.. can be collected in a triangle fan 0,1,2,3 etc..)
Thanks very much for this very speedy code





Hi ,
Ok Delauney rules in good tesselation. But in the case of nonconvex poly you have to use the constrained form of the algorithm (DCT). You can achieve good tesselation without get rid of your algorithm :
as a post  process phase you can "mimimize" the edge size of convex quads. It's like use the turn edge tools in 3ds max. In this way, long triangles are converted in more equilaterals ones.
If i got time i'll try and send it to you.





A more little explanation about my article. In order to tesselate the polygon i use this tecnique:
First compute the normal of polygon (i use the newell method see Graphic Gems..)
For each sequence of three vertex ( i, j, k ) in the polygon compute the vector area (alias normal of triangle).
If the normal go in the opposite direction of polygon normal the triangle is 'concave' and go ahead.
If the area il 0.0 the point j is alligned from i to k and eliminated from the list of vertex.
If the normal of triangle is in the same direction of polygon normal the triangle is convex. In the last case check if any other point is inside the triangle (the IsPointInside function). This function test if the point is on solid angle ik ^ jk. if this is true compute distance of intersection k>point to line ij and test distance. If all is good emit triangle, remove vertex j from list and go to the next triplet....
The reason for wich i posted this article is that i don't find this tecnique in any book or article and ave a doubt about the mathematical basic of my algoritm In other words is true that it work in any case ? (my experience ask yes but is very far from a theorem...)
The Delauney algortim work fine but is 'computational' more expensive than my algortim (using my Delauney implementation) for this reason i try this way. At the end my apologize for my poor english but my sincerly idea is to contribute to codeproject and suggest a way to resolv a problem that i found. Thanks pepito.





(excuse me for my poor english too ) )
I didn't want you to use a delaunay algorithm. My message intention was to show another way than Delaunay to improve you algorithm. The one i describe is only an idea to turn edges to have better result. And i don't take it from any book too and i don't think it's computationnal intensive. I think this idea can be plug as a post process of you algorithm.
I respect you intention to contribute. And my idea is to contribute to the improvment of your. This was my only intention.
Thanks
Jeckle





This is a good start towards providing more information in your article. If you can provide a bit more detail then you should consider updating it.





I would suggest using a delauney triangulation  it will cut down the number of thin strips, and produce a much better tesselation.
Here's a link..
or do a search on google.





It appeared as though the Delauney method only worked for polygons that were contained within the convex hull of the set of polygons. It appears as the method shown here works on concave polygons as well.





A more little explanation about my article. In order to tesselate the polygon i use this tecnique:
First compute the normal of polygon (i use the newell method see Graphic Gems..)
For each sequence of three vertex ( i, j, k ) in the polygon compute the vector area (alias normal of triangle).
If the normal go in the opposite direction of polygon normal the triangle is 'concave' and go ahead.
If the area il 0.0 the point j is alligned from i to k and eliminated from the list of vertex.
If the normal of triangle is in the same direction of polygon normal the triangle is convex. In the last case check if any other point is inside the triangle (the IsPointInside function). This function test if the point is on solid angle ik ^ jk. if this is true compute distance of intersection k>point to line ij and test distance. If all is good emit triangle, remove vertex j from list and go to the next triplet....
The reason for wich i posted this article is that i don't find this tecnique in any book or article and ave a doubt about the mathematical basic of my algoritm In other words is true that it work in any case ? (my experience ask yes but is very far from a theorem...)
The Delauney algortim work fine but is 'computational' more expensive than my algortim (using my Delauney implementation) for this reason i try this way. At the end my apologize fro my poor english but my sincerly idea is to contribute to codeproject and suggest a way to resolv a problem that i found. Thanks pepito.





Pepito Sbazzeguti... "Gratta il Pepito, viene fuori il Peppone!"
Certo che avresti potuto essere più originale con lo pseudonimo.
Samantha Fox





Peppone for President!
Don Camillo





thank you guys ! I am only a senator but in the future, with some TV network...D





Ah, spiritoso, eh?
Forza Berlusca, non ti curar di lor ma guarda e passa!
Samantha Fox





I have a suggestion for you: Write up that article properly!
That is, why don't you put some explanation of the problem itself, the solution utilized by your code, the potential use of the code and some code examples of how to use it in another application etc. ?





Sorry, and my apologize, but my english is very poor.!!!! This is a basic class to use in alternative to tools like gluTesselate. The glu function is much flexible but in the (frequent) case in wich you ave a simple polygon this class let you to take a more control.
For instance:
dont insert new points in the polygon (and if you attach vertex property like color or vertex texture coordinate dont request any interpolation of this parameters)
dont use expensive time functions like square root etc. is fast like gluTesselate (try it)
work in 3D
Pepito





Perhaps because his English isn't too hot?
Who made you the article Gestapo around here?





Anonymous wrote:
Perhaps because his English isn't too hot?
Who made you the article Gestapo around here?
You must understand that it takes more than just good code to make a good article. An explanation of how and why is essential.
Even if English isn't your first language, there's no reason an author shouldn't write it first in his or her own native language and then ask for assistance (via the Collaboration/Testing forum or even the Lounge) in translating it into English before posting.
Of course, these days you can also do some limited translation via the web, which may be enough.
Remember that there's no need to worry about English in an article being perfect  CPians are pretty understanding of language barriers.
Andy Metcalfe  Sonardyne International Ltd
Trouble with resource IDs? Try the Resource ID Organiser AddIn for Visual C++
"I would be careful in separating your wierdness, a good quirky weirdness, from the disturbed wierdness of people who take pleasure from PVC sheep with fruit repositories."
 Paul Watson





What is wrong with you people? The guy has put together an interesting piece of code that people like me and possibly many others appreciate. Whilst I agree it is possible to get far more out of an article when it is properly written up, if someone submitting an article doesn't want to, or feels it would take excessive time to translate into a language that is not their own, then it is up to them. I wish people would stop being so critical of other people's efforts. If you don't like the article don't read it. If you have a criticism to make then at least be constructive. If you are that bothered Andy then why not offer to translate an article yourself. And as for George...
People contibuting code should be encouraged. It takes 5 minutes to write a criticism and boost your ego, it takes a lot more effort to write a decent peice of code.
Gary McHale



