/// <summary>Calculates the orientation of the triangle formed by p->q->r.</summary> /// <remarks> /// Calculates the orientation of the triangle formed by p->q->r. Returns 1 /// for counter-clockwise, -1 for clockwise, and 0 for collinear. May use /// high precision arithmetics for some special degenerate cases. /// </remarks> public static int OrientationRobust(com.epl.geometry.Point2D p, com.epl.geometry.Point2D q, com.epl.geometry.Point2D r) { com.epl.geometry.ECoordinate det_ec = new com.epl.geometry.ECoordinate(); det_ec.Set(q.x); det_ec.Sub(p.x); com.epl.geometry.ECoordinate rp_y_ec = new com.epl.geometry.ECoordinate(); rp_y_ec.Set(r.y); rp_y_ec.Sub(p.y); com.epl.geometry.ECoordinate qp_y_ec = new com.epl.geometry.ECoordinate(); qp_y_ec.Set(q.y); qp_y_ec.Sub(p.y); com.epl.geometry.ECoordinate rp_x_ec = new com.epl.geometry.ECoordinate(); rp_x_ec.Set(r.x); rp_x_ec.Sub(p.x); det_ec.Mul(rp_y_ec); qp_y_ec.Mul(rp_x_ec); det_ec.Sub(qp_y_ec); if (!det_ec.IsFuzzyZero()) { double det_ec_value = det_ec.Value(); if (det_ec_value < 0.0) { return(-1); } if (det_ec_value > 0.0) { return(1); } return(0); } // Need extended precision decimal det_mp = new decimal(q.x); decimal px_mp = new decimal(p.x); decimal py_mp = new decimal(p.y); det_mp = decimal.Subtract(det_mp, px_mp); decimal rp_y_mp = new decimal(r.y); rp_y_mp = decimal.Subtract(rp_y_mp, py_mp); decimal qp_y_mp = new decimal(q.y); qp_y_mp = decimal.Subtract(qp_y_mp, py_mp); decimal rp_x_mp = new decimal(r.x); rp_x_mp = decimal.Subtract(rp_x_mp, px_mp); det_mp = decimal.Multiply(det_mp, rp_y_mp); qp_y_mp = decimal.Multiply(qp_y_mp, rp_x_mp); det_mp = decimal.Subtract(det_mp, qp_y_mp); return(System.Math.Sign(det_mp)); }
// Orientation predicates private static com.epl.geometry.ECoordinate Determinant_(com.epl.geometry.Point2D p, com.epl.geometry.Point2D q, com.epl.geometry.Point2D r) { com.epl.geometry.ECoordinate det_ec = new com.epl.geometry.ECoordinate(); det_ec.Set(q.x); det_ec.Sub(p.x); com.epl.geometry.ECoordinate rp_y_ec = new com.epl.geometry.ECoordinate(); rp_y_ec.Set(r.y); rp_y_ec.Sub(p.y); com.epl.geometry.ECoordinate qp_y_ec = new com.epl.geometry.ECoordinate(); qp_y_ec.Set(q.y); qp_y_ec.Sub(p.y); com.epl.geometry.ECoordinate rp_x_ec = new com.epl.geometry.ECoordinate(); rp_x_ec.Set(r.x); rp_x_ec.Sub(p.x); det_ec.Mul(rp_y_ec); qp_y_ec.Mul(rp_x_ec); det_ec.Sub(qp_y_ec); return(det_ec); }
/// <summary>Calculates if the point s is inside of the circumcircle inscribed by the clockwise oriented triangle p-q-r.</summary> /// <remarks> /// Calculates if the point s is inside of the circumcircle inscribed by the clockwise oriented triangle p-q-r. /// Returns 1 for outside, -1 for inside, and 0 for cocircular. /// Note that the convention used here differs from what is commonly found in literature, which can define the relation /// in terms of a counter-clockwise oriented circle, and this flips the sign (think of the signed volume of the tetrahedron). /// May use high precision arithmetics for some special cases. /// </remarks> internal static int InCircleRobust(com.epl.geometry.Point2D p, com.epl.geometry.Point2D q, com.epl.geometry.Point2D r, com.epl.geometry.Point2D s) { com.epl.geometry.ECoordinate psx_ec = new com.epl.geometry.ECoordinate(); com.epl.geometry.ECoordinate psy_ec = new com.epl.geometry.ECoordinate(); psx_ec.Set(p.x); psx_ec.Sub(s.x); psy_ec.Set(p.y); psy_ec.Sub(s.y); com.epl.geometry.ECoordinate qsx_ec = new com.epl.geometry.ECoordinate(); com.epl.geometry.ECoordinate qsy_ec = new com.epl.geometry.ECoordinate(); qsx_ec.Set(q.x); qsx_ec.Sub(s.x); qsy_ec.Set(q.y); qsy_ec.Sub(s.y); com.epl.geometry.ECoordinate rsx_ec = new com.epl.geometry.ECoordinate(); com.epl.geometry.ECoordinate rsy_ec = new com.epl.geometry.ECoordinate(); rsx_ec.Set(r.x); rsx_ec.Sub(s.x); rsy_ec.Set(r.y); rsy_ec.Sub(s.y); com.epl.geometry.ECoordinate psx_ec_qsy_ec = new com.epl.geometry.ECoordinate(); psx_ec_qsy_ec.Set(psx_ec); psx_ec_qsy_ec.Mul(qsy_ec); com.epl.geometry.ECoordinate psy_ec_qsx_ec = new com.epl.geometry.ECoordinate(); psy_ec_qsx_ec.Set(psy_ec); psy_ec_qsx_ec.Mul(qsx_ec); com.epl.geometry.ECoordinate qsx_ec_rsy_ec = new com.epl.geometry.ECoordinate(); qsx_ec_rsy_ec.Set(qsx_ec); qsx_ec_rsy_ec.Mul(rsy_ec); com.epl.geometry.ECoordinate qsy_ec_rsx_ec = new com.epl.geometry.ECoordinate(); qsy_ec_rsx_ec.Set(qsy_ec); qsy_ec_rsx_ec.Mul(rsx_ec); com.epl.geometry.ECoordinate psx_ec_rsy_ec = new com.epl.geometry.ECoordinate(); psx_ec_rsy_ec.Set(psx_ec); psx_ec_rsy_ec.Mul(rsy_ec); com.epl.geometry.ECoordinate psy_ec_rsx_ec = new com.epl.geometry.ECoordinate(); psy_ec_rsx_ec.Set(psy_ec); psy_ec_rsx_ec.Mul(rsx_ec); com.epl.geometry.ECoordinate pq_det_ec = new com.epl.geometry.ECoordinate(); pq_det_ec.Set(psx_ec_qsy_ec); pq_det_ec.Sub(psy_ec_qsx_ec); com.epl.geometry.ECoordinate qr_det_ec = new com.epl.geometry.ECoordinate(); qr_det_ec.Set(qsx_ec_rsy_ec); qr_det_ec.Sub(qsy_ec_rsx_ec); com.epl.geometry.ECoordinate pr_det_ec = new com.epl.geometry.ECoordinate(); pr_det_ec.Set(psx_ec_rsy_ec); pr_det_ec.Sub(psy_ec_rsx_ec); com.epl.geometry.ECoordinate psx_ec_psx_ec = new com.epl.geometry.ECoordinate(); psx_ec_psx_ec.Set(psx_ec); psx_ec_psx_ec.Mul(psx_ec); com.epl.geometry.ECoordinate psy_ec_psy_ec = new com.epl.geometry.ECoordinate(); psy_ec_psy_ec.Set(psy_ec); psy_ec_psy_ec.Mul(psy_ec); com.epl.geometry.ECoordinate qsx_ec_qsx_ec = new com.epl.geometry.ECoordinate(); qsx_ec_qsx_ec.Set(qsx_ec); qsx_ec_qsx_ec.Mul(qsx_ec); com.epl.geometry.ECoordinate qsy_ec_qsy_ec = new com.epl.geometry.ECoordinate(); qsy_ec_qsy_ec.Set(qsy_ec); qsy_ec_qsy_ec.Mul(qsy_ec); com.epl.geometry.ECoordinate rsx_ec_rsx_ec = new com.epl.geometry.ECoordinate(); rsx_ec_rsx_ec.Set(rsx_ec); rsx_ec_rsx_ec.Mul(rsx_ec); com.epl.geometry.ECoordinate rsy_ec_rsy_ec = new com.epl.geometry.ECoordinate(); rsy_ec_rsy_ec.Set(rsy_ec); rsy_ec_rsy_ec.Mul(rsy_ec); com.epl.geometry.ECoordinate p_parab_ec = new com.epl.geometry.ECoordinate(); p_parab_ec.Set(psx_ec_psx_ec); p_parab_ec.Add(psy_ec_psy_ec); com.epl.geometry.ECoordinate q_parab_ec = new com.epl.geometry.ECoordinate(); q_parab_ec.Set(qsx_ec_qsx_ec); q_parab_ec.Add(qsy_ec_qsy_ec); com.epl.geometry.ECoordinate r_parab_ec = new com.epl.geometry.ECoordinate(); r_parab_ec.Set(rsx_ec_rsx_ec); r_parab_ec.Add(rsy_ec_rsy_ec); p_parab_ec.Mul(qr_det_ec); q_parab_ec.Mul(pr_det_ec); r_parab_ec.Mul(pq_det_ec); com.epl.geometry.ECoordinate det_ec = new com.epl.geometry.ECoordinate(); det_ec.Set(p_parab_ec); det_ec.Sub(q_parab_ec); det_ec.Add(r_parab_ec); if (!det_ec.IsFuzzyZero()) { double det_ec_value = det_ec.Value(); if (det_ec_value < 0.0) { return(-1); } if (det_ec_value > 0.0) { return(1); } return(0); } return(InCircleRobustMP_(p, q, r, s)); }