/**
* Test Case for the In Circle Test!
	double pa[3] = {1,0,0};
	double pb[3] = {0,0,1};
	double pc[3] = {0,1,0};

	double pp[3] = {0.25,0.25,0.5};

	double ppout1[3] = {-5,0.25,0.5};
	double ppout2[3] = {5.0,0.25,0.5};
	double ppout3[3] = {0.25,5.0,0.5};

	bool isIn1 = IsInPlanarTriangle(pa,pb,pc,ppout1);
	bool isIn2 = IsInPlanarTriangle(pa,pb,pc,ppout2);
	bool isIn3 = IsInPlanarTriangle(pa,pb,pc,ppout3);

	bool isIn = IsInPlanarTriangle(pa,pb,pc,pp);
*/
bool IsInPlanarTriangle(double *pa, double *pb, double *pc, double *pp)
{
	if ( orient2d(pa,pb,pp)<0&& orient2d(pb,pc,pp)<0 && orient2d(pc,pa,pp)<0) {
		return false;
	}
	return true;
}
Esempio n. 2
0
 bool pointIntersectsTriangle(const P2 &p, const P2vec &tri) {
   int orient = isAnticlockwise(tri) ? +1 : -1;
   if (orient2d(tri[0], tri[1], p) * orient < 0) return false;
   if (orient2d(tri[1], tri[2], p) * orient < 0) return false;
   if (orient2d(tri[2], tri[0], p) * orient < 0) return false;
   return true;
 }
Esempio n. 3
0
void DepthBuffer::drawTriangle(BinnedTriangle& tri,vec2i tilePos) {
	vec2i v0(tri.v[0].x,tri.v[0].y);
	vec2i v1(tri.v[1].x,tri.v[1].y);
	vec2i v2(tri.v[2].x,tri.v[2].y);
	float zz[3] = { tri.z[0],tri.z[1],tri.z[2] };

	int32 minx = std::min(v0.x,std::min(v1.x,v2.x));
	int32 miny = std::min(v0.y,std::min(v1.y,v2.y));
	int32 maxx = std::max(v0.x,std::max(v1.x,v2.x));
	int32 maxy = std::max(v0.y,std::max(v1.y,v2.y));

	minx = std::max(minx,tilePos.x); miny = std::max(miny,tilePos.y);
	maxx = std::min(maxx,tilePos.x+tileSize_.x-1); maxy = std::min(maxy,tilePos.y+tileSize_.y-1);

	int32 a01 = v0.y - v1.y; int32 b01 = v1.x - v0.x;
	int32 a12 = v1.y - v2.y; int32 b12 = v2.x - v1.x;
	int32 a20 = v2.y - v0.y; int32 b20 = v0.x - v2.x;

	vec2i p(minx,miny);

	auto w0_row = orient2d(v1,v2,p);
	auto w1_row = orient2d(v2,v0,p);
	auto w2_row = orient2d(v0,v1,p);

	float* tilePixels = data_ + tilePos.x*tileSize_.y + (tilePos.y*tileSize_.x)*tileCount_.x;
	
	int32 idx2  = minx-tilePos.x + (miny - tilePos.y)*tileSize_.x;
	int32 spanx = maxx-minx;
	
	for(int32 endIdx2 = idx2+(tileSize_.x)*(maxy-miny);idx2<=endIdx2;idx2+=tileSize_.x){
		auto w0 = w0_row;
		auto w1 = w1_row;
		auto w2 = w2_row;

		//float betaf = float(w1);
		//float gamaf = float(w2);
		//float depth = zz[0] + betaf*zz[1] + gamaf*zz[2];
		//float depthInc = float(a20)*zz[1] + float(a01)*zz[2];
		auto idx = idx2;
		for(int32 endIdx = idx+spanx;idx<=endIdx;++idx){
			if((w0|w1|w2) >= 0){
				float betaf = float(w1);
				float gamaf = float(w2);
				float depth = zz[0] + betaf*zz[1] + gamaf*zz[2];

				auto d = tilePixels[idx];
				d = depth<d?depth:d;
				tilePixels[idx] = d;
			}

			w0+=a12;
			w1+=a20;
			w2+=a01;
			//depth+=depthInc;
		}
		w0_row += b12;
		w1_row += b20;
		w2_row += b01;
	}
}
Esempio n. 4
0
/*!
 *  The polylines must be different.
 *
 *  \param globalverts global vertices vector
 *  \param v1 the first polyline
 *  \param v2
 *  \param p1 the second polyline
 *  \param p2
 *
 *  \return  0 if they don't intersect <BR>
 *           1 if they do <BR>
 */
int SimplePolygon::doIntersect( DCTPVec2dvector &globalverts, int v1, int v2, int p1, int p2 ) const
{
  // check if they share vertices
  if ( v1 == p1 || v1 == p2 || v2 == p1 || v2 == p2 ) return 0;

  double pa[ 2 ];
  double pb[ 2 ];
  double pc[ 2 ];
  double pd[ 2 ];
  const int vv1 = vertices[ v1 ];
  const int vv2 = vertices[ v2 ];
  const int vp1 = vertices[ p1 ];
  const int vp2 = vertices[ p2 ];

  pa[ 0 ] = globalverts[ vv1 ][0];
  pa[ 1 ] = globalverts[ vv1 ][1];
  pb[ 0 ] = globalverts[ vv2 ][0];
  pb[ 1 ] = globalverts[ vv2 ][1];
  pc[ 0 ] = globalverts[ vp1 ][0];
  pc[ 1 ] = globalverts[ vp1 ][1];
  pd[ 0 ] = globalverts[ vp2 ][0];
  pd[ 1 ] = globalverts[ vp2 ][1];

  const double r1 = orient2d(pa, pc, pd);
  const double r2 = orient2d(pb, pc, pd);
  if( ( r1 < 0.0 ) && ( r2 < 0.0 ) )
  {
    return 0;
  }
  if( ( r1 > 0.0 ) && ( r2 > 0.0 ) )
  {
    return 0;
  }

  const double r3 = orient2d(pc, pa, pb);
  const double r4 = orient2d(pd, pa, pb);
  if( ( r3 < 0.0 ) && ( r4 < 0.0 ) )
  {
    return 0;
  }
  if( ( r3 > 0.0 ) && ( r4 > 0.0 ) )
  {
    return 0;
  }
  return 1;

  // do intersect??
  /*
   * r1 and r2 must have different signs ( <0, >0, =0 ) AND
   * r3 and r4 must also have different signs in suffice intersection of
   * the two lines.
   */
/*  bool s1 = ( !(( r1 < 0  &&  r2 < 0 ) || ( r1 > 0  && r2 > 0 )) );
  bool s2 = ( !(( r3 < 0  &&  r4 < 0 ) || ( r3 > 0  && r4 > 0 )) );

  if ( s1  && s2 ) return 1;
  else return 0;*/

}
Esempio n. 5
0
 int triangleLineOrientation(const P2 &p1, const P2 &p2, const P2vec &tri) {
   double lo, hi, tmp;
   lo = hi = orient2d(p1, p2, tri[0]);
   tmp = orient2d(p1, p2, tri[1]); lo = std::min(lo, tmp); hi = std::max(hi, tmp);
   tmp = orient2d(p1, p2, tri[2]); lo = std::min(lo, tmp); hi = std::max(hi, tmp);
   if (hi < 0.0) return -1;
   if (lo > 0.0) return +1;
   return 0;
 }
Esempio n. 6
0
void tricircumcenter3d(double*a, double*b, double*c, double*circumcenter,double*cond)
{
    double xba, yba, zba, xca, yca, zca;
    double balength, calength;
    double xcrossbc, ycrossbc, zcrossbc;
    double denominator;
    double xcirca, ycirca, zcirca;
#ifdef EXACT
	double ta[2],tb[2],tc[2];
#endif
    /* Use coordinates relative to point `a' of the triangle. */
    xba = b[0] - a[0];
    yba = b[1] - a[1];
    zba = b[2] - a[2];
    xca = c[0] - a[0];
    yca = c[1] - a[1];
    zca = c[2] - a[2];
    /* Squares of lengths of the edges incident to `a'. */
    balength = xba * xba + yba * yba + zba * zba;
    calength = xca * xca + yca * yca + zca * zca;
  
    /* Cross product of these edges. */
#ifdef EXACT
    /* Use orient2d() from http://www.cs.cmu.edu/~quake/robust.html     */
        /*   to ensure a correctly signed (and reasonably accurate) result, */
        /*   avoiding any possibility of division by zero.                  */
        ta[0]=b[1];ta[1]=b[2];tb[0]=c[1];tb[1]=c[2];tc[0]=a[1];tc[1]=a[2];
        xcrossbc = orient2d(ta,tb,tc);
        ta[0]=b[2];ta[1]=b[0];tb[0]=c[2];tb[1]=c[0];tc[0]=a[2];tc[1]=a[0];
        ycrossbc = orient2d(ta,tb,tc);
        ta[0]=b[0];ta[1]=b[1];tb[0]=c[0];tb[1]=c[1];tc[0]=a[0];tc[1]=a[1];
        zcrossbc = orient2d(ta,tb,tc);
#else
        /* Take your chances with floating-point roundoff. */
        xcrossbc = yba * zca - yca * zba;
        ycrossbc = zba * xca - zca * xba;
        zcrossbc = xba * yca - xca * yba;
#endif

        /* Calculate the denominator of the formulae. */
        denominator = 0.5 / (xcrossbc * xcrossbc + ycrossbc * ycrossbc +
                             zcrossbc * zcrossbc);

        /* Calculate offset (from `a') of circumcenter. */
        xcirca = ((balength * yca - calength * yba) * zcrossbc -
                  (balength * zca - calength * zba) * ycrossbc) * denominator;
        ycirca = ((balength * zca - calength * zba) * xcrossbc -
                  (balength * xca - calength * xba) * zcrossbc) * denominator;
        zcirca = ((balength * xca - calength * xba) * ycrossbc -
                  (balength * yca - calength * yba) * xcrossbc) * denominator;
        circumcenter[0] = xcirca;
        circumcenter[1] = ycirca;
        circumcenter[2] = zcirca;

}
Esempio n. 7
0
 /** 
  * \brief Determine whether p is internal to the anticlockwise
  *        angle abc, where b is the apex of the angle.
  *
  * @param[in] a 
  * @param[in] b 
  * @param[in] c 
  * @param[in] p 
  * 
  * @return true, if p is contained in the anticlockwise angle from
  *               b->a to b->c. Reflex angles contain p if p lies
  *               on b->a or on b->c. Acute angles do not contain p
  *               if p lies on b->a or on b->c. This is so that
  *               internalToAngle(a,b,c,p) = !internalToAngle(c,b,a,p)
  */
 inline bool internalToAngle(const P2 &a,
                             const P2 &b,
                             const P2 &c,
                             const P2 &p) {
   bool reflex = (a < c) ?  orient2d(b, a, c) <= 0.0 : orient2d(b, c, a) > 0.0;
   double d1 = orient2d(b, a, p);
   double d2 = orient2d(b, c, p);
   if (reflex) {
     return d1 >= 0.0 || d2 <= 0.0;
   } else {
     return d1 > 0.0 && d2 < 0.0;
   }
 }
Esempio n. 8
0
/*!
 *  \param globalverts global vertices vector
 *  \param v1 first vertex
 *  \param v2 second vertex
 *  \param v3 third vertex
 *  \param p the point
 *  \return 0 if not inside <BR>
 *          1 if inside <BR>
 */
int SimplePolygon::isInsideCircumCircle( DCTPVec2dvector &globalverts, int v1, int v2, int v3, int p ) const
{
  double pa[2], pb[2], pc[2], pd[2];

  pa [ 0 ] = globalverts[ vertices[ v1 ] ][0];
  pa [ 1 ] = globalverts[ vertices[ v1 ] ][1];
  pb [ 0 ] = globalverts[ vertices[ v2 ] ][0];
  pb [ 1 ] = globalverts[ vertices[ v2 ] ][1];
  pc [ 0 ] = globalverts[ vertices[ v3 ] ][0];
  pc [ 1 ] = globalverts[ vertices[ v3 ] ][1];
  pd [ 0 ] = globalverts[ vertices[ p ] ][0];
  pd [ 1 ] = globalverts[ vertices[ p ] ][1];
  // check for order of (pa, pb, pc) they must be in counterclockwise order
  double order = orient2d( pa, pb, pc );
  double dres;
  if ( order < 0.0 ) // clockwise order -> change order
    dres = incircle( pa, pc, pb, pd );
  else
    dres = incircle( pa, pb, pc, pd );

  //std::cerr << pa[ 0 ] << "," << pa[ 1 ] << " ";
  //std::cerr << pb[ 0 ] << "," << pb[ 1 ] << " ";
  //std::cerr << pc[ 0 ] << "," << pc[ 1 ] << " ";
  //std::cerr << pd[ 0 ] << "," << pd[ 1 ] << std::endl;
  //std::cerr << "Inside Circumcircle: " << dres << std::endl;   // >0 if inside

  if ( dres <= 0 ) return 0;
  else return 1;
}
Esempio n. 9
0
bool SimplePolygon::isReversed( DCTPVec2dvector &globalverts )
{
	unsigned int		ui_vertex;
	unsigned int		ui_upperleft;
	const unsigned int	cui_vertex_cnt = vertices.size( );
	double				ad_p[ 2 ];
	double				ad_v[ 2 ];
	double				ad_n[ 2 ];

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

	ad_p[ 0 ] = globalverts[ vertices[ ( ui_upperleft + cui_vertex_cnt - 1 ) % cui_vertex_cnt ] ][0];
	ad_p[ 1 ] = globalverts[ vertices[ ( ui_upperleft + cui_vertex_cnt - 1 ) % cui_vertex_cnt ] ][1];
	ad_v[ 0 ] = globalverts[ vertices[ ui_upperleft ] ][0];
	ad_v[ 1 ] = globalverts[ vertices[ ui_upperleft ] ][1];
	ad_n[ 0 ] = globalverts[ vertices[ ( ui_upperleft + 1 ) % cui_vertex_cnt ] ][0];
	ad_n[ 1 ] = globalverts[ vertices[ ( ui_upperleft + 1 ) % cui_vertex_cnt ] ][1];

	return ( orient2d( ad_p, ad_v, ad_n ) <= 0.0 );
}
Esempio n. 10
0
Exact_adaptive_kernel::Oriented_side Exact_adaptive_kernel::oriented_side (Point2 const& pa, Point2 const& pb, Point2 const& test)
{
    double r = orient2d(pa.coord(), pb.coord(), test.coord());
    if (r > 0.0)
        return ON_POSITIVE_SIDE;
    else if (r < 0.0)
        return ON_NEGATIVE_SIDE;
    else
        return ON_ORIENTED_BOUNDARY;
}
Esempio n. 11
0
    bool lineIntersectsTriangle(const P2 &p1, const P2 &p2, const P2vec &tri) {
      double s[3];
      // does tri lie on one side or the other of p1-p2?
      s[0] = orient2d(p1, p2, tri[0]);
      s[1] = orient2d(p1, p2, tri[1]);
      s[2] = orient2d(p1, p2, tri[2]);
      if (*std::max_element(s, s+3) < 0) return false;
      if (*std::min_element(s, s+3) > 0) return false;

      // does line lie entirely to the right of a triangle edge?
      int orient = isAnticlockwise(tri) ? +1 : -1;
      if (orient2d(tri[0], tri[1], p1) * orient < 0 && orient2d(tri[0], tri[1], p2) * orient < 0) return false;
      if (orient2d(tri[1], tri[2], p1) * orient < 0 && orient2d(tri[1], tri[2], p2) * orient < 0) return false;
      if (orient2d(tri[2], tri[0], p1) * orient < 0 && orient2d(tri[2], tri[0], p2) * orient < 0) return false;
      return true;
    }
Esempio n. 12
0
    bool lineSegmentIntersection_simple(const P2 &l1v1, const P2 &l1v2,
                                        const P2 &l2v1, const P2 &l2v2) {
      geom::aabb<2> l1_aabb, l2_aabb;
      l1_aabb.fit(l1v1, l1v2);
      l2_aabb.fit(l2v1, l2v2);

      if (l1_aabb.maxAxisSeparation(l2_aabb) > 0.0) {
        return false;
      }

      double l1v1_side = orient2d(l2v1, l2v2, l1v1);
      double l1v2_side = orient2d(l2v1, l2v2, l1v2);

      double l2v1_side = orient2d(l1v1, l1v2, l2v1);
      double l2v2_side = orient2d(l1v1, l1v2, l2v2);

      if (l1v1_side * l1v2_side > 0.0 || l2v1_side * l2v2_side > 0.0) {
        return false;
      }

      return true;
    }
// returns true if the ray cast from p along positive z axis hits triangle in
// exactly one spot, with edge cases handled appropriately
static bool
tri_zcast(const Vec3d& p,
          const Vec3d& q,
          const Vec3d& r,
          const Vec3d& s)
{
    // robustly find orientation of qrs in 2D xy projection
    double qrs=orient2d(q.v, r.v, s.v);
    if(qrs>0)
        return tri_zcast_inner(p, qrs, q, r, s);
    else if(qrs<0)
        return tri_zcast_inner(p, -qrs, q, s, r); // flip triangle to reorient
    else
        return false; // triangle is degenerate in 2D projection - ignore
}
Esempio n. 14
0
Oriented_side Exact_adaptive_kernel::oriented_side( Point2 const& pa, Point2 const& pb, Point2 const& test )
{
  double r = orient2d( pa.data(), pb.data(), test.data() );

  if ( r > 0.0 )
  {
    return ON_POSITIVE_SIDE;
  }

  if ( r < 0.0 )
  {
    return ON_NEGATIVE_SIDE;
  }

  return ON_ORIENTED_BOUNDARY;
}
Esempio n. 15
0
void triorthocenter(double a[], double b[], double c[],
	double orthocenter[], double* cnum)
{
    double xba, yba, wba, xca, yca, wca;
    double balength, calength;
    double denominator;
    double xcirca, ycirca;

    /* Use coordinates relative to point `a' of the triangle. */
    xba = b[0] - a[0];
    yba = b[1] - a[1];
    wba = b[2] - a[2];
    xca = c[0] - a[0];
    yca = c[1] - a[1];
    wca = b[2] - a[2];
    /* Squares of lengths of the edges incident to `a'. */
    balength = xba * xba + yba * yba - wba;
    calength = xca * xca + yca * yca - wca;

    /* Calculate the denominator of the formulae. */
#ifdef EXACT
    /* Use orient2d() from http://www.cs.cmu.edu/~quake/robust.html     */
        /*   to ensure a correctly signed (and reasonably accurate) result, */
        /*   avoiding any possibility of division by zero.                  */
        *cnum = orient2d(b, c, a);
        denominator = 0.5 / (*cnum);
#else
        /* Take your chances with floating-point roundoff. */
        denominator = 0.5 / (xba * yca - yba * xca);
		*cnum = 1.0; // a value !=0
#endif

        /* Calculate offset (from `a') of circumcenter. */
        xcirca = (yca * balength - yba * calength) * denominator;  
        ycirca = (xba * calength - xca * balength) * denominator;  
        orthocenter[0] = xcirca;
        orthocenter[1] = ycirca;

}
Esempio n. 16
0
bool SimplePolygon::isConvex( DCTPVec2dvector &globalverts )
{
	unsigned int		ui_next;
	const unsigned int	cui_vertex_cnt = vertices.size( );
	double			ad_p[ 2 ];
	double			ad_v[ 2 ];
	double			ad_n[ 2 ];

	ad_p[ 0 ] = globalverts[ vertices[ cui_vertex_cnt - 2 ] ][0];
	ad_p[ 1 ] = globalverts[ vertices[ cui_vertex_cnt - 2 ] ][1];
	ad_v[ 0 ] = globalverts[ vertices[ cui_vertex_cnt - 1 ] ][0];
	ad_v[ 1 ] = globalverts[ vertices[ cui_vertex_cnt - 1 ] ][1];
	for( ui_next = 0; ui_next < cui_vertex_cnt; ++ui_next )
	{
//		std::cerr <<"ui_next:" << ui_next << std::endl;
		ad_n[ 0 ] = globalverts[ vertices[ ui_next ] ][0];
		ad_n[ 1 ] = globalverts[ vertices[ ui_next ] ][1];
		// previous, current, and next vertices must be in
		// counterclockwise order for the polygon to be convex
		// (because our tessellator always gives CCW polygons)
		if( orient2d( ad_p, ad_v, ad_n ) < 0.0 )
		{
//			std::cerr << ad_p[ 0 ] << " " << ad_p[ 1 ] << std::endl;
//			std::cerr << ad_v[ 0 ] << " " << ad_v[ 1 ] << std::endl;
//			std::cerr << ad_n[ 0 ] << " " << ad_n[ 1 ] << std::endl << std::endl;
			// not convex
			return false;
		}
		ad_p[ 0 ] = ad_v[ 0 ];
		ad_p[ 1 ] = ad_v[ 1 ];
		ad_v[ 0 ] = ad_n[ 0 ];
		ad_v[ 1 ] = ad_n[ 1 ];
	}

//	std::cerr << "convex" << std::endl;
	return true;
}
Esempio n. 17
0
double Exact_adaptive_kernel::signed_area( Point2 const& pa, Point2 const& pb, Point2 const& pc )
{
  return 0.5 * orient2d( pa.data(), pb.data(), pc.data() );
}
Esempio n. 18
0
inline double LeftTurn(const double a[2], const double b[2], const double c[2]){
	extern double orient2d(double*, double*, double*);
	return orient2d((double*)a, (double*)b, (double*)c);
}
Esempio n. 19
0
bool n3d_prepare(
    n3d_rasterizer_t::triangle_t& tri,
    const n3d_vertex_t& v0,
    const n3d_vertex_t& v1,
    const n3d_vertex_t& v2,
    const uint32_t flags)
{
    const vec4f_t& vp0 = v0.p_;
    const vec4f_t& vp1 = v1.p_;
    const vec4f_t& vp2 = v2.p_;

    // the signed triangle area
    const float t_area = (vp1.x - vp0.x) * (vp2.y - vp0.y) -
                         (vp2.x - vp0.x) * (vp1.y - vp0.y);

    // check for back face
    if (t_area <= 0.f)
        return false;
    // reciprocal of area for normalization
    const float rt_area = 1.f / t_area;

    // find normalized barycentric coordinates
    tri.v_ [e_attr_b0] = orient2d(vp1, vp2) * rt_area;
    tri.sx_[e_attr_b0] = (vp1.y - vp2.y)    * rt_area;
    tri.sy_[e_attr_b0] = (vp2.x - vp1.x)    * rt_area;

    tri.v_ [e_attr_b1] = orient2d(vp2, vp0) * rt_area;
    tri.sx_[e_attr_b1] = (vp2.y - vp0.y)    * rt_area;
    tri.sy_[e_attr_b1] = (vp0.x - vp2.x)    * rt_area;

    tri.v_ [e_attr_b2] = orient2d(vp0, vp1) * rt_area;
    tri.sx_[e_attr_b2] = (vp0.y - vp1.y)    * rt_area;
    tri.sy_[e_attr_b2] = (vp1.x - vp0.x)    * rt_area;

    // calculate 1 / w for vertices
    const float v0w = 1.f / v0.p_.w;
    const float v1w = 1.f / v1.p_.w;
    const float v2w = 1.f / v2.p_.w;

    //(todo) update all of this to use SSE

    // find triangle bounds
    tri.min_.x = min3(vp0.x, vp1.x, vp2.x);
    tri.min_.y = min3(vp0.y, vp1.y, vp2.y);
    tri.max_.x = max3(vp0.x, vp1.x, vp2.x) + 1.f;
    tri.max_.y = max3(vp0.y, vp1.y, vp2.y) + 1.f;

// barycenteric interpolate 1 param
#define BLERPW(B) ((tri.B[0] * v0w) + \
                   (tri.B[1] * v1w) + \
                   (tri.B[2] * v2w))

// barycentric interpolate 3 param
#define BLERPA(B, A) ((tri.B[0] * v0.attr_[A] * v0w) + \
                      (tri.B[1] * v1.attr_[A] * v1w) + \
                      (tri.B[2] * v2.attr_[A] * v2w))

    // interplate 1 / w
    tri.v_ [e_attr_w] = BLERPW(v_);
    tri.sx_[e_attr_w] = BLERPW(sx_);
    tri.sy_[e_attr_w] = BLERPW(sy_);

#if 0
    for (uint32_t i = 0; i < v0.attr_.size(); ++i) {
      tri.v_ [e_attr_custom + i] = BLERPA(v_,  i);
      tri.sx_[e_attr_custom + i] = BLERPA(sx_, i);
      tri.sy_[e_attr_custom + i] = BLERPA(sy_, i);
    }
#endif

#undef BLERPW
#undef BLERPA
    return true;
}
// helper function for tri_zcast below...
// Here we are given a robust 2d orientation of qrs in xy projection, which
// must be positive.
static bool
tri_zcast_inner(const Vec3d& p,
                double qrs,
                const Vec3d& q,
                const Vec3d& r,
                const Vec3d& s)
{
    assert(qrs>0);

    // first check if point is above or below triangle in z
    double pqrs=orient3d(p.v, q.v, r.v, s.v);
    if(pqrs>=0) return false; // point is on or above triangle - no intersection

    // then check if point lies outside triangle in 2D xy projection
    double pqr=orient2d(p.v, q.v, r.v);
    if(pqr<0) return false;
    double prs=orient2d(p.v, r.v, s.v);
    if(prs<0) return false;
    double psq=orient2d(p.v, s.v, q.v);
    if(psq<0) return false;

    // note: the following tests are somewhat redundant, but it's a pretty
    // tiny optimization to eliminate the redundancy compared to the loss in
    // clarity.

    // check if point is strictly inside the triangle in xy
    if(pqr>0 && prs>0 && psq>0) return true;

    // check if point is strictly on edge qr
    if(pqr==0 && prs>0 && psq>0){
        if(q[1]<r[1]) return false;
        if(q[1]>r[1]) return true;
        if(q[0]<r[0]) return true;
        assert(q[0]>r[0]); // q!=r because triangle is not degenerate
        return false;
    }

    // check if point is strictly on edge rs
    if(prs==0 && pqr>0 && psq>0){
        if(r[1]<s[1]) return false;
        if(r[1]>s[1]) return true;
        if(r[0]<s[0]) return true;
        assert(r[0]>s[0]); // r!=s because triangle is not degenerate
        return false;
    }
    
    // check if point is strictly on edge sq
    if(psq==0 && pqr>0 && prs>0){
        if(s[1]<q[1]) return false;
        if(s[1]>q[1]) return true;
        if(s[0]<q[0]) return true;
        assert(s[0]>q[0]); // r!=s because triangle is not degenerate
        return false;
    }
   
    // check if point is on vertex q
    if(p[0]==q[0] && p[1]==q[1]){
        return q[1]>=r[1] && q[1]<s[1];
    }
   
    // check if point is on vertex r
    if(p[0]==r[0] && p[1]==r[1]){
        return r[1]>=s[1] && r[1]<q[1];
    }
   
    // check if point is on vertex s
    if(p[0]==s[0] && p[1]==s[1]){
        return s[1]>=q[1] && s[1]<r[1];
    }

    assert(false); // we should have covered all cases at this point
    return false; // just to quiet compiler warnings
}
Esempio n. 21
0
 bool isAnticlockwise(const P2vec &tri) {
   return orient2d(tri[0], tri[1], tri[2]) > 0.0;
 }
Esempio n. 22
0
/*Type of Cut Strategy is defined as:
 * (useAltCut, useVertical) = (true, true)  => Alternating Cuts
 * (useAltCut, useVertical) = (true, false) => Horizontal Cuts*
 * (useAltCut, useVertical) = (false, true)  => Vertical Cuts
 * */
void delaunay(Vertex **ppVertices, long numVertices, Edge **ppLe, Edge **ppRe,
		bool useAltCuts, bool useVertical) {
    NOT_NULL(ppVertices);
    
    if(numVertices == 2) {
        Edge *pA = Edge::makeEdge();
        if(*ppVertices[0] > *ppVertices[1]) {
            ELEM_SWAP(ppVertices[0], ppVertices[1]);
        }
        pA->setOrg(ppVertices[0]);
        pA->setDest(ppVertices[1]);
        *ppLe = pA;
        *ppRe = pA->Sym();
    }
    else if(numVertices == 3) {
        Edge *pA = Edge::makeEdge(),
             *pB = Edge::makeEdge(),
             *pC = 0;

        if(*ppVertices[0] > *ppVertices[1]) {
            ELEM_SWAP(ppVertices[0], ppVertices[1]);
        }
        if(*ppVertices[1] > *ppVertices[2]) {
            ELEM_SWAP(ppVertices[1], ppVertices[2]);
        }

        Edge::splice(pA->Sym(), pB);
        pA->setOrg(ppVertices[0]);
        pA->setDest(ppVertices[1]);
        pB->setOrg(ppVertices[1]);
        pB->setDest(ppVertices[2]);
        
        REAL ccw = orient2d(ppVertices[0]->Pos(), ppVertices[1]->Pos(), ppVertices[2]->Pos());
        if(ccw > 0) {
            pC = Edge::connect(pB, pA);
            *ppLe = pA;
            *ppRe = pB->Sym();
        }
        else if(ccw < 0) {
            pC = Edge::connect(pB, pA);
            *ppLe = pC->Sym();
            *ppRe = pC;
        }
        else {
            *ppLe = pA;
            *ppRe = pB->Sym();
        }
    }
    else {
        long middle = std::floor(numVertices/2);
        Edge *pLdo = 0, 
             *pLdi = 0, 
             *pRdi = 0, 
             *pRdo = 0;

        //These vertices are used for merging a horizontal cut
        Vertex *pBotMax = 0, //highest vertex of bottom half
               *pTopMin = 0, //lowest vertex of top half
               *pMin    = 0, //Lexicographically max vertex
               *pMax    = 0; //Lexicographically min vertex
        
        //Find median partition by X or Y, depending on whether we're using a vertical cut
        std::nth_element(ppVertices, ppVertices+middle, ppVertices+numVertices, useVertical ? Vertex::lessX : Vertex::lessY);

        //Recursive calls
        delaunay(ppVertices, middle, &pLdo, &pLdi, useAltCuts, useAltCuts ? !useVertical : useVertical);
        delaunay(ppVertices+middle, numVertices - middle, &pRdi, &pRdo, useAltCuts, useAltCuts ? !useVertical : useVertical);
        
        //Modify ldi be highest in bottom half and rdi to be lowest in top half
        if(!useVertical) {
            pBotMax = ppVertices[0];
            pTopMin = ppVertices[middle];
            pMin    = (*ppVertices[0] < *ppVertices[middle]) ? ppVertices[0] : ppVertices[middle];
            pMax    = (*ppVertices[0] > *ppVertices[middle]) ? ppVertices[0] : ppVertices[middle];;
            for(long i=1; i < middle; i++) {
                if(*ppVertices[i] < *pMin) {
                    pMin = ppVertices[i];
                }
                else if(*ppVertices[i] > *pMax) {
                    pMax = ppVertices[i];
                }
                
                if(ppVertices[i]->gtY(*pBotMax)) {
                    pBotMax = ppVertices[i];
                }
            }
            for(long i=middle+1; i < numVertices; i++) {
                if(*ppVertices[i] < *pMin) {
                    pMin = ppVertices[i];
                }
                else if(*ppVertices[i] > *pMax) {
                    pMax = ppVertices[i];
                }
                
                if(ppVertices[i]->ltY(*pTopMin)) {
                    pTopMin = ppVertices[i];
                }
            }
            
            pLdi = pBotMax->getCWHullEdge();
            pRdi = pTopMin->getCCWHullEdge();
        }
        
        
        //Compute the lower common tangent of two sets of vertices
        while (1) {
            if(pLdi->leftOf(pRdi->Org())) {
                pLdi = pLdi->Lnext();
            }
            else if(pRdi->rightOf(pLdi->Org())) {
                pRdi = pRdi->Rprev();
            }
            else {
                break;
            }
        }

        // Create a first cross edge pBasel from pRdi.origin to pLdi.origin
        Edge *pBasel = Edge::connect(pRdi->Sym(), pLdi);

        if(pLdi->Org() == pLdo->Org()) {
            pLdo = pBasel->Sym();
        }
        if(pRdi->Org() == pRdo->Org()) {
            pRdo = pBasel;
        }

        //Merging two halves
        while(1) {
            //Locate the first Left point pLcand to be encou
        	Edge *pLcand = pBasel->Sym()->Onext();
            bool leftFinished  = !pLcand->valid(pBasel);
            if(!leftFinished) {
                while(incircle(pBasel->Dest()->Pos(), 
                               pBasel->Org()->Pos(), 
                               pLcand->Dest()->Pos(),  
                               pLcand->Onext()->Dest()->Pos()) > 0) {
                
                    Edge *pT = pLcand->Onext();
                    Edge::deleteEdge(pLcand);
                    pLcand = pT;
                }
            }
            
            //Symmetrically locate the first R point to be hit
            Edge *pRcand = pBasel->Oprev();
            bool rightFinished = !pRcand->valid(pBasel);
            if(!rightFinished) {
                while(incircle(pBasel->Dest()->Pos(), 
                               pBasel->Org()->Pos(), 
                               pRcand->Dest()->Pos(),  
                               pRcand->Oprev()->Dest()->Pos()) > 0) {
                
                    Edge *pT = pRcand->Oprev();
                    Edge::deleteEdge(pRcand);
                    pRcand = pT;
                }
            }

            //both are invalid, pBasel is upper common tangent
            if(leftFinished && rightFinished) {
                break;
            }
            //the next cross edge is to be connected to either pLcand.dest or pRcand.dest
            if(leftFinished || 
               (!rightFinished && incircle(pLcand->Dest()->Pos(), 
                                                  pLcand->Org()->Pos(), 
                                                  pRcand->Org()->Pos(), 
                                                  pRcand->Dest()->Pos()) > 0)) {
                pBasel = Edge::connect(pRcand, pBasel->Sym());
            }
            else {
                pBasel = Edge::connect(pBasel->Sym(), pLcand->Sym());
            }
        }

        //Modify pLdo and pRdo if we merging a horizontal cut
        if(!useVertical) {
            pLdo = pMin->getCCWHullEdge();
            pRdo = pMax->getCWHullEdge();
        }

        *ppLe = pLdo;
        *ppRe = pRdo;
    }
    return;
}
Esempio n. 23
0
int SimplePolygon::intersectPolygon( DCTPVec2dvector &globalverts, simplepolygonvector &polylist )
{
  int oldNum = vertices.size();
  int i1, i2;
  Vec2d min, max;
  Vec2d p3, p4;
  unsigned char test, ptest;

//  std::cerr << "Removing intersections... " << oldNum << std::endl;

  for( i2 = 2; i2 < oldNum; ++i2 )
  {
    const Vec2d &p1 = globalverts[ vertices[ i2 ] ];
    const Vec2d &p2 = globalverts[ vertices[ ( i2 + 1 ) % oldNum ] ];

    min = max = p1;
    if( min[0] > p2[0] )
      min[0] = p2[0];
    else if( max[0] < p2[0] )
      max[0] = p2[0];
    if( min[1] > p2[1] )
      min[1] = p2[1];
    else if( max[1] < p2[1] )
      max[1] = p2[1];

    const unsigned int start = ( i2 == oldNum - 1 ) ? 1 : 0;

    p4 = globalverts[ vertices[ start ] ];
    test = 0;
    if( p4[0] - max[0] > DCTP_EPS ) test |= 0x01;
    if( min[0] - p4[0] > DCTP_EPS ) test |= 0x02;
    if( p4[1] - max[1] > DCTP_EPS ) test |= 0x04;
    if( min[1] - p4[1] > DCTP_EPS ) test |= 0x08;

    for( i1 = start; i1 < i2 - 1; ++i1 )
    {
      p3 = p4;
      p4 = globalverts[ vertices[ i1 + 1 ] ];
      ptest = test;
      test = 0;
      if( p4[0] - max[0] > DCTP_EPS ) test |= 0x01;
      if( min[0] - p4[0] > DCTP_EPS ) test |= 0x02;
      if( p4[1] - max[1] > DCTP_EPS ) test |= 0x04;
      if( min[1] - p4[1] > DCTP_EPS ) test |= 0x08;
      if( ( test & ptest ) == 0 )
      {
//         std::cerr << i1 << "," << i1 + 1 << " overlaps " << i2 << "," << i2 + 1 << std::endl;
        // the bounding boxes overlap
        int iip = -1;
        bool intersect = false;
        double d1[ 2 ] = { p1[0], p1[1] };
        double d2[ 2 ] = { p2[0], p2[1] };
        double d3[ 2 ] = { p3[0], p3[1] };
        double d4[ 2 ] = { p4[0], p4[1] };

        if( ( orient2d( d1, d2, d3 ) == 0.0 ) &&
            ( orient2d( d1, d2, d4 ) == 0.0 ) )
        {
          // the lines are colinear => ... p1 p4 ... ; p2 ... p3
          intersect = true;
        }
        else
        {
          if( doIntersect( globalverts, i1, i1 + 1, i2, ( i2 + 1 ) % oldNum ) )
          {
            // the lines intersect => ... p1 ip p4 ... ; ip p2 ... p3
            Vec2d v1 = p2 - p1;
            Vec2d v2 = p4 - p3;
            Vec2d pp = p3 - p1;
            double a = pp[0] * v2[1] - pp[1] * v2[0];
            double b = v1[0] * v2[1] - v1[1] * v2[0];
            Vec2d ip = p1 + v1 * ( a / b );

            if( DCTPVecIsEqual( ip , p1 ) )
            {
              iip = vertices[ i1 ];
            }
            else if( DCTPVecIsEqual( ip , p2 ) )
            {
              iip = vertices[ i1 + 1 ];
            }
            else if( DCTPVecIsEqual( ip , p3 ) )
            {
              iip = vertices[ i2 ];
            }
            else if( DCTPVecIsEqual( ip , p4 ) )
            {
              iip = vertices[ ( i2 + 1 ) % oldNum ];
            }
            else
            {
              iip = globalverts.size();
              globalverts.resize( iip + 1 );
              globalverts[ iip ] = ip;
            }

//			std::cerr << p1[0] << "," << p1[1] << " - " << p2[0] << "," << p2[1] << std::endl;
//			std::cerr << p3[0] << "," << p3[1] << " - " << p4[0] << "," << p4[1] << std::endl;
//			std::cerr << globalverts[ iip ][0] << "," << globalverts[ iip ][1] << " - " << std::endl;
            intersect = true;
          }
        }
        if( intersect )
        {
          int i;
          int newNum;
          DCTPivector newPoints( oldNum );
          SimplePolygon poly;

//          std::cerr << i1 << "," << i1 + 1 << " intersects " << i2 << "," << i2 + 1 << std::endl;

          // copy points 0 ... i1
          for( i = 0; i <= i1; ++i )
          {
            newPoints[ i ] = vertices[ i ];
          }
          newNum = i;

          // copy iip's
          if( iip >= 0 )
          {
            if( ( iip != vertices[ i1 ] ) &&
                ( iip != vertices[ ( i2 + 1 ) % oldNum ] ) )
            {
              newPoints[ newNum ] = iip;
              ++newNum;
            }
            if( ( iip != vertices[ i2 ] ) &&
                ( iip != vertices[ i1 + 1 ] ) )
            {
              poly.vertices.resize( i2 + 1 - i1 );
              poly.vertices[ i2 - i1 ] = iip;
            }
            else
            {
              poly.vertices.resize( i2 - i1 );
            }
          }
          else
          {
            poly.vertices.resize( i2 - i1 );
          }

          // copy i1+1 ... i2
          for( i = 0; i < i2 - i1; ++i )
          {
            poly.vertices[ i ] = vertices[ i1 + i + 1 ];
          }

          // copy i2+1 ... n
          for( i = i2 + 1; i < oldNum; ++i )
          {
            newPoints[ newNum ] = vertices[ i ];
            ++newNum;
          }

          // copy new points back to polygon
          vertices.resize( newNum );
          for( i2 = 0; i2 < newNum; ++i2 )
          {
            vertices[ i2 ] = newPoints[ i2 ];
          }

//          std::cerr << "split in " << newNum << "," << poly.vertices.size() << std::endl;

          // triangulate the new polygon
          while( poly.intersectPolygon( globalverts, polylist ) ) { }
          if( poly.isReversed( globalverts ) )
          {
//            std::cerr << "Ignoring reversed polygon." << std::endl;
          }
          else
          {
            // Ok, we have a valid polygon, so triangulate it.
            poly.triangulate( globalverts, polylist );
          }

          // check if there are other intersections
          return 1;
        }
      }
    }
  }

  // polygon had no intersections so we are finished
  return 0;
}
Esempio n. 24
0
/*!
 *  Note that this has complexity O(n).
 *
 *  \param globalverts the global vertices vector
 *  \return zero on success, and a negative integer if some error occured.
 */
int SimplePolygon::removeLinearPoints( DCTPVec2dvector &globalverts, const Vec2d min, const Vec2d max )
{
  int oldNum = vertices.size( );
  int newNum = 0;
  DCTPivector newPoints( oldNum ); // waste some memory to have linear time
  int i;
  int last = oldNum - 1;

//  std::cerr << "Removing linear points... " << oldNum << std::endl;

  // insert nonlienaer points in new array
  for( i = 0; i < oldNum; ++i )
  {
    Vec2d p = globalverts[ vertices[ i ] ];
    // check for double vertices
    if( DCTPVecIsNotEqual( p , globalverts[ vertices[ last ] ] ) )
    {
      Vec2d pp = globalverts[ vertices[ last ] ];
      Vec2d pn = globalverts[ vertices[ ( i + 1 ) % oldNum ] ];

      if( ( ( p[0] - min[0] < DCTP_EPS ) && ( pn[0] - min[0] < DCTP_EPS ) ) ||
          ( ( p[1] - min[1] < DCTP_EPS ) && ( pn[1] - min[1] < DCTP_EPS ) ) ||
          ( ( max[0] - p[0] < DCTP_EPS ) && ( max[0] - pn[0] < DCTP_EPS ) ) ||
          ( ( max[1] - p[1] < DCTP_EPS ) && ( max[1] - pn[1] < DCTP_EPS ) ) )
      {
        newPoints[ newNum ] = vertices[ i ];
        ++newNum;
        last = i;
      }
      else
      {
        double d1[ 2 ], d2[ 2 ], d3[ 2 ];
        d1[ 0 ] = pp[0];
        d1[ 1 ] = pp[1];
        d2[ 0 ] = p[0];
        d2[ 1 ] = p[1];
        d3[ 0 ] = pn[0];
        d3[ 1 ] = pn[1];
        if( orient2d( d1, d2, d3 ) != 0 )
        {
          newPoints[ newNum ] = vertices[ i ];
          ++newNum;
          last = i;
        }
/*        else if( ( pp[1] != pn[1] ) && ( pp[0] != pn[0] ) )
        {
          std::cerr << "removing point " <<std::endl;
          std::cerr << pp[0] << "," << pp[1] << std::endl;
          std::cerr << "(" << p[0] << "," << p[1] << ")" << std::endl;
          std::cerr << pn[0] << "," << pn[1] << std::endl;
          char x[ 256 ];
          gets( x );
        }*/
      }
    }
  }

//  std::cerr << newNum << " points left." << std::endl;

  // copy new points
  if( newNum != oldNum )
  {
    vertices.resize( newNum );
    for( i = 0; i < newNum; ++i )
    {
      vertices[ i ] = newPoints[ i ];
    }
    return 1;
  }

  return 0;
}
Esempio n. 25
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. 26
0
/*!
 *  `i1' and `i2' must already be an edge of the polygon, and the third point `i3'
 *  be a point of the polygon different from `i1' and `i2'. The polygon's lines
 *  must not cross each other.
 *
 *  \param globalverts global vertices vector
 *  \param i1 first point
 *  \param i2 second point (must form an edge with the first point)
 *  \param i3 third point
 *  \return 1 if not inside <BR>
 *          0 if inside <BR>
 *          and a negative value if an error happened.
 */
int SimplePolygon::isInsidePolygon( DCTPVec2dvector &globalverts, int i1, int i2, int i3 ) const
{
  double dres;
  const int size = vertices.size( );
  const int vi1 = vertices[ i1 ];
  const int vi2 = vertices[ i2 ];
  const int vi3 = vertices[ i3 ];
  const int prev = vertices[ ( size + i1 - 1 ) % size ];
  const int next = vertices[ ( i2 + 1 ) % size ];

  // the third (i3) point must lie to the left of the edge (i2, next)
  // (NOT! on the edge) to be inside
  double p2[ 2 ], p3[ 2 ], pn[ 2 ];
  p3 [ 0 ] = globalverts[ vi3 ][0];
  p3 [ 1 ] = globalverts[ vi3 ][1];
  p2 [ 0 ] = globalverts[ vi2 ][0];
  p2 [ 1 ] = globalverts[ vi2 ][1];
  pn [ 0 ] = globalverts[ next ][0];
  pn [ 1 ] = globalverts[ next ][1];

  if( vi3 != next )
  {
	  dres = orient2d( p3, p2, pn );
//	  std::cerr << "next edge test: " << dres << std::endl;

	  if ( dres < 0.0 ) return 1;
  }

  // the third (i3) point must also lie to the left of the edge (prev, i1)
  // (NOT! on the edge) to be inside
  double p1[ 2 ], pp[ 2 ];
  pp [ 0 ] = globalverts[ prev ][0];
  pp [ 1 ] = globalverts[ prev ][1];
  p1 [ 0 ] = globalverts[ vi1 ][0];
  p1 [ 1 ] = globalverts[ vi1 ][1];

  if( vi3 != prev )
  {
	  dres = orient2d( p3, pp, p1 );
//	  std::cerr << "prev edge test: " << dres << std::endl;

	  if ( dres < 0.0 ) return 1;
  }

  // the third (i3) point must also lie to the left of the edge (i1, i2)
  // (NOT! on the edge) to be inside

  dres = orient2d( p3, p1, p2 );
//  std::cerr << "actual edge test: " << dres << std::endl;

  if ( dres <= 0.0 ) return 1;

//  if( m_bConvex ) return 0;	// don't need intersection test for convex polygons

  // the triangle is not completely outside the polygon, we have to
  // go for the intersection test.
  // FIXME/TODO: use bounding boxes to speed up testing:
  // only test with those edges that are at least partially in the
  // bounding box of the triangle to be tested

  int res;
  int j = size - 1;
  Vec2d min, max;
  unsigned char test, ptest;

  min = max = globalverts[ vi1 ];
  if( min[0] > globalverts[ vi2 ][0] )
    min[0] = globalverts[ vi2 ][0];
  else if( max[0] < globalverts[ vi2 ][0] )
    max[0] = globalverts[ vi2 ][0];
  if( min[1] > globalverts[ vi2 ][1] )
    min[1] = globalverts[ vi2 ][1];
  else if( max[1] < globalverts[ vi2 ][1] )
    max[1] = globalverts[ vi2 ][1];
  if( min[0] > globalverts[ vi3 ][0] )
    min[0] = globalverts[ vi3 ][0];
  else if( max[0] < globalverts[ vi3 ][0] )
    max[0] = globalverts[ vi3 ][0];
  if( min[1] > globalverts[ vi3 ][1] )
    min[1] = globalverts[ vi3 ][1];
  else if( max[1] < globalverts[ vi3 ][1] )
    max[1] = globalverts[ vi3 ][1];

  const Vec2d &pj = globalverts[ vertices[ j ] ];
  test = 0;
  if( pj[0] - max[0] > DCTP_EPS ) test |= 0x01;
  if( min[0] - pj[0] > DCTP_EPS ) test |= 0x02;
  if( pj[1] - max[1] > DCTP_EPS ) test |= 0x04;
  if( min[1] - pj[1] > DCTP_EPS ) test |= 0x08;

  for ( int i = 0; i < size; i++ )
  {
    ptest = test;
    test = 0;
    const Vec2d &pi = globalverts[ vertices[ i ] ];
    if( pi[0] - max[0] > DCTP_EPS ) test |= 0x01;
    if( min[0] - pi[0] > DCTP_EPS ) test |= 0x02;
    if( pi[1] - max[1] > DCTP_EPS ) test |= 0x04;
    if( min[1] - pi[1] > DCTP_EPS ) test |= 0x08;
    if( ( test & ptest ) == 0 )
    {
//      std::cerr << "checking: " << v1 << " " << v3 << " and i: " << i << std::endl;
      res = doIntersect( globalverts, i1, i3, j, i );
      if ( res ) return res; // either intersection or error
      res = doIntersect( globalverts, i2, i3, j, i );
      if ( res ) return res; // see above
    }
    j = i;
  }

  return 0;
}
Esempio n. 27
0
void
CalcPixels2(double Edges[3][2], int **Pixels, int *counter)
{
    int i;
    double minX=10000000,maxX=-10000000,minY=100000000,maxY=-100000000;
    for (i=0;i<3;i++){
        Edges[i][0] = round(Edges[i][0]);
        Edges[i][1] = round(Edges[i][1]);
    }
    for (i=0;i<3;i++){
        if (Edges[i][0]<minX){
            minX = Edges[i][0];
        }
        if (Edges[i][0]>maxX){
            maxX = Edges[i][0];
        }
        if (Edges[i][1]<minY){
            minY = Edges[i][1];
        }
        if (Edges[i][1]>maxY){
            maxY = Edges[i][1];
        }
    }
    *counter = 0;
    int A01 = Edges[0][1] - Edges[1][1], B01 = Edges[1][0] - Edges[0][0];
    int A12 = Edges[1][1] - Edges[2][1], B12 = Edges[2][0] - Edges[1][0];
    int A20 = Edges[2][1] - Edges[0][1], B20 = Edges[0][0] - Edges[2][0];
    struct Point2D p = { minX, minY };
    struct Point2D v0 = { Edges[0][0], Edges[0][1]};
    struct Point2D v1 = { Edges[1][0], Edges[1][1]};
    struct Point2D v2 = { Edges[2][0], Edges[2][1]};
    int w0_row = orient2d(v1, v2, p);
    int w1_row = orient2d(v2, v0, p);
    int w2_row = orient2d(v0, v1, p);
    for (p.y = minY; p.y <= maxY; p.y++) {
        int w0 = w0_row;
        int w1 = w1_row;
        int w2 = w2_row;
        for (p.x = minX; p.x <= maxX; p.x++) {
            if (w0 >= 0 && w1 >= 0 && w2 >= 0){
                Pixels[*counter][0] = p.x;
                Pixels[*counter][1] = p.y;
                *counter+=1;
            }
            else if(len2d(v1,v2,p)<0.99){
                Pixels[*counter][0] = p.x;
                Pixels[*counter][1] = p.y;
                *counter+=1;
            }
            else if(len2d(v2,v0,p)<0.99){
                Pixels[*counter][0] = p.x;
                Pixels[*counter][1] = p.y;
                *counter+=1;
            }
            else if(len2d(v0,v1,p)<0.99){
                Pixels[*counter][0] = p.x;
                Pixels[*counter][1] = p.y;
                *counter+=1;
            }
            w0 += A12;
            w1 += A20;
            w2 += A01;
        }
        w0_row += B12;
        w1_row += B20;
        w2_row += B01;
    }
}
Esempio n. 28
0
Orient PredWrapper::doOrient3DSoSOnly
(
const RealType* p0,
const RealType* p1,
const RealType* p2,
const RealType* p3,
int v0,
int v1,
int v2,
int v3
) const
{
    ////
    // Sort points using vertex as key, also note their sorted order
    ////

    const int DIM    = 3;
    const int NUM    = DIM + 1;
    const RealType* p[NUM] = { p0, p1, p2, p3 };
    int v[NUM]       = { v0, v1, v2, v3 };
    int pn           = 1;

    for ( int i = 0; i < 3; ++i )
    {
        int minI = i; 

        for ( int j = i + 1; j < 4; ++j ) 
            if ( v[j] < v[minI] )
                minI = j; 

        if ( minI != i )
        {
            int tempI = v[minI]; 
            v[minI]   = v[i]; 
            v[i]      = tempI; 
            pn        = -pn;

            //cuSwap( p[minI], p[i] );
            std::swap( p[minI], p[i] );
        }
    }

    RealType result = 0;
    RealType pa2[2], pb2[2], pc2[2];
    int depth;

	for ( depth = 0; depth < 14; ++depth )
	{
		switch ( depth )
		{
		case 0:
			pa2[0] = p[1][0];
			pa2[1] = p[1][1];
			pb2[0] = p[2][0];
			pb2[1] = p[2][1];
			pc2[0] = p[3][0];
			pc2[1] = p[3][1];
			break;
		case 1:
			pa2[0] = p[1][0];
			pa2[1] = p[1][2];
			pb2[0] = p[2][0];
			pb2[1] = p[2][2];
			pc2[0] = p[3][0];
			pc2[1] = p[3][2];
			break;
		case 2:
			pa2[0] = p[1][1];
			pa2[1] = p[1][2];
			pb2[0] = p[2][1];
			pb2[1] = p[2][2];
			pc2[0] = p[3][1];
			pc2[1] = p[3][2];
			break;
		case 3:
			pa2[0] = p[0][0];
			pa2[1] = p[0][1];
			pb2[0] = p[2][0];
			pb2[1] = p[2][1];
			pc2[0] = p[3][0];
			pc2[1] = p[3][1];
			break;
		case 4:
			result = p[2][0] - p[3][0];
			break;
		case 5:
			result = p[2][1] - p[3][1];
			break;
		case 6:
			pa2[0] = p[0][0];
			pa2[1] = p[0][2];
			pb2[0] = p[2][0];
			pb2[1] = p[2][2];
			pc2[0] = p[3][0];
			pc2[1] = p[3][2];
			break;
		case 7:
			result = p[2][2] - p[3][2];
			break;
		case 8:
			pa2[0] = p[0][1];
			pa2[1] = p[0][2];
			pb2[0] = p[2][1];
			pb2[1] = p[2][2];
			pc2[0] = p[3][1];
			pc2[1] = p[3][2];
			break;
		case 9:
			pa2[0] = p[0][0];
			pa2[1] = p[0][1];
			pb2[0] = p[1][0];
			pb2[1] = p[1][1];
			pc2[0] = p[3][0];
			pc2[1] = p[3][1];
			break;
		case 10:
			result = p[1][0] - p[3][0];
			break;
		case 11:
			result = p[1][1] - p[3][1];
			break;
		case 12:
			result = p[0][0] - p[3][0];
			break;
        default:
			result = 1.0;
			break;
		}

        switch ( depth )
        {
        case 0:
        case 1:
        case 2:
        case 3:
        case 6:
        case 8:
        case 9:
            result = orient2d( pa2, pb2, pc2 );
        }
			
		if ( result != 0 )
			break;
	}

    switch ( depth )
    {
    case 1:
    case 3:
    case 5:
    case 8:
    case 10:
        result = -result;
    }

	const RealType det = result * pn;

    return ortToOrient( det );
}