/*Added by J.Callut*/ void pqInsertIfSpaceOrGreaterThanMin(ElementType X, PriorityQueue H){ ElementType min; if( ! pqIsFull( H ) ) pqInsert( X, H ); else{ min = pqFindMin(H); if(H->compareElementType(&(X),&(min)) > 0){ pqDeleteMin(H); pqInsert( X, H ); } } }
static int InitPriorityQ( TESStesselator *tess ) /* * Insert all vertices into the priority queue which determines the * order in which vertices cross the sweep line. */ { PriorityQ *pq; TESSvertex *v, *vHead; int vertexCount = 0; vHead = &tess->mesh->vHead; for( v = vHead->next; v != vHead; v = v->next ) { vertexCount++; } /* Make sure there is enough space for sentinels. */ vertexCount += MAX( 8, tess->alloc.extraVertices ); pq = tess->pq = pqNewPriorityQ( &tess->alloc, vertexCount, (int (*)(PQkey, PQkey)) tesvertLeq ); if (pq == NULL) return 0; vHead = &tess->mesh->vHead; for( v = vHead->next; v != vHead; v = v->next ) { v->pqHandle = pqInsert( &tess->alloc, pq, v ); if (v->pqHandle == INV_HANDLE) break; } if (v != vHead || !pqInit( &tess->alloc, pq ) ) { pqDeletePriorityQ( &tess->alloc, tess->pq ); tess->pq = NULL; return 0; } return 1; }
static int InitPriorityQ( GLUtesselator *tess ) /* * Insert all vertices into the priority queue which determines the * order in which vertices cross the sweep line. */ { PriorityQ *pq; GLUvertex *v, *vHead; /* __gl_pqSortNewPriorityQ */ pq = tess->pq = pqNewPriorityQ( (int (*)(PQkey, PQkey)) __gl_vertLeq ); if (pq == NULL) return 0; vHead = &tess->mesh->vHead; for( v = vHead->next; v != vHead; v = v->next ) { v->pqHandle = pqInsert( pq, v ); /* __gl_pqSortInsert */ if (v->pqHandle == LONG_MAX) break; } if (v != vHead || !pqInit( pq ) ) { /* __gl_pqSortInit */ pqDeletePriorityQ(tess->pq); /* __gl_pqSortDeletePriorityQ */ tess->pq = NULL; return 0; } return 1; }
static int CheckForIntersect( TESStesselator *tess, ActiveRegion *regUp ) /* * Check the upper and lower edges of the given region to see if * they intersect. If so, create the intersection and add it * to the data structures. * * Returns TRUE if adding the new intersection resulted in a recursive * call to AddRightEdges(); in this case all "dirty" regions have been * checked for intersections, and possibly regUp has been deleted. */ { ActiveRegion *regLo = RegionBelow(regUp); TESShalfEdge *eUp = regUp->eUp; TESShalfEdge *eLo = regLo->eUp; TESSvertex *orgUp = eUp->Org; TESSvertex *orgLo = eLo->Org; TESSvertex *dstUp = eUp->Dst; TESSvertex *dstLo = eLo->Dst; TESSreal tMinUp, tMaxLo; TESSvertex isect, *orgMin; TESShalfEdge *e; assert( ! VertEq( dstLo, dstUp )); assert( EdgeSign( dstUp, tess->event, orgUp ) <= 0 ); assert( EdgeSign( dstLo, tess->event, orgLo ) >= 0 ); assert( orgUp != tess->event && orgLo != tess->event ); assert( ! regUp->fixUpperEdge && ! regLo->fixUpperEdge ); if( orgUp == orgLo ) return FALSE; /* right endpoints are the same */ tMinUp = MIN( orgUp->t, dstUp->t ); tMaxLo = MAX( orgLo->t, dstLo->t ); if( tMinUp > tMaxLo ) return FALSE; /* t ranges do not overlap */ if( VertLeq( orgUp, orgLo )) { if( EdgeSign( dstLo, orgUp, orgLo ) > 0 ) return FALSE; } else { if( EdgeSign( dstUp, orgLo, orgUp ) < 0 ) return FALSE; } /* At this point the edges intersect, at least marginally */ DebugEvent( tess ); tesedgeIntersect( dstUp, orgUp, dstLo, orgLo, &isect ); /* The following properties are guaranteed: */ assert( MIN( orgUp->t, dstUp->t ) <= isect.t ); assert( isect.t <= MAX( orgLo->t, dstLo->t )); assert( MIN( dstLo->s, dstUp->s ) <= isect.s ); assert( isect.s <= MAX( orgLo->s, orgUp->s )); if( VertLeq( &isect, tess->event )) { /* The intersection point lies slightly to the left of the sweep line, * so move it until it''s slightly to the right of the sweep line. * (If we had perfect numerical precision, this would never happen * in the first place). The easiest and safest thing to do is * replace the intersection by tess->event. */ isect.s = tess->event->s; isect.t = tess->event->t; } /* Similarly, if the computed intersection lies to the right of the * rightmost origin (which should rarely happen), it can cause * unbelievable inefficiency on sufficiently degenerate inputs. * (If you have the test program, try running test54.d with the * "X zoom" option turned on). */ orgMin = VertLeq( orgUp, orgLo ) ? orgUp : orgLo; if( VertLeq( orgMin, &isect )) { isect.s = orgMin->s; isect.t = orgMin->t; } if( VertEq( &isect, orgUp ) || VertEq( &isect, orgLo )) { /* Easy case -- intersection at one of the right endpoints */ (void) CheckForRightSplice( tess, regUp ); return FALSE; } if( (! VertEq( dstUp, tess->event ) && EdgeSign( dstUp, tess->event, &isect ) >= 0) || (! VertEq( dstLo, tess->event ) && EdgeSign( dstLo, tess->event, &isect ) <= 0 )) { /* Very unusual -- the new upper or lower edge would pass on the * wrong side of the sweep event, or through it. This can happen * due to very small numerical errors in the intersection calculation. */ if( dstLo == tess->event ) { /* Splice dstLo into eUp, and process the new region(s) */ if (tessMeshSplitEdge( tess->mesh, eUp->Sym ) == NULL) longjmp(tess->env,1); if ( !tessMeshSplice( tess->mesh, eLo->Sym, eUp ) ) longjmp(tess->env,1); regUp = TopLeftRegion( tess, regUp ); if (regUp == NULL) longjmp(tess->env,1); eUp = RegionBelow(regUp)->eUp; FinishLeftRegions( tess, RegionBelow(regUp), regLo ); AddRightEdges( tess, regUp, eUp->Oprev, eUp, eUp, TRUE ); return TRUE; } if( dstUp == tess->event ) { /* Splice dstUp into eLo, and process the new region(s) */ if (tessMeshSplitEdge( tess->mesh, eLo->Sym ) == NULL) longjmp(tess->env,1); if ( !tessMeshSplice( tess->mesh, eUp->Lnext, eLo->Oprev ) ) longjmp(tess->env,1); regLo = regUp; regUp = TopRightRegion( regUp ); e = RegionBelow(regUp)->eUp->Rprev; regLo->eUp = eLo->Oprev; eLo = FinishLeftRegions( tess, regLo, NULL ); AddRightEdges( tess, regUp, eLo->Onext, eUp->Rprev, e, TRUE ); return TRUE; } /* Special case: called from ConnectRightVertex. If either * edge passes on the wrong side of tess->event, split it * (and wait for ConnectRightVertex to splice it appropriately). */ if( EdgeSign( dstUp, tess->event, &isect ) >= 0 ) { RegionAbove(regUp)->dirty = regUp->dirty = TRUE; if (tessMeshSplitEdge( tess->mesh, eUp->Sym ) == NULL) longjmp(tess->env,1); eUp->Org->s = tess->event->s; eUp->Org->t = tess->event->t; } if( EdgeSign( dstLo, tess->event, &isect ) <= 0 ) { regUp->dirty = regLo->dirty = TRUE; if (tessMeshSplitEdge( tess->mesh, eLo->Sym ) == NULL) longjmp(tess->env,1); eLo->Org->s = tess->event->s; eLo->Org->t = tess->event->t; } /* leave the rest for ConnectRightVertex */ return FALSE; } /* General case -- split both edges, splice into new vertex. * When we do the splice operation, the order of the arguments is * arbitrary as far as correctness goes. However, when the operation * creates a new face, the work done is proportional to the size of * the new face. We expect the faces in the processed part of * the mesh (ie. eUp->Lface) to be smaller than the faces in the * unprocessed original contours (which will be eLo->Oprev->Lface). */ if (tessMeshSplitEdge( tess->mesh, eUp->Sym ) == NULL) longjmp(tess->env,1); if (tessMeshSplitEdge( tess->mesh, eLo->Sym ) == NULL) longjmp(tess->env,1); if ( !tessMeshSplice( tess->mesh, eLo->Oprev, eUp ) ) longjmp(tess->env,1); eUp->Org->s = isect.s; eUp->Org->t = isect.t; eUp->Org->pqHandle = pqInsert( &tess->alloc, tess->pq, eUp->Org ); if (eUp->Org->pqHandle == INV_HANDLE) { pqDeletePriorityQ( &tess->alloc, tess->pq ); tess->pq = NULL; longjmp(tess->env,1); } GetIntersectData( tess, eUp->Org, orgUp, dstUp, orgLo, dstLo ); RegionAbove(regUp)->dirty = regUp->dirty = regLo->dirty = TRUE; return FALSE; }
int main() { struct pq_t *p1=NULL, *p2=NULL; char cmd[10240]; size_t cap, keySize, objSize; int ret; void *data1, *data2; int opChoice, pqChoice = 1; struct pq_t *now_pq; now_pq = p1; int keyType, objType; int (*cmp)(const void *, const void*); data1=malloc(sizeof(double)*10); data2=malloc(sizeof(double)*10); for(;;) { if(now_pq==NULL) { printf("The pq%d needs to be initialized.\n", pqChoice); if(pqChoice == 1){ printf("Init step 1. key type: d for double, others for short:\n"); scanf("%s",cmd); keyType=(cmd[0]=='d')?__DS__DOUBLE__:__DS__SHORT__; printf("Init step 2. object type: d for double, others for short:\n"); scanf("%s",cmd); objType=(cmd[0]=='d')?__DS__DOUBLE__:__DS__SHORT__; } else printf("pq2 has same key/object size and cmp as pq1\n"); printf("Init step 3. Capacity: "); scanf("%zu",&cap); if(pqChoice == 1) now_pq = p1 = pqAlloc(); else now_pq = p2 = pqAlloc(); if(keyType == __DS__DOUBLE__){ keySize = sizeof(double); cmp = doubleGT; } else{ keySize = sizeof(short); cmp = shortGT; } if(objType == __DS__DOUBLE__) objSize = sizeof(double); else objSize = sizeof(short); ret=pqInit(now_pq, keySize, objSize, cap, cmp); if(ret) { puts("Not enough memory."); pqFree(now_pq); now_pq=NULL; if(pqChoice == 1) p1 = NULL; else{ p2 = NULL; now_pq = p1; pqChoice = 1; } } else puts("Initialization done."); } else { // printf("now_pq:%x, pq1:%x, pq2:%x\n", now_pq, p1, p2); printf("size/capacity: %zu/%zu\n", pqSize(now_pq), pqCap(now_pq)); printf("now is in Priority Queue %d:\n", pqChoice); size_t keySize=pqKeySize(now_pq); size_t objSize=pqObjSize(now_pq); printf("Valid operations: 1)insert, 2)extract max, 3)max, 4)union, 5)empty,\n"); printf(" 6)switch to another pq, 7)free 2 pqs, 8)quit\n"); for(opChoice=0;opChoice<=0||opChoice>8;sscanf(cmd,"%d",&opChoice)) scanf("%s",cmd); if(opChoice==1) { printf("Input a %s value for key: ",keySize==sizeof(double)?"double":"short"); getData(keyType,data1); printf("Input a %s value for obj: ",objSize==sizeof(double)?"double":"short"); getData(objType,data2); ret=pqInsert(now_pq, data1, data2); if(ret == __DS__PQ__FULL__) printf("The pq%d is full!\n", pqChoice); else if(ret == __DS__PQ__OBJ_EXIST__){ printf("The object "); printData(objType, data2); printf(" is in the pq%d now!\n", pqChoice); } } else if(opChoice>=2 && opChoice<=3) { if(opChoice == 2) ret=pqExtractMax(now_pq, data1, data2); else if(opChoice == 3) ret=pqMax(now_pq, data1, data2); // printf("pq op!\n"); if(!ret) { printf("The result is <"); printData(keyType, data1); printf(", "); printData(objType, data2); puts(">."); } else printf("The pq%d is empty!\n", pqChoice); } else if(opChoice==4){ if(p2 == NULL){ printf("pq2 is empty. you can't union it.\n"); } else{ printf("Choose you want to union(p1, p2) or union(p2, p1).\n"); printf("Input 1 for former, else for latter.\n"); char cmd2[1024] = {0}; int choice; scanf("%s", cmd2); choice = (cmd2[0]=='1')?1:2; if(choice == 1){ ret = pqUnion(p1, p2); } else{ ret = pqUnion(p2, p1); if(ret == __DS__PQ__NORMAL__){ p1 = p2; } } if(ret == __DS__PQ__NORMAL__){ p2 = NULL; pqChoice = 1; now_pq = p1; } else if(ret == __DS__PQ__FULL__) printf("pq1 doesn't have enough place to merge pq2.\n"); else if(ret == __DS__PQ__DIFF_SIZE__) printf("You can union two different type priority queues.\n"); } } else if(opChoice==5) { if(pqEmpty(now_pq)) printf("The pq%d is empty.\n", pqChoice); else printf("The pq%d is not empty.\n", pqChoice); } else if(opChoice==6){ pqChoice = (pqChoice==1)?2:1; now_pq = (pqChoice==1)?p1:p2; } else if(opChoice==7) { if(p2 != NULL) pqFree(p2); if(p1 != NULL) pqFree(p1); p1 = p2 = NULL; pqChoice = 1; now_pq = p1; } else break; } } free(data1); free(data2); return 0; }