// Try to find two segements that are not degenerate internal virtual bool Calc_side(com.epl.geometry.Point2D inputPoint, bool bRight, com.epl.geometry.MultiPath multipath, int vertexIndex, int pathIndex) { com.epl.geometry.SegmentIterator segIter = multipath.QuerySegmentIterator(); this.Find_analysis_pair_from_index(inputPoint, segIter, vertexIndex, pathIndex); if (this.m_i1 != -1 && this.m_i2 == -1) { // could not find a pair of segments return(this.m_bRight1); } if (this.m_i1 != -1 && this.m_i2 != -1) { if (this.m_bRight1 == this.m_bRight2) { return(this.m_bRight1); } else { // no conflicting result for the side // the conflicting result, that we are trying to resolve, // happens in the obtuse (outer) side of the turn only. segIter.ResetToVertex(this.m_i1, -1); com.epl.geometry.Segment segment1 = segIter.NextSegment(); com.epl.geometry.Point2D tang1 = segment1._getTangent(1.0); segIter.ResetToVertex(this.m_i2, -1); com.epl.geometry.Segment segment2 = segIter.NextSegment(); com.epl.geometry.Point2D tang2 = segment2._getTangent(0.0); double cross = tang1.CrossProduct(tang2); if (cross >= 0) { // the obtuse angle is on the right side return(true); } else { // the obtuse angle is on the right side return(false); } } } else { System.Diagnostics.Debug.Assert((this.m_i1 == -1 && this.m_i2 == -1)); return(bRight); } }
internal virtual int Find_prev_non_degenerate(com.epl.geometry.SegmentIterator segIter, int index) { segIter.ResetToVertex(index, -1); while (segIter.HasPreviousSegment()) { com.epl.geometry.Segment segment = segIter.PreviousSegment(); double length = segment.CalculateLength2D(); if (length != 0) { return(segIter.GetStartPointIndex()); } } return(-1); }
internal virtual void Find_analysis_pair_from_index(com.epl.geometry.Point2D inputPoint, com.epl.geometry.SegmentIterator segIter, int vertexIndex, int pathIndex) { this.m_i1 = this.Find_non_degenerate(segIter, vertexIndex, pathIndex); if (this.m_i1 != -1) { segIter.ResetToVertex(this.m_i1, -1); com.epl.geometry.Segment segment1 = segIter.NextSegment(); double t1 = segment1.GetClosestCoordinate(inputPoint, false); com.epl.geometry.Point2D p1 = segment1.GetCoord2D(t1); double d1 = com.epl.geometry.Point2D.SqrDistance(p1, inputPoint); com.epl.geometry.Point2D pq = new com.epl.geometry.Point2D(); pq.SetCoords(p1); pq.Sub(segment1.GetStartXY()); com.epl.geometry.Point2D pr = new com.epl.geometry.Point2D(); pr.SetCoords(inputPoint); pr.Sub(segment1.GetStartXY()); this.m_bRight1 = (pq.CrossProduct(pr) < 0); this.m_i2 = this.Find_next_non_degenerate(segIter, this.m_i1); if (this.m_i2 != -1) { segIter.ResetToVertex(this.m_i2, -1); com.epl.geometry.Segment segment2 = segIter.NextSegment(); double t2 = segment2.GetClosestCoordinate(inputPoint, false); com.epl.geometry.Point2D p2 = segment2.GetCoord2D(t2); double d2 = com.epl.geometry.Point2D.SqrDistance(p2, inputPoint); if (d2 > d1) { this.m_i2 = -1; } else { pq.SetCoords(p2); pq.Sub(segment2.GetStartXY()); pr.SetCoords(inputPoint); pr.Sub(segment2.GetStartXY()); this.m_bRight2 = (pq.CrossProduct(pr) < 0); } } if (this.m_i2 == -1) { this.m_i2 = this.Find_prev_non_degenerate(segIter, this.m_i1); if (this.m_i2 != -1) { segIter.ResetToVertex(this.m_i2, -1); com.epl.geometry.Segment segment2 = segIter.NextSegment(); double t2 = segment2.GetClosestCoordinate(inputPoint, false); com.epl.geometry.Point2D p2 = segment2.GetCoord2D(t2); double d2 = com.epl.geometry.Point2D.SqrDistance(p2, inputPoint); if (d2 > d1) { this.m_i2 = -1; } else { pq.SetCoords(p2); pq.Sub(segment2.GetStartXY()); pr.SetCoords(inputPoint); pr.Sub(segment2.GetStartXY()); this.m_bRight2 = (pq.CrossProduct(pr) < 0); int itemp = this.m_i1; this.m_i1 = this.m_i2; this.m_i2 = itemp; bool btemp = this.m_bRight1; this.m_bRight1 = this.m_bRight2; this.m_bRight2 = btemp; } } } } }
internal virtual com.epl.geometry.Proximity2DResult MultiPathGetNearestCoordinate(com.epl.geometry.MultiPath geom, com.epl.geometry.Point2D inputPoint, bool bTestPolygonInterior, bool bCalculateLeftRightSide) { if (geom.GetType() == com.epl.geometry.Geometry.Type.Polygon && bTestPolygonInterior) { com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); geom.QueryEnvelope2D(env); double tolerance = com.epl.geometry.InternalUtils.CalculateToleranceFromGeometry(null, env, false); com.epl.geometry.PolygonUtils.PiPResult pipResult; if (bCalculateLeftRightSide) { pipResult = com.epl.geometry.PolygonUtils.IsPointInPolygon2D((com.epl.geometry.Polygon)geom, inputPoint, 0.0); } else { pipResult = com.epl.geometry.PolygonUtils.IsPointInPolygon2D((com.epl.geometry.Polygon)geom, inputPoint, tolerance); } if (pipResult != com.epl.geometry.PolygonUtils.PiPResult.PiPOutside) { com.epl.geometry.Proximity2DResult result = new com.epl.geometry.Proximity2DResult(inputPoint, 0, 0.0); if (bCalculateLeftRightSide) { result.SetRightSide(true); } return(result); } } com.epl.geometry.SegmentIterator segIter = geom.QuerySegmentIterator(); com.epl.geometry.Point2D closest = new com.epl.geometry.Point2D(); int closestVertexIndex = -1; int closestPathIndex = -1; double closestDistanceSq = com.epl.geometry.NumberUtils.DoubleMax(); bool bRight = false; int num_candidates = 0; while (segIter.NextPath()) { while (segIter.HasNextSegment()) { com.epl.geometry.Segment segment = segIter.NextSegment(); double t = segment.GetClosestCoordinate(inputPoint, false); com.epl.geometry.Point2D point = segment.GetCoord2D(t); double distanceSq = com.epl.geometry.Point2D.SqrDistance(point, inputPoint); if (distanceSq < closestDistanceSq) { num_candidates = 1; closest = point; closestVertexIndex = segIter.GetStartPointIndex(); closestPathIndex = segIter.GetPathIndex(); closestDistanceSq = distanceSq; } else { if (distanceSq == closestDistanceSq) { num_candidates++; } } } } com.epl.geometry.Proximity2DResult result_1 = new com.epl.geometry.Proximity2DResult(closest, closestVertexIndex, System.Math.Sqrt(closestDistanceSq)); if (bCalculateLeftRightSide) { segIter.ResetToVertex(closestVertexIndex, closestPathIndex); com.epl.geometry.Segment segment = segIter.NextSegment(); bRight = (com.epl.geometry.Point2D.OrientationRobust(inputPoint, segment.GetStartXY(), segment.GetEndXY()) < 0); if (num_candidates > 1) { com.epl.geometry.OperatorProximity2DLocal.Side_helper sideHelper = new com.epl.geometry.OperatorProximity2DLocal.Side_helper(this); sideHelper.Reset(); bRight = sideHelper.Calc_side(inputPoint, bRight, geom, closestVertexIndex, closestPathIndex); } result_1.SetRightSide(bRight); } return(result_1); }