Small tweaks to CDT
- added CDT support for demo
- added infinity-loop safety guard on CDT iteration count
- visit all 4 neighbours
- changed to options based API
diff --git a/Example/example.c b/Example/example.c
index acbc388..2d4e23b 100644
--- a/Example/example.c
+++ b/Example/example.c
@@ -56,6 +56,7 @@
int run = 1;
+int cdt = 0;
static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
{
@@ -65,6 +66,8 @@
glfwSetWindowShouldClose(window, GL_TRUE);
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
run = !run;
+ if (key == GLFW_KEY_C && action == GLFW_PRESS)
+ cdt = !cdt;
}
int main(int argc, char *argv[])
@@ -79,14 +82,15 @@
float t = 0.0f, pt = 0.0f;
TESSalloc ma;
TESStesselator* tess = 0;
- const int nvp = 6;
+ const int nvp = 3;
unsigned char* vflags = 0;
- int nvflags = 0;
#ifdef USE_POOL
struct MemPool pool;
unsigned char mem[1024*1024];
+ int nvflags = 0;
#else
int allocated = 0;
+ double t0 = 0, t1 = 0;
#endif
TESS_NOTUSED(argc);
TESS_NOTUSED(argv);
@@ -104,7 +108,7 @@
if (!fg) return -1;
printf("go...\n");
-
+
// Flip y
for (it = bg; it != NULL; it = it->next)
for (i = 0; i < it->npts; ++i)
@@ -138,7 +142,7 @@
it->pts[i*2+1] -= cy;
}
}
-
+
// Find BG bounds.
bounds[0] = bounds[2] = bg->pts[0];
bounds[1] = bounds[3] = bg->pts[1];
@@ -154,7 +158,7 @@
if (y > bounds[3]) bounds[3] = y;
}
}
-
+
#ifdef USE_POOL
pool.size = 0;
@@ -168,6 +172,8 @@
#else
+ t0 = glfwGetTime();
+
memset(&ma, 0, sizeof(ma));
ma.memalloc = stdAlloc;
ma.memfree = stdFree;
@@ -178,6 +184,8 @@
if (!tess)
return -1;
+ tessSetOption(tess, TESS_CONSTRAINED_DELAUNAY_TRIANGULATION, 1);
+
// Offset the foreground shape to center of the bg.
offx = (bounds[2]+bounds[0])/2;
offy = (bounds[3]+bounds[1])/2;
@@ -189,7 +197,7 @@
it->pts[i*2+1] += offy;
}
}
-
+
// Add contours.
for (it = bg; it != NULL; it = it->next)
tessAddContour(tess, 2, it->pts, sizeof(float)*2, it->npts);
@@ -197,10 +205,14 @@
tessAddContour(tess, 2, it->pts, sizeof(float)*2, it->npts);
if (!tessTesselate(tess, TESS_WINDING_POSITIVE, TESS_POLYGONS, nvp, 2, 0))
return -1;
+
+ t1 = glfwGetTime();
+
+ printf("Time: %.3f ms\n", (t1 - t0) * 1000.0f);
printf("Memory used: %.1f kB\n", allocated/1024.0f);
-
+
#endif
-
+
mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
width = mode->width - 40;
height = mode->height - 80;
@@ -221,17 +233,27 @@
view[2] = cx + w*1.2f;
view[1] = cy - w*1.2f*(float)height/(float)width;
view[3] = cy + w*1.2f*(float)height/(float)width;
-
+
glfwSetTime(0);
while (!glfwWindowShouldClose(window))
{
- float ct = (float)glfwGetTime();
+ int winWidth, winHeight;
+ int fbWidth, fbHeight;
+ float pxr, ct;
+
+ glfwGetWindowSize(window, &winWidth, &winHeight);
+ glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
+
+ // Calculate pixel ration for hi-dpi devices.
+ pxr = (float)fbWidth / (float)winWidth;
+
+ ct = (float)glfwGetTime();
if (run) t += ct - pt;
pt = ct;
-
+
// Update and render
- glViewport(0, 0, width, height);
+ glViewport(0, 0, fbWidth, fbHeight);
glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
@@ -251,9 +273,11 @@
tess = tessNewTess(&ma);
if (tess)
{
+ tessSetOption(tess, TESS_CONSTRAINED_DELAUNAY_TRIANGULATION, cdt);
+
offx = (view[2]+view[0])/2 + sinf(t) * (view[2]-view[0])/2;
offy = (view[3]+view[1])/2 + cosf(t*3.13f) * (view[3]-view[1])/6;
-
+
for (it = fg; it != NULL; it = it->next)
{
for (i = 0; i < it->npts; ++i)
@@ -293,7 +317,7 @@
nvflags = nverts;
vflags = (unsigned char*)malloc(sizeof(unsigned char)*nvflags);
}
-
+
if (vflags)
{
// Vertex indices describe the order the indices were added and can be used
@@ -303,7 +327,7 @@
for (i = 0; i < nverts; ++i)
vflags[i] = vinds[i] == TESS_UNDEF ? 1 : 0;
}
-
+
for (i = 0; i < nelems; ++i)
{
int b = elems[i*2];
@@ -314,9 +338,9 @@
tess = 0;
}
else
- tess = 0;
+ tess = 0;
}
-#endif
+#endif
// Draw tesselated pieces.
if (tess)
@@ -326,7 +350,7 @@
const int* elems = tessGetElements(tess);
const int nverts = tessGetVertexCount(tess);
const int nelems = tessGetElementCount(tess);
-
+
// Draw polygons.
glColor4ub(255,255,255,128);
for (i = 0; i < nelems; ++i)
@@ -337,7 +361,10 @@
glVertex2f(verts[p[j]*2], verts[p[j]*2+1]);
glEnd();
}
-
+
+ glLineWidth(1.0f * pxr);
+ glPointSize(3.0f * pxr);
+
glColor4ub(0,0,0,16);
for (i = 0; i < nelems; ++i)
{
@@ -347,9 +374,8 @@
glVertex2f(verts[p[j]*2], verts[p[j]*2+1]);
glEnd();
}
-
+
glColor4ub(0,0,0,128);
- glPointSize(3.0f);
glBegin(GL_POINTS);
for (i = 0; i < nverts; ++i)
{
@@ -360,21 +386,22 @@
glVertex2f(verts[i*2], verts[i*2+1]);
}
glEnd();
+
glPointSize(1.0f);
}
-
+
glEnable(GL_DEPTH_TEST);
glfwSwapBuffers(window);
glfwPollEvents();
}
-
+
if (tess) tessDeleteTess(tess);
-
+
if (vflags)
free(vflags);
-
- svgDelete(bg);
- svgDelete(fg);
+
+ svgDelete(bg);
+ svgDelete(fg);
glfwTerminate();
return 0;
diff --git a/Include/tesselator.h b/Include/tesselator.h
index 6e51e32..38e05f1 100755
--- a/Include/tesselator.h
+++ b/Include/tesselator.h
@@ -1,5 +1,5 @@
/*
-** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
** Copyright (C) [dates of first publication] Silicon Graphics, Inc.
** All Rights Reserved.
**
@@ -9,10 +9,10 @@
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
** of the Software, and to permit persons to whom the Software is furnished to do so,
** subject to the following conditions:
-**
+**
** The above copyright notice including the dates of first publication and either this
** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be
-** included in all copies or substantial portions of the Software.
+** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
@@ -20,7 +20,7 @@
** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
** OR OTHER DEALINGS IN THE SOFTWARE.
-**
+**
** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not
** be used in advertising or otherwise to promote the sale, use or other dealings in
** this Software without prior written authorization from Silicon Graphics, Inc.
@@ -106,17 +106,22 @@
// }
// glEnd();
// }
-//
-// TESS_CONSTRAINED_DELAUNAY_TRIANGLES
-// Similar to TESS_POLYGONS, but we output only triangles and we attempt to provide a valid
-// Constrained Delaunay triangulation.
enum TessElementType
{
TESS_POLYGONS,
TESS_CONNECTED_POLYGONS,
TESS_BOUNDARY_CONTOURS,
- TESS_CONSTRAINED_DELAUNAY_TRIANGLES
+};
+
+
+// TESS_CONSTRAINED_DELAUNAY_TRIANGULATION
+// If enabled, the initial triagulation is improved with non-robust Constrained Delayney triangulation.
+// Disable by default.
+
+enum TessOption
+{
+ TESS_CONSTRAINED_DELAUNAY_TRIANGULATION,
};
typedef float TESSreal;
@@ -138,12 +143,12 @@
// how often to allocate memory from the system versus how much extra space the system
// should allocate. Reasonable defaults are show in commects below, they will be used if
// the bucket sizes are zero.
-//
+//
// The use may left the memrealloc to be null. In that case, the tesselator will not try to
// dynamically grow int's internal arrays. The tesselator only needs the reallocation when it
// has found intersecting segments and needs to add new vertex. This defency can be cured by
// allocating some extra vertices beforehand. The 'extraVertices' variable allows to specify
-// number of expected extra vertices.
+// number of expected extra vertices.
struct TESSalloc
{
void *(*memalloc)( void *userData, unsigned int size );
@@ -189,12 +194,18 @@
// count - number of vertices in contour.
void tessAddContour( TESStesselator *tess, int size, const void* pointer, int stride, int count );
+// tessSetOption() - Toggles optional tessellation parameters
+// Parameters:
+// option - one of TessOption
+// value - 1 if enabled, 0 if disabled.
+void tessSetOption( TESStesselator *tess, int option, int value );
+
// tessTesselate() - tesselate contours.
// Parameters:
// tess - pointer to tesselator object.
// windingRule - winding rules used for tesselation, must be one of TessWindingRule.
// elementType - defines the tesselation result element type, must be one of TessElementType.
-// polySize - defines maximum vertices per polygons if output is polygons. If elementType is TESS_CONSTRAINED_DELAUNAY_TRIANGLES, this parameter is ignored.
+// polySize - defines maximum vertices per polygons if output is polygons.
// vertexSize - defines the number of coordinates in tesselation result vertex, must be 2 or 3.
// normal - defines the normal of the input contours, of null the normal is calculated automatically.
// Returns:
@@ -212,7 +223,7 @@
// Every point added using tessAddContour() will get a new index starting at 0.
// New vertices generated at the intersections of segments are assigned value TESS_UNDEF.
const TESSindex* tessGetVertexIndices( TESStesselator *tess );
-
+
// tessGetElementCount() - Returns number of elements in the the tesselated output.
int tessGetElementCount( TESStesselator *tess );
diff --git a/Source/geom.c b/Source/geom.c
index 00b307a..97a5046 100755
--- a/Source/geom.c
+++ b/Source/geom.c
@@ -1,5 +1,5 @@
/*
-** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
** Copyright (C) [dates of first publication] Silicon Graphics, Inc.
** All Rights Reserved.
**
@@ -9,10 +9,10 @@
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
** of the Software, and to permit persons to whom the Software is furnished to do so,
** subject to the following conditions:
-**
+**
** The above copyright notice including the dates of first publication and either this
** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be
-** included in all copies or substantial portions of the Software.
+** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
@@ -20,7 +20,7 @@
** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
** OR OTHER DEALINGS IN THE SOFTWARE.
-**
+**
** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not
** be used in advertising or otherwise to promote the sale, use or other dealings in
** this Software without prior written authorization from Silicon Graphics, Inc.
@@ -266,16 +266,13 @@
*/
TESSreal calcAngle( TESSvertex *v0, TESSvertex *v1, TESSvertex *v2 )
{
- TESSreal num;
- TESSreal den;
- TESSreal a[2];
- TESSreal b[2];
- a[0] = v2->s - v1->s;
- a[1] = v2->t - v1->t;
- b[0] = v0->s - v1->s;
- b[1] = v0->t - v1->t;
- num = a[0] * b[0] + a[1] * b[1];
- den = sqrt( a[0] * a[0] + a[1] * a[1] ) * sqrt( b[0] * b[0] + b[1] * b[1] );
+ TESSreal num, den, ax, ay, bx, by;
+ ax = v2->s - v1->s;
+ ay = v2->t - v1->t;
+ bx = v0->s - v1->s;
+ by = v0->t - v1->t;
+ num = ax * bx + ay * by;
+ den = sqrt( ax * ax + ay * ay ) * sqrt( bx * bx + by * by );
if ( den > 0.0 ) num /= den;
if ( num < -1.0 ) num = -1.0;
if ( num > 1.0 ) num = 1.0;
@@ -288,5 +285,5 @@
int tesedgeIsLocallyDelaunay( TESShalfEdge *e )
{
return (calcAngle(e->Lnext->Org, e->Lnext->Lnext->Org, e->Org) +
- calcAngle(e->Sym->Lnext->Org, e->Sym->Lnext->Lnext->Org, e->Sym->Org)) < (M_PI + 0.01);
+ calcAngle(e->Sym->Lnext->Org, e->Sym->Lnext->Lnext->Org, e->Sym->Org)) < (M_PI + 0.01);
}
diff --git a/Source/tess.c b/Source/tess.c
index 5699b18..1233b6d 100755
--- a/Source/tess.c
+++ b/Source/tess.c
@@ -1,5 +1,5 @@
/*
-** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
** Copyright (C) [dates of first publication] Silicon Graphics, Inc.
** All Rights Reserved.
**
@@ -9,10 +9,10 @@
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
** of the Software, and to permit persons to whom the Software is furnished to do so,
** subject to the following conditions:
-**
+**
** The above copyright notice including the dates of first publication and either this
** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be
-** included in all copies or substantial portions of the Software.
+** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
@@ -20,7 +20,7 @@
** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
** OR OTHER DEALINGS IN THE SOFTWARE.
-**
+**
** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not
** be used in advertising or otherwise to promote the sale, use or other dealings in
** this Software without prior written authorization from Silicon Graphics, Inc.
@@ -177,7 +177,7 @@
#define S_UNIT_X (RandomSweep ? (2*drand48()-1) : 1.0)
#define S_UNIT_Y (RandomSweep ? (2*drand48()-1) : 0.0)
#else
-#if defined(SLANTED_SWEEP)
+#if defined(SLANTED_SWEEP)
/* The "feature merging" is not intended to be complete. There are
* special cases where edges are nearly parallel to the sweep line
* which are not implemented. The algorithm should still behave
@@ -286,7 +286,7 @@
* (what else would it do??) The region must consist of a single
* loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this
* case means that any vertical line intersects the interior of the
-* region in a single interval.
+* region in a single interval.
*
* Tessellation consists of adding interior edges (actually pairs of
* half-edges), to split the region into non-overlapping triangles.
@@ -436,43 +436,49 @@
return e;
}
-/*
- Starting with a valid triangulation, uses the Edge Flip algorithm to
- refine the triangulation into a Constrained Delaunay Triangulation.
-*/
-int tessMeshRefineDelaunay( TESSmesh *mesh, TESSalloc *alloc )
-{
- /* At this point, we have a valid, but not optimal, triangulation.
- We refine the triangulation using the Edge Flip algorithm */
-/*
- 1) Find all internal edges
- 2) Mark all dual edges
- 3) insert all dual edges into a queue
-*/
+// Starting with a valid triangulation, uses the Edge Flip algorithm to
+// refine the triangulation into a Constrained Delaunay Triangulation.
+void tessMeshRefineDelaunay( TESSmesh *mesh, TESSalloc *alloc )
+{
+ // At this point, we have a valid, but not optimal, triangulation.
+ // We refine the triangulation using the Edge Flip algorithm
+ //
+ // 1) Find all internal edges
+ // 2) Mark all dual edges
+ // 3) insert all dual edges into a queue
+
TESSface *f;
EdgeStack stack;
TESShalfEdge *e;
- TESShalfEdge *edges[4];
+ int maxFaces = 0, maxIter = 0, iter = 0;
+
stackInit(&stack, alloc);
+
for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
if ( f->inside) {
e = f->anEdge;
do {
- e->mark = EdgeIsInternal(e); /* Mark internal edges */
- if (e->mark && !e->Sym->mark) stackPush(&stack, e); /* Insert into queue */
+ e->mark = EdgeIsInternal(e); // Mark internal edges
+ if (e->mark && !e->Sym->mark) stackPush(&stack, e); // Insert into queue
e = e->Lnext;
} while (e != f->anEdge);
+ maxFaces++;
}
}
-
+
+ // The algorithm should converge on O(n^2), since the predicate is not robust,
+ // we'll save guard against infinite loop.
+ maxIter = maxFaces * maxFaces;
+
// Pop stack until we find a reversed edge
// Flip the reversed edge, and insert any of the four opposite edges
// which are internal and not already in the stack (!marked)
- while (!stackEmpty(&stack)) {
+ while (!stackEmpty(&stack) && iter < maxIter) {
e = stackPop(&stack);
e->mark = e->Sym->mark = 0;
if (!tesedgeIsLocallyDelaunay(e)) {
+ TESShalfEdge *edges[4];
int i;
tessMeshFlipEdge(mesh, e);
// for each opposite edge
@@ -480,18 +486,17 @@
edges[1] = e->Lprev;
edges[2] = e->Sym->Lnext;
edges[3] = e->Sym->Lprev;
- for (i=0;i<3;i++) {
+ for (i = 0; i < 4; i++) {
if (!edges[i]->mark && EdgeIsInternal(edges[i])) {
edges[i]->mark = edges[i]->Sym->mark = 1;
stackPush(&stack, edges[i]);
}
}
}
+ iter++;
}
-
- stackDelete(&stack);
- return 1;
+ stackDelete(&stack);
}
@@ -584,7 +589,7 @@
if (alloc == NULL)
alloc = &defaulAlloc;
-
+
/* Only initialize fields which can be changed by the api. Other fields
* are initialized where they are used.
*/
@@ -605,7 +610,7 @@
tess->alloc.dictNodeBucketSize = 512;
if (tess->alloc.regionBucketSize == 0)
tess->alloc.regionBucketSize = 256;
-
+
tess->normal[0] = 0;
tess->normal[1] = 0;
tess->normal[2] = 0;
@@ -629,7 +634,7 @@
tess->outOfMemory = 0;
tess->vertexIndexCounter = 0;
-
+
tess->vertices = 0;
tess->vertexIndices = 0;
tess->vertexCount = 0;
@@ -641,9 +646,9 @@
void tessDeleteTess( TESStesselator *tess )
{
-
+
struct TESSalloc alloc = tess->alloc;
-
+
deleteBucketAlloc( tess->regionPool );
if( tess->mesh != NULL ) {
@@ -722,7 +727,7 @@
edge = edge->Lnext;
}
while (edge != f->anEdge);
-
+
assert( faceVerts <= polySize );
f->n = maxFaceCount;
@@ -739,7 +744,7 @@
tess->outOfMemory = 1;
return;
}
-
+
tess->vertexCount = maxVertexCount;
tess->vertices = (TESSreal*)tess->alloc.memalloc( tess->alloc.userData,
sizeof(TESSreal) * tess->vertexCount * vertexSize );
@@ -756,7 +761,7 @@
tess->outOfMemory = 1;
return;
}
-
+
// Output vertices.
for ( v = mesh->vHead.next; v != &mesh->vHead; v = v->next )
{
@@ -778,7 +783,7 @@
for ( f = mesh->fHead.next; f != &mesh->fHead; f = f->next )
{
if ( !f->inside ) continue;
-
+
// Store polygon
edge = f->anEdge;
faceVerts = 0;
@@ -847,7 +852,7 @@
tess->outOfMemory = 1;
return;
}
-
+
tess->vertices = (TESSreal*)tess->alloc.memalloc( tess->alloc.userData,
sizeof(TESSreal) * tess->vertexCount * vertexSize );
if (!tess->vertices)
@@ -863,7 +868,7 @@
tess->outOfMemory = 1;
return;
}
-
+
verts = tess->vertices;
elements = tess->elements;
vertInds = tess->vertexIndices;
@@ -964,6 +969,17 @@
}
}
+void tessSetOption( TESStesselator *tess, int option, int value )
+{
+ switch(option)
+ {
+ case TESS_CONSTRAINED_DELAUNAY_TRIANGULATION:
+ tess->processCDT = value > 0 ? 1 : 0;
+ break;
+ }
+}
+
+
int tessTesselate( TESStesselator *tess, int windingRule, int elementType,
int polySize, int vertexSize, const TESSreal* normal )
{
@@ -984,7 +1000,7 @@
}
tess->vertexIndexCounter = 0;
-
+
if (normal)
{
tess->normal[0] = normal[0];
@@ -999,7 +1015,7 @@
if (vertexSize > 3)
vertexSize = 3;
- if (setjmp(tess->env) != 0) {
+ if (setjmp(tess->env) != 0) {
/* come back here if out of memory */
return 0;
}
@@ -1033,12 +1049,9 @@
if (elementType == TESS_BOUNDARY_CONTOURS) {
rc = tessMeshSetWindingNumber( mesh, 1, TRUE );
} else {
- rc = tessMeshTessellateInterior( mesh );
- if (elementType == TESS_CONSTRAINED_DELAUNAY_TRIANGLES) {
- rc = tessMeshRefineDelaunay( mesh, &tess->alloc );
- elementType = TESS_POLYGONS;
- polySize = 3;
- }
+ rc = tessMeshTessellateInterior( mesh );
+ if (rc != 0 && tess->processCDT != 0)
+ tessMeshRefineDelaunay( mesh, &tess->alloc );
}
if (rc == 0) longjmp(tess->env,1); /* could've used a label */
diff --git a/Source/tess.h b/Source/tess.h
index c8c747b..c1f981f 100755
--- a/Source/tess.h
+++ b/Source/tess.h
@@ -1,5 +1,5 @@
/*
-** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
** Copyright (C) [dates of first publication] Silicon Graphics, Inc.
** All Rights Reserved.
**
@@ -9,10 +9,10 @@
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
** of the Software, and to permit persons to whom the Software is furnished to do so,
** subject to the following conditions:
-**
+**
** The above copyright notice including the dates of first publication and either this
** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be
-** included in all copies or substantial portions of the Software.
+** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
@@ -20,7 +20,7 @@
** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
** OR OTHER DEALINGS IN THE SOFTWARE.
-**
+**
** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not
** be used in advertising or otherwise to promote the sale, use or other dealings in
** this Software without prior written authorization from Silicon Graphics, Inc.
@@ -61,6 +61,8 @@
TESSreal bmin[2];
TESSreal bmax[2];
+ int processCDT; /* option to run Constrained Delayney pass. */
+
/*** state needed for the line sweep ***/
int windingRule; /* rule for determining polygon interior */
@@ -71,7 +73,7 @@
struct BucketAlloc* regionPool;
TESSindex vertexIndexCounter;
-
+
TESSreal *vertices;
TESSindex *vertexIndices;
int vertexCount;
@@ -79,7 +81,7 @@
int elementCount;
TESSalloc alloc;
-
+
jmp_buf env; /* place to jump to when memAllocs fail */
};