// check // that x // projections // overlap // check that // y // projections // overlap /// <summary> /// Intersects this envelope with the other and stores result in this /// envelope. /// </summary> /// <returns> /// True if this envelope intersects the other, otherwise sets this /// envelope to empty state and returns False. /// </returns> public bool Intersect(com.epl.geometry.Envelope2D other) { if (IsEmpty() || other.IsEmpty()) { return(false); } if (other.xmin > xmin) { xmin = other.xmin; } if (other.xmax < xmax) { xmax = other.xmax; } if (other.ymin > ymin) { ymin = other.ymin; } if (other.ymax < ymax) { ymax = other.ymax; } bool bIntersecting = xmin <= xmax && ymin <= ymax; if (!bIntersecting) { SetEmpty(); } return(bIntersecting); }
/// <summary>Returns squared max distance between two bounding boxes.</summary> /// <remarks>Returns squared max distance between two bounding boxes. This is furthest distance between points on the two envelopes.</remarks> /// <param name="other">The bounding box to calculate the max distance two.</param> /// <returns>Squared distance value.</returns> public double SqrMaxDistance(com.epl.geometry.Envelope2D other) { if (IsEmpty() || other.IsEmpty()) { return(com.epl.geometry.NumberUtils.TheNaN); } double dist = 0; com.epl.geometry.Point2D[] points = new com.epl.geometry.Point2D[4]; QueryCorners(points); com.epl.geometry.Point2D[] points_o = new com.epl.geometry.Point2D[4]; other.QueryCorners(points_o); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { double d = com.epl.geometry.Point2D.SqrDistance(points[i], points_o[j]); if (d > dist) { dist = d; } } } return(dist); }
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); }
/// <summary> /// Initializes an orhtonormal transformation from the Src and Dest /// rectangles. /// </summary> /// <remarks> /// Initializes an orhtonormal transformation from the Src and Dest /// rectangles. /// The result transformation proportionally fits the Src into the Dest. The /// center of the Src will be in the center of the Dest. /// </remarks> internal void InitializeFromRectIsotropic(com.epl.geometry.Envelope2D src, com.epl.geometry.Envelope2D dest) { if (src.IsEmpty() || dest.IsEmpty() || 0 == src.GetWidth() || 0 == src.GetHeight()) { SetZero(); } else { yx = 0; xy = 0; xx = dest.GetWidth() / src.GetWidth(); yy = dest.GetHeight() / src.GetHeight(); if (xx > yy) { xx = yy; } else { yy = xx; } com.epl.geometry.Point2D destCenter = dest.GetCenter(); com.epl.geometry.Point2D srcCenter = src.GetCenter(); xd = destCenter.x - srcCenter.x * xx; yd = destCenter.y - srcCenter.y * yy; } }
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); }
public void Merge(com.epl.geometry.Envelope2D other) { if (other.IsEmpty()) { return; } Merge(other.xmin, other.ymin); Merge(other.xmax, other.ymax); }
/// <summary>Transforms envelope</summary> /// <param name="env">The envelope that is to be transformed</param> internal void Transform(com.epl.geometry.Envelope2D env) { if (env.IsEmpty()) { return; } com.epl.geometry.Point2D[] buf = new com.epl.geometry.Point2D[4]; env.QueryCorners(buf); Transform(buf, buf); env.SetFromPoints(buf, 4); }
/// <summary>Initialize transformation from two rectangles.</summary> internal void InitializeFromRect(com.epl.geometry.Envelope2D src, com.epl.geometry.Envelope2D dest) { if (src.IsEmpty() || dest.IsEmpty() || 0 == src.GetWidth() || 0 == src.GetHeight()) { SetZero(); } else { xy = yx = 0; xx = dest.GetWidth() / src.GetWidth(); yy = dest.GetHeight() / src.GetHeight(); xd = dest.xmin - src.xmin * xx; yd = dest.ymin - src.ymin * yy; } }
internal static com.epl.geometry.QuadTreeImpl BuildQuadTreeForPaths(com.epl.geometry.MultiPathImpl multipathImpl) { com.epl.geometry.Envelope2D extent = new com.epl.geometry.Envelope2D(); multipathImpl.QueryLooseEnvelope2D(extent); if (extent.IsEmpty()) { return(null); } com.epl.geometry.QuadTreeImpl quad_tree_impl = new com.epl.geometry.QuadTreeImpl(extent, 8); int hint_index = -1; com.epl.geometry.Envelope2D boundingbox = new com.epl.geometry.Envelope2D(); bool resized_extent = false; do { for (int ipath = 0, npaths = multipathImpl.GetPathCount(); ipath < npaths; ipath++) { multipathImpl.QueryPathEnvelope2D(ipath, boundingbox); hint_index = quad_tree_impl.Insert(ipath, boundingbox, hint_index); if (hint_index == -1) { if (resized_extent) { throw com.epl.geometry.GeometryException.GeometryInternalError(); } //This is usually happens because esri shape buffer contains geometry extent which is slightly different from the true extent. //Recalculate extent multipathImpl.CalculateEnvelope2D(extent, false); resized_extent = true; quad_tree_impl.Reset(extent, 8); break; } else { //break the for loop resized_extent = false; } } }while (resized_extent); return(quad_tree_impl); }
public override bool Equals(object _other) { if (_other == this) { return(true); } if (!(_other is com.epl.geometry.Envelope2D)) { return(false); } com.epl.geometry.Envelope2D other = (com.epl.geometry.Envelope2D)_other; if (IsEmpty() && other.IsEmpty()) { return(true); } if (xmin != other.xmin || ymin != other.ymin || xmax != other.xmax || ymax != other.ymax) { return(false); } return(true); }
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 virtual com.epl.geometry.Geometry TryFastIntersectPolylinePolygon_(com.epl.geometry.Polyline polyline, com.epl.geometry.Polygon polygon) { com.epl.geometry.MultiPathImpl polylineImpl = (com.epl.geometry.MultiPathImpl)polyline._getImpl(); com.epl.geometry.MultiPathImpl polygonImpl = (com.epl.geometry.MultiPathImpl)polygon._getImpl(); double tolerance = com.epl.geometry.InternalUtils.CalculateToleranceFromGeometry(m_spatial_reference, polygon, false); com.epl.geometry.Envelope2D clipEnvelope = new com.epl.geometry.Envelope2D(); { polygonImpl.QueryEnvelope2D(clipEnvelope); com.epl.geometry.Envelope2D env1 = new com.epl.geometry.Envelope2D(); polylineImpl.QueryEnvelope2D(env1); env1.Inflate(2.0 * tolerance, 2.0 * tolerance); clipEnvelope.Intersect(env1); System.Diagnostics.Debug.Assert((!clipEnvelope.IsEmpty())); } clipEnvelope.Inflate(10 * tolerance, 10 * tolerance); if (true) { double tol = 0; com.epl.geometry.Geometry clippedPolyline = com.epl.geometry.Clipper.Clip(polyline, clipEnvelope, tol, 0.0); polyline = (com.epl.geometry.Polyline)clippedPolyline; polylineImpl = (com.epl.geometry.MultiPathImpl)polyline._getImpl(); } com.epl.geometry.AttributeStreamOfInt32 clipResult = new com.epl.geometry.AttributeStreamOfInt32(0); int unresolvedSegments = -1; com.epl.geometry.GeometryAccelerators accel = polygonImpl._getAccelerators(); if (accel != null) { com.epl.geometry.RasterizedGeometry2D rgeom = accel.GetRasterizedGeometry(); if (rgeom != null) { unresolvedSegments = 0; clipResult.Reserve(polylineImpl.GetPointCount() + polylineImpl.GetPathCount()); com.epl.geometry.Envelope2D seg_env = new com.epl.geometry.Envelope2D(); com.epl.geometry.SegmentIteratorImpl iter = polylineImpl.QuerySegmentIterator(); while (iter.NextPath()) { while (iter.HasNextSegment()) { com.epl.geometry.Segment seg = iter.NextSegment(); seg.QueryEnvelope2D(seg_env); com.epl.geometry.RasterizedGeometry2D.HitType hit = rgeom.QueryEnvelopeInGeometry(seg_env); if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Inside) { clipResult.Add(1); } else { if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Outside) { clipResult.Add(0); } else { clipResult.Add(-1); unresolvedSegments++; } } } } } } if (polygon.GetPointCount() > 5) { double tol = 0; com.epl.geometry.Geometry clippedPolygon = com.epl.geometry.Clipper.Clip(polygon, clipEnvelope, tol, 0.0); polygon = (com.epl.geometry.Polygon)clippedPolygon; polygonImpl = (com.epl.geometry.MultiPathImpl)polygon._getImpl(); accel = polygonImpl._getAccelerators(); } //update accelerators if (unresolvedSegments < 0) { unresolvedSegments = polylineImpl.GetSegmentCount(); } // Some heuristics to decide if it makes sense to go with fast intersect // vs going with the regular planesweep. double totalPoints = (double)(polylineImpl.GetPointCount() + polygonImpl.GetPointCount()); double thisAlgorithmComplexity = ((double)unresolvedSegments * polygonImpl.GetPointCount()); // assume the worst case. double planesweepComplexity = System.Math.Log(totalPoints) * totalPoints; double empiricConstantFactorPlaneSweep = 4; if (thisAlgorithmComplexity > planesweepComplexity * empiricConstantFactorPlaneSweep) { // Based on the number of input points, we deduced that the // plansweep performance should be better than the brute force // performance. return null; } // resort to planesweep if quadtree does not help com.epl.geometry.QuadTreeImpl polygonQuadTree = null; com.epl.geometry.SegmentIteratorImpl polygonIter = polygonImpl.QuerySegmentIterator(); // Some logic to decide if it makes sense to build a quadtree on the // polygon segments if (accel != null && accel.GetQuadTree() != null) { polygonQuadTree = accel.GetQuadTree(); } if (polygonQuadTree == null && polygonImpl.GetPointCount() > 20) { polygonQuadTree = com.epl.geometry.InternalUtils.BuildQuadTree(polygonImpl); } com.epl.geometry.Polyline result_polyline = (com.epl.geometry.Polyline)polyline.CreateInstance(); com.epl.geometry.MultiPathImpl resultPolylineImpl = (com.epl.geometry.MultiPathImpl)result_polyline._getImpl(); com.epl.geometry.QuadTreeImpl.QuadTreeIteratorImpl qIter = null; com.epl.geometry.SegmentIteratorImpl polylineIter = polylineImpl.QuerySegmentIterator(); double[] @params = new double[9]; com.epl.geometry.AttributeStreamOfDbl intersections = new com.epl.geometry.AttributeStreamOfDbl(0); com.epl.geometry.SegmentBuffer segmentBuffer = new com.epl.geometry.SegmentBuffer(); int start_index = -1; int inCount = 0; int segIndex = 0; bool bOptimized = clipResult.Size() > 0; // The algorithm is like that: // Loop through all the segments of the polyline. // For each polyline segment, intersect it with each of the polygon // segments. // If no intersections found then, // If the polyline segment is completely inside, it is added to the // result polyline. // If it is outside, it is thrown out. // If it intersects, then cut the polyline segment to pieces and test // each part of the intersected result. // The cut pieces will either have one point inside, or one point // outside, or the middle point inside/outside. // int polylinePathIndex = -1; while (polylineIter.NextPath()) { polylinePathIndex = polylineIter.GetPathIndex(); int stateNewPath = 0; int stateAddSegment = 1; int stateManySegments = 2; int stateManySegmentsContinuePath = 2; int stateManySegmentsNewPath = 3; int state = stateNewPath; start_index = -1; inCount = 0; while (polylineIter.HasNextSegment()) { int clipStatus = bOptimized ? (int)clipResult.Get(segIndex) : -1; segIndex++; com.epl.geometry.Segment polylineSeg = polylineIter.NextSegment(); if (clipStatus < 0) { System.Diagnostics.Debug.Assert((clipStatus == -1)); // Analyse polyline segment for intersection with the // polygon. if (polygonQuadTree != null) { if (qIter == null) { qIter = polygonQuadTree.GetIterator(polylineSeg, tolerance); } else { qIter.ResetIterator(polylineSeg, tolerance); } int path_index = -1; for (int ind = qIter.Next(); ind != -1; ind = qIter.Next()) { polygonIter.ResetToVertex(polygonQuadTree.GetElement(ind)); // path_index path_index = polygonIter.GetPathIndex(); com.epl.geometry.Segment polygonSeg = polygonIter.NextSegment(); // intersect polylineSeg and polygonSeg. int count = polylineSeg.Intersect(polygonSeg, null, @params, null, tolerance); for (int i = 0; i < count; i++) { intersections.Add(@params[i]); } } } else { // no quadtree built polygonIter.ResetToFirstPath(); while (polygonIter.NextPath()) { while (polygonIter.HasNextSegment()) { com.epl.geometry.Segment polygonSeg = polygonIter.NextSegment(); // intersect polylineSeg and polygonSeg. int count = polylineSeg.Intersect(polygonSeg, null, @params, null, tolerance); for (int i = 0; i < count; i++) { intersections.Add(@params[i]); } } } } if (intersections.Size() > 0) { // intersections detected. intersections.Sort(0, intersections.Size()); // std::sort(intersections.begin(), // intersections.end()); double t0 = 0; intersections.Add(1.0); int status = -1; for (int i = 0, n = intersections.Size(); i < n; i++) { double t = intersections.Get(i); if (t == t0) { continue; } bool bWholeSegment = false; com.epl.geometry.Segment resSeg; if (t0 != 0 || t != 1.0) { polylineSeg.Cut(t0, t, segmentBuffer); resSeg = segmentBuffer.Get(); } else { resSeg = polylineSeg; bWholeSegment = true; } if (state >= stateManySegments) { resultPolylineImpl.AddSegmentsFromPath(polylineImpl, polylinePathIndex, start_index, inCount, state == stateManySegmentsNewPath); if (AnalyseClipSegment_(polygon, resSeg.GetStartXY(), tolerance) != 1) { if (AnalyseClipSegment_(polygon, resSeg, tolerance) != 1) { return null; } } //someting went wrong we'll falback to slower but robust planesweep code. resultPolylineImpl.AddSegment(resSeg, false); state = stateAddSegment; inCount = 0; } else { status = AnalyseClipSegment_(polygon, resSeg, tolerance); switch (status) { case 1: { if (!bWholeSegment) { resultPolylineImpl.AddSegment(resSeg, state == stateNewPath); state = stateAddSegment; } else { if (state < stateManySegments) { start_index = polylineIter.GetStartPointIndex() - polylineImpl.GetPathStart(polylinePathIndex); inCount = 1; if (state == stateNewPath) { state = stateManySegmentsNewPath; } else { System.Diagnostics.Debug.Assert((state == stateAddSegment)); state = stateManySegmentsContinuePath; } } else { inCount++; } } break; } case 0: { state = stateNewPath; start_index = -1; inCount = 0; break; } default: { return null; } } } // may happen if a segment // coincides with the border. t0 = t; } } else { clipStatus = AnalyseClipSegment_(polygon, polylineSeg.GetStartXY(), tolerance); // simple // case // no // intersection. // Both // points // must // be // inside. if (clipStatus < 0) { System.Diagnostics.Debug.Assert((clipStatus >= 0)); return null; } // something goes wrong, resort to // planesweep System.Diagnostics.Debug.Assert((AnalyseClipSegment_(polygon, polylineSeg.GetEndXY(), tolerance) == clipStatus)); if (clipStatus == 1) { // the whole segment inside if (state < stateManySegments) { System.Diagnostics.Debug.Assert((inCount == 0)); start_index = polylineIter.GetStartPointIndex() - polylineImpl.GetPathStart(polylinePathIndex); if (state == stateNewPath) { state = stateManySegmentsNewPath; } else { System.Diagnostics.Debug.Assert((state == stateAddSegment)); state = stateManySegmentsContinuePath; } } inCount++; } else { System.Diagnostics.Debug.Assert((state < stateManySegments)); start_index = -1; inCount = 0; } } intersections.Clear(false); } else { // clip status is determined by other means if (clipStatus == 0) { // outside System.Diagnostics.Debug.Assert((AnalyseClipSegment_(polygon, polylineSeg, tolerance) == 0)); System.Diagnostics.Debug.Assert((start_index < 0)); System.Diagnostics.Debug.Assert((inCount == 0)); continue; } if (clipStatus == 1) { System.Diagnostics.Debug.Assert((AnalyseClipSegment_(polygon, polylineSeg, tolerance) == 1)); if (state == stateNewPath) { state = stateManySegmentsNewPath; start_index = polylineIter.GetStartPointIndex() - polylineImpl.GetPathStart(polylinePathIndex); } else { if (state == stateAddSegment) { state = stateManySegmentsContinuePath; start_index = polylineIter.GetStartPointIndex() - polylineImpl.GetPathStart(polylinePathIndex); } else { System.Diagnostics.Debug.Assert((state >= stateManySegments)); } } inCount++; continue; } } } if (state >= stateManySegments) { resultPolylineImpl.AddSegmentsFromPath(polylineImpl, polylinePathIndex, start_index, inCount, state == stateManySegmentsNewPath); start_index = -1; } } return result_polyline; }
public static void Test_perf_quad_tree() { com.epl.geometry.Envelope extent1 = new com.epl.geometry.Envelope(); extent1.SetCoords(-1000, -1000, 1000, 1000); com.epl.geometry.RandomCoordinateGenerator generator1 = new com.epl.geometry.RandomCoordinateGenerator(1000, extent1, 0.001); //HiResTimer timer; for (int N = 16; N <= 1024; N *= 2) { //timer.StartMeasurement(); com.epl.geometry.Envelope2D extent = new com.epl.geometry.Envelope2D(); extent.SetCoords(-1000, -1000, 1000, 1000); System.Collections.Generic.Dictionary <int, com.epl.geometry.Envelope2D> data = new System.Collections.Generic.Dictionary <int, com.epl.geometry.Envelope2D>(0); com.epl.geometry.QuadTree qt = new com.epl.geometry.QuadTree(extent, 10); for (int i = 0; i < N; i++) { com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); com.epl.geometry.Point2D center = generator1.GetRandomCoord().GetXY(); double w = 10; env.SetCoords(center, w, w); env.Intersect(extent); if (env.IsEmpty()) { continue; } int h = qt.Insert(i, env); data[h] = env; } int ecount = 0; com.epl.geometry.AttributeStreamOfInt32 handles = new com.epl.geometry.AttributeStreamOfInt32(0); com.epl.geometry.QuadTree.QuadTreeIterator iter = qt.GetIterator(); System.Collections.Generic.IEnumerator <System.Collections.Generic.KeyValuePair <int, com.epl.geometry.Envelope2D> > pairs = data.GetEnumerator(); while (pairs.MoveNext()) { System.Collections.Generic.KeyValuePair <int, com.epl.geometry.Envelope2D> entry = pairs.Current; iter.ResetIterator((com.epl.geometry.Envelope2D)entry.Value, 0.001); bool remove_self = false; for (int h = iter.Next(); h != -1; h = iter.Next()) { if (h != entry.Key) { handles.Add(h); } else { remove_self = true; } ecount++; } for (int i_1 = 0; i_1 < handles.Size(); i_1++) { qt.RemoveElement(handles.Get(i_1)); } //remove elements that were selected. if (remove_self) { qt.RemoveElement(entry.Key); } handles.Resize(0); } } }
/// <summary>Indicates whether this envelope contains any points.</summary> /// <returns>boolean Returns true if the envelope is empty.</returns> public override bool IsEmpty() { return(m_envelope.IsEmpty()); }