/************************************************************************** * * * 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 #include #include #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; } }