// 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); } }
public static com.epl.geometry.QuadTree BuildQuadTree(com.epl.geometry.MultiPath multipath) { com.epl.geometry.Envelope2D extent = new com.epl.geometry.Envelope2D(); multipath.QueryEnvelope2D(extent); com.epl.geometry.QuadTree quadTree = new com.epl.geometry.QuadTree(extent, 8); int hint_index = -1; com.epl.geometry.SegmentIterator seg_iter = multipath.QuerySegmentIterator(); while (seg_iter.NextPath()) { while (seg_iter.HasNextSegment()) { com.epl.geometry.Segment segment = seg_iter.NextSegment(); int index = seg_iter.GetStartPointIndex(); com.epl.geometry.Envelope2D boundingbox = new com.epl.geometry.Envelope2D(); segment.QueryEnvelope2D(boundingbox); hint_index = quadTree.Insert(index, boundingbox, hint_index); } } return(quadTree); }
internal virtual bool RgHelper(com.epl.geometry.RasterizedGeometry2D rg, com.epl.geometry.MultiPath mp) { com.epl.geometry.SegmentIterator iter = mp.QuerySegmentIterator(); while (iter.NextPath()) { while (iter.HasNextSegment()) { com.epl.geometry.Segment seg = iter.NextSegment(); int count = 20; for (int i = 0; i < count; i++) { double t = (1.0 * i / count); com.epl.geometry.Point2D pt = seg.GetCoord2D(t); com.epl.geometry.RasterizedGeometry2D.HitType hit = rg.QueryPointInGeometry(pt.x, pt.y); if (hit != com.epl.geometry.RasterizedGeometry2D.HitType.Border) { return(false); } } } } if (mp.GetType() != com.epl.geometry.Geometry.Type.Polygon) { return(true); } com.epl.geometry.Polygon poly = (com.epl.geometry.Polygon)mp; com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); poly.QueryEnvelope2D(env); int count_1 = 100; for (int iy = 0; iy < count_1; iy++) { double ty = 1.0 * iy / count_1; double y = env.ymin * (1.0 - ty) + ty * env.ymax; for (int ix = 0; ix < count_1; ix++) { double tx = 1.0 * ix / count_1; double x = env.xmin * (1.0 - tx) + tx * env.xmax; com.epl.geometry.RasterizedGeometry2D.HitType hit = rg.QueryPointInGeometry(x, y); com.epl.geometry.PolygonUtils.PiPResult res = com.epl.geometry.PolygonUtils.IsPointInPolygon2D(poly, new com.epl.geometry.Point2D(x, y), 0); if (res == com.epl.geometry.PolygonUtils.PiPResult.PiPInside) { bool bgood = (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Border || hit == com.epl.geometry.RasterizedGeometry2D.HitType.Inside); if (!bgood) { return(false); } } else { if (res == com.epl.geometry.PolygonUtils.PiPResult.PiPOutside) { bool bgood = (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Border || hit == com.epl.geometry.RasterizedGeometry2D.HitType.Outside); if (!bgood) { return(false); } } else { bool bgood = (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Border); if (!bgood) { return(false); } } } } } return(true); }
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); }
private double BruteForceMultiPathMultiPoint_(com.epl.geometry.MultiPath geometryA, com.epl.geometry.MultiPoint geometryB, bool geometriesAreDisjoint) { /* const */ /* const */ com.epl.geometry.SegmentIterator segIterA = geometryA.QuerySegmentIterator(); com.epl.geometry.Envelope2D env2DSegmentA = new com.epl.geometry.Envelope2D(); double minSqrDistance = com.epl.geometry.NumberUtils.DoubleMax(); com.epl.geometry.Point2D inputPoint = new com.epl.geometry.Point2D(); double t = -1; double sqrDistance = minSqrDistance; /* const */ com.epl.geometry.MultiPointImpl multiPointImplB = (com.epl.geometry.MultiPointImpl)geometryB._getImpl(); int pointCountB = multiPointImplB.GetPointCount(); bool bDoPiPTest = !geometriesAreDisjoint && (geometryA.GetType() == com.epl.geometry.Geometry.Type.Polygon); while (segIterA.NextPath()) { while (segIterA.HasNextSegment()) { /* const */ com.epl.geometry.Segment segmentA = segIterA.NextSegment(); segmentA.QueryEnvelope2D(env2DSegmentA); // if multipointB has only 1 vertex then it is faster to not // test for // env2DSegmentA.distance(env2DgeometryB) if (pointCountB > 1 && env2DSegmentA.SqrDistance(this.m_env2DgeometryB) > minSqrDistance) { continue; } for (int i = 0; i < pointCountB; i++) { multiPointImplB.GetXY(i, inputPoint); if (bDoPiPTest) { // Test for polygon containment. This takes the // place of a more general intersection test at the // beginning of the operator if (com.epl.geometry.PolygonUtils.IsPointInPolygon2D((com.epl.geometry.Polygon)geometryA, inputPoint, 0) != com.epl.geometry.PolygonUtils.PiPResult.PiPOutside) { return(0.0); } } t = segmentA.GetClosestCoordinate(inputPoint, false); inputPoint.Sub(segmentA.GetCoord2D(t)); sqrDistance = inputPoint.SqrLength(); if (sqrDistance < minSqrDistance) { if (sqrDistance == 0.0) { return(0.0); } minSqrDistance = sqrDistance; } } // No need to do point-in-polygon anymore (if it is a // polygon vs polyline) bDoPiPTest = false; } } return(System.Math.Sqrt(minSqrDistance)); }
private double BruteForceMultiPathMultiPath_(com.epl.geometry.MultiPath geometryA, com.epl.geometry.MultiPath geometryB, bool geometriesAreDisjoint) { /* const */ /* const */ // It may be beneficial to have the geometry with less vertices // always be geometryA. com.epl.geometry.SegmentIterator segIterA = geometryA.QuerySegmentIterator(); com.epl.geometry.SegmentIterator segIterB = geometryB.QuerySegmentIterator(); com.epl.geometry.Envelope2D env2DSegmentA = new com.epl.geometry.Envelope2D(); com.epl.geometry.Envelope2D env2DSegmentB = new com.epl.geometry.Envelope2D(); double minSqrDistance = com.epl.geometry.NumberUtils.DoubleMax(); if (!geometriesAreDisjoint) { // Geometries might be non-disjoint. Check if they intersect // using point-in-polygon tests if (this.WeakIntersectionTest_(geometryA, geometryB, segIterA, segIterB)) { return(0.0); } } // if geometries are known disjoint, don't bother to do any tests // for polygon containment // nested while-loop insanity while (segIterA.NextPath()) { while (segIterA.HasNextSegment()) { /* const */ com.epl.geometry.Segment segmentA = segIterA.NextSegment(); segmentA.QueryEnvelope2D(env2DSegmentA); if (env2DSegmentA.SqrDistance(this.m_env2DgeometryB) > minSqrDistance) { continue; } while (segIterB.NextPath()) { while (segIterB.HasNextSegment()) { /* const */ com.epl.geometry.Segment segmentB = segIterB.NextSegment(); segmentB.QueryEnvelope2D(env2DSegmentB); if (env2DSegmentA.SqrDistance(env2DSegmentB) < minSqrDistance) { // get distance between segments double sqrDistance = segmentA.Distance(segmentB, geometriesAreDisjoint); sqrDistance *= sqrDistance; if (sqrDistance < minSqrDistance) { if (sqrDistance == 0.0) { return(0.0); } minSqrDistance = sqrDistance; } } } } segIterB.ResetToFirstPath(); } } return(System.Math.Sqrt(minSqrDistance)); }
private com.epl.geometry.Geometry DensifyMultiPath(com.epl.geometry.MultiPath geom) { com.epl.geometry.MultiPath densifiedPoly = (com.epl.geometry.MultiPath)geom.CreateInstance(); com.epl.geometry.SegmentIterator iter = geom.QuerySegmentIterator(); while (iter.NextPath()) { bool bStartNewPath = true; while (iter.HasNextSegment()) { com.epl.geometry.Segment seg = iter.NextSegment(); if (seg.GetType().Value() != com.epl.geometry.Geometry.GeometryType.Line) { throw new com.epl.geometry.GeometryException("not implemented"); } bool bIsClosing = iter.IsClosingSegment(); double len = seg.CalculateLength2D(); if (len > m_maxLength) { // need to split double dcount = System.Math.Ceiling(len / m_maxLength); com.epl.geometry.Point point = new com.epl.geometry.Point(geom.GetDescription()); // LOCALREFCLASS1(Point, // VertexDescription, // point, // geom.getDescription()); if (bStartNewPath) { bStartNewPath = false; seg.QueryStart(point); densifiedPoly.StartPath(point); } double dt = 1.0 / dcount; double t = dt; for (int i = 0, n = (int)dcount - 1; i < n; i++) { seg.QueryCoord(t, point); densifiedPoly.LineTo(point); t += dt; } if (!bIsClosing) { seg.QueryEnd(point); densifiedPoly.LineTo(point); } else { densifiedPoly.ClosePathWithLine(); } bStartNewPath = false; } else { if (!bIsClosing) { densifiedPoly.AddSegment(seg, bStartNewPath); } else { densifiedPoly.ClosePathWithLine(); } bStartNewPath = false; } } } return((com.epl.geometry.Geometry)densifiedPoly); }