Пример #1
0
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*/
}
Пример #2
0
//
// 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;
}
Пример #3
0
//
// 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);

}
Пример #4
0
//
// 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);
      }
    }
  }