private static int QuickTest2DMVEnvelopeRasterOnly(com.epl.geometry.MultiVertexGeometry geomA, com.epl.geometry.Envelope2D geomBEnv, double tolerance) { // Use rasterized Geometry only: com.epl.geometry.RasterizedGeometry2D rgeomA; com.epl.geometry.MultiVertexGeometryImpl mpImpl = (com.epl.geometry.MultiVertexGeometryImpl)geomA._getImpl(); com.epl.geometry.GeometryAccelerators gaccel = mpImpl._getAccelerators(); if (gaccel != null) { rgeomA = gaccel.GetRasterizedGeometry(); } else { return(-1); } if (rgeomA != null) { com.epl.geometry.RasterizedGeometry2D.HitType hitres = rgeomA.QueryEnvelopeInGeometry(geomBEnv); if (hitres == com.epl.geometry.RasterizedGeometry2D.HitType.Outside) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Disjoint); } if (hitres == com.epl.geometry.RasterizedGeometry2D.HitType.Inside) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Contains); } } else { return(-1); } return(0); }
internal static void TestPointsOnPolyline2D_(com.epl.geometry.Polyline poly, com.epl.geometry.Point2D[] input_points, int count, double tolerance, com.epl.geometry.PolygonUtils.PiPResult[] test_results) { com.epl.geometry.MultiPathImpl mp_impl = (com.epl.geometry.MultiPathImpl)poly._getImpl(); com.epl.geometry.GeometryAccelerators accel = mp_impl._getAccelerators(); com.epl.geometry.RasterizedGeometry2D rgeom = null; if (accel != null) { rgeom = accel.GetRasterizedGeometry(); } int pointsLeft = count; for (int i = 0; i < count; i++) { test_results[i] = com.epl.geometry.PolygonUtils.PiPResult.PiPInside; // set to impossible value if (rgeom != null) { com.epl.geometry.Point2D input_point = input_points[i]; com.epl.geometry.RasterizedGeometry2D.HitType hit = rgeom.QueryPointInGeometry(input_point.x, input_point.y); if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Outside) { test_results[i] = com.epl.geometry.PolygonUtils.PiPResult.PiPOutside; pointsLeft--; } } } if (pointsLeft != 0) { com.epl.geometry.SegmentIteratorImpl iter = mp_impl.QuerySegmentIterator(); while (iter.NextPath() && pointsLeft != 0) { while (iter.HasNextSegment() && pointsLeft != 0) { com.epl.geometry.Segment segment = iter.NextSegment(); for (int i_1 = 0; i_1 < count && pointsLeft != 0; i_1++) { if (test_results[i_1] == com.epl.geometry.PolygonUtils.PiPResult.PiPInside) { if (segment.IsIntersecting(input_points[i_1], tolerance)) { test_results[i_1] = com.epl.geometry.PolygonUtils.PiPResult.PiPBoundary; pointsLeft--; } } } } } } for (int i_2 = 0; i_2 < count; i_2++) { if (test_results[i_2] == com.epl.geometry.PolygonUtils.PiPResult.PiPInside) { test_results[i_2] = com.epl.geometry.PolygonUtils.PiPResult.PiPOutside; } } }
public static int IsPointInPolygon(com.epl.geometry.Polygon inputPolygon, com.epl.geometry.Point2D inputPoint, double tolerance) { if (inputPolygon.IsEmpty()) { return(0); } com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); inputPolygon.QueryLooseEnvelope(env); env.Inflate(tolerance, tolerance); if (!env.Contains(inputPoint)) { return(0); } com.epl.geometry.MultiPathImpl mpImpl = (com.epl.geometry.MultiPathImpl)inputPolygon._getImpl(); com.epl.geometry.GeometryAccelerators accel = mpImpl._getAccelerators(); if (accel != null) { // geometry has spatial indices built. Try using them. com.epl.geometry.RasterizedGeometry2D rgeom = accel.GetRasterizedGeometry(); if (rgeom != null) { com.epl.geometry.RasterizedGeometry2D.HitType hit = rgeom.QueryPointInGeometry(inputPoint.x, inputPoint.y); if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Inside) { return(1); } else { if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Outside) { return(0); } } } com.epl.geometry.QuadTreeImpl qtree = accel.GetQuadTree(); if (qtree != null) { return(_isPointInPolygonInternalWithQuadTree(inputPolygon, qtree, inputPoint, tolerance)); } } return(_isPointInPolygonInternal(inputPolygon, inputPoint, tolerance)); }
internal static int IsPointInPolygon(com.epl.geometry.Polygon inputPolygon, double inputPointXVal, double inputPointYVal, double tolerance) { if (inputPolygon.IsEmpty()) { return(0); } com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); inputPolygon.QueryLooseEnvelope(env); env.Inflate(tolerance, tolerance); if (!env.Contains(inputPointXVal, inputPointYVal)) { return(0); } com.epl.geometry.MultiPathImpl mpImpl = (com.epl.geometry.MultiPathImpl)inputPolygon._getImpl(); com.epl.geometry.GeometryAccelerators accel = mpImpl._getAccelerators(); if (accel != null) { com.epl.geometry.RasterizedGeometry2D rgeom = accel.GetRasterizedGeometry(); if (rgeom != null) { com.epl.geometry.RasterizedGeometry2D.HitType hit = rgeom.QueryPointInGeometry(inputPointXVal, inputPointYVal); if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Inside) { return(1); } else { if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Outside) { return(0); } } } } return(_isPointInPolygonInternal(inputPolygon, new com.epl.geometry.Point2D(inputPointXVal, inputPointYVal), tolerance)); }
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.Geometry TryFastIntersectPolylinePolygon_(com.epl.geometry.Polyline polyline, com.epl.geometry.Polygon polygon) { com.epl.geometry.MultiPathImpl polylineImpl = (com.epl.geometry.MultiPathImpl)polyline._getImpl(); com.epl.geometry.MultiPathImpl polygonImpl = (com.epl.geometry.MultiPathImpl)polygon._getImpl(); double tolerance = com.epl.geometry.InternalUtils.CalculateToleranceFromGeometry(m_spatial_reference, polygon, false); com.epl.geometry.Envelope2D clipEnvelope = new com.epl.geometry.Envelope2D(); { polygonImpl.QueryEnvelope2D(clipEnvelope); com.epl.geometry.Envelope2D env1 = new com.epl.geometry.Envelope2D(); polylineImpl.QueryEnvelope2D(env1); env1.Inflate(2.0 * tolerance, 2.0 * tolerance); clipEnvelope.Intersect(env1); System.Diagnostics.Debug.Assert((!clipEnvelope.IsEmpty())); } clipEnvelope.Inflate(10 * tolerance, 10 * tolerance); if (true) { double tol = 0; com.epl.geometry.Geometry clippedPolyline = com.epl.geometry.Clipper.Clip(polyline, clipEnvelope, tol, 0.0); polyline = (com.epl.geometry.Polyline)clippedPolyline; polylineImpl = (com.epl.geometry.MultiPathImpl)polyline._getImpl(); } com.epl.geometry.AttributeStreamOfInt32 clipResult = new com.epl.geometry.AttributeStreamOfInt32(0); int unresolvedSegments = -1; com.epl.geometry.GeometryAccelerators accel = polygonImpl._getAccelerators(); if (accel != null) { com.epl.geometry.RasterizedGeometry2D rgeom = accel.GetRasterizedGeometry(); if (rgeom != null) { unresolvedSegments = 0; clipResult.Reserve(polylineImpl.GetPointCount() + polylineImpl.GetPathCount()); com.epl.geometry.Envelope2D seg_env = new com.epl.geometry.Envelope2D(); com.epl.geometry.SegmentIteratorImpl iter = polylineImpl.QuerySegmentIterator(); while (iter.NextPath()) { while (iter.HasNextSegment()) { com.epl.geometry.Segment seg = iter.NextSegment(); seg.QueryEnvelope2D(seg_env); com.epl.geometry.RasterizedGeometry2D.HitType hit = rgeom.QueryEnvelopeInGeometry(seg_env); if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Inside) { clipResult.Add(1); } else { if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Outside) { clipResult.Add(0); } else { clipResult.Add(-1); unresolvedSegments++; } } } } } } if (polygon.GetPointCount() > 5) { double tol = 0; com.epl.geometry.Geometry clippedPolygon = com.epl.geometry.Clipper.Clip(polygon, clipEnvelope, tol, 0.0); polygon = (com.epl.geometry.Polygon)clippedPolygon; polygonImpl = (com.epl.geometry.MultiPathImpl)polygon._getImpl(); accel = polygonImpl._getAccelerators(); } //update accelerators if (unresolvedSegments < 0) { unresolvedSegments = polylineImpl.GetSegmentCount(); } // Some heuristics to decide if it makes sense to go with fast intersect // vs going with the regular planesweep. double totalPoints = (double)(polylineImpl.GetPointCount() + polygonImpl.GetPointCount()); double thisAlgorithmComplexity = ((double)unresolvedSegments * polygonImpl.GetPointCount()); // assume the worst case. double planesweepComplexity = System.Math.Log(totalPoints) * totalPoints; double empiricConstantFactorPlaneSweep = 4; if (thisAlgorithmComplexity > planesweepComplexity * empiricConstantFactorPlaneSweep) { // Based on the number of input points, we deduced that the // plansweep performance should be better than the brute force // performance. return null; } // resort to planesweep if quadtree does not help com.epl.geometry.QuadTreeImpl polygonQuadTree = null; com.epl.geometry.SegmentIteratorImpl polygonIter = polygonImpl.QuerySegmentIterator(); // Some logic to decide if it makes sense to build a quadtree on the // polygon segments if (accel != null && accel.GetQuadTree() != null) { polygonQuadTree = accel.GetQuadTree(); } if (polygonQuadTree == null && polygonImpl.GetPointCount() > 20) { polygonQuadTree = com.epl.geometry.InternalUtils.BuildQuadTree(polygonImpl); } com.epl.geometry.Polyline result_polyline = (com.epl.geometry.Polyline)polyline.CreateInstance(); com.epl.geometry.MultiPathImpl resultPolylineImpl = (com.epl.geometry.MultiPathImpl)result_polyline._getImpl(); com.epl.geometry.QuadTreeImpl.QuadTreeIteratorImpl qIter = null; com.epl.geometry.SegmentIteratorImpl polylineIter = polylineImpl.QuerySegmentIterator(); double[] @params = new double[9]; com.epl.geometry.AttributeStreamOfDbl intersections = new com.epl.geometry.AttributeStreamOfDbl(0); com.epl.geometry.SegmentBuffer segmentBuffer = new com.epl.geometry.SegmentBuffer(); int start_index = -1; int inCount = 0; int segIndex = 0; bool bOptimized = clipResult.Size() > 0; // The algorithm is like that: // Loop through all the segments of the polyline. // For each polyline segment, intersect it with each of the polygon // segments. // If no intersections found then, // If the polyline segment is completely inside, it is added to the // result polyline. // If it is outside, it is thrown out. // If it intersects, then cut the polyline segment to pieces and test // each part of the intersected result. // The cut pieces will either have one point inside, or one point // outside, or the middle point inside/outside. // int polylinePathIndex = -1; while (polylineIter.NextPath()) { polylinePathIndex = polylineIter.GetPathIndex(); int stateNewPath = 0; int stateAddSegment = 1; int stateManySegments = 2; int stateManySegmentsContinuePath = 2; int stateManySegmentsNewPath = 3; int state = stateNewPath; start_index = -1; inCount = 0; while (polylineIter.HasNextSegment()) { int clipStatus = bOptimized ? (int)clipResult.Get(segIndex) : -1; segIndex++; com.epl.geometry.Segment polylineSeg = polylineIter.NextSegment(); if (clipStatus < 0) { System.Diagnostics.Debug.Assert((clipStatus == -1)); // Analyse polyline segment for intersection with the // polygon. if (polygonQuadTree != null) { if (qIter == null) { qIter = polygonQuadTree.GetIterator(polylineSeg, tolerance); } else { qIter.ResetIterator(polylineSeg, tolerance); } int path_index = -1; for (int ind = qIter.Next(); ind != -1; ind = qIter.Next()) { polygonIter.ResetToVertex(polygonQuadTree.GetElement(ind)); // path_index path_index = polygonIter.GetPathIndex(); com.epl.geometry.Segment polygonSeg = polygonIter.NextSegment(); // intersect polylineSeg and polygonSeg. int count = polylineSeg.Intersect(polygonSeg, null, @params, null, tolerance); for (int i = 0; i < count; i++) { intersections.Add(@params[i]); } } } else { // no quadtree built polygonIter.ResetToFirstPath(); while (polygonIter.NextPath()) { while (polygonIter.HasNextSegment()) { com.epl.geometry.Segment polygonSeg = polygonIter.NextSegment(); // intersect polylineSeg and polygonSeg. int count = polylineSeg.Intersect(polygonSeg, null, @params, null, tolerance); for (int i = 0; i < count; i++) { intersections.Add(@params[i]); } } } } if (intersections.Size() > 0) { // intersections detected. intersections.Sort(0, intersections.Size()); // std::sort(intersections.begin(), // intersections.end()); double t0 = 0; intersections.Add(1.0); int status = -1; for (int i = 0, n = intersections.Size(); i < n; i++) { double t = intersections.Get(i); if (t == t0) { continue; } bool bWholeSegment = false; com.epl.geometry.Segment resSeg; if (t0 != 0 || t != 1.0) { polylineSeg.Cut(t0, t, segmentBuffer); resSeg = segmentBuffer.Get(); } else { resSeg = polylineSeg; bWholeSegment = true; } if (state >= stateManySegments) { resultPolylineImpl.AddSegmentsFromPath(polylineImpl, polylinePathIndex, start_index, inCount, state == stateManySegmentsNewPath); if (AnalyseClipSegment_(polygon, resSeg.GetStartXY(), tolerance) != 1) { if (AnalyseClipSegment_(polygon, resSeg, tolerance) != 1) { return null; } } //someting went wrong we'll falback to slower but robust planesweep code. resultPolylineImpl.AddSegment(resSeg, false); state = stateAddSegment; inCount = 0; } else { status = AnalyseClipSegment_(polygon, resSeg, tolerance); switch (status) { case 1: { if (!bWholeSegment) { resultPolylineImpl.AddSegment(resSeg, state == stateNewPath); state = stateAddSegment; } else { if (state < stateManySegments) { start_index = polylineIter.GetStartPointIndex() - polylineImpl.GetPathStart(polylinePathIndex); inCount = 1; if (state == stateNewPath) { state = stateManySegmentsNewPath; } else { System.Diagnostics.Debug.Assert((state == stateAddSegment)); state = stateManySegmentsContinuePath; } } else { inCount++; } } break; } case 0: { state = stateNewPath; start_index = -1; inCount = 0; break; } default: { return null; } } } // may happen if a segment // coincides with the border. t0 = t; } } else { clipStatus = AnalyseClipSegment_(polygon, polylineSeg.GetStartXY(), tolerance); // simple // case // no // intersection. // Both // points // must // be // inside. if (clipStatus < 0) { System.Diagnostics.Debug.Assert((clipStatus >= 0)); return null; } // something goes wrong, resort to // planesweep System.Diagnostics.Debug.Assert((AnalyseClipSegment_(polygon, polylineSeg.GetEndXY(), tolerance) == clipStatus)); if (clipStatus == 1) { // the whole segment inside if (state < stateManySegments) { System.Diagnostics.Debug.Assert((inCount == 0)); start_index = polylineIter.GetStartPointIndex() - polylineImpl.GetPathStart(polylinePathIndex); if (state == stateNewPath) { state = stateManySegmentsNewPath; } else { System.Diagnostics.Debug.Assert((state == stateAddSegment)); state = stateManySegmentsContinuePath; } } inCount++; } else { System.Diagnostics.Debug.Assert((state < stateManySegments)); start_index = -1; inCount = 0; } } intersections.Clear(false); } else { // clip status is determined by other means if (clipStatus == 0) { // outside System.Diagnostics.Debug.Assert((AnalyseClipSegment_(polygon, polylineSeg, tolerance) == 0)); System.Diagnostics.Debug.Assert((start_index < 0)); System.Diagnostics.Debug.Assert((inCount == 0)); continue; } if (clipStatus == 1) { System.Diagnostics.Debug.Assert((AnalyseClipSegment_(polygon, polylineSeg, tolerance) == 1)); if (state == stateNewPath) { state = stateManySegmentsNewPath; start_index = polylineIter.GetStartPointIndex() - polylineImpl.GetPathStart(polylinePathIndex); } else { if (state == stateAddSegment) { state = stateManySegmentsContinuePath; start_index = polylineIter.GetStartPointIndex() - polylineImpl.GetPathStart(polylinePathIndex); } else { System.Diagnostics.Debug.Assert((state >= stateManySegments)); } } inCount++; continue; } } } if (state >= stateManySegments) { resultPolylineImpl.AddSegmentsFromPath(polylineImpl, polylinePathIndex, start_index, inCount, state == stateManySegmentsNewPath); start_index = -1; } } return result_polyline; }
public static int QuickTest2D_Accelerated_DisjointOrContains(com.epl.geometry.Geometry geomA, com.epl.geometry.Geometry geomB, double tolerance) { int gtA = geomA.GetType().Value(); int gtB = geomB.GetType().Value(); com.epl.geometry.GeometryAccelerators accel; bool endWhileStatement = false; do { if (com.epl.geometry.Geometry.IsMultiVertex(gtA)) { com.epl.geometry.MultiVertexGeometryImpl impl = (com.epl.geometry.MultiVertexGeometryImpl)geomA._getImpl(); accel = impl._getAccelerators(); if (accel != null) { com.epl.geometry.RasterizedGeometry2D rgeom = accel.GetRasterizedGeometry(); if (rgeom != null) { if (gtB == com.epl.geometry.Geometry.GeometryType.Point) { com.epl.geometry.Point2D ptB = ((com.epl.geometry.Point)geomB).GetXY(); com.epl.geometry.RasterizedGeometry2D.HitType hit = rgeom.QueryPointInGeometry(ptB.x, ptB.y); if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Inside) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Contains); } else { if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Outside) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Disjoint); } } break; } com.epl.geometry.Envelope2D envB = new com.epl.geometry.Envelope2D(); geomB.QueryEnvelope2D(envB); com.epl.geometry.RasterizedGeometry2D.HitType hit_1 = rgeom.QueryEnvelopeInGeometry(envB); if (hit_1 == com.epl.geometry.RasterizedGeometry2D.HitType.Inside) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Contains); } else { if (hit_1 == com.epl.geometry.RasterizedGeometry2D.HitType.Outside) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Disjoint); } } break; } } } }while (endWhileStatement); accel = null; do { if (com.epl.geometry.Geometry.IsMultiVertex(gtB)) { com.epl.geometry.MultiVertexGeometryImpl impl = (com.epl.geometry.MultiVertexGeometryImpl)geomB._getImpl(); accel = impl._getAccelerators(); if (accel != null) { com.epl.geometry.RasterizedGeometry2D rgeom = accel.GetRasterizedGeometry(); if (rgeom != null) { if (gtA == com.epl.geometry.Geometry.GeometryType.Point) { com.epl.geometry.Point2D ptA = ((com.epl.geometry.Point)geomA).GetXY(); com.epl.geometry.RasterizedGeometry2D.HitType hit = rgeom.QueryPointInGeometry(ptA.x, ptA.y); if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Inside) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Within); } else { if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Outside) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Disjoint); } } break; } com.epl.geometry.Envelope2D envA = new com.epl.geometry.Envelope2D(); geomA.QueryEnvelope2D(envA); com.epl.geometry.RasterizedGeometry2D.HitType hit_1 = rgeom.QueryEnvelopeInGeometry(envA); if (hit_1 == com.epl.geometry.RasterizedGeometry2D.HitType.Inside) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Within); } else { if (hit_1 == com.epl.geometry.RasterizedGeometry2D.HitType.Outside) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Disjoint); } } break; } } } }while (endWhileStatement); return(0); }