// Mirrors wkt private static void ExportPolygonToGeoJson_(int export_flags, com.epl.geometry.Polygon polygon, com.epl.geometry.JsonWriter json_writer) { com.epl.geometry.MultiPathImpl polygon_impl = (com.epl.geometry.MultiPathImpl)(polygon._getImpl()); if ((export_flags & com.epl.geometry.GeoJsonExportFlags.geoJsonExportFailIfNotSimple) != 0) { int simple = polygon_impl.GetIsSimple(0.0); if (simple != com.epl.geometry.MultiVertexGeometryImpl.GeometryXSimple.Strong) { throw new com.epl.geometry.GeometryException("corrupted geometry"); } } int point_count = polygon.GetPointCount(); int polygon_count = polygon_impl.GetOGCPolygonCount(); if (point_count > 0 && polygon_count == 0) { throw new com.epl.geometry.GeometryException("corrupted geometry"); } int precision = 17 - (31 & (export_flags >> 13)); bool bFixedPoint = (com.epl.geometry.GeoJsonExportFlags.geoJsonExportPrecisionFixedPoint & export_flags) != 0; bool b_export_zs = polygon_impl.HasAttribute(com.epl.geometry.VertexDescription.Semantics.Z) && (export_flags & com.epl.geometry.GeoJsonExportFlags.geoJsonExportStripZs) == 0; bool b_export_ms = polygon_impl.HasAttribute(com.epl.geometry.VertexDescription.Semantics.M) && (export_flags & com.epl.geometry.GeoJsonExportFlags.geoJsonExportStripMs) == 0; if (!b_export_zs && b_export_ms) { throw new System.ArgumentException("invalid argument"); } int path_count = 0; com.epl.geometry.AttributeStreamOfDbl position = null; com.epl.geometry.AttributeStreamOfDbl zs = null; com.epl.geometry.AttributeStreamOfDbl ms = null; com.epl.geometry.AttributeStreamOfInt8 path_flags = null; com.epl.geometry.AttributeStreamOfInt32 paths = null; if (point_count > 0) { position = (com.epl.geometry.AttributeStreamOfDbl)polygon_impl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.POSITION); path_flags = polygon_impl.GetPathFlagsStreamRef(); paths = polygon_impl.GetPathStreamRef(); path_count = polygon_impl.GetPathCount(); if (b_export_zs) { if (polygon_impl._attributeStreamIsAllocated(com.epl.geometry.VertexDescription.Semantics.Z)) { zs = (com.epl.geometry.AttributeStreamOfDbl)polygon_impl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.Z); } } if (b_export_ms) { if (polygon_impl._attributeStreamIsAllocated(com.epl.geometry.VertexDescription.Semantics.M)) { ms = (com.epl.geometry.AttributeStreamOfDbl)polygon_impl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.M); } } } if ((export_flags & com.epl.geometry.GeoJsonExportFlags.geoJsonExportPreferMultiGeometry) == 0 && polygon_count <= 1) { PolygonTaggedText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, paths, path_count, json_writer); } else { MultiPolygonTaggedText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, path_flags, paths, polygon_count, path_count, json_writer); } }
internal static void ExportPolygonToWkt(int export_flags, com.epl.geometry.Polygon polygon, System.Text.StringBuilder @string) { com.epl.geometry.MultiPathImpl polygon_impl = (com.epl.geometry.MultiPathImpl)polygon._getImpl(); if ((export_flags & com.epl.geometry.WktExportFlags.wktExportFailIfNotSimple) != 0) { int simple = polygon_impl.GetIsSimple(0.0); if (simple != com.epl.geometry.MultiVertexGeometryImpl.GeometryXSimple.Strong) { throw new com.epl.geometry.GeometryException("corrupted geometry"); } } int point_count = polygon.GetPointCount(); int polygon_count = polygon_impl.GetOGCPolygonCount(); if (point_count > 0 && polygon_count == 0) { throw new com.epl.geometry.GeometryException("corrupted geometry"); } int precision = 17 - (7 & (export_flags >> 13)); bool b_export_zs = polygon_impl.HasAttribute(com.epl.geometry.VertexDescription.Semantics.Z) && (export_flags & com.epl.geometry.WktExportFlags.wktExportStripZs) == 0; bool b_export_ms = polygon_impl.HasAttribute(com.epl.geometry.VertexDescription.Semantics.M) && (export_flags & com.epl.geometry.WktExportFlags.wktExportStripMs) == 0; int path_count = 0; com.epl.geometry.AttributeStreamOfDbl position = null; com.epl.geometry.AttributeStreamOfDbl zs = null; com.epl.geometry.AttributeStreamOfDbl ms = null; com.epl.geometry.AttributeStreamOfInt8 path_flags = null; com.epl.geometry.AttributeStreamOfInt32 paths = null; if (point_count > 0) { position = (com.epl.geometry.AttributeStreamOfDbl)(polygon_impl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.POSITION)); path_flags = polygon_impl.GetPathFlagsStreamRef(); paths = polygon_impl.GetPathStreamRef(); path_count = polygon_impl.GetPathCount(); if (b_export_zs) { if (polygon_impl._attributeStreamIsAllocated(com.epl.geometry.VertexDescription.Semantics.Z)) { zs = (com.epl.geometry.AttributeStreamOfDbl)polygon_impl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.Z); } } if (b_export_ms) { if (polygon_impl._attributeStreamIsAllocated(com.epl.geometry.VertexDescription.Semantics.M)) { ms = (com.epl.geometry.AttributeStreamOfDbl)polygon_impl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.M); } } } if ((export_flags & com.epl.geometry.WktExportFlags.wktExportPolygon) != 0) { if (polygon_count > 1) { throw new System.ArgumentException("Cannot export a Polygon with specified export flags: " + export_flags); } PolygonTaggedText_(precision, b_export_zs, b_export_ms, zs, ms, position, path_flags, paths, path_count, @string); } else { MultiPolygonTaggedText_(precision, b_export_zs, b_export_ms, zs, ms, position, path_flags, paths, polygon_count, path_count, @string); } }
public static void TestRandom() { int passcount = 10; int figureSize = 100; int figureSize2 = 100; com.epl.geometry.Envelope extent1 = new com.epl.geometry.Envelope(); com.epl.geometry.Envelope extent2 = new com.epl.geometry.Envelope(); com.epl.geometry.Envelope extent3 = new com.epl.geometry.Envelope(); com.epl.geometry.Envelope extent4 = new com.epl.geometry.Envelope(); extent1.SetCoords(-10000, 5000, 10000, 25000); // red extent2.SetCoords(-10000, 2000, 10000, 8000); // blue extent3.SetCoords(-10000, -8000, 10000, -2000); // blue extent4.SetCoords(-10000, -25000, 10000, -5000); // red com.epl.geometry.RandomCoordinateGenerator generator1 = new com.epl.geometry.RandomCoordinateGenerator(System.Math.Max(figureSize, 10000), extent1, 0.001); com.epl.geometry.RandomCoordinateGenerator generator2 = new com.epl.geometry.RandomCoordinateGenerator(System.Math.Max(figureSize, 10000), extent2, 0.001); com.epl.geometry.RandomCoordinateGenerator generator3 = new com.epl.geometry.RandomCoordinateGenerator(System.Math.Max(figureSize, 10000), extent3, 0.001); com.epl.geometry.RandomCoordinateGenerator generator4 = new com.epl.geometry.RandomCoordinateGenerator(System.Math.Max(figureSize, 10000), extent4, 0.001); System.Random random = new System.Random(1982); int rand_max = 511; int qCount = 0; int eCount = 0; int bCount = 0; for (int c = 0; c < passcount; c++) { com.epl.geometry.Polygon polyRed = new com.epl.geometry.Polygon(); com.epl.geometry.Polygon polyBlue = new com.epl.geometry.Polygon(); int r = figureSize; if (r < 3) { continue; } com.epl.geometry.Point pt; for (int j = 0; j < r; j++) { int rand = random.Next(rand_max); bool bRandomNew = (r > 10) && ((1.0 * rand) / rand_max > 0.95); pt = generator1.GetRandomCoord(); if (j == 0 || bRandomNew) { polyRed.StartPath(pt); } else { polyRed.LineTo(pt); } } for (int j_1 = 0; j_1 < r; j_1++) { int rand = random.Next(rand_max); bool bRandomNew = (r > 10) && ((1.0 * rand) / rand_max > 0.95); pt = generator4.GetRandomCoord(); if (j_1 == 0 || bRandomNew) { polyRed.StartPath(pt); } else { polyRed.LineTo(pt); } } r = figureSize2; if (r < 3) { continue; } for (int j_2 = 0; j_2 < r; j_2++) { int rand = random.Next(rand_max); bool bRandomNew = (r > 10) && ((1.0 * rand) / rand_max > 0.95); pt = generator2.GetRandomCoord(); if (j_2 == 0 || bRandomNew) { polyBlue.StartPath(pt); } else { polyBlue.LineTo(pt); } } for (int j_3 = 0; j_3 < r; j_3++) { int rand = random.Next(rand_max); bool bRandomNew = (r > 10) && ((1.0 * rand) / rand_max > 0.95); pt = generator3.GetRandomCoord(); if (j_3 == 0 || bRandomNew) { polyBlue.StartPath(pt); } else { polyBlue.LineTo(pt); } } com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); // Quad_tree com.epl.geometry.QuadTree quadTree = BuildQuadTree(polyBlue); com.epl.geometry.QuadTree.QuadTreeIterator iterator = quadTree.GetIterator(); com.epl.geometry.SegmentIteratorImpl _segIterRed = ((com.epl.geometry.MultiPathImpl)polyRed._getImpl()).QuerySegmentIterator(); while (_segIterRed.NextPath()) { while (_segIterRed.HasNextSegment()) { com.epl.geometry.Segment segmentRed = _segIterRed.NextSegment(); segmentRed.QueryEnvelope2D(env); iterator.ResetIterator(env, 0.001); while (iterator.Next() != -1) { qCount++; } } } // Envelope_2D_intersector System.Collections.Generic.List <com.epl.geometry.Envelope2D> envelopes_red = new System.Collections.Generic.List <com.epl.geometry.Envelope2D>(); System.Collections.Generic.List <com.epl.geometry.Envelope2D> envelopes_blue = new System.Collections.Generic.List <com.epl.geometry.Envelope2D>(); com.epl.geometry.SegmentIterator segIterRed = polyRed.QuerySegmentIterator(); while (segIterRed.NextPath()) { while (segIterRed.HasNextSegment()) { com.epl.geometry.Segment segment = segIterRed.NextSegment(); env = new com.epl.geometry.Envelope2D(); segment.QueryEnvelope2D(env); envelopes_red.Add(env); } } com.epl.geometry.SegmentIterator segIterBlue = polyBlue.QuerySegmentIterator(); while (segIterBlue.NextPath()) { while (segIterBlue.HasNextSegment()) { com.epl.geometry.Segment segment = segIterBlue.NextSegment(); env = new com.epl.geometry.Envelope2D(); segment.QueryEnvelope2D(env); envelopes_blue.Add(env); } } com.epl.geometry.Envelope2DIntersectorImpl intersector = new com.epl.geometry.Envelope2DIntersectorImpl(); intersector.SetTolerance(0.001); intersector.StartRedConstruction(); for (int i = 0; i < envelopes_red.Count; i++) { intersector.AddRedEnvelope(i, envelopes_red[i]); } intersector.EndRedConstruction(); intersector.StartBlueConstruction(); for (int i_1 = 0; i_1 < envelopes_blue.Count; i_1++) { intersector.AddBlueEnvelope(i_1, envelopes_blue[i_1]); } intersector.EndBlueConstruction(); while (intersector.Next()) { eCount++; } NUnit.Framework.Assert.IsTrue(qCount == eCount); } }
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; }
/// <summary>Tests if Point is inside the Polygon's ring.</summary> /// <remarks> /// Tests if Point is inside the Polygon's ring. Returns PiPOutside if not in /// ring, PiPInside if in the ring, PiPBoundary is if on the border. It tests /// border only if the tolerance is greater than 0, otherwise PiPBoundary cannot be /// returned. Note: If the tolerance is not 0, the test is more expensive /// because it calculates closest distance from a point to each segment. /// O(n) complexity, where n is the number of ring segments. /// </remarks> public static com.epl.geometry.PolygonUtils.PiPResult IsPointInRing2D(com.epl.geometry.Polygon polygon, int iRing, com.epl.geometry.Point2D inputPoint, double tolerance) { com.epl.geometry.MultiPathImpl polygonImpl = (com.epl.geometry.MultiPathImpl)polygon._getImpl(); int res = com.epl.geometry.PointInPolygonHelper.IsPointInRing(polygonImpl, iRing, inputPoint, tolerance, null); if (res == 0) { return(com.epl.geometry.PolygonUtils.PiPResult.PiPOutside); } if (res == 1) { return(com.epl.geometry.PolygonUtils.PiPResult.PiPInside); } // return PiPResult.PiPBoundary; return(com.epl.geometry.PolygonUtils.PiPResult.PiPInside); }
internal static com.epl.geometry.Geometry PolylineMinusArea_(com.epl.geometry.Geometry geometry, com.epl.geometry.Geometry area, int area_type, com.epl.geometry.SpatialReference sr, com.epl.geometry.ProgressTracker progress_tracker) { // construct the complement of the Polygon (or Envelope) com.epl.geometry.Envelope envelope = new com.epl.geometry.Envelope(); geometry.QueryEnvelope(envelope); com.epl.geometry.Envelope2D env_2D = new com.epl.geometry.Envelope2D(); area.QueryEnvelope2D(env_2D); envelope.Merge(env_2D); double dw = 0.1 * envelope.GetWidth(); double dh = 0.1 * envelope.GetHeight(); envelope.Inflate(dw, dh); com.epl.geometry.Polygon complement = new com.epl.geometry.Polygon(); complement.AddEnvelope(envelope, false); com.epl.geometry.MultiPathImpl complementImpl = (com.epl.geometry.MultiPathImpl)(complement._getImpl()); if (area_type == com.epl.geometry.Geometry.GeometryType.Polygon) { com.epl.geometry.MultiPathImpl polygonImpl = (com.epl.geometry.MultiPathImpl)(area._getImpl()); complementImpl.Add(polygonImpl, true); } else { complementImpl.AddEnvelope((com.epl.geometry.Envelope)(area), true); } com.epl.geometry.OperatorFactoryLocal projEnv = com.epl.geometry.OperatorFactoryLocal.GetInstance(); com.epl.geometry.OperatorIntersection operatorIntersection = (com.epl.geometry.OperatorIntersection)projEnv.GetOperator(com.epl.geometry.Operator.Type.Intersection); com.epl.geometry.Geometry difference = operatorIntersection.Execute(geometry, complement, sr, progress_tracker); return(difference); }
public static void TestQuadTreeWithDuplicates() { int pass_count = 10; int figure_size = 400; int figure_size2 = 100; com.epl.geometry.Envelope extent1 = new com.epl.geometry.Envelope(); extent1.SetCoords(-100000, -100000, 100000, 100000); com.epl.geometry.RandomCoordinateGenerator generator1 = new com.epl.geometry.RandomCoordinateGenerator(System.Math.Max(figure_size, 10000), extent1, 0.001); System.Random random = new System.Random(2013); int rand_max = 32; com.epl.geometry.Polygon poly_red = new com.epl.geometry.Polygon(); com.epl.geometry.Polygon poly_blue = new com.epl.geometry.Polygon(); int r = figure_size; for (int c = 0; c < pass_count; c++) { com.epl.geometry.Point pt; for (int j = 0; j < r; j++) { int rand = random.Next(rand_max); bool b_random_new = r > 10 && ((1.0 * rand) / rand_max > 0.95); pt = generator1.GetRandomCoord(); if (j == 0 || b_random_new) { poly_blue.StartPath(pt); } else { poly_blue.LineTo(pt); } } com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); com.epl.geometry.QuadTree quad_tree_blue = BuildQuadTree_((com.epl.geometry.MultiPathImpl)poly_blue._getImpl(), false); com.epl.geometry.QuadTree quad_tree_blue_duplicates = BuildQuadTree_((com.epl.geometry.MultiPathImpl)poly_blue._getImpl(), true); com.epl.geometry.Envelope2D e1 = quad_tree_blue.GetDataExtent(); com.epl.geometry.Envelope2D e2 = quad_tree_blue_duplicates.GetDataExtent(); NUnit.Framework.Assert.IsTrue(e1.Equals(e2)); NUnit.Framework.Assert.IsTrue(quad_tree_blue.GetElementCount() == poly_blue.GetSegmentCount()); com.epl.geometry.SegmentIterator seg_iter_blue = poly_blue.QuerySegmentIterator(); poly_red.SetEmpty(); r = figure_size2; if (r < 3) { continue; } for (int j_1 = 0; j_1 < r; j_1++) { int rand = random.Next(rand_max); bool b_random_new = r > 10 && ((1.0 * rand) / rand_max > 0.95); pt = generator1.GetRandomCoord(); if (j_1 == 0 || b_random_new) { poly_red.StartPath(pt); } else { poly_red.LineTo(pt); } } com.epl.geometry.QuadTree.QuadTreeIterator iterator = quad_tree_blue.GetIterator(); com.epl.geometry.SegmentIteratorImpl seg_iter_red = ((com.epl.geometry.MultiPathImpl)poly_red._getImpl()).QuerySegmentIterator(); System.Collections.Generic.Dictionary <int, bool> map1 = new System.Collections.Generic.Dictionary <int, bool>(0); int count = 0; int intersections_per_query = 0; while (seg_iter_red.NextPath()) { while (seg_iter_red.HasNextSegment()) { com.epl.geometry.Segment segment_red = seg_iter_red.NextSegment(); segment_red.QueryEnvelope2D(env); iterator.ResetIterator(env, 0.0); int count_upper = 0; int element_handle; while ((element_handle = iterator.Next()) != -1) { count_upper++; int index = quad_tree_blue.GetElement(element_handle); bool iter = map1.ContainsKey(index); if (!iter) { count++; map1[index] = true; } intersections_per_query++; } int intersection_count = quad_tree_blue.GetIntersectionCount(env, 0.0, -1); NUnit.Framework.Assert.IsTrue(intersection_count == count_upper); } } seg_iter_red.ResetToFirstPath(); System.Collections.Generic.Dictionary <int, bool> map2 = new System.Collections.Generic.Dictionary <int, bool>(0); com.epl.geometry.QuadTree.QuadTreeIterator iterator_duplicates = quad_tree_blue_duplicates.GetIterator(); int count_duplicates = 0; int intersections_per_query_duplicates = 0; while (seg_iter_red.NextPath()) { while (seg_iter_red.HasNextSegment()) { com.epl.geometry.Segment segment_red = seg_iter_red.NextSegment(); segment_red.QueryEnvelope2D(env); iterator_duplicates.ResetIterator(env, 0.0); int count_lower = 0; System.Collections.Generic.Dictionary <int, bool> map_per_query = new System.Collections.Generic.Dictionary <int, bool>(0); int count_upper = 0; int element_handle; while ((element_handle = iterator_duplicates.Next()) != -1) { count_upper++; int index = quad_tree_blue_duplicates.GetElement(element_handle); bool iter = map2.ContainsKey(index); if (!iter) { count_duplicates++; map2[index] = true; } bool iter_lower = map_per_query.ContainsKey(index); if (!iter_lower) { count_lower++; intersections_per_query_duplicates++; map_per_query[index] = true; } int q = quad_tree_blue_duplicates.GetQuad(element_handle); NUnit.Framework.Assert.IsTrue(quad_tree_blue_duplicates.GetSubTreeElementCount(q) >= quad_tree_blue_duplicates.GetContainedSubTreeElementCount(q)); } int intersection_count = quad_tree_blue_duplicates.GetIntersectionCount(env, 0.0, -1); bool b_has_data = quad_tree_blue_duplicates.HasData(env, 0.0); NUnit.Framework.Assert.IsTrue(b_has_data || intersection_count == 0); NUnit.Framework.Assert.IsTrue(count_lower <= intersection_count && intersection_count <= count_upper); NUnit.Framework.Assert.IsTrue(count_upper <= 4 * count_lower); } } NUnit.Framework.Assert.IsTrue(count == count_duplicates); NUnit.Framework.Assert.IsTrue(intersections_per_query == intersections_per_query_duplicates); } }
internal static com.epl.geometry.Geometry PolygonTaggedText(bool b_multi_polygon, int import_flags, com.epl.geometry.WktParser wkt_parser) { com.epl.geometry.MultiPath multi_path; com.epl.geometry.MultiPathImpl multi_path_impl; com.epl.geometry.AttributeStreamOfDbl zs = null; com.epl.geometry.AttributeStreamOfDbl ms = null; com.epl.geometry.AttributeStreamOfDbl position; com.epl.geometry.AttributeStreamOfInt32 paths; com.epl.geometry.AttributeStreamOfInt8 path_flags; position = (com.epl.geometry.AttributeStreamOfDbl)com.epl.geometry.AttributeStreamBase.CreateDoubleStream(0); paths = (com.epl.geometry.AttributeStreamOfInt32)com.epl.geometry.AttributeStreamBase.CreateIndexStream(1, 0); path_flags = (com.epl.geometry.AttributeStreamOfInt8)com.epl.geometry.AttributeStreamBase.CreateByteStream(1, unchecked ((byte)0)); multi_path = new com.epl.geometry.Polygon(); multi_path_impl = (com.epl.geometry.MultiPathImpl)multi_path._getImpl(); int current_token = wkt_parser.NextToken(); if (current_token == com.epl.geometry.WktParser.WktToken.attribute_z) { zs = (com.epl.geometry.AttributeStreamOfDbl)com.epl.geometry.AttributeStreamBase.CreateDoubleStream(0, com.epl.geometry.NumberUtils.TheNaN); multi_path_impl.AddAttribute(com.epl.geometry.VertexDescription.Semantics.Z); wkt_parser.NextToken(); } else { if (current_token == com.epl.geometry.WktParser.WktToken.attribute_m) { ms = (com.epl.geometry.AttributeStreamOfDbl)com.epl.geometry.AttributeStreamBase.CreateDoubleStream(0, com.epl.geometry.NumberUtils.TheNaN); multi_path_impl.AddAttribute(com.epl.geometry.VertexDescription.Semantics.M); wkt_parser.NextToken(); } else { if (current_token == com.epl.geometry.WktParser.WktToken.attribute_zm) { zs = (com.epl.geometry.AttributeStreamOfDbl)com.epl.geometry.AttributeStreamBase.CreateDoubleStream(0, com.epl.geometry.NumberUtils.TheNaN); ms = (com.epl.geometry.AttributeStreamOfDbl)com.epl.geometry.AttributeStreamBase.CreateDoubleStream(0, com.epl.geometry.NumberUtils.TheNaN); multi_path_impl.AddAttribute(com.epl.geometry.VertexDescription.Semantics.Z); multi_path_impl.AddAttribute(com.epl.geometry.VertexDescription.Semantics.M); wkt_parser.NextToken(); } } } int point_count; if (b_multi_polygon) { point_count = MultiPolygonText(zs, ms, position, paths, path_flags, wkt_parser); } else { point_count = PolygonText(zs, ms, position, paths, path_flags, 0, wkt_parser); } if (point_count != 0) { System.Diagnostics.Debug.Assert((2 * point_count == position.Size())); multi_path_impl.SetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.POSITION, position); multi_path_impl.SetPathStreamRef(paths); multi_path_impl.SetPathFlagsStreamRef(path_flags); if (zs != null) { multi_path_impl.SetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.Z, zs); } if (ms != null) { multi_path_impl.SetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.M, ms); } multi_path_impl.NotifyModified(com.epl.geometry.MultiVertexGeometryImpl.DirtyFlags.DirtyAll); com.epl.geometry.AttributeStreamOfInt8 path_flags_clone = new com.epl.geometry.AttributeStreamOfInt8(path_flags); for (int i = 0; i < path_flags_clone.Size() - 1; i++) { if (((int)path_flags_clone.Read(i) & (int)com.epl.geometry.PathFlags.enumOGCStartPolygon) != 0) { // Should // be // clockwise if (!com.epl.geometry.InternalUtils.IsClockwiseRing(multi_path_impl, i)) { multi_path_impl.ReversePath(i); } } else { // make clockwise // Should be counter-clockwise if (com.epl.geometry.InternalUtils.IsClockwiseRing(multi_path_impl, i)) { multi_path_impl.ReversePath(i); } } } // make // counter-clockwise multi_path_impl.SetPathFlagsStreamRef(path_flags_clone); } if ((import_flags & (int)com.epl.geometry.WktImportFlags.wktImportNonTrusted) == 0) { multi_path_impl.SetIsSimple(com.epl.geometry.MultiVertexGeometryImpl.GeometryXSimple.Weak, 0.0, false); } multi_path_impl.SetDirtyOGCFlags(false); return(multi_path); }
public static int IsPointInAnyOuterRing(com.epl.geometry.Polygon inputPolygon, com.epl.geometry.Point2D inputPoint, double tolerance) { com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); inputPolygon.QueryLooseEnvelope(env); env.Inflate(tolerance, tolerance); if (!env.Contains(inputPoint)) { return(0); } // Note: // Wolfgang had noted that this could be optimized if the exterior rings // have positive area: // Only test the positive rings and bail out immediately when in a // positive ring. // The worst case complexity is still O(n), but on average for polygons // with holes, that would be faster. // However, that method would not work if polygon is reversed, while the // one here works fine same as PointInPolygon. bool bAltenate = false; // use winding in this test com.epl.geometry.PointInPolygonHelper helper = new com.epl.geometry.PointInPolygonHelper(bAltenate, inputPoint, tolerance); com.epl.geometry.MultiPathImpl mpImpl = (com.epl.geometry.MultiPathImpl)inputPolygon._getImpl(); com.epl.geometry.SegmentIteratorImpl iter = mpImpl.QuerySegmentIterator(); while (iter.NextPath()) { double ringArea = mpImpl.CalculateRingArea2D(iter.GetPathIndex()); bool bIsHole = ringArea < 0; if (!bIsHole) { helper.m_windnum = 0; while (iter.HasNextSegment()) { com.epl.geometry.Segment segment = iter.NextSegment(); if (helper.ProcessSegment(segment)) { return(-1); } } // point on boundary if (helper.m_windnum != 0) { return(1); } } } return(helper.Result()); }
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)); }
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)); }
private static int _isPointInPolygonInternalWithQuadTree(com.epl.geometry.Polygon inputPolygon, com.epl.geometry.QuadTreeImpl quadTree, com.epl.geometry.Point2D inputPoint, double tolerance) { com.epl.geometry.Envelope2D envPoly = new com.epl.geometry.Envelope2D(); inputPolygon.QueryLooseEnvelope(envPoly); envPoly.Inflate(tolerance, tolerance); bool bAltenate = inputPolygon.GetFillRule() == com.epl.geometry.Polygon.FillRule.enumFillRuleOddEven; com.epl.geometry.PointInPolygonHelper helper = new com.epl.geometry.PointInPolygonHelper(bAltenate, inputPoint, tolerance); com.epl.geometry.MultiPathImpl mpImpl = (com.epl.geometry.MultiPathImpl)inputPolygon._getImpl(); com.epl.geometry.SegmentIteratorImpl iter = mpImpl.QuerySegmentIterator(); com.epl.geometry.Envelope2D queryEnv = new com.epl.geometry.Envelope2D(); queryEnv.SetCoords(envPoly); queryEnv.xmax = inputPoint.x + tolerance; // no need to query segments to // the right of the point. // Only segments to the left // matter. queryEnv.ymin = inputPoint.y - tolerance; queryEnv.ymax = inputPoint.y + tolerance; com.epl.geometry.QuadTreeImpl.QuadTreeIteratorImpl qiter = quadTree.GetIterator(queryEnv, tolerance); for (int qhandle = qiter.Next(); qhandle != -1; qhandle = qiter.Next()) { iter.ResetToVertex(quadTree.GetElement(qhandle)); if (iter.HasNextSegment()) { com.epl.geometry.Segment segment = iter.NextSegment(); if (helper.ProcessSegment(segment)) { return(-1); } } } // point on boundary return(helper.Result()); }
private static int _isPointInPolygonInternal(com.epl.geometry.Polygon inputPolygon, com.epl.geometry.Point2D inputPoint, double tolerance) { bool bAltenate = inputPolygon.GetFillRule() == com.epl.geometry.Polygon.FillRule.enumFillRuleOddEven; com.epl.geometry.PointInPolygonHelper helper = new com.epl.geometry.PointInPolygonHelper(bAltenate, inputPoint, tolerance); com.epl.geometry.MultiPathImpl mpImpl = (com.epl.geometry.MultiPathImpl)inputPolygon._getImpl(); com.epl.geometry.SegmentIteratorImpl iter = mpImpl.QuerySegmentIterator(); while (iter.NextPath()) { while (iter.HasNextSegment()) { com.epl.geometry.Segment segment = iter.NextSegment(); if (helper.ProcessSegment(segment)) { return(-1); } } } // point on boundary return(helper.Result()); }