public override bool Equals(com.epl.geometry.AttributeStreamBase other, int start, int end) { if (other == null) { return(false); } if (!(other is com.epl.geometry.AttributeStreamOfDbl)) { return(false); } com.epl.geometry.AttributeStreamOfDbl _other = (com.epl.geometry.AttributeStreamOfDbl)other; int size = Size(); int sizeOther = _other.Size(); if (end > size || end > sizeOther && (size != sizeOther)) { return(false); } if (end > size) { end = size; } for (int i = start; i < end; i++) { if (Read(i) != _other.Read(i)) { return(false); } } return(true); }
public AttributeStreamOfDbl(com.epl.geometry.AttributeStreamOfDbl other, int maxSize) { m_size = other.Size(); if (m_size > maxSize) { m_size = maxSize; } int sz = m_size; if (sz < 2) { sz = 2; } m_buffer = new double[sz]; System.Array.Copy(other.m_buffer, 0, m_buffer, 0, m_size); }
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 static int LineStringText(bool b_ring, com.epl.geometry.AttributeStreamOfDbl zs, com.epl.geometry.AttributeStreamOfDbl ms, com.epl.geometry.AttributeStreamOfDbl position, com.epl.geometry.AttributeStreamOfInt32 paths, com.epl.geometry.AttributeStreamOfInt8 path_flags , com.epl.geometry.WktParser wkt_parser) { // At start of LineStringText int current_token = wkt_parser.CurrentToken(); int point_count = 0; if (current_token == com.epl.geometry.WktParser.WktToken.empty) { return(point_count); } bool b_start_path = true; double startx = com.epl.geometry.NumberUtils.TheNaN; double starty = com.epl.geometry.NumberUtils.TheNaN; double startz = com.epl.geometry.NumberUtils.TheNaN; double startm = com.epl.geometry.NumberUtils.TheNaN; current_token = wkt_parser.NextToken(); while (current_token != com.epl.geometry.WktParser.WktToken.right_paren) { // At start of x double x = wkt_parser.CurrentNumericLiteral(); wkt_parser.NextToken(); double y = wkt_parser.CurrentNumericLiteral(); wkt_parser.NextToken(); double z = com.epl.geometry.NumberUtils.TheNaN; double m = com.epl.geometry.NumberUtils.TheNaN; if (wkt_parser.HasZs()) { z = wkt_parser.CurrentNumericLiteral(); wkt_parser.NextToken(); } if (wkt_parser.HasMs()) { m = wkt_parser.CurrentNumericLiteral(); wkt_parser.NextToken(); } current_token = wkt_parser.CurrentToken(); bool b_add_point = true; if (b_ring && point_count >= 2 && current_token == com.epl.geometry.WktParser.WktToken.right_paren) { // If the last point in the ring is not equal to the start // point, then let's add it. if ((startx == x || (com.epl.geometry.NumberUtils.IsNaN(startx) && com.epl.geometry.NumberUtils.IsNaN(x))) && (starty == y || (com.epl.geometry.NumberUtils.IsNaN(starty) && com.epl.geometry.NumberUtils.IsNaN(y))) && (!wkt_parser.HasZs() || startz == z || (com.epl.geometry.NumberUtils .IsNaN(startz) && com.epl.geometry.NumberUtils.IsNaN(z))) && (!wkt_parser.HasMs() || startm == m || (com.epl.geometry.NumberUtils.IsNaN(startm) && com.epl.geometry.NumberUtils.IsNaN(m)))) { b_add_point = false; } } if (b_add_point) { if (b_start_path) { b_start_path = false; startx = x; starty = y; startz = z; startm = m; } point_count++; AddToStreams(zs, ms, position, x, y, z, m); } } if (point_count == 1) { point_count++; AddToStreams(zs, ms, position, startx, starty, startz, startm); } paths.Add(position.Size() / 2); path_flags.Add(unchecked ((byte)0)); return(point_count); }
// for (int i = start, n = start + count; i < n; i++) // write(i, v); public override void WriteRange(int startElement, int count, com.epl.geometry.AttributeStreamBase _src, int srcStart, bool bForward, int stride) { if (startElement < 0 || count < 0 || srcStart < 0) { throw new System.ArgumentException(); } if (!bForward && (stride <= 0 || (count % stride != 0))) { throw new System.ArgumentException(); } com.epl.geometry.AttributeStreamOfDbl src = (com.epl.geometry.AttributeStreamOfDbl)_src; // the input // type must // match if (src.Size() < (int)(srcStart + count)) { throw new System.ArgumentException(); } if (count == 0) { return; } if (Size() < count + startElement) { Resize(count + startElement); } if (_src == (com.epl.geometry.AttributeStreamBase) this) { _selfWriteRangeImpl(startElement, count, srcStart, bForward, stride); return; } if (bForward) { int j = startElement; int offset = srcStart; for (int i = 0; i < count; i++) { m_buffer[j] = src.m_buffer[offset]; j++; offset++; } } else { int j = startElement; int offset = srcStart + count - stride; if (stride == 1) { for (int i = 0; i < count; i++) { m_buffer[j] = src.m_buffer[offset]; j++; offset--; } } else { for (int i = 0, n = count / stride; i < n; i++) { for (int k = 0; k < stride; k++) { m_buffer[j + k] = src.m_buffer[offset + k]; } j += stride; offset -= stride; } } } }
/// <exception cref="System.Exception"/> private static com.epl.geometry.Geometry ImportFromJsonMultiPath(bool b_polygon, com.epl.geometry.JsonReader parser, com.epl.geometry.AttributeStreamOfDbl @as, com.epl.geometry.AttributeStreamOfDbl bs) { if (parser.CurrentToken() != com.epl.geometry.JsonReader.Token.START_ARRAY) { throw new com.epl.geometry.GeometryException("failed to parse multipath: array of array of vertices is expected"); } com.epl.geometry.MultiPath multipath; if (b_polygon) { multipath = new com.epl.geometry.Polygon(); } else { multipath = new com.epl.geometry.Polyline(); } com.epl.geometry.AttributeStreamOfInt32 parts = (com.epl.geometry.AttributeStreamOfInt32)com.epl.geometry.AttributeStreamBase.CreateIndexStream(0); com.epl.geometry.AttributeStreamOfDbl position = (com.epl.geometry.AttributeStreamOfDbl)com.epl.geometry.AttributeStreamBase.CreateDoubleStream(2, 0); com.epl.geometry.AttributeStreamOfInt8 pathFlags = (com.epl.geometry.AttributeStreamOfInt8)com.epl.geometry.AttributeStreamBase.CreateByteStream(0); // set up min max variables double[] buf = new double[4]; double[] start = new double[4]; int point_count = 0; int path_count = 0; byte pathFlag = b_polygon ? unchecked ((byte)com.epl.geometry.PathFlags.enumClosed) : 0; int requiredSize = b_polygon ? 3 : 2; // At start of rings while (parser.NextToken() != com.epl.geometry.JsonReader.Token.END_ARRAY) { if (parser.CurrentToken() != com.epl.geometry.JsonReader.Token.START_ARRAY) { throw new com.epl.geometry.GeometryException("failed to parse multipath: ring/path array is expected"); } int pathPointCount = 0; bool b_first = true; int sz = 0; int szstart = 0; parser.NextToken(); while (parser.CurrentToken() != com.epl.geometry.JsonReader.Token.END_ARRAY) { if (parser.CurrentToken() != com.epl.geometry.JsonReader.Token.START_ARRAY) { throw new com.epl.geometry.GeometryException("failed to parse multipath: array is expected, rings/paths vertices consist of arrays of cooridinates"); } sz = 0; while (parser.NextToken() != com.epl.geometry.JsonReader.Token.END_ARRAY) { buf[sz++] = ReadDouble(parser); } if (sz < 2) { throw new com.epl.geometry.GeometryException("failed to parse multipath: each vertex array has to have at least 2 elements"); } parser.NextToken(); do { if (position.Size() == point_count * 2) { int c = point_count * 3; if (c % 2 != 0) { c++; } // have to be even if (c < 8) { c = 8; } else { if (c < 32) { c = 32; } } position.Resize(c); } position.Write(2 * point_count, buf[0]); position.Write(2 * point_count + 1, buf[1]); if (@as.Size() == point_count) { int c = (point_count * 3) / 2; // have to be even if (c < 4) { c = 4; } else { if (c < 16) { c = 16; } } @as.Resize(c); } if (sz > 2) { @as.Write(point_count, buf[2]); } else { @as.Write(point_count, com.epl.geometry.NumberUtils.NaN()); } if (bs.Size() == point_count) { int c = (point_count * 3) / 2; // have to be even if (c < 4) { c = 4; } else { if (c < 16) { c = 16; } } bs.Resize(c); } if (sz > 3) { bs.Write(point_count, buf[3]); } else { bs.Write(point_count, com.epl.geometry.NumberUtils.NaN()); } if (b_first) { path_count++; parts.Add(point_count); pathFlags.Add(pathFlag); b_first = false; szstart = sz; start[0] = buf[0]; start[1] = buf[1]; start[2] = buf[2]; start[3] = buf[3]; } point_count++; pathPointCount++; }while (pathPointCount < requiredSize && parser.CurrentToken() == com.epl.geometry.JsonReader.Token.END_ARRAY); } if (b_polygon && pathPointCount > requiredSize && sz == szstart && start[0] == buf[0] && start[1] == buf[1] && start[2] == buf[2] && start[3] == buf[3]) { // remove the end point that is equal to the start point. point_count--; pathPointCount--; } if (pathPointCount == 0) { continue; } } // skip empty paths if (point_count != 0) { parts.Resize(path_count); pathFlags.Resize(path_count); if (point_count > 0) { parts.Add(point_count); pathFlags.Add(unchecked ((byte)0)); } com.epl.geometry.MultiPathImpl mp_impl = (com.epl.geometry.MultiPathImpl)multipath._getImpl(); mp_impl.SetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.POSITION, position); mp_impl.SetPathFlagsStreamRef(pathFlags); mp_impl.SetPathStreamRef(parts); } return(multipath); }
/// <exception cref="System.Exception"/> private static com.epl.geometry.Geometry ImportFromJsonMultiPoint(com.epl.geometry.JsonReader parser, com.epl.geometry.AttributeStreamOfDbl @as, com.epl.geometry.AttributeStreamOfDbl bs) { if (parser.CurrentToken() != com.epl.geometry.JsonReader.Token.START_ARRAY) { throw new com.epl.geometry.GeometryException("failed to parse multipoint: array of vertices is expected"); } int point_count = 0; com.epl.geometry.MultiPoint multipoint; multipoint = new com.epl.geometry.MultiPoint(); com.epl.geometry.AttributeStreamOfDbl position = (com.epl.geometry.AttributeStreamOfDbl)(com.epl.geometry.AttributeStreamBase.CreateDoubleStream(2, 0)); // At start of rings int sz; double[] buf = new double[4]; while (parser.NextToken() != com.epl.geometry.JsonReader.Token.END_ARRAY) { if (parser.CurrentToken() != com.epl.geometry.JsonReader.Token.START_ARRAY) { throw new com.epl.geometry.GeometryException("failed to parse multipoint: array is expected, multipoint vertices consist of arrays of cooridinates"); } sz = 0; while (parser.NextToken() != com.epl.geometry.JsonReader.Token.END_ARRAY) { buf[sz++] = ReadDouble(parser); } if (sz < 2) { throw new com.epl.geometry.GeometryException("failed to parse multipoint: each vertex array has to have at least 2 elements"); } if (position.Size() == 2 * point_count) { int c = point_count * 3; if (c % 2 != 0) { c++; } // have to be even position.Resize(c); } position.Write(2 * point_count, buf[0]); position.Write(2 * point_count + 1, buf[1]); if (@as.Size() == point_count) { int c = (point_count * 3) / 2; if (c < 4) { c = 4; } else { if (c < 16) { c = 16; } } @as.Resize(c); } if (sz > 2) { @as.Write(point_count, buf[2]); } else { @as.Write(point_count, com.epl.geometry.NumberUtils.NaN()); } if (bs.Size() == point_count) { int c = (point_count * 3) / 2; if (c < 4) { c = 4; } else { if (c < 16) { c = 16; } } bs.Resize(c); } if (sz > 3) { bs.Write(point_count, buf[3]); } else { bs.Write(point_count, com.epl.geometry.NumberUtils.NaN()); } point_count++; } if (point_count != 0) { com.epl.geometry.MultiPointImpl mp_impl = (com.epl.geometry.MultiPointImpl)multipoint._getImpl(); mp_impl.Resize(point_count); mp_impl.SetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.POSITION, position); } return(multipoint); }