void algo(int * const part, double ** const matrice, PriorityQueue * const Qpart, PriorityQueue * const Q, PriorityQueue * const Qinst, double ** const D, int n, int * const deficit, int * const surplus) { int p,u,v,j; double d; if(*deficit == *surplus) /*if the current partition is balanced*/ { p = PQ_deleteMax(Qpart); /*we get the subset with the highest possible gain in p and remove it from Qpart*/ u = PQ_deleteMax(&Q[p]); /*then we get the vertex with this highest possible gain in u and remove it from Q[p] */ *deficit = part[u]; /*p becomes the deficit */ } else /*the current partition is not balanced*/ { u = PQ_deleteMax(&Q[*surplus]); /*we get the vertex with the highest possible gain in surplus and remove it from Q[surplus] */ PQ_delete(Qpart, part[u]); /*then we remove surplus from Qpart (note that u is from surplus so part[u] is surplus) */ } d = PQ_findMaxKey(&Q[part[u]]); /*we get the next highest possible gain in part[u] (without taking u in account as we already removed it from Q[part[u])*/ PQ_insert(Qpart, part[u], d); /*we put part[u] back in Qpart with its new highest possible gain*/ j = PQ_deleteMax(&Qinst[u]); /*we get from Qinst[u] the subset in which we have to move u to get the highest gain.*/ if ( j < 0){ if(tm_get_verbose_level() >= CRITICAL) fprintf(stderr,"Error Max element in priority queue negative!\n"); exit(-1); } *surplus = j; /*this subset becomes surplus*/ for(v=0; v < n; ++v) /*we scan though all edges (u,v) */ { j = part[u]; /*we set j to the starting subset */ D[v][j]= D[v][j] - matrice[u][v]; /*we compute the new D[v, i] (here j has the value of the starting subset of u, that's why we say i) */ PQ_adjustKey(&Qinst[v], j, D[v][j]); /*we update this gain in Qinst[v]*/ j = *surplus; /*we put back the arrival subset in j*/ D[v][j] = D[v][j] + matrice[u][v]; /*matrice[u][v]; we compute the new D[v, j]*/ PQ_adjustKey(&Qinst[v], j, D[v][j]);/*we update this gain in Qinst[v]*/ d = PQ_findMaxKey(&Qinst[v]) - D[v][part[v]]; /*we compute v's new highest possible gain*/ PQ_adjustKey(&Q[part[v]], v, d); /*we update it in Q[p[v]]*/ d = PQ_findMaxKey(&Q[part[v]]); /*we get the highest possible gain in v's subset*/ PQ_adjustKey(Qpart, part[v], d); /*we update it in Qpart*/ } part[u] = *surplus; /*we move u from i to j (here surplus has the value of j the arrival subset)*/ d = PQ_findMaxKey(&Qinst[u]) - D[u][part[u]]; /*we compute the new u's highest possible gain*/ if(!PQ_isEmpty(&Qinst[u])) /*if at least one more move of u is possible*/ PQ_insert(&Q[part[u]], u, d); /*we insert u in the Q queue of its new subset*/ PQ_adjustKey(Qpart, part[u], d); /*we update the new highest possible gain in u's subset*/ }
// // Add the points two the two initial triangles of a Tin tile from // file. Also add points from neighbor boundary arrays to the // triangulation to have boundary consistancy // TIN_TILE *initTilePoints(TIN_TILE *tt, double e, short useNodata){ // First two tris TRIANGLE *first = tt->t; TRIANGLE *second = tt->t->p1p3; // Get back to the beginning of the tile data file rewind(tt->gridFile); // Now build list of points in the triangle // Create a dummy tail for both point lists first->points = Q_init(); second->points = Q_init(); first->maxE = DONE; second->maxE = DONE; // Build the two point lists register int row, col; ELEV_TYPE maxE_first=0; ELEV_TYPE maxE_second=0; ELEV_TYPE tempE = 0; R_POINT temp; // iterate through all points and distribute them to the // two triangles for(row=0;row<tt->nrows;row++) { temp.x=row+tt->iOffset; for(col=0;col<tt->ncols;col++) { temp.y=col+tt->jOffset; fread(&temp.z,sizeof(ELEV_TYPE), 1, tt->gridFile); // Only set Z values for corner points since they already exist if(row==0 && col==0){ tt->nw->z = temp.z; continue; } if(row==0 && col==tt->ncols-1){ tt->ne->z = temp.z; continue; } if(row==tt->nrows-1 && col==tt->ncols-1){ tt->se->z = temp.z; continue; } if(row==tt->nrows-1 && col==0){ tt->sw->z = temp.z; continue; } //Ignore edge points if internal tile if(tt->iOffset != 0 && row == 0) continue; if(tt->jOffset != 0 && col == 0) continue; //Skip nodata or change it to min-1 if(temp.z == tt->nodata){ if(!useNodata) continue; else temp.z = tt->min-1; } // Add to the first triangle's list if(inTri2D(first->p1, first->p2, first->p3, &temp)) { Q_insert_elem_head(first->points, temp); //Update max error tempE = findError(temp.x,temp.y,temp.z,first); if (tempE > maxE_first) { maxE_first = tempE; assert(Q_first(first->points)); // store pointer to triangle w/ max err first->maxE = &Q_first(first->points)->e; first->maxErrorValue = tempE; } } // Add to the second triangle's list else { assert(inTri2D(second->p1, second->p2, second->p3, &temp)); Q_insert_elem_head(second->points, temp); //Update max error tempE = findError(temp.x,temp.y,temp.z,second); if (tempE > maxE_second) { maxE_second = tempE; assert(Q_first(second->points)); // store pointer to triangle w/ max err second->maxE = &Q_first(second->points)->e; second->maxErrorValue = tempE; } } }//for col }//for row //end distribute points among initial triangles DEBUG {checkPointList(first); checkPointList(second);} // First triangle has no points with error > e, mark as done if (first->maxE == DONE){ Q_free_queue(first->points); first->points = NULL; first->maxErrorValue = 0; } // Insert max error point into the PQ else PQ_insert(tt->pq,first); // Second triangle has no points with error > e, mark as done if (second->maxE == DONE){ Q_free_queue(second->points); second->points = NULL; second->maxErrorValue = 0; } // Insert max error point into the PQ else PQ_insert(tt->pq,second); // Initialize point pointer arrays // At most points can have (tl*tl)-2*tl points in it // At most bPoints and rPoints can have tl points tt->points = (R_POINT **)malloc( ((tt->nrows * tt->ncols) - (tt->nrows + tt->ncols)) * sizeof(R_POINT*)); tt->bPoints = (R_POINT **)malloc( tt->ncols * sizeof(R_POINT*)); tt->rPoints = (R_POINT **)malloc( tt->nrows * sizeof(R_POINT*)); // Add points to point pointer array tt->points[0]=tt->nw;//nw tt->bPoints[0]=tt->sw;//sw tt->bPoints[1]=tt->se;//se tt->rPoints[0]=tt->ne;//ne tt->rPoints[1]=tt->se;//se tt->pointsCount = 1; tt->bPointsCount = 2; tt->rPointsCount = 2; // // Add boundary points to the triangulation // int i; COORD_TYPE prevX = 0,prevY = 0; TRIANGLE *t1,*t2, *s, *sp; s = tt->t; sp = tt->t->p1p3; if(tt->left != NULL){ // The first & last point in this array are corner points for this // tile so we ignore them for(i = 1; i < tt->left->rPointsCount-1; i++){ assert(s && tt->pq && tt->left->rPoints[i]); assert(prevX <= tt->left->rPoints[i]->x && prevY <= tt->left->rPoints[i]->y); assert(tt->left->rPoints[i] != tt->nw && tt->left->rPoints[i] != tt->ne && tt->left->rPoints[i] != tt->sw && tt->left->rPoints[i] != tt->se); // add 2 tris in s t1 = addTri(tt, s->p1, tt->left->rPoints[i], s->p3, NULL,whichTri(s,s->p1,s->p3,tt),NULL); assert(t1); t2 = addTri(tt, tt->left->rPoints[i], s->p2, s->p3, NULL,t1,whichTri(s,s->p2,s->p3,tt)); assert(t2); // Verify that t1 and t2 are really inside s triangleCheck(s,t1,t2,NULL); // Distribute points in the 2 triangles if(s->maxE != DONE){ s->p1p2 = s->p1p3 = s->p2p3 = NULL; distrPoints(t1,t2,NULL,s,NULL,e,tt); //Mark triangle s for deletion from pq before distrpoints so we //can include its maxE in the newly created triangle PQ_delete(tt->pq,s->pqIndex); } else{ // Since distrpoints normally fixes corner we need to do it here if(s == tt->t){ updateTinTileCorner(tt,t1,t2,NULL); } t1->maxE = t2->maxE = DONE; t1->points = t2->points = NULL; } removeTri(s); tt->numTris++; tt->numPoints++; // Now split the next lowest boundary triangle s = t2; // Should we enforce Delaunay here? prevX = tt->left->rPoints[i]->x; prevY = tt->left->rPoints[i]->y; } } if(tt->top != NULL){ // The first & last point in this array are corner points for this // tile so we ignore them s = sp; prevX = prevY = 0; for(i = 1; i < tt->top->bPointsCount-1; i++){ assert(s && tt->pq && tt->top->bPoints[i]); assert(prevX <= tt->top->bPoints[i]->x && prevY <= tt->top->bPoints[i]->y); // add 2 tris in s t1 = addTri(tt, s->p1, tt->top->bPoints[i], s->p3, NULL,whichTri(s,s->p1,s->p3,tt),NULL); assert(t1); t2 = addTri(tt, tt->top->bPoints[i], s->p2, s->p3, NULL,t1,whichTri(s,s->p2,s->p3,tt)); assert(t2); // Verify that t1 and t2 are really inside s triangleCheck(s,t1,t2,NULL); // Distribute points in the 2 triangles if(s->maxE != DONE){ distrPoints(t1,t2,NULL,s,NULL,e,tt); //Mark triangle sp for deletion from pq before distrpoints so we //can include its maxE in the newly created triangle s->p1p2 = s->p1p3 = s->p2p3 = NULL; PQ_delete(tt->pq,s->pqIndex); } else{ // Since distrpoints normally fixes corner we need to do it here if(s == tt->t){ updateTinTileCorner(tt,t1,t2,NULL); } t1->maxE = t2->maxE = DONE; t1->points = t2->points = NULL; } removeTri(s); tt->numTris++; tt->numPoints++; // Now split the next lowest boundary triangle s = t2; // Should we enforce Delaunay here? prevX = tt->top->bPoints[i]->x; prevY = tt->top->bPoints[i]->y; } } return tt; }
// // Swap the common edge between two triangles t1 and t2. The common // edge should always be edge ac, abc are part of t1 and acd are part // of t2. // void edgeSwap(TRIANGLE *t1, TRIANGLE *t2, R_POINT *a, R_POINT *b, R_POINT *c, R_POINT *d, double e, TIN_TILE *tt){ // Common edge must be ac assert(isEndPoint(t1,a) && isEndPoint(t1,b) && isEndPoint(t1,c) && isEndPoint(t2,a) && isEndPoint(t2,c) && isEndPoint(t2,d)); assert(a != b && a != c && a != d && b != c && b != d && c != d); assert(t1 != t2); // Add the two new triangles with the swapped edge TRIANGLE *tn1, *tn2; tn1 = addTri(tt,a, b, d,whichTri(t1,a,b,tt),whichTri(t2,a,d,tt),NULL); tn2 = addTri(tt,c, b, d,whichTri(t1,c,b,tt),whichTri(t2,c,d,tt),tn1); assert(isEndPoint(tn1,a) && isEndPoint(tn1,b) && isEndPoint(tn1,d) && isEndPoint(tn2,b) && isEndPoint(tn2,c) && isEndPoint(tn2,d)); assert(tn1->p2p3 == tn2 && tn2->p2p3 == tn1); if(tn1->p1p2 != NULL) assert(whichTri(tn1->p1p2,a,b,tt) == tn1); if(tn1->p1p3 != NULL) assert(whichTri(tn1->p1p3,a,d,tt) == tn1); if(tn2->p1p2 != NULL) assert(whichTri(tn2->p1p2,c,b,tt) == tn2); if(tn2->p1p3 != NULL) assert(whichTri(tn2->p1p3,c,d,tt) == tn2); // Debug DEBUG{ printf("EdgeSwap: \n"); printTriangle(t1); printTriangle(t2); printTriangle(tn1); printTriangle(tn2); } // Distribute point list from t1 and t2 to tn1 and tn2. Distribute // points requires that the fourth argument (s) be a valid triangle // with a point list so we must check that t1 and t2 are not already // done and thus do not have a point list. If at least one does then // call distribute points with s = the trinagle with the valid point // list. If both are done then the newly created triangles are done // tooand need to be marked accordingly if(t1->maxE != DONE && t2->maxE != DONE) distrPoints(tn1,tn2,NULL,t1,t2,e,tt); else if(t1->maxE != DONE){ distrPoints(tn1,tn2,NULL,t1,NULL,e,tt); } else if(t2->maxE != DONE){ distrPoints(tn1,tn2,NULL,t2,NULL,e,tt); } else{ tn1->maxE = tn2->maxE = DONE; tn1->points = tn2->points= NULL; } // Update the corner if the corner is being swapped. Distrpoints // will not always catch this so it must be done here if(t1 == tt->t || t2 == tt->t){ updateTinTileCorner(tt,tn1,tn2,NULL); } // mark triangles for deletion from the PQ t1->p1p2 = t1->p1p3 = t1->p2p3 = NULL; t2->p1p2 = t2->p1p3 = t2->p2p3 = NULL; PQ_delete(tt->pq,t1->pqIndex); PQ_delete(tt->pq,t2->pqIndex); removeTri(t1); removeTri(t2); DEBUG{checkPointList(tn1); checkPointList(tn2);} // We have created two different triangles, we need to check // delaunay on their 2 edges enforceDelaunay(tn1,a,d,b,e,tt); enforceDelaunay(tn2,c,d,b,e,tt); }
// // Add triangles and distribute points when there are two collinear // triangles. Assumes that maxE is on line pa pb // void fixCollinear(R_POINT *pa, R_POINT *pb, R_POINT *pc, TRIANGLE* s, double e, R_POINT *maxError, TIN_TILE *tt, short delaunay){ assert(s && tt->pq && maxError); TRIANGLE *sp, *t1, *t2, *t3, *t4; // add 2 tris in s t1 = addTri(tt,pa, maxError, pc,NULL,whichTri(s,pa,pc,tt),NULL); assert(t1); t2 = addTri(tt,maxError, pc, pb,t1,NULL,whichTri(s,pb,pc,tt)); assert(t2); DEBUG{triangleCheck(s,t1,t2,NULL);} // Distribute points in the 2 triangles distrPoints(t1,t2,NULL,s,NULL,e,tt); DEBUG{checkPointList(t1); checkPointList(t2);} // Find other triangle Note: there may not be another triangle if s // is on the edge sp = whichTri(s,pa,pb,tt); // If there is a triangle on the other side of the collinear edge // then we need to split that triangle into two if(sp != NULL){ // Find the unknown point of the triangle on the other side of the line R_POINT *pd; pd = findThirdPoint(sp->p1,sp->p2,sp->p3,pa,pb); assert(pd); // If this triangle is in the other tile we need to make sure we // work with that tile TIN_TILE *ttn; ttn = whichTileTri(pa,pb,pd,tt); assert(ttn); assert(pointInTile(pd,ttn)); // add 2 tris adjacent to s on pa pb t3 = addTri(ttn,pa,maxError,pd,t1,whichTri(sp,pd,pa,ttn),NULL); assert(t3); t4 = addTri(ttn,pb,maxError,pd,t2,whichTri(sp,pd,pb,ttn),t3); assert(t4); DEBUG{triangleCheck(sp,t3,t4,NULL);} // 1 more tri ttn->numTris++; //If this triangle was already "done" meaning it has no more //points in it's point list > MaxE then we don't distribute points //because sp has no point list if(sp->maxE != DONE){ distrPoints(t3,t4,NULL,sp,NULL,e,ttn); //Mark triangle sp for deletion from pq before distrpoints so we //can include its maxE in the newly created triangle sp->p1p2 = sp->p1p3 = sp->p2p3 = NULL; PQ_delete(ttn->pq,sp->pqIndex); } else{ // Since distrpoints normally fixes corner we need to do it here if(sp == tt->t){ updateTinTileCorner(ttn,t3,t4,NULL); } t3->maxE = t4->maxE = DONE; t3->points = t4->points = NULL; } DEBUG{checkPointList(t3); checkPointList(t4);} removeTri(sp); // Enforce delaunay on two new edges of the new triangles if // specified if(delaunay){ // we enforce on the edge that does not have maxE as an // endpoint, so the 4th argument to enforceDelaunay should // always be the maxE point to s for that particular tri enforceDelaunay(t1,t1->p1,t1->p3,t1->p2,e,tt); enforceDelaunay(t2,t2->p2,t2->p3,t2->p1,e,tt); if(ttn == tt){ enforceDelaunay(t3,t3->p1,t3->p3,t3->p2,e,ttn); enforceDelaunay(t4,t4->p1,t4->p3,t4->p2,e,ttn); } } }