|
|
/**************************************************************************
* * * Copyright (C) 1989, Silicon Graphics, Inc. * * * * These coded instructions, statements, and computer programs contain * * unpublished proprietary information of Silicon Graphics, Inc., and * * are protected by Federal copyright law. They may not be disclosed * * to third parties or copied or duplicated in any form, in whole or * * in part, without the prior written consent of Silicon Graphics, Inc. * * * **************************************************************************/
/* monotonize.c */
/* Derrick Burns - 1989 */
#include <glos.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "monotone.h"
static Vert * __gl_connectedge( GLUtriangulatorObj *, Vert *, Vert * );
/*----------------------------------------------------------------------------
* monotonize - add edges to a polygon to create monotone pieces *---------------------------------------------------------------------------- */
void __gl_monotonize( GLUtriangulatorObj *tobj ) { Ray *ray, *new_ray1, *new_ray2;
__gl_sort_priorityq( tobj ); while( __gl_more_priorityq( tobj ) ) { Vert *vert = __gl_remove_priorityq( tobj );
if( vert->vclass == VC_NO_CLASS ) { ray = __gl_findray_raylist( tobj, vert ); if( ray->orientation == __gl_ccw_vert( vert ) ) __gl_reverse_vert( vert ); (void) __gl_classify_all( vert ); }
switch (vert->vclass) {
case VC_OK_RIGHT: /* two new rays */
assert( vert->ray == 0 );
ray = __gl_findray_raylist( tobj, vert );
if( ray->orientation != 0 ) __gl_in_error( tobj, 3 );
/* compute top ray */ new_ray1 = __gl_new_ray( tobj, 0 ); __gl_recalc_ray(new_ray1, vert, vert->prev); if( vert->prev->vclass != VC_BAD_RIGHT ) vert->prev->ray = new_ray1;
/* compute middle ray */ new_ray2 = __gl_new_ray( tobj, 1 ); __gl_recalc_ray(new_ray2, vert, vert->next); if( vert->next->vclass != VC_OK_LEFT ) vert->next->ray = new_ray2;
new_ray2->vertex = vert;
assert( ! ray->mustconnect );
__gl_add2_raylist( ray->prev, new_ray1, new_ray2 );
break;
case VC_BAD_LEFT: /* two new rays */
assert( vert->ray == 0 );
ray = __gl_findray_raylist( tobj, vert );
if( ray->orientation != 1 ) __gl_in_error( tobj, 3 );
/* compute top ray */ new_ray1 = __gl_new_ray( tobj, 1 ); __gl_recalc_ray(new_ray1, vert, vert->next); if( vert->next->vclass != VC_OK_LEFT ) vert->next->ray = new_ray1;
/* compute middle ray */ new_ray2 = __gl_new_ray( tobj, 0 ); __gl_recalc_ray(new_ray2, vert, vert->prev); if( vert->prev->vclass != VC_BAD_RIGHT ) vert->prev->ray = new_ray2;
new_ray1->vertex = __gl_connectedge( tobj,vert, ray->vertex);
/* update bottom ray */ ray->mustconnect = 0; ray->vertex = vert;
__gl_add2_raylist( ray->prev, new_ray1, new_ray2 );
break;
case VC_OK_LEFT: /* two rays disappear */ ray = vert->ray; if ( ray == NULL ) __gl_in_error( tobj, 4 ); __gl_checkray_vert( tobj, vert, ray->prev, ray->next->next ); /* region above_ray top ray is outside */ assert( ! ray->mustconnect ); assert( ray->next );
/* region above_ray middle ray is inside */ if( ray->next->mustconnect ) { __gl_triangulateloop( tobj,__gl_connectedge( tobj,vert,ray->next->vertex)); __gl_triangulateloop( tobj, vert ); } else { __gl_triangulateloop( tobj, vert ); }
/* region above_ray bottom ray is outside */ assert( ray->next->next ); assert( ! ray->next->next->mustconnect );
__gl_remove2_raylist( tobj, ray ); __gl_delete_ray( tobj, ray->next ); __gl_delete_ray( tobj, ray ); break;
case VC_BAD_RIGHT: /* two rays disappear */ ray = vert->ray; if ( ray == NULL || ray->next == NULL ) __gl_in_error( tobj, 4 ); __gl_checkray_vert( tobj, vert, ray->prev, ray->next->next ); if (ray->mustconnect) { vert = __gl_connectedge( tobj, vert, ray->vertex ); __gl_triangulateloop( tobj, ray->vertex->next ); }
if ( ray->next->mustconnect ) { __gl_in_error( tobj, 8 ); }
assert( ray->next ); assert( ray->next->next );
if (ray->next->next->mustconnect) __gl_triangulateloop( tobj, __gl_connectedge( tobj, vert, ray->next->next->vertex) ); ray->next->next->vertex = vert; ray->next->next->mustconnect = 1; __gl_remove2_raylist( tobj, ray ); __gl_delete_ray( tobj, ray->next ); __gl_delete_ray( tobj, ray ); break;
case VC_OK_TOP: /* one ray changes ends and coords */ ray = vert->ray; if( ray == NULL || ray->next == NULL ) __gl_in_error( tobj, 4 ); __gl_checkray_vert( tobj, vert, ray->prev, ray->next ); __gl_recalc_ray( ray, vert, vert->next ); if( vert->next->vclass != VC_OK_LEFT ) vert->next->ray = ray;
if (ray->mustconnect) { ray->vertex = __gl_connectedge( tobj,vert,ray->vertex); ray->mustconnect = 0; __gl_triangulateloop( tobj, vert ); } else { ray->vertex = vert; }
assert( ray->next ); assert( ! ray->next->mustconnect ); break;
case VC_OK_BOTTOM: /* one ray changes ends and coords */ ray = vert->ray; if ( ray == NULL || ray->next == NULL ) __gl_in_error( tobj, 4 ); __gl_checkray_vert( tobj, vert, ray->prev, ray->next ); __gl_recalc_ray( ray, vert, vert->prev ); if( vert->prev->vclass != VC_BAD_RIGHT ) vert->prev->ray = ray;
assert( ! ray->mustconnect ); assert( ray->next );
if (ray->next->mustconnect) { __gl_triangulateloop( tobj,__gl_connectedge( tobj,vert, ray->next->vertex)); ray->next->mustconnect = 0; ray->next->vertex = vert; } else { ray->next->vertex = vert; }
break;
case VC_BAD_LONE: break;
case VC_BAD_ERROR: __gl_in_error( tobj, 4 ); return;
case VC_NO_CLASS: assert( 0 ); break; } } return; } /*----------------------------------------------------------------------------
* connectedge - create two anti-parallel edges splitting a polygon *---------------------------------------------------------------------------- */
static Vert * __gl_connectedge( GLUtriangulatorObj *tobj, Vert *x, Vert *y ) { Vert *newx, *newy;
if( x == 0 || y == 0 || y->prev == 0 || x->next == 0 ) { __gl_in_error( tobj, 5 ); return 0; } else { assert( x->prev->next == x ); assert( x->next->prev == x ); assert( y->prev->next == y ); assert( y->next->prev == y ); assert( x->next != y ); assert( x != y );
newx = (Vert *) __gl_new_vert( tobj ); newx->myid = x->myid; newx->nextid = x->nextid; newx->ray = x->ray; newx->vclass = x->vclass; #ifdef ADDED
newx->added = x->added; #endif
newx->s = x->s; newx->t = x->t; newx->data = x->data;
newy = (Vert *) __gl_new_vert( tobj ); newy->myid = y->myid; newy->nextid = y->nextid; newy->ray = y->ray; newy->vclass = y->vclass; #ifdef ADDED
newy->added = 1; #endif
newy->s = y->s; newy->t = y->t; newy->data = y->data;
newx->prev = newy; newx->next = x->next; newy->next = newx; newy->prev = y->prev; newx->next->prev = newx; newy->prev->next = newy; x->next = y; y->prev = x; #ifdef ADDED
x->added = 1; #endif
assert( x->prev->next == x ); assert( x->next->prev == x ); assert( y->prev->next == y ); assert( y->next->prev == y ); assert( newx->prev->next == newx ); assert( newx->next->prev == newx ); assert( newy->prev->next == newy ); assert( newy->next->prev == newy ); return newx; } }
|