/// <summary> /// Forumla to calculate signed area /// <list type="bullet"> /// <item>Positive if CCW</item> /// <item>Negative if CW</item> /// <item>0 if collinear</item> /// </list> /// <code> /// A[P1,P2,P3] = (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1) /// = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3) /// </code> /// </summary> public static Orientation orient2d(TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc) { double detleft = (pa.getX() - pc.getX()) * (pb.getY() - pc.getY()); double detright = (pa.getY() - pc.getY()) * (pb.getX() - pc.getX()); double val = detleft - detright; if (val > -EPSILON && val < EPSILON) { return(Orientation.Collinear); } else if (val > 0) { return(Orientation.CCW); } return(Orientation.CW); }
// Returns triangle circumcircle point and radius // public static Tuple2<TPoint, Double> circumCircle( TPoint a, TPoint b, TPoint c ) // { // double A = det( a, b, c ); // double C = detC( a, b, c ); // // double sa = a.getX() * a.getX() + a.getY() * a.getY(); // double sb = b.getX() * b.getX() + b.getY() * b.getY(); // double sc = c.getX() * c.getX() + c.getY() * c.getY(); // // TPoint bx1 = new TPoint( sa, a.getY() ); // TPoint bx2 = new TPoint( sb, b.getY() ); // TPoint bx3 = new TPoint( sc, c.getY() ); // double bx = det( bx1, bx2, bx3 ); // // TPoint by1 = new TPoint( sa, a.getX() ); // TPoint by2 = new TPoint( sb, b.getX() ); // TPoint by3 = new TPoint( sc, c.getX() ); // double by = det( by1, by2, by3 ); // // double x = bx / ( 2 * A ); // double y = by / ( 2 * A ); // // TPoint center = new TPoint( x, y ); // double radius = Math.sqrt( bx * bx + by * by - 4 * A * C ) / ( 2 * Math.abs( A ) ); // // return new Tuple2<TPoint, Double>( center, radius ); // } /// <summary> /// smartIncircle /// Requirement: /// <list type="number"> /// <item>a,b and c form a triangle.</item> /// <item>a and d is know to be on opposite side of bc</item> /// </list> /// <code> /// a /// + /// / \ /// / \ /// b/ \c /// +-------+ /// / B \ /// / \ /// </code> /// <b>Fact</b>: d has to be in area B to have a chance to be inside the circle formed by /// a,b and c<br> /// d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW<br> /// This preknowledge gives us a way to optimize the incircle test /// </summary> /// <param name="a">triangle point, opposite d</param> /// <param name="b">triangle point</param> /// <param name="c">triangle point</param> /// <param name="d">point opposite a</param> /// <return>true if d is inside circle, false if on circle edge</return> /// public static bool smartIncircle(TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc, TriangulationPoint pd) { double pdx = pd.getX(); double pdy = pd.getY(); double adx = pa.getX() - pdx; double ady = pa.getY() - pdy; double bdx = pb.getX() - pdx; double bdy = pb.getY() - pdy; double adxbdy = adx * bdy; double bdxady = bdx * ady; double oabd = adxbdy - bdxady; // oabd = orient2d(pa,pb,pd); if (oabd <= 0) { return(false); } double cdx = pc.getX() - pdx; double cdy = pc.getY() - pdy; double cdxady = cdx * ady; double adxcdy = adx * cdy; double ocad = cdxady - adxcdy; // ocad = orient2d(pc,pa,pd); if (ocad <= 0) { return(false); } double bdxcdy = bdx * cdy; double cdxbdy = cdx * bdy; double alift = adx * adx + ady * ady; double blift = bdx * bdx + bdy * bdy; double clift = cdx * cdx + cdy * cdy; double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd; return(det > 0); }
/// <summary> /// inScanArea /// </summary> /// <see cref="smartIncircle"/> /// public static bool inScanArea(TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc, TriangulationPoint pd) { double pdx = pd.getX(); double pdy = pd.getY(); double adx = pa.getX() - pdx; double ady = pa.getY() - pdy; double bdx = pb.getX() - pdx; double bdy = pb.getY() - pdy; double adxbdy = adx * bdy; double bdxady = bdx * ady; double oabd = adxbdy - bdxady; // oabd = orient2d(pa,pb,pd); if (oabd <= 0) { return(false); } double cdx = pc.getX() - pdx; double cdy = pc.getY() - pdy; double cdxady = cdx * ady; double adxcdy = adx * cdy; double ocad = cdxady - adxcdy; // ocad = orient2d(pc,pa,pd); if (ocad <= 0) { return(false); } return(true); }