internal virtual com.epl.geometry.Geometry Intersect(com.epl.geometry.Geometry input_geom) { com.epl.geometry.Geometry dst_geom = TryNativeImplementation_(input_geom); if (dst_geom != null) { return dst_geom; } com.epl.geometry.Envelope2D commonExtent = com.epl.geometry.InternalUtils.GetMergedExtent(m_geomIntersector, input_geom); // return Topological_operations::intersection(input_geom, // m_geomIntersector, m_spatial_reference, m_progress_tracker); // Preprocess geometries to be clipped to the extent of intersection to // get rid of extra segments. double t = com.epl.geometry.InternalUtils.CalculateToleranceFromGeometry(m_spatial_reference, commonExtent, true); com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); m_geomIntersector.QueryEnvelope2D(env); com.epl.geometry.Envelope2D env1 = new com.epl.geometry.Envelope2D(); input_geom.QueryEnvelope2D(env1); env.Inflate(2.0 * t, 2.0 * t); env.Intersect(env1); System.Diagnostics.Debug.Assert((!env.IsEmpty())); env.Inflate(100 * t, 100 * t); double tol = 0; com.epl.geometry.Geometry clippedIntersector = com.epl.geometry.Clipper.Clip(m_geomIntersector, env, tol, 0.0); com.epl.geometry.Geometry clippedInputGeom = com.epl.geometry.Clipper.Clip(input_geom, env, tol, 0.0); // perform the clip return com.epl.geometry.TopologicalOperations.Intersection(clippedInputGeom, clippedIntersector, m_spatial_reference, m_progress_tracker); }
internal virtual com.epl.geometry.GeometryCursor IntersectEx(com.epl.geometry.Geometry input_geom) { System.Diagnostics.Debug.Assert((m_dimensionMask != -1)); com.epl.geometry.Geometry dst_geom = TryNativeImplementation_(input_geom); if (dst_geom != null) { com.epl.geometry.Geometry[] res_vec = new com.epl.geometry.Geometry[3]; res_vec[dst_geom.GetDimension()] = dst_geom; return PrepareVector_(input_geom.GetDescription(), m_dimensionMask, res_vec); } com.epl.geometry.Envelope2D commonExtent = com.epl.geometry.InternalUtils.GetMergedExtent(m_geomIntersector, input_geom); double t = com.epl.geometry.InternalUtils.CalculateToleranceFromGeometry(m_spatial_reference, commonExtent, true); // Preprocess geometries to be clipped to the extent of intersection to // get rid of extra segments. com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); m_geomIntersector.QueryEnvelope2D(env); env.Inflate(2 * t, 2 * t); com.epl.geometry.Envelope2D env1 = new com.epl.geometry.Envelope2D(); input_geom.QueryEnvelope2D(env1); env.Intersect(env1); System.Diagnostics.Debug.Assert((!env.IsEmpty())); env.Inflate(100 * t, 100 * t); double tol = 0; com.epl.geometry.Geometry clippedIntersector = com.epl.geometry.Clipper.Clip(m_geomIntersector, env, tol, 0.0); com.epl.geometry.Geometry clippedInputGeom = com.epl.geometry.Clipper.Clip(input_geom, env, tol, 0.0); // perform the clip com.epl.geometry.Geometry[] res_vec_1; res_vec_1 = com.epl.geometry.TopologicalOperations.IntersectionEx(clippedInputGeom, clippedIntersector, m_spatial_reference, m_progress_tracker); return PrepareVector_(input_geom.GetDescription(), m_dimensionMask, res_vec_1); }
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()); }
//dbgSaveToBitmap("c:/temp/_dbg.bmp"); internal bool TryRenderAsSmallEnvelope_(com.epl.geometry.Envelope2D env) { if (!env.IsIntersecting(m_geomEnv)) { return(true); } com.epl.geometry.Envelope2D envPix = new com.epl.geometry.Envelope2D(); envPix.SetCoords(env); m_transform.Transform(env); double strokeHalfWidthPixX = m_stroke_half_widthX_pix; double strokeHalfWidthPixY = m_stroke_half_widthY_pix; if (envPix.GetWidth() > 2 * strokeHalfWidthPixX + 1 || envPix.GetHeight() > 2 * strokeHalfWidthPixY + 1) { return(false); } // This envelope is too narrow/small, so that it can be just drawn as a // rectangle using only boundary color. envPix.Inflate(strokeHalfWidthPixX, strokeHalfWidthPixY); envPix.xmax += 1.0; envPix.ymax += 1.0; // take into account that it does not draw right and // bottom edges. m_callback.SetColor(m_rasterizer, 2); FillEnvelope(m_rasterizer, envPix); return(true); }
private static int QuickTest2DMultiPointEnvelope(com.epl.geometry.MultiPoint geomA, com.epl.geometry.Envelope2D geomBEnv, double tolerance, int testType) { // Add early bailout for disjoint test. com.epl.geometry.Envelope2D envBMinus = geomBEnv; envBMinus.Inflate(-tolerance, -tolerance); com.epl.geometry.Envelope2D envBPlus = geomBEnv; envBPlus.Inflate(tolerance, tolerance); int dres = 0; for (int i = 0, n = geomA.GetPointCount(); i < n; i++) { com.epl.geometry.Point2D ptA; ptA = geomA.GetXY(i); int res = ReverseResult(QuickTest2DEnvelopePoint(envBPlus, envBMinus, ptA, tolerance)); if (res != (int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Disjoint) { dres |= res; if (testType == (int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Disjoint) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Intersects); } } } if (dres == 0) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Disjoint); } if (dres == (int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Within) { return(dres); } return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Overlaps); }
public com.epl.geometry.Envelope2D GetInflated(double dx, double dy) { com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); env.SetCoords(this.xmin, this.ymin, this.xmax, this.ymax); env.Inflate(dx, dy); return(env); }
internal static com.epl.geometry.Geometry MultiPointSymDiffPoint_(com.epl.geometry.MultiPoint multi_point, com.epl.geometry.Point point, double tolerance, com.epl.geometry.ProgressTracker progress_tracker) { com.epl.geometry.MultiPointImpl multipointImpl = (com.epl.geometry.MultiPointImpl)(multi_point._getImpl()); com.epl.geometry.AttributeStreamOfDbl position = (com.epl.geometry.AttributeStreamOfDbl)(multipointImpl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.POSITION)); int point_count = multi_point.GetPointCount(); com.epl.geometry.Point2D point2D = point.GetXY(); com.epl.geometry.MultiPoint new_multipoint = (com.epl.geometry.MultiPoint)(multi_point.CreateInstance()); double tolerance_cluster = tolerance * System.Math.Sqrt(2.0) * 1.00001; com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); multi_point.QueryEnvelope2D(env); env.Inflate(tolerance_cluster, tolerance_cluster); if (env.Contains(point2D)) { double tolerance_cluster_sq = tolerance_cluster * tolerance_cluster; bool b_found_covered = false; bool[] covered = new bool[point_count]; for (int i = 0; i < point_count; i++) { covered[i] = false; } for (int i_1 = 0; i_1 < point_count; i_1++) { double x = position.Read(2 * i_1); double y = position.Read(2 * i_1 + 1); double dx = x - point2D.x; double dy = y - point2D.y; if (dx * dx + dy * dy <= tolerance_cluster_sq) { b_found_covered = true; covered[i_1] = true; } } if (!b_found_covered) { new_multipoint.Add(multi_point, 0, point_count); new_multipoint.Add(point); } else { for (int i_2 = 0; i_2 < point_count; i_2++) { if (!covered[i_2]) { new_multipoint.Add(multi_point, i_2, i_2 + 1); } } } } else { new_multipoint.Add(multi_point, 0, point_count); new_multipoint.Add(point); } return(new_multipoint); }
// return the input point internal static com.epl.geometry.Geometry PointMinusEnvelope_(com.epl.geometry.Point point, com.epl.geometry.Envelope envelope, double tolerance, com.epl.geometry.ProgressTracker progress_tracker) { com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); envelope.QueryEnvelope2D(env); env.Inflate(tolerance, tolerance); com.epl.geometry.Point2D pt = point.GetXY(); if (!env.Contains(pt)) { return(point); } return(point.CreateInstance()); }
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()); }
private static int QuickTest2DEnvelopePoint(com.epl.geometry.Envelope2D geomAEnv, com.epl.geometry.Point2D ptB, double tolerance) { com.epl.geometry.Envelope2D envAMinus = geomAEnv; envAMinus.Inflate(-tolerance, -tolerance); if (envAMinus.Contains(ptB)) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Contains); } // clementini's contains com.epl.geometry.Envelope2D envAPlus = geomAEnv; envAPlus.Inflate(tolerance, tolerance); if (envAPlus.Contains(ptB)) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Touches); } // clementini's touches return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Disjoint); }
internal static com.epl.geometry.Geometry MultiPointMinusPolygon_(com.epl.geometry.MultiPoint multi_point, com.epl.geometry.Polygon polygon, double tolerance, com.epl.geometry.ProgressTracker progress_tracker) { com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); polygon.QueryEnvelope2D(env); env.Inflate(tolerance, tolerance); int point_count = multi_point.GetPointCount(); bool b_found_covered = false; bool[] covered = new bool[point_count]; for (int i = 0; i < point_count; i++) { covered[i] = false; } com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D(); for (int i_1 = 0; i_1 < point_count; i_1++) { multi_point.GetXY(i_1, pt); if (!env.Contains(pt)) { continue; } com.epl.geometry.PolygonUtils.PiPResult result = com.epl.geometry.PolygonUtils.IsPointInPolygon2D(polygon, pt, tolerance); if (result == com.epl.geometry.PolygonUtils.PiPResult.PiPOutside) { continue; } b_found_covered = true; covered[i_1] = true; } if (!b_found_covered) { return(multi_point); } com.epl.geometry.MultiPoint new_multipoint = (com.epl.geometry.MultiPoint)multi_point.CreateInstance(); for (int i_2 = 0; i_2 < point_count; i_2++) { if (!covered[i_2]) { new_multipoint.Add(multi_point, i_2, i_2 + 1); } } return(new_multipoint); }
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 void _testPointsInEnvelope2D(com.epl.geometry.Envelope2D env2D, double[] xyStreamBuffer, int pointCount, double tolerance, com.epl.geometry.PolygonUtils.PiPResult[] testResults) { if (xyStreamBuffer.Length / 2 < pointCount || testResults.Length < pointCount) { throw new System.ArgumentException(); } if (env2D.IsEmpty()) { for (int i = 0; i < pointCount; i++) { testResults[i] = com.epl.geometry.PolygonUtils.PiPResult.PiPOutside; } return; } com.epl.geometry.Envelope2D envIn = env2D; // note for java port - assignement by value envIn.Inflate(-tolerance * 0.5, -tolerance * 0.5); com.epl.geometry.Envelope2D envOut = env2D; // note for java port - assignement by value envOut.Inflate(tolerance * 0.5, tolerance * 0.5); for (int i_1 = 0; i_1 < pointCount; i_1++) { if (envIn.Contains(xyStreamBuffer[i_1 * 2], xyStreamBuffer[i_1 * 2 + 1])) { testResults[i_1] = com.epl.geometry.PolygonUtils.PiPResult.PiPInside; } else { if (!envIn.Contains(xyStreamBuffer[i_1 * 2], xyStreamBuffer[i_1 * 2 + 1])) { testResults[i_1] = com.epl.geometry.PolygonUtils.PiPResult.PiPOutside; } else { testResults[i_1] = com.epl.geometry.PolygonUtils.PiPResult.PiPBoundary; } } } }
internal static com.epl.geometry.Geometry PointMinusPolyline_(com.epl.geometry.Point point, com.epl.geometry.Polyline polyline, double tolerance, com.epl.geometry.ProgressTracker progress_tracker) { com.epl.geometry.Point2D pt = point.GetXY(); com.epl.geometry.SegmentIterator seg_iter = polyline.QuerySegmentIterator(); double tolerance_cluster = tolerance * System.Math.Sqrt(2.0) * 1.00001; double tolerance_cluster_sq = tolerance_cluster * tolerance_cluster; com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); while (seg_iter.NextPath()) { while (seg_iter.HasNextSegment()) { com.epl.geometry.Segment segment = seg_iter.NextSegment(); segment.QueryEnvelope2D(env); env.Inflate(tolerance_cluster, tolerance_cluster); if (!env.Contains(pt)) { continue; } if (segment.IsIntersecting(pt, tolerance)) { return(point.CreateInstance()); } // check segment end points to the cluster tolerance com.epl.geometry.Point2D end_point = segment.GetStartXY(); if (com.epl.geometry.Point2D.SqrDistance(pt, end_point) <= tolerance_cluster_sq) { return(point.CreateInstance()); } end_point = segment.GetEndXY(); if (com.epl.geometry.Point2D.SqrDistance(pt, end_point) <= tolerance_cluster_sq) { return(point.CreateInstance()); } } } return(point); }
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 void Init(com.epl.geometry.MultiVertexGeometryImpl geom, double toleranceXY, int rasterSizeBytes) { // _ASSERT(CanUseAccelerator(geom)); m_width = System.Math.Max((int)(System.Math.Sqrt(rasterSizeBytes) * 2 + 0.5), 64); m_scanLineSize = (m_width * 2 + 31) / 32; // 2 bits per pixel m_geomEnv = new com.epl.geometry.Envelope2D(); m_toleranceXY = toleranceXY; // calculate bitmap size int size = 0; int width = m_width; int scanLineSize = m_scanLineSize; while (width >= 8) { size += width * scanLineSize; width /= 2; scanLineSize = (width * 2 + 31) / 32; } // allocate the bitmap, that contains the base and the mip-levels m_bitmap = new int[size]; for (int i = 0; i < size; i++) { m_bitmap[i] = 0; } m_rasterizer = new com.epl.geometry.SimpleRasterizer(); com.epl.geometry.RasterizedGeometry2DImpl.ScanCallbackImpl callback = new com.epl.geometry.RasterizedGeometry2DImpl.ScanCallbackImpl(this, m_bitmap, m_scanLineSize); m_callback = callback; m_rasterizer.Setup(m_width, m_width, callback); geom.QueryEnvelope2D(m_geomEnv); if (m_geomEnv.GetWidth() > m_width * m_geomEnv.GetHeight() || m_geomEnv.GetHeight() > m_geomEnv.GetWidth() * m_width) { } // the geometry is thin and the rasterizer is not needed. m_geomEnv.Inflate(toleranceXY, toleranceXY); com.epl.geometry.Envelope2D worldEnv = new com.epl.geometry.Envelope2D(); com.epl.geometry.Envelope2D pixEnv = com.epl.geometry.Envelope2D.Construct(1, 1, m_width - 2, m_width - 2); double minWidth = toleranceXY * pixEnv.GetWidth(); // min width is such // that the size of // one pixel is // equal to the // tolerance double minHeight = toleranceXY * pixEnv.GetHeight(); worldEnv.SetCoords(m_geomEnv.GetCenter(), System.Math.Max(minWidth, m_geomEnv.GetWidth()), System.Math.Max(minHeight, m_geomEnv.GetHeight())); m_stroke_half_widthX_pix = worldEnv.GetWidth() / pixEnv.GetWidth(); m_stroke_half_widthY_pix = worldEnv.GetHeight() / pixEnv.GetHeight(); // The stroke half width. Later it will be inflated to account for // pixels size. m_stroke_half_width = m_toleranceXY; m_transform = new com.epl.geometry.Transformation2D(); m_transform.InitializeFromRect(worldEnv, pixEnv); // geom to pixels com.epl.geometry.Transformation2D identityTransform = new com.epl.geometry.Transformation2D(); switch (geom.GetType().Value()) { case com.epl.geometry.Geometry.GeometryType.MultiPoint: { callback.SetColor(m_rasterizer, 2); FillPoints(m_rasterizer, (com.epl.geometry.MultiPointImpl)geom, m_stroke_half_width); break; } case com.epl.geometry.Geometry.GeometryType.Polyline: { callback.SetColor(m_rasterizer, 2); StrokeDrawPolyPath(m_rasterizer, (com.epl.geometry.MultiPathImpl)geom._getImpl(), m_stroke_half_width); break; } case com.epl.geometry.Geometry.GeometryType.Polygon: { bool isWinding = false; // NOTE: change when winding is supported callback.SetColor(m_rasterizer, 1); FillMultiPath(m_rasterizer, m_transform, (com.epl.geometry.MultiPathImpl)geom, isWinding); callback.SetColor(m_rasterizer, 2); StrokeDrawPolyPath(m_rasterizer, (com.epl.geometry.MultiPathImpl)geom._getImpl(), m_stroke_half_width); break; } } m_dx = m_transform.xx; m_dy = m_transform.yy; m_x0 = m_transform.xd; m_y0 = m_transform.yd; BuildLevels(); }
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; }
internal virtual com.epl.geometry.Geometry TryNativeImplementation_(com.epl.geometry.Geometry input_geom) { // A note on attributes: // 1. The geometry with lower dimension wins in regard to the // attributes. // 2. If the dimensions are the same, the input_geometry attributes win. // 3. The exception to the 2. is when the input is an Envelope, and the // intersector is a polygon, then the intersector wins. // A note on the tolerance: // This operator performs a simple intersection operation. Should it use // the tolerance? // Example: Point is intersected by the envelope. // If it is slightly outside of the envelope, should we still return it // if it is closer than the tolerance? // Should we do crack and cluster and snap the point coordinates to the // envelope boundary? // // Consider floating point arithmetics approach. When you compare // doubles, you should use an epsilon (equals means ::fabs(a - b) < // eps), however when you add/subtract, etc them, you do not use // epsilon. // Shouldn't we do same here? Relational operators use tolerance, but // the action operators don't. com.epl.geometry.Envelope2D mergedExtent = com.epl.geometry.InternalUtils.GetMergedExtent(input_geom, m_geomIntersector); double tolerance = com.epl.geometry.InternalUtils.CalculateToleranceFromGeometry(m_spatial_reference, mergedExtent, false); int gtInput = input_geom.GetType().Value(); bool bInputEmpty = input_geom.IsEmpty(); bool bGeomIntersectorEmpty = m_geomIntersector.IsEmpty(); bool bResultIsEmpty = bInputEmpty || bGeomIntersectorEmpty; if (!bResultIsEmpty) { // test envelopes com.epl.geometry.Envelope2D env2D1 = new com.epl.geometry.Envelope2D(); input_geom.QueryEnvelope2D(env2D1); com.epl.geometry.Envelope2D env2D2 = new com.epl.geometry.Envelope2D(); m_geomIntersector.QueryEnvelope2D(env2D2); env2D2.Inflate(2.0 * tolerance, 2.0 * tolerance); bResultIsEmpty = !env2D1.IsIntersecting(env2D2); } if (!bResultIsEmpty) { // try accelerated test int res = com.epl.geometry.OperatorInternalRelationUtils.QuickTest2D_Accelerated_DisjointOrContains(m_geomIntersector, input_geom, tolerance); if (res == com.epl.geometry.OperatorInternalRelationUtils.Relation.Disjoint) { // disjoint bResultIsEmpty = true; } else { if ((res & com.epl.geometry.OperatorInternalRelationUtils.Relation.Within) != 0) { // intersector // is // within // the // input_geom // TODO: // assign // input_geom // attributes // first return m_geomIntersector; } else { if ((res & com.epl.geometry.OperatorInternalRelationUtils.Relation.Contains) != 0) { // intersector // contains // input_geom return input_geom; } } } } if (bResultIsEmpty) { // When one geometry or both are empty, we need to // return an empty geometry. // Here we do that end also ensure the type is // correct. // That is the lower dimension need to be // returned. Also, for Point vs Multi_point, an // empty Point need to be returned. int dim1 = com.epl.geometry.Geometry.GetDimensionFromType(gtInput); int dim2 = com.epl.geometry.Geometry.GetDimensionFromType(m_geomIntersectorType); if (dim1 < dim2) { return ReturnEmpty_(input_geom, bInputEmpty); } else { if (dim1 > dim2) { return ReturnEmptyIntersector_(); } else { if (dim1 == 0) { if (gtInput == com.epl.geometry.Geometry.GeometryType.MultiPoint && m_geomIntersectorType == com.epl.geometry.Geometry.GeometryType.Point) { // point // vs // Multi_point // need // special // treatment // to // ensure // Point // is // returned // always. return ReturnEmptyIntersector_(); } else { // Both input and intersector have same gtype, or input is // Point. return ReturnEmpty_(input_geom, bInputEmpty); } } else { return ReturnEmpty_(input_geom, bInputEmpty); } } } } // Note: No empty geometries after this point! // Warning: Do not try clip for polylines and polygons. // Try clip of Envelope with Envelope. if ((m_dimensionMask == -1 || m_dimensionMask == (1 << 2)) && gtInput == com.epl.geometry.Geometry.GeometryType.Envelope && m_geomIntersectorType == com.epl.geometry.Geometry.GeometryType.Envelope) { com.epl.geometry.Envelope env1 = (com.epl.geometry.Envelope)input_geom; com.epl.geometry.Envelope env2 = (com.epl.geometry.Envelope)m_geomIntersector; com.epl.geometry.Envelope2D env2D_1 = new com.epl.geometry.Envelope2D(); env1.QueryEnvelope2D(env2D_1); com.epl.geometry.Envelope2D env2D_2 = new com.epl.geometry.Envelope2D(); env2.QueryEnvelope2D(env2D_2); env2D_1.Intersect(env2D_2); com.epl.geometry.Envelope result_env = new com.epl.geometry.Envelope(); env1.CopyTo(result_env); result_env.SetEnvelope2D(env2D_1); return result_env; } // Use clip for Point and Multi_point with Envelope if ((gtInput == com.epl.geometry.Geometry.GeometryType.Envelope && com.epl.geometry.Geometry.GetDimensionFromType(m_geomIntersectorType) == 0) || (m_geomIntersectorType == com.epl.geometry.Geometry.GeometryType.Envelope && com.epl.geometry.Geometry.GetDimensionFromType(gtInput ) == 0)) { com.epl.geometry.Envelope env = gtInput == com.epl.geometry.Geometry.GeometryType.Envelope ? (com.epl.geometry.Envelope)input_geom : (com.epl.geometry.Envelope)m_geomIntersector; com.epl.geometry.Geometry other = gtInput == com.epl.geometry.Geometry.GeometryType.Envelope ? m_geomIntersector : input_geom; com.epl.geometry.Envelope2D env_2D = new com.epl.geometry.Envelope2D(); env.QueryEnvelope2D(env_2D); return com.epl.geometry.Clipper.Clip(other, env_2D, tolerance, 0); } if ((com.epl.geometry.Geometry.GetDimensionFromType(gtInput) == 0 && com.epl.geometry.Geometry.GetDimensionFromType(m_geomIntersectorType) > 0) || (com.epl.geometry.Geometry.GetDimensionFromType(gtInput) > 0 && com.epl.geometry.Geometry.GetDimensionFromType(m_geomIntersectorType ) == 0)) { // multipoint // intersection double tolerance1 = com.epl.geometry.InternalUtils.CalculateToleranceFromGeometry(m_spatial_reference, input_geom, false); if (gtInput == com.epl.geometry.Geometry.GeometryType.MultiPoint) { return com.epl.geometry.TopologicalOperations.Intersection((com.epl.geometry.MultiPoint)input_geom, m_geomIntersector, tolerance1); } if (gtInput == com.epl.geometry.Geometry.GeometryType.Point) { return com.epl.geometry.TopologicalOperations.Intersection((com.epl.geometry.Point)input_geom, m_geomIntersector, tolerance1); } if (m_geomIntersectorType == com.epl.geometry.Geometry.GeometryType.MultiPoint) { return com.epl.geometry.TopologicalOperations.Intersection((com.epl.geometry.MultiPoint)m_geomIntersector, input_geom, tolerance1); } if (m_geomIntersectorType == com.epl.geometry.Geometry.GeometryType.Point) { return com.epl.geometry.TopologicalOperations.Intersection((com.epl.geometry.Point)m_geomIntersector, input_geom, tolerance1); } throw com.epl.geometry.GeometryException.GeometryInternalError(); } // Try Polyline vs Polygon if ((m_dimensionMask == -1 || m_dimensionMask == (1 << 1)) && (gtInput == com.epl.geometry.Geometry.GeometryType.Polyline) && (m_geomIntersectorType == com.epl.geometry.Geometry.GeometryType.Polygon)) { return TryFastIntersectPolylinePolygon_((com.epl.geometry.Polyline)(input_geom), (com.epl.geometry.Polygon)(m_geomIntersector)); } // Try Polygon vs Polyline if ((m_dimensionMask == -1 || m_dimensionMask == (1 << 1)) && (gtInput == com.epl.geometry.Geometry.GeometryType.Polygon) && (m_geomIntersectorType == com.epl.geometry.Geometry.GeometryType.Polyline)) { return TryFastIntersectPolylinePolygon_((com.epl.geometry.Polyline)(m_geomIntersector), (com.epl.geometry.Polygon)(input_geom)); } return null; }
public static int IsPointInRing(com.epl.geometry.MultiPathImpl inputPolygonImpl, int iRing, com.epl.geometry.Point2D inputPoint, double tolerance, com.epl.geometry.QuadTree quadTree) { com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); inputPolygonImpl.QueryLooseEnvelope2D(env); env.Inflate(tolerance, tolerance); if (!env.Contains(inputPoint)) { return(0); } bool bAltenate = true; com.epl.geometry.PointInPolygonHelper helper = new com.epl.geometry.PointInPolygonHelper(bAltenate, inputPoint, tolerance); if (quadTree != null) { com.epl.geometry.Envelope2D queryEnv = new com.epl.geometry.Envelope2D(); queryEnv.SetCoords(env); 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.SegmentIteratorImpl iter = inputPolygonImpl.QuerySegmentIterator(); com.epl.geometry.QuadTree.QuadTreeIterator qiter = quadTree.GetIterator(queryEnv, tolerance); for (int qhandle = qiter.Next(); qhandle != -1; qhandle = qiter.Next()) { iter.ResetToVertex(quadTree.GetElement(qhandle), iRing); if (iter.HasNextSegment()) { if (iter.GetPathIndex() != iRing) { continue; } com.epl.geometry.Segment segment = iter.NextSegment(); if (helper.ProcessSegment(segment)) { return(-1); } } } // point on boundary return(helper.Result()); } else { com.epl.geometry.SegmentIteratorImpl iter = inputPolygonImpl.QuerySegmentIterator(); iter.ResetToPath(iRing); if (iter.NextPath()) { while (iter.HasNextSegment()) { com.epl.geometry.Segment segment = iter.NextSegment(); if (helper.ProcessSegment(segment)) { return(-1); } } } // point on boundary return(helper.Result()); } }
public static void TestEnvelope2Dintersector() { System.Collections.Generic.List <com.epl.geometry.Envelope2D> envelopes = new System.Collections.Generic.List <com.epl.geometry.Envelope2D>(0); com.epl.geometry.Envelope2D env0 = new com.epl.geometry.Envelope2D(2, 3, 4, 4); com.epl.geometry.Envelope2D env1 = new com.epl.geometry.Envelope2D(5, 13, 9, 15); com.epl.geometry.Envelope2D env2 = new com.epl.geometry.Envelope2D(6, 9, 11, 12); com.epl.geometry.Envelope2D env3 = new com.epl.geometry.Envelope2D(8, 10, 9, 17); com.epl.geometry.Envelope2D env4 = new com.epl.geometry.Envelope2D(11.001, 12, 14, 14); com.epl.geometry.Envelope2D env5 = new com.epl.geometry.Envelope2D(1, 3, 3, 4); com.epl.geometry.Envelope2D env6 = new com.epl.geometry.Envelope2D(0, 2, 5, 10); com.epl.geometry.Envelope2D env7 = new com.epl.geometry.Envelope2D(4, 7, 5, 10); com.epl.geometry.Envelope2D env8 = new com.epl.geometry.Envelope2D(3, 15, 15, 15); com.epl.geometry.Envelope2D env9 = new com.epl.geometry.Envelope2D(0, 9, 14, 9); com.epl.geometry.Envelope2D env10 = new com.epl.geometry.Envelope2D(0, 8.999, 14, 8.999); envelopes.Add(env0); envelopes.Add(env1); envelopes.Add(env2); envelopes.Add(env3); envelopes.Add(env4); envelopes.Add(env5); envelopes.Add(env6); envelopes.Add(env7); envelopes.Add(env8); envelopes.Add(env9); envelopes.Add(env10); com.epl.geometry.Envelope2DIntersectorImpl intersector = new com.epl.geometry.Envelope2DIntersectorImpl(); intersector.SetTolerance(0.001); intersector.StartConstruction(); for (int i = 0; i < envelopes.Count; i++) { intersector.AddEnvelope(i, envelopes[i]); } intersector.EndConstruction(); int count = 0; while (intersector.Next()) { int env_a = intersector.GetHandleA(); int env_b = intersector.GetHandleB(); count++; com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); env.SetCoords(envelopes[env_a]); env.Inflate(0.001, 0.001); NUnit.Framework.Assert.IsTrue(env.IsIntersecting(envelopes[env_b])); } System.Diagnostics.Debug.Assert((count == 16)); com.epl.geometry.Envelope2DIntersectorImpl intersector2 = new com.epl.geometry.Envelope2DIntersectorImpl(); intersector2.SetTolerance(0.0); intersector2.StartConstruction(); for (int i_1 = 0; i_1 < envelopes.Count; i_1++) { intersector2.AddEnvelope(i_1, envelopes[i_1]); } intersector2.EndConstruction(); count = 0; while (intersector2.Next()) { int env_a = intersector2.GetHandleA(); int env_b = intersector2.GetHandleB(); count++; com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); env.SetCoords(envelopes[env_a]); NUnit.Framework.Assert.IsTrue(env.IsIntersecting(envelopes[env_b])); } System.Diagnostics.Debug.Assert((count == 13)); env0 = new com.epl.geometry.Envelope2D(0, 0, 0, 10); env1 = new com.epl.geometry.Envelope2D(0, 10, 10, 10); env2 = new com.epl.geometry.Envelope2D(10, 0, 10, 10); env3 = new com.epl.geometry.Envelope2D(0, 0, 10, 0); envelopes.Clear(); envelopes.Add(env0); envelopes.Add(env1); envelopes.Add(env2); envelopes.Add(env3); com.epl.geometry.Envelope2DIntersectorImpl intersector3 = new com.epl.geometry.Envelope2DIntersectorImpl(); intersector3.SetTolerance(0.001); intersector3.StartConstruction(); for (int i_2 = 0; i_2 < envelopes.Count; i_2++) { intersector3.AddEnvelope(i_2, envelopes[i_2]); } intersector3.EndConstruction(); count = 0; while (intersector3.Next()) { int env_a = intersector3.GetHandleA(); int env_b = intersector3.GetHandleB(); count++; com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); env.SetCoords(envelopes[env_a]); NUnit.Framework.Assert.IsTrue(env.IsIntersecting(envelopes[env_b])); } NUnit.Framework.Assert.IsTrue(count == 4); env0 = new com.epl.geometry.Envelope2D(0, 0, 0, 10); envelopes.Clear(); envelopes.Add(env0); envelopes.Add(env0); envelopes.Add(env0); envelopes.Add(env0); com.epl.geometry.Envelope2DIntersectorImpl intersector4 = new com.epl.geometry.Envelope2DIntersectorImpl(); intersector4.SetTolerance(0.001); intersector4.StartConstruction(); for (int i_3 = 0; i_3 < envelopes.Count; i_3++) { intersector4.AddEnvelope(i_3, envelopes[i_3]); } intersector4.EndConstruction(); count = 0; while (intersector4.Next()) { int env_a = intersector4.GetHandleA(); int env_b = intersector4.GetHandleB(); count++; com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); env.SetCoords(envelopes[env_a]); NUnit.Framework.Assert.IsTrue(env.IsIntersecting(envelopes[env_b])); } System.Diagnostics.Debug.Assert((count == 6)); env0 = new com.epl.geometry.Envelope2D(0, 10, 10, 10); envelopes.Clear(); envelopes.Add(env0); envelopes.Add(env0); envelopes.Add(env0); envelopes.Add(env0); com.epl.geometry.Envelope2DIntersectorImpl intersector5 = new com.epl.geometry.Envelope2DIntersectorImpl(); intersector5.SetTolerance(0.001); intersector5.StartConstruction(); for (int i_4 = 0; i_4 < envelopes.Count; i_4++) { intersector5.AddEnvelope(i_4, envelopes[i_4]); } intersector5.EndConstruction(); count = 0; while (intersector5.Next()) { int env_a = intersector5.GetHandleA(); int env_b = intersector5.GetHandleB(); count++; com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); env.SetCoords(envelopes[env_a]); NUnit.Framework.Assert.IsTrue(env.IsIntersecting(envelopes[env_b])); } NUnit.Framework.Assert.IsTrue(count == 6); }
internal static com.epl.geometry.Geometry Difference(com.epl.geometry.Geometry geometry_a, com.epl.geometry.Geometry geometry_b, com.epl.geometry.SpatialReference spatial_reference, com.epl.geometry.ProgressTracker progress_tracker) { if (geometry_a.IsEmpty() || geometry_b.IsEmpty()) { return(geometry_a); } int dimension_a = geometry_a.GetDimension(); int dimension_b = geometry_b.GetDimension(); if (dimension_a > dimension_b) { return(geometry_a); } int type_a = geometry_a.GetType().Value(); int type_b = geometry_b.GetType().Value(); com.epl.geometry.Envelope2D env_a = new com.epl.geometry.Envelope2D(); com.epl.geometry.Envelope2D env_b = new com.epl.geometry.Envelope2D(); com.epl.geometry.Envelope2D env_merged = new com.epl.geometry.Envelope2D(); geometry_a.QueryEnvelope2D(env_a); geometry_b.QueryEnvelope2D(env_b); env_merged.SetCoords(env_a); env_merged.Merge(env_b); double tolerance = com.epl.geometry.InternalUtils.CalculateToleranceFromGeometry(spatial_reference, env_merged, false); double tolerance_cluster = tolerance * System.Math.Sqrt(2.0) * 1.00001; com.epl.geometry.Envelope2D env_a_inflated = new com.epl.geometry.Envelope2D(); env_a_inflated.SetCoords(env_a); env_a_inflated.Inflate(tolerance_cluster, tolerance_cluster); // inflate // by // cluster // tolerance if (!env_a_inflated.IsIntersecting(env_b)) { return(geometry_a); } if (dimension_a == 1 && dimension_b == 2) { return(PolylineMinusArea_(geometry_a, geometry_b, type_b, spatial_reference, progress_tracker)); } if (type_a == com.epl.geometry.Geometry.GeometryType.Point) { com.epl.geometry.Geometry geometry_b_; if (com.epl.geometry.MultiPath.IsSegment(type_b)) { geometry_b_ = new com.epl.geometry.Polyline(geometry_b.GetDescription()); ((com.epl.geometry.Polyline)(geometry_b_)).AddSegment((com.epl.geometry.Segment)(geometry_b), true); } else { geometry_b_ = geometry_b; } switch (type_b) { case com.epl.geometry.Geometry.GeometryType.Polygon: { return(PointMinusPolygon_((com.epl.geometry.Point)(geometry_a), (com.epl.geometry.Polygon)(geometry_b_), tolerance, progress_tracker)); } case com.epl.geometry.Geometry.GeometryType.Polyline: { return(PointMinusPolyline_((com.epl.geometry.Point)(geometry_a), (com.epl.geometry.Polyline)(geometry_b_), tolerance, progress_tracker)); } case com.epl.geometry.Geometry.GeometryType.MultiPoint: { return(PointMinusMultiPoint_((com.epl.geometry.Point)(geometry_a), (com.epl.geometry.MultiPoint)(geometry_b_), tolerance, progress_tracker)); } case com.epl.geometry.Geometry.GeometryType.Envelope: { return(PointMinusEnvelope_((com.epl.geometry.Point)(geometry_a), (com.epl.geometry.Envelope)(geometry_b_), tolerance, progress_tracker)); } case com.epl.geometry.Geometry.GeometryType.Point: { return(PointMinusPoint_((com.epl.geometry.Point)(geometry_a), (com.epl.geometry.Point)(geometry_b_), tolerance, progress_tracker)); } default: { throw new System.ArgumentException(); } } } else { if (type_a == com.epl.geometry.Geometry.GeometryType.MultiPoint) { switch (type_b) { case com.epl.geometry.Geometry.GeometryType.Polygon: { return(MultiPointMinusPolygon_((com.epl.geometry.MultiPoint)(geometry_a), (com.epl.geometry.Polygon)(geometry_b), tolerance, progress_tracker)); } case com.epl.geometry.Geometry.GeometryType.Envelope: { return(MultiPointMinusEnvelope_((com.epl.geometry.MultiPoint)(geometry_a), (com.epl.geometry.Envelope)(geometry_b), tolerance, progress_tracker)); } case com.epl.geometry.Geometry.GeometryType.Point: { return(MultiPointMinusPoint_((com.epl.geometry.MultiPoint)(geometry_a), (com.epl.geometry.Point)(geometry_b), tolerance, progress_tracker)); } default: { break; } } } } return(com.epl.geometry.TopologicalOperations.Difference(geometry_a, geometry_b, spatial_reference, progress_tracker)); }
internal static com.epl.geometry.Envelope2DIntersectorImpl GetEnvelope2DIntersector(com.epl.geometry.MultiPathImpl multipathImplA, com.epl.geometry.MultiPathImpl multipathImplB, double tolerance) { com.epl.geometry.Envelope2D env_a = new com.epl.geometry.Envelope2D(); com.epl.geometry.Envelope2D env_b = new com.epl.geometry.Envelope2D(); multipathImplA.QueryLooseEnvelope2D(env_a); multipathImplB.QueryLooseEnvelope2D(env_b); env_a.Inflate(tolerance, tolerance); env_b.Inflate(tolerance, tolerance); com.epl.geometry.Envelope2D envInter = new com.epl.geometry.Envelope2D(); envInter.SetCoords(env_a); envInter.Intersect(env_b); com.epl.geometry.SegmentIteratorImpl segIterA = multipathImplA.QuerySegmentIterator(); com.epl.geometry.SegmentIteratorImpl segIterB = multipathImplB.QuerySegmentIterator(); com.epl.geometry.Envelope2DIntersectorImpl intersector = new com.epl.geometry.Envelope2DIntersectorImpl(); intersector.SetTolerance(tolerance); bool b_found_red = false; intersector.StartRedConstruction(); while (segIterA.NextPath()) { while (segIterA.HasNextSegment()) { com.epl.geometry.Segment segmentA = segIterA.NextSegment(); segmentA.QueryEnvelope2D(env_a); if (!env_a.IsIntersecting(envInter)) { continue; } b_found_red = true; com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); env.SetCoords(env_a); intersector.AddRedEnvelope(segIterA.GetStartPointIndex(), env); } } intersector.EndRedConstruction(); if (!b_found_red) { return(null); } bool b_found_blue = false; intersector.StartBlueConstruction(); while (segIterB.NextPath()) { while (segIterB.HasNextSegment()) { com.epl.geometry.Segment segmentB = segIterB.NextSegment(); segmentB.QueryEnvelope2D(env_b); if (!env_b.IsIntersecting(envInter)) { continue; } b_found_blue = true; com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); env.SetCoords(env_b); intersector.AddBlueEnvelope(segIterB.GetStartPointIndex(), env); } } intersector.EndBlueConstruction(); if (!b_found_blue) { return(null); } return(intersector); }
private static int QuickTest2DEnvelopeEnvelope(com.epl.geometry.Envelope2D geomAEnv, com.epl.geometry.Envelope2D geomBEnv, double tolerance) { // firstly check for contains and within to give a chance degenerate // envelopes to work. // otherwise, if there are two degenerate envelopes that are equal, // Touch relation may occur. int res = 0; if (geomAEnv.Contains(geomBEnv)) { res |= (int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Contains; } if (geomBEnv.Contains(geomAEnv)) { res |= (int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Within; } if (res != 0) { return(res); } com.epl.geometry.Envelope2D envAMinus = geomAEnv; envAMinus.Inflate(-tolerance, -tolerance); // Envelope A interior com.epl.geometry.Envelope2D envBMinus = geomBEnv; envBMinus.Inflate(-tolerance, -tolerance); // Envelope B interior if (envAMinus.IsIntersecting(envBMinus)) { com.epl.geometry.Envelope2D envAPlus = geomAEnv; envAPlus.Inflate(tolerance, tolerance); // Envelope A interior plus // boundary res = envAPlus.Contains(geomBEnv) ? (int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Contains : 0; com.epl.geometry.Envelope2D envBPlus = geomBEnv; envBPlus.Inflate(tolerance, tolerance); // Envelope A interior plus // boundary res |= envBPlus.Contains(geomAEnv) ? (int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Within : 0; if (res != 0) { return(res); } return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Overlaps); } else { // Clementini's Overlap com.epl.geometry.Envelope2D envAPlus = geomAEnv; envAPlus.Inflate(tolerance, tolerance); // Envelope A interior plus // boundary com.epl.geometry.Envelope2D envBPlus = geomBEnv; envBPlus.Inflate(tolerance, tolerance); // Envelope A interior plus // boundary if (envAPlus.IsIntersecting(envBPlus)) { return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Touches); } else { // Clementini Touch return((int)com.epl.geometry.OperatorInternalRelationUtils.Relation.Disjoint); } } }
private bool CrackBruteForce_() { com.epl.geometry.EditShape.VertexIterator iter_1 = m_shape.QueryVertexIterator(false); bool b_cracked = false; com.epl.geometry.Line line_1 = new com.epl.geometry.Line(); com.epl.geometry.Line line_2 = new com.epl.geometry.Line(); com.epl.geometry.Envelope2D seg_1_env = new com.epl.geometry.Envelope2D(); seg_1_env.SetEmpty(); com.epl.geometry.Envelope2D seg_2_env = new com.epl.geometry.Envelope2D(); seg_2_env.SetEmpty(); bool assume_intersecting = false; com.epl.geometry.Point helper_point = new com.epl.geometry.Point(); com.epl.geometry.SegmentIntersector segment_intersector = new com.epl.geometry.SegmentIntersector(); for (int vertex_1 = iter_1.Next(); vertex_1 != -1; vertex_1 = iter_1.Next()) { com.epl.geometry.ProgressTracker.CheckAndThrow(m_progress_tracker); int GT_1 = m_shape.GetGeometryType(iter_1.CurrentGeometry()); com.epl.geometry.Segment seg_1 = null; bool seg_1_zero = false; if (!com.epl.geometry.Geometry.IsPoint(GT_1)) { seg_1 = GetSegment_(vertex_1, line_1); if (seg_1 == null) { continue; } seg_1.QueryEnvelope2D(seg_1_env); seg_1_env.Inflate(m_tolerance, m_tolerance); if (seg_1.IsDegenerate(m_tolerance)) { // do not crack with // degenerate segments if (seg_1.IsDegenerate(0)) { seg_1_zero = true; seg_1 = null; } else { continue; } } } com.epl.geometry.EditShape.VertexIterator iter_2 = m_shape.QueryVertexIterator(iter_1); int vertex_2 = iter_2.Next(); if (vertex_2 != -1) { vertex_2 = iter_2.Next(); } for (; vertex_2 != -1; vertex_2 = iter_2.Next()) { int GT_2 = m_shape.GetGeometryType(iter_2.CurrentGeometry()); com.epl.geometry.Segment seg_2 = null; bool seg_2_zero = false; if (!com.epl.geometry.Geometry.IsPoint(GT_2)) { seg_2 = GetSegment_(vertex_2, line_2); if (seg_2 == null) { continue; } seg_2.QueryEnvelope2D(seg_2_env); if (seg_2.IsDegenerate(m_tolerance)) { // do not crack with // degenerate segments if (seg_2.IsDegenerate(0)) { seg_2_zero = true; seg_2 = null; } else { continue; } } } int split_count_1 = 0; int split_count_2 = 0; if (seg_1 != null && seg_2 != null) { if (seg_1_env.IsIntersectingNE(seg_2_env)) { segment_intersector.PushSegment(seg_1); segment_intersector.PushSegment(seg_2); segment_intersector.Intersect(m_tolerance, assume_intersecting); split_count_1 = segment_intersector.GetResultSegmentCount(0); split_count_2 = segment_intersector.GetResultSegmentCount(1); if (split_count_1 + split_count_2 > 0) { m_shape.SplitSegment_(vertex_1, segment_intersector, 0, true); m_shape.SplitSegment_(vertex_2, segment_intersector, 1, true); } segment_intersector.Clear(); } } else { if (seg_1 != null) { com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D(); m_shape.GetXY(vertex_2, pt); if (seg_1_env.Contains(pt)) { segment_intersector.PushSegment(seg_1); m_shape.QueryPoint(vertex_2, helper_point); segment_intersector.Intersect(m_tolerance, helper_point, 0, 1.0, assume_intersecting); split_count_1 = segment_intersector.GetResultSegmentCount(0); if (split_count_1 > 0) { m_shape.SplitSegment_(vertex_1, segment_intersector, 0, true); if (seg_2_zero) { //seg_2 was zero length. Need to change all coincident points //segment at vertex_2 is dzero length, change all attached zero length segments int v_to = -1; for (int v = m_shape.GetNextVertex(vertex_2); v != -1 && v != vertex_2; v = m_shape.GetNextVertex(v)) { seg_2 = GetSegment_(v, line_2); v_to = v; if (seg_2 == null || !seg_2.IsDegenerate(0)) { break; } } //change from vertex_2 to v_to (inclusive). for (int v_1 = vertex_2; v_1 != -1; v_1 = m_shape.GetNextVertex(v_1)) { m_shape.SetPoint(v_1, segment_intersector.GetResultPoint()); if (v_1 == v_to) { break; } } } else { m_shape.SetPoint(vertex_2, segment_intersector.GetResultPoint()); } } segment_intersector.Clear(); } } else { if (seg_2 != null) { com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D(); m_shape.GetXY(vertex_1, pt); seg_2_env.Inflate(m_tolerance, m_tolerance); if (seg_2_env.Contains(pt)) { segment_intersector.PushSegment(seg_2); m_shape.QueryPoint(vertex_1, helper_point); segment_intersector.Intersect(m_tolerance, helper_point, 0, 1.0, assume_intersecting); split_count_2 = segment_intersector.GetResultSegmentCount(0); if (split_count_2 > 0) { m_shape.SplitSegment_(vertex_2, segment_intersector, 0, true); if (seg_1_zero) { //seg_1 was zero length. Need to change all coincident points //segment at vertex_2 is dzero length, change all attached zero length segments int v_to = -1; for (int v = m_shape.GetNextVertex(vertex_1); v != -1 && v != vertex_1; v = m_shape.GetNextVertex(v)) { seg_2 = GetSegment_(v, line_2); //using here seg_2 for seg_1 v_to = v; if (seg_2 == null || !seg_2.IsDegenerate(0)) { break; } } //change from vertex_2 to v_to (inclusive). for (int v_1 = vertex_1; v_1 != -1; v_1 = m_shape.GetNextVertex(v_1)) { m_shape.SetPoint(v_1, segment_intersector.GetResultPoint()); if (v_1 == v_to) { break; } } } else { m_shape.SetPoint(vertex_1, segment_intersector.GetResultPoint()); } } segment_intersector.Clear(); } } else { continue; } } } // points on points if (split_count_1 + split_count_2 != 0) { if (split_count_1 != 0) { seg_1 = m_shape.GetSegment(vertex_1); // reload segment // after split if (seg_1 == null) { if (!m_shape.QueryLineConnector(vertex_1, line_1)) { continue; } seg_1 = line_1; line_1.QueryEnvelope2D(seg_1_env); } else { seg_1.QueryEnvelope2D(seg_1_env); } if (seg_1.IsDegenerate(m_tolerance)) { // do not crack with // degenerate // segments break; } } b_cracked = true; } } } return(b_cracked); }
internal static com.epl.geometry.Envelope2DIntersectorImpl GetEnvelope2DIntersectorForParts(com.epl.geometry.MultiPathImpl multipathImplA, com.epl.geometry.MultiPathImpl multipathImplB, double tolerance, bool bExteriorOnlyA, bool bExteriorOnlyB) { int type_a = multipathImplA.GetType().Value(); int type_b = multipathImplB.GetType().Value(); com.epl.geometry.Envelope2D env_a = new com.epl.geometry.Envelope2D(); com.epl.geometry.Envelope2D env_b = new com.epl.geometry.Envelope2D(); multipathImplA.QueryLooseEnvelope2D(env_a); multipathImplB.QueryLooseEnvelope2D(env_b); env_a.Inflate(tolerance, tolerance); env_b.Inflate(tolerance, tolerance); com.epl.geometry.Envelope2D envInter = new com.epl.geometry.Envelope2D(); envInter.SetCoords(env_a); envInter.Intersect(env_b); com.epl.geometry.Envelope2DIntersectorImpl intersector = new com.epl.geometry.Envelope2DIntersectorImpl(); intersector.SetTolerance(tolerance); bool b_found_red = false; intersector.StartRedConstruction(); for (int ipath_a = 0, npaths = multipathImplA.GetPathCount(); ipath_a < npaths; ipath_a++) { if (bExteriorOnlyA && type_a == com.epl.geometry.Geometry.GeometryType.Polygon && !multipathImplA.IsExteriorRing(ipath_a)) { continue; } multipathImplA.QueryPathEnvelope2D(ipath_a, env_a); if (!env_a.IsIntersecting(envInter)) { continue; } b_found_red = true; intersector.AddRedEnvelope(ipath_a, env_a); } intersector.EndRedConstruction(); if (!b_found_red) { return(null); } bool b_found_blue = false; intersector.StartBlueConstruction(); for (int ipath_b = 0, npaths = multipathImplB.GetPathCount(); ipath_b < npaths; ipath_b++) { if (bExteriorOnlyB && type_b == com.epl.geometry.Geometry.GeometryType.Polygon && !multipathImplB.IsExteriorRing(ipath_b)) { continue; } multipathImplB.QueryPathEnvelope2D(ipath_b, env_b); if (!env_b.IsIntersecting(envInter)) { continue; } b_found_blue = true; intersector.AddBlueEnvelope(ipath_b, env_b); } intersector.EndBlueConstruction(); if (!b_found_blue) { return(null); } return(intersector); }
/// <summary>Changes the dimensions of the envelope while preserving the center.</summary> /// <remarks> /// Changes the dimensions of the envelope while preserving the center. New width /// is Width + 2 * dx, new height is Height + 2 * dy. If the result envelope /// width or height becomes negative, the envelope is set to be empty. /// </remarks> /// <param name="dx">The inflation along the x-axis.</param> /// <param name="dy">The inflation along the y-axis.</param> public virtual void Inflate(double dx, double dy) { _touch(); m_envelope.Inflate(dx, dy); }