Esempio n. 1
0
void findSecondPoint(const PT *pts, int i, Point2f &center, float &radius)
{
    center.x = (float)(pts[0].x + pts[i].x) / 2.0f;
    center.y = (float)(pts[0].y + pts[i].y) / 2.0f;
    float dx = (float)(pts[0].x - pts[i].x);
    float dy = (float)(pts[0].y - pts[i].y);
    radius = (float)norm(Point2f(dx, dy)) / 2.0f + EPS;

    for (int j = 1; j < i; ++j)
    {
        dx = center.x - (float)pts[j].x;
        dy = center.y - (float)pts[j].y;
        if (norm(Point2f(dx, dy)) < radius)
        {
            continue;
        }
        else
        {
            findThirdPoint(pts, i, j, center, radius);
        }
    }
}
Esempio n. 2
0
//
// Enforce delaunay on triangle t. Assume that p1 & p2 are the
// endpoints to the edge that is being checked for delaunay
//
void enforceDelaunay(TRIANGLE *t, R_POINT *p1, R_POINT *p2, R_POINT *p3,
		     double e, TIN_TILE *tt){
  assert(t);

  // Since we have tiles we cannot garauntee global delaunay. We must
  // not enforce delaunay on boundary edges, that is edges that are on
  // the same boundary together.
  if(!(edgeOnBoundary(p1,p2,tt))){
    
    // Find the triangle on the other side of edge p1p2
    TRIANGLE *tn = whichTri(t,p1,p2,tt);  
    
    // If tn is NULL then we are done, otherwise we need to check delaunay
    if(tn != NULL){
      
      // Find point across from edge p1p2 in tn
      R_POINT *d = findThirdPoint(tn->p1,tn->p2,tn->p3,p1,p2);
      
      if(CircumCircle(d->x,d->y,p1->x,p1->y,p2->x,p2->y,p3->x,p3->y)){
	edgeSwap(t,tn,p1,p3,p2,d,e,tt);
      }
    }
  }
}
Esempio n. 3
0
/*!
 *  Note that the resulting triangulation will not necessarily be complex,
 *  since it's constrained by the polygon's edges.
 *
 *  Besides triangulating the polygon this method also does:
 *  - insertion of the new polygons (triangles) at the end of
 *    the polygon list.
 *  - setting up marking information for the new polygons.
 *
 *  \param polylist the global list of polygons
 *  \param selfindex the index of this polygon in the global list
 *  \return zero on success, and a negative integer if some error occured.
 */
int SimplePolygon::triangulate( DCTPVec2dvector &globalverts, simplepolygonvector &polylist)
{
#ifdef OSG_TRIANGULATE_CONVEX
	if( ( !is_marked ) && ( m_bConvex ) )
	{
//		std::cerr <<"triangulating convex: " <<vertices.size() << std::endl;
		switch( vertices.size( ) )
		{
			case 0:
			case 1:
			case 2:
				return 0;
			case 3:
				{
					polylist.push_back( *this );
				}
				return 0;
		}

		unsigned int		ui_prev;
		unsigned int		ui_mid;
		unsigned int		ui_next;
		const unsigned int	cui_vertex_cnt = vertices.size( );
		SimplePolygon		cl_poly;

		ui_mid = 0;
		for( ui_prev = 1; ui_prev < cui_vertex_cnt; ++ui_prev )
		{
			if( globalverts[ vertices[ ui_prev ] ][1] < globalverts[ vertices[ ui_mid ] ][1] )
			{
				ui_mid = ui_prev;
			}
			else if( ( globalverts[ vertices[ ui_prev ] ][1] == globalverts[ vertices[ ui_mid ] ][1] ) &&
					 ( globalverts[ vertices[ ui_prev ] ][0] < globalverts[ vertices[ ui_mid ] ][0] ) )
			{
				ui_mid = ui_prev;
			}
		}

		ui_prev = ( ui_mid + cui_vertex_cnt - 1 ) % cui_vertex_cnt;
		ui_next = ( ui_mid + 1 ) % cui_vertex_cnt;

		cl_poly.vertices.resize( 3 );
		cl_poly.is_marked = is_marked;
		cl_poly.vertices[ 0 ] = vertices[ ui_mid ];
		cl_poly.vertices[ 1 ] = vertices[ ui_next ];
		cl_poly.vertices[ 2 ] = vertices[ ui_prev ];

		ui_prev = ( ui_prev + cui_vertex_cnt - 1 ) % cui_vertex_cnt;
		ui_next = ( ui_next + 1 ) % cui_vertex_cnt;

		while( cl_poly.vertices[ 1 ] != cl_poly.vertices[ 2 ] )
		{
			polylist.push_back( cl_poly );
			if( globalverts[ vertices[ ui_prev ] ][1] < globalverts[ vertices[ ui_next ] ][1] )
			{
				cl_poly.vertices[ 0 ] = cl_poly.vertices[ 2 ];
				cl_poly.vertices[ 2 ] = vertices[ ui_prev ];
				ui_prev = ( ui_prev + cui_vertex_cnt - 1 ) % cui_vertex_cnt;
			}
			else if( ( globalverts[ vertices[ ui_prev ] ][1] == globalverts[ vertices[ ui_next ] ][1] ) &&
					 ( globalverts[ vertices[ ui_prev ] ][0] < globalverts[ vertices[ ui_next ] ][0] ) )
			{
				cl_poly.vertices[ 0 ] = cl_poly.vertices[ 2 ];
				cl_poly.vertices[ 2 ] = vertices[ ui_prev ];
				ui_prev = ( ui_prev + cui_vertex_cnt - 1 ) % cui_vertex_cnt;
			}
			else
			{
				cl_poly.vertices[ 0 ] = cl_poly.vertices[ 1 ];
				cl_poly.vertices[ 1 ] = vertices[ ui_next ];
				ui_next = ( ui_next + 1 ) % cui_vertex_cnt;
			}
		}
		return 0;
	}
#endif

//  std::cerr << " triangulate in, size: " << vertices.size() << std::endl;
	switch( vertices.size( ) )
	{
		case 0:
		case 1:
		case 2:
			return 0;
		case 3:
			{
				polylist.push_back( *this );
//				SimplePolygon p;
//				p.vertices = vertices;
//				p.is_marked = is_marked;
//				std::cerr << "adding polygon of 3 vertices into the list..." << std::endl;
//				polylist.push_back( p ); // FIXME, this is not too elegant
//				std::cerr << "triangulate out!!!" << std::endl;
			}
			return 0;
		case 4:
			{
				const int		ci_v1 = vertices[ 0 ];
				const int		ci_v2 = vertices[ 1 ];
				const int		ci_v3 = vertices[ 2 ];
				const int		ci_v4 = vertices[ 3 ];
				const double	cd_sdist1 = ( globalverts[ ci_v1 ] - globalverts[ ci_v3 ] ).squareLength( );
				const double	cd_sdist2 = ( globalverts[ ci_v2 ] - globalverts[ ci_v4 ] ).squareLength( );
				double			ad_pa[ 2 ];
				double			ad_pb[ 2 ];
				double			ad_pc[ 2 ];
				double			ad_pd[ 2 ];
				SimplePolygon	p;

				p.vertices.resize( 3 );
				p.is_marked = is_marked;

				ad_pa[ 0 ] = globalverts[ ci_v1 ][0];
				ad_pa[ 1 ] = globalverts[ ci_v1 ][1];
				ad_pb[ 0 ] = globalverts[ ci_v2 ][0];
				ad_pb[ 1 ] = globalverts[ ci_v2 ][1];
				ad_pc[ 0 ] = globalverts[ ci_v3 ][0];
				ad_pc[ 1 ] = globalverts[ ci_v3 ][1];
				ad_pd[ 0 ] = globalverts[ ci_v4 ][0];
				ad_pd[ 1 ] = globalverts[ ci_v4 ][1];

				if( cd_sdist1 - cd_sdist2 < DCTP_EPS )
				{
/*					const double cd_r1 = orient2d( ad_pa, ad_pb, ad_pc );
					const double cd_r2 = orient2d( ad_pa, ad_pb, ad_pd );
					if( ( ( cd_r1 <= 0.0 ) && ( cd_r2 <= 0.0 ) ) ||
						( ( cd_r1 >= 0.0 ) && ( cd_r2 >= 0.0 ) ) )*/
					if( ( orient2d( ad_pa, ad_pb, ad_pc ) <= 0.0 ) ||
						( orient2d( ad_pa, ad_pd, ad_pc ) >= 0.0 ) ||
						( incircle( ad_pa, ad_pb, ad_pc, ad_pd ) > 0.0 ) )
					{
						p.vertices[ 0 ] = ci_v1;
						p.vertices[ 1 ] = ci_v2;
						p.vertices[ 2 ] = ci_v4;
						polylist.push_back( p );
						p.vertices[ 0 ] = ci_v2;
						p.vertices[ 1 ] = ci_v3;
						p.vertices[ 2 ] = ci_v4;
						polylist.push_back( p );
//						std::cerr << globalverts[ ci_v1 ] << globalverts[ ci_v2 ] << globalverts[ ci_v3 ] << globalverts[ ci_v4 ] << std::endl;
					}
					else
					{
						p.vertices[ 0 ] = ci_v1;
						p.vertices[ 1 ] = ci_v2;
						p.vertices[ 2 ] = ci_v3;
						polylist.push_back( p );
						p.vertices[ 0 ] = ci_v1;
						p.vertices[ 1 ] = ci_v3;
						p.vertices[ 2 ] = ci_v4;
						polylist.push_back( p );
					}
				}
				else
				{
//					const double cd_r1 = orient2d( ad_pc, ad_pd, ad_pa );
//					const double cd_r2 = orient2d( ad_pc, ad_pd, ad_pb );
//					if( ( ( cd_r1 <= 0.0 ) && ( cd_r2 <= 0.0 ) ) ||
//						( ( cd_r1 >= 0.0 ) && ( cd_r2 >= 0.0 ) ) )
					if( ( orient2d( ad_pb, ad_pc, ad_pd ) <= 0.0 ) ||
						( orient2d( ad_pb, ad_pa, ad_pd ) >= 0.0 ) ||
						( incircle( ad_pa, ad_pb, ad_pd, ad_pc ) > 0.0 ) )
					{
						p.vertices[ 0 ] = ci_v1;
						p.vertices[ 1 ] = ci_v2;
						p.vertices[ 2 ] = ci_v3;
						polylist.push_back( p );
						p.vertices[ 0 ] = ci_v1;
						p.vertices[ 1 ] = ci_v3;
						p.vertices[ 2 ] = ci_v4;
						polylist.push_back( p );
//						std::cerr << globalverts[ ci_v1 ] << globalverts[ ci_v2 ] << globalverts[ ci_v3 ] << globalverts[ ci_v4 ] << std::endl;
					}
					else
					{
						p.vertices[ 0 ] = ci_v1;
						p.vertices[ 1 ] = ci_v2;
						p.vertices[ 2 ] = ci_v4;
						polylist.push_back( p );
						p.vertices[ 0 ] = ci_v2;
						p.vertices[ 1 ] = ci_v3;
						p.vertices[ 2 ] = ci_v4;
						polylist.push_back( p );
					}
				}
			}
			return 0;
	}

  // recalc valid third points!
  v1tp = -1;
  validThirdPoints.resize( vertices.size( ) );

  SimplePolygon poly;
  int i2, i3; // this is an index into the vertices[] vector
  int err;
  DCTPivector verts; //p1verts, p2verts, p3verts;
  int i;
  int j;
  // pseudo random (reproduces same triangulation)
  int offs = ( int( globalverts[ vertices[ 0 ] ][0] * vertices.size( ) ) ) % vertices.size( );

/*  for( i = 0; i < vertices.size( ); ++i )
  {
    std::cerr << globalverts[ vertices[ i ] ][0] << ",";
    std::cerr << globalverts[ vertices[ i ] ][1] << std::endl;
  }*/

  for( j = 0; j < int(vertices.size()); j++ ) {
	i = ( j + offs ) % vertices.size( );
//    v1 = vertices[ i ];
    if ( i == int(vertices.size()) - 1 )
      i2 = 0; //v2 = vertices [ 0 ];
    else
      i2 = i + 1; //v2 = vertices[ i + 1 ];
    err = findThirdPoint( globalverts, i, i2, i3 );
    if ( err ) return err;
    if ( i3 >= 0 ) {
      // build p1
      int k = i2; // !!!
      verts.resize( 0 );
      while ( k != i3 ) {
//        std::cerr << " k: " << k;
        verts.push_back( vertices[ k ] );
        k++; if ( k == int(vertices.size()) ) k = 0;
      } // while k
      verts.push_back( vertices[ k ] ); // record the last one aswell
//      std::cerr << " k: " << k << std::endl;
      poly.vertices = verts;
      poly.is_marked = is_marked;
//      std::cerr << "calling p1... " << std::endl;
      err = poly.triangulate( globalverts, polylist);
      if ( err ) return err;
      // build p2
      verts.resize( 3 );
      verts[ 0 ] = vertices[ i ];
      verts[ 1 ] = vertices[ i2 ];
      verts[ 2 ] = vertices[ i3 ];
      poly.vertices = verts;
      poly.is_marked = is_marked;
//      std::cerr << "adding p2 to the list..." << std::endl;
      polylist.push_back( poly );
      // build p3
      k = i3;
      verts.resize( 0 );
      while ( k != i ) {
        verts.push_back( vertices[ k ] );
        k++; if ( k == int(vertices.size()) ) k = 0;
      } // while k
      verts.push_back( vertices[ k ] ); // record the last one aswell
      poly.vertices = verts;
      poly.is_marked = is_marked;
//      std::cerr << "calling p3... " << std::endl;
      err = poly.triangulate( globalverts, polylist );
      if ( err ) return err;
//      std::cerr << "triangulate out!!!" << std::endl;
      return 0;
    } // if
  } // for i
/*  SWARNING << "triangulate out WITH ERROR!!!" << endLog;

  for( i = 0; i < vertices.size( ); ++i )
  {
    std::cerr << globalverts[ vertices[ i ] ][0] << ",";
    std::cerr << globalverts[ vertices[ i ] ][1] << std::endl;
  }*/

//  char x[ 256 ];
//  gets( x );

  return -1;
}
Esempio n. 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);
      }
    }
  }