// Tests if Ring1 is inside Ring2. // We assume here that the Polygon is Weak Simple. That is if one point of // Ring1 is found to be inside of Ring2, then // we assume that all of Ring1 is inside Ring2. internal static bool _isRingInRing2D(com.epl.geometry.MultiPath polygon, int iRing1, int iRing2, double tolerance, com.epl.geometry.QuadTree quadTree) { com.epl.geometry.MultiPathImpl polygonImpl = (com.epl.geometry.MultiPathImpl)polygon._getImpl(); com.epl.geometry.SegmentIteratorImpl segIter = polygonImpl.QuerySegmentIterator(); segIter.ResetToPath(iRing1); if (!segIter.NextPath() || !segIter.HasNextSegment()) { throw new com.epl.geometry.GeometryException("corrupted geometry"); } int res = 2; while (res == 2 && segIter.HasNextSegment()) { com.epl.geometry.Segment segment = segIter.NextSegment(); com.epl.geometry.Point2D point = segment.GetCoord2D(0.5); res = com.epl.geometry.PointInPolygonHelper.IsPointInRing(polygonImpl, iRing2, point, tolerance, quadTree); } if (res == 2) { throw com.epl.geometry.GeometryException.GeometryInternalError(); } if (res == 1) { return(true); } return(false); }
private com.epl.geometry.Geometry Generalize(com.epl.geometry.Geometry geom) { com.epl.geometry.Geometry.Type gt = geom.GetType(); if (com.epl.geometry.Geometry.IsPoint(gt.Value())) { return(geom); } if (gt == com.epl.geometry.Geometry.Type.Envelope) { com.epl.geometry.Polygon poly = new com.epl.geometry.Polygon(geom.GetDescription()); poly.AddEnvelope((com.epl.geometry.Envelope)geom, false); return(Generalize(poly)); } if (geom.IsEmpty()) { return(geom); } com.epl.geometry.MultiPath mp = (com.epl.geometry.MultiPath)geom; com.epl.geometry.MultiPath dstmp = (com.epl.geometry.MultiPath)geom.CreateInstance(); com.epl.geometry.Line line = new com.epl.geometry.Line(); for (int ipath = 0, npath = mp.GetPathCount(); ipath < npath; ipath++) { GeneralizePath((com.epl.geometry.MultiPathImpl)mp._getImpl(), ipath, (com.epl.geometry.MultiPathImpl)dstmp._getImpl(), line); } return(dstmp); }
public OGCLinearRing(com.epl.geometry.MultiPath mp, int pathIndex, com.epl.geometry.SpatialReference sr, bool reversed) : base(mp, pathIndex, sr, reversed) { if (!mp.IsClosedPath(0)) { throw new System.ArgumentException("LinearRing path must be closed"); } }
public OGCLineString(com.epl.geometry.MultiPath mp, int pathIndex, com.epl.geometry.SpatialReference sr, bool reversed) { multiPath = new com.epl.geometry.Polyline(); if (!mp.IsEmpty()) { multiPath.AddPath(mp, pathIndex, !reversed); } esriSR = sr; }
public static com.epl.geometry.Point[] PointsFromMultiPath(com.epl.geometry.MultiPath geom) { int numberOfPoints = geom.GetPointCount(); com.epl.geometry.Point[] points = new com.epl.geometry.Point[numberOfPoints]; for (int i = 0; i < geom.GetPointCount(); i++) { points[i] = geom.GetPoint(i); } return(points); }
public virtual bool IsClosed() { com.epl.geometry.MultiPath mp = (com.epl.geometry.MultiPath)GetEsriGeometry(); for (int i = 0, n = mp.GetPathCount(); i < n; i++) { if (!mp.IsClosedPathInXYPlane(i)) { return(false); } } return(true); }
internal void ShiftPath(com.epl.geometry.MultiPath inputGeom, int iPath, double shift) { com.epl.geometry.MultiVertexGeometryImpl vertexGeometryImpl = (com.epl.geometry.MultiVertexGeometryImpl)inputGeom._getImpl(); com.epl.geometry.AttributeStreamOfDbl xyStream = (com.epl.geometry.AttributeStreamOfDbl)vertexGeometryImpl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.POSITION); int i1 = inputGeom.GetPathStart(iPath); int i2 = inputGeom.GetPathEnd(iPath); com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D(); while (i1 < i2) { xyStream.Read(i1, pt); pt.x += shift; xyStream.Write(i1, pt); i1++; } }
public static com.epl.geometry.QuadTree BuildQuadTree(com.epl.geometry.MultiPath multipath) { com.epl.geometry.Envelope2D extent = new com.epl.geometry.Envelope2D(); multipath.QueryEnvelope2D(extent); com.epl.geometry.QuadTree quadTree = new com.epl.geometry.QuadTree(extent, 8); int hint_index = -1; com.epl.geometry.SegmentIterator seg_iter = multipath.QuerySegmentIterator(); while (seg_iter.NextPath()) { while (seg_iter.HasNextSegment()) { com.epl.geometry.Segment segment = seg_iter.NextSegment(); int index = seg_iter.GetStartPointIndex(); com.epl.geometry.Envelope2D boundingbox = new com.epl.geometry.Envelope2D(); segment.QueryEnvelope2D(boundingbox); hint_index = quadTree.Insert(index, boundingbox, hint_index); } } return(quadTree); }
private com.epl.geometry.Geometry DensifyMultiPath(com.epl.geometry.MultiPath geom) { com.epl.geometry.MultiPath densifiedPoly = (com.epl.geometry.MultiPath)geom.CreateInstance(); com.epl.geometry.SegmentIterator iter = geom.QuerySegmentIterator(); while (iter.NextPath()) { bool bStartNewPath = true; while (iter.HasNextSegment()) { com.epl.geometry.Segment seg = iter.NextSegment(); if (seg.GetType().Value() != com.epl.geometry.Geometry.GeometryType.Line) { throw new com.epl.geometry.GeometryException("not implemented"); } bool bIsClosing = iter.IsClosingSegment(); double len = seg.CalculateLength2D(); if (len > m_maxLength) { // need to split double dcount = System.Math.Ceiling(len / m_maxLength); com.epl.geometry.Point point = new com.epl.geometry.Point(geom.GetDescription()); // LOCALREFCLASS1(Point, // VertexDescription, // point, // geom.getDescription()); if (bStartNewPath) { bStartNewPath = false; seg.QueryStart(point); densifiedPoly.StartPath(point); } double dt = 1.0 / dcount; double t = dt; for (int i = 0, n = (int)dcount - 1; i < n; i++) { seg.QueryCoord(t, point); densifiedPoly.LineTo(point); t += dt; } if (!bIsClosing) { seg.QueryEnd(point); densifiedPoly.LineTo(point); } else { densifiedPoly.ClosePathWithLine(); } bStartNewPath = false; } else { if (!bIsClosing) { densifiedPoly.AddSegment(seg, bStartNewPath); } else { densifiedPoly.ClosePathWithLine(); } bStartNewPath = false; } } } return((com.epl.geometry.Geometry)densifiedPoly); }
/// <summary>Appends all paths from another multipath.</summary> /// <param name="src">The multipath to append to this multipath.</param> /// <param name="bReversePaths"> /// TRUE if the multipath is added should be added with its paths /// reversed. /// </param> public virtual void Add(com.epl.geometry.MultiPath src, bool bReversePaths) { m_impl.Add((com.epl.geometry.MultiPathImpl)src._getImpl(), bReversePaths); }
internal virtual bool RgHelper(com.epl.geometry.RasterizedGeometry2D rg, com.epl.geometry.MultiPath mp) { com.epl.geometry.SegmentIterator iter = mp.QuerySegmentIterator(); while (iter.NextPath()) { while (iter.HasNextSegment()) { com.epl.geometry.Segment seg = iter.NextSegment(); int count = 20; for (int i = 0; i < count; i++) { double t = (1.0 * i / count); com.epl.geometry.Point2D pt = seg.GetCoord2D(t); com.epl.geometry.RasterizedGeometry2D.HitType hit = rg.QueryPointInGeometry(pt.x, pt.y); if (hit != com.epl.geometry.RasterizedGeometry2D.HitType.Border) { return(false); } } } } if (mp.GetType() != com.epl.geometry.Geometry.Type.Polygon) { return(true); } com.epl.geometry.Polygon poly = (com.epl.geometry.Polygon)mp; com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); poly.QueryEnvelope2D(env); int count_1 = 100; for (int iy = 0; iy < count_1; iy++) { double ty = 1.0 * iy / count_1; double y = env.ymin * (1.0 - ty) + ty * env.ymax; for (int ix = 0; ix < count_1; ix++) { double tx = 1.0 * ix / count_1; double x = env.xmin * (1.0 - tx) + tx * env.xmax; com.epl.geometry.RasterizedGeometry2D.HitType hit = rg.QueryPointInGeometry(x, y); com.epl.geometry.PolygonUtils.PiPResult res = com.epl.geometry.PolygonUtils.IsPointInPolygon2D(poly, new com.epl.geometry.Point2D(x, y), 0); if (res == com.epl.geometry.PolygonUtils.PiPResult.PiPInside) { bool bgood = (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Border || hit == com.epl.geometry.RasterizedGeometry2D.HitType.Inside); if (!bgood) { return(false); } } else { if (res == com.epl.geometry.PolygonUtils.PiPResult.PiPOutside) { bool bgood = (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Border || hit == com.epl.geometry.RasterizedGeometry2D.HitType.Outside); if (!bgood) { return(false); } } else { bool bgood = (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Border); if (!bgood) { return(false); } } } } } return(true); }
/// <summary>Returns true if the given path of the input MultiPath is convex.</summary> /// <remarks> /// Returns true if the given path of the input MultiPath is convex. Returns false otherwise. /// \param multi_path The MultiPath to check if the path is convex. /// \param path_index The path of the MultiPath to check if its convex. /// </remarks> internal static bool IsPathConvex(com.epl.geometry.MultiPath multi_path, int path_index, com.epl.geometry.ProgressTracker progress_tracker) { com.epl.geometry.MultiPathImpl mimpl = (com.epl.geometry.MultiPathImpl)multi_path._getImpl(); int path_start = mimpl.GetPathStart(path_index); int path_end = mimpl.GetPathEnd(path_index); bool bxyclosed = !mimpl.IsClosedPath(path_index) && mimpl.IsClosedPathInXYPlane(path_index); com.epl.geometry.AttributeStreamOfDbl position = (com.epl.geometry.AttributeStreamOfDbl)(mimpl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.POSITION)); int position_start = 2 * path_start; int position_end = 2 * path_end; if (bxyclosed) { position_end -= 2; } if (position_end - position_start < 6) { return(true); } // This matches the logic for case 1 of the tree hull algorithm. The idea is inductive. We assume we have a convex hull pt_0,...,pt_m, and we see if // a new point (pt_pivot) is among the transitive tournament for pt_0, knowing that pt_pivot comes after pt_m. // We check three conditions: // 1) pt_m->pt_pivot->pt_0 is clockwise (closure across the boundary is convex) // 2) pt_1->pt_pivot->pt_0 is clockwise (the first step forward is convex) (pt_1 is the next point after pt_0) // 3) pt_m->pt_pivot->pt_m_prev is clockwise (the first step backwards is convex) (pt_m_prev is the previous point before pt_m) // If all three of the above conditions are clockwise, then pt_pivot is among the transitive tournament for pt_0, and therefore the polygon pt_0, ..., pt_m, pt_pivot is convex. com.epl.geometry.Point2D pt_0 = new com.epl.geometry.Point2D(); com.epl.geometry.Point2D pt_m = new com.epl.geometry.Point2D(); com.epl.geometry.Point2D pt_pivot = new com.epl.geometry.Point2D(); position.Read(position_start, pt_0); position.Read(position_start + 2, pt_m); position.Read(position_start + 4, pt_pivot); // Initial inductive step com.epl.geometry.ECoordinate det_ec = Determinant_(pt_m, pt_pivot, pt_0); if (det_ec.IsFuzzyZero() || !IsClockwise_(det_ec.Value())) { return(false); } com.epl.geometry.Point2D pt_1 = new com.epl.geometry.Point2D(pt_m.x, pt_m.y); com.epl.geometry.Point2D pt_m_prev = new com.epl.geometry.Point2D(); // Assume that pt_0,...,pt_m is convex. Check if the next point, pt_pivot, maintains the convex invariant. for (int i = position_start + 6; i < position_end; i += 2) { pt_m_prev.SetCoords(pt_m); pt_m.SetCoords(pt_pivot); position.Read(i, pt_pivot); det_ec = Determinant_(pt_m, pt_pivot, pt_0); if (det_ec.IsFuzzyZero() || !IsClockwise_(det_ec.Value())) { return(false); } det_ec = Determinant_(pt_1, pt_pivot, pt_0); if (det_ec.IsFuzzyZero() || !IsClockwise_(det_ec.Value())) { return(false); } det_ec = Determinant_(pt_m, pt_pivot, pt_m_prev); if (det_ec.IsFuzzyZero() || !IsClockwise_(det_ec.Value())) { return(false); } } return(true); }
private static int ExportMultiPathToESRIShape(bool bPolygon, int exportFlags, com.epl.geometry.MultiPath multipath, System.IO.BinaryWriter shapeBuffer) { com.epl.geometry.MultiPathImpl multipathImpl = (com.epl.geometry.MultiPathImpl)multipath._getImpl(); bool bExportZs = multipathImpl.HasAttribute(com.epl.geometry.VertexDescription.Semantics.Z) && (exportFlags & com.epl.geometry.ShapeExportFlags.ShapeExportStripZs) == 0; bool bExportMs = multipathImpl.HasAttribute(com.epl.geometry.VertexDescription.Semantics.M) && (exportFlags & com.epl.geometry.ShapeExportFlags.ShapeExportStripMs) == 0; bool bExportIDs = multipathImpl.HasAttribute(com.epl.geometry.VertexDescription.Semantics.ID) && (exportFlags & com.epl.geometry.ShapeExportFlags.ShapeExportStripIDs) == 0; bool bHasCurves = multipathImpl.HasNonLinearSegments(); bool bArcViewNaNs = (exportFlags & com.epl.geometry.ShapeExportFlags.ShapeExportTrueNaNs) == 0; int partCount = multipathImpl.GetPathCount(); int pointCount = multipathImpl.GetPointCount(); if (!bPolygon) { for (int ipart = 0; ipart < partCount; ipart++) { if (multipath.IsClosedPath(ipart)) { pointCount++; } } } else { pointCount += partCount; } int size = (4) + (4 * 8) + (4) + (4) + (partCount * 4) + pointCount * 2 * 8; /* type */ /* envelope */ /* part count */ /* point count */ /* start indices */ /* xy coordinates */ if (bExportZs) { size += (2 * 8) + (pointCount * 8); } /* min max */ /* zs */ if (bExportMs) { size += (2 * 8) + (pointCount * 8); } /* min max */ /* ms */ if (bExportIDs) { size += pointCount * 4; } /* ids */ if (bHasCurves) { } // to-do: curves if (size >= com.epl.geometry.NumberUtils.IntMax()) { throw new com.epl.geometry.GeometryException("invalid call"); } if (shapeBuffer == null) { return(size); } else { if (((System.IO.MemoryStream)shapeBuffer.BaseStream).Capacity < size) { throw new com.epl.geometry.GeometryException("buffer is too small"); } } int offset = 0; // Determine the shape type int type; if (!bExportZs && !bExportMs) { if (bExportIDs || bHasCurves) { type = bPolygon ? com.epl.geometry.ShapeType.ShapeGeneralPolygon : com.epl.geometry.ShapeType.ShapeGeneralPolyline; if (bExportIDs) { type |= com.epl.geometry.ShapeModifiers.ShapeHasIDs; } if (bHasCurves) { type |= com.epl.geometry.ShapeModifiers.ShapeHasCurves; } } else { type = bPolygon ? com.epl.geometry.ShapeType.ShapePolygon : com.epl.geometry.ShapeType.ShapePolyline; } } else { if (bExportZs && !bExportMs) { if (bExportIDs || bHasCurves) { type = bPolygon ? com.epl.geometry.ShapeType.ShapeGeneralPolygon : com.epl.geometry.ShapeType.ShapeGeneralPolyline; type |= com.epl.geometry.ShapeModifiers.ShapeHasZs; if (bExportIDs) { type |= com.epl.geometry.ShapeModifiers.ShapeHasIDs; } if (bHasCurves) { type |= com.epl.geometry.ShapeModifiers.ShapeHasCurves; } } else { type = bPolygon ? com.epl.geometry.ShapeType.ShapePolygonZ : com.epl.geometry.ShapeType.ShapePolylineZ; } } else { if (bExportMs && !bExportZs) { if (bExportIDs || bHasCurves) { type = bPolygon ? com.epl.geometry.ShapeType.ShapeGeneralPolygon : com.epl.geometry.ShapeType.ShapeGeneralPolyline; type |= com.epl.geometry.ShapeModifiers.ShapeHasMs; if (bExportIDs) { type |= com.epl.geometry.ShapeModifiers.ShapeHasIDs; } if (bHasCurves) { type |= com.epl.geometry.ShapeModifiers.ShapeHasCurves; } } else { type = bPolygon ? com.epl.geometry.ShapeType.ShapePolygonM : com.epl.geometry.ShapeType.ShapePolylineM; } } else { if (bExportIDs || bHasCurves) { type = bPolygon ? com.epl.geometry.ShapeType.ShapeGeneralPolygon : com.epl.geometry.ShapeType.ShapeGeneralPolyline; type |= com.epl.geometry.ShapeModifiers.ShapeHasZs | com.epl.geometry.ShapeModifiers.ShapeHasMs; if (bExportIDs) { type |= com.epl.geometry.ShapeModifiers.ShapeHasIDs; } if (bHasCurves) { type |= com.epl.geometry.ShapeModifiers.ShapeHasCurves; } } else { type = bPolygon ? com.epl.geometry.ShapeType.ShapePolygonZM : com.epl.geometry.ShapeType.ShapePolylineZM; } } } } // write type shapeBuffer.Write(type); offset += 4; // write Envelope com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); multipathImpl.QueryEnvelope2D(env); // calls _VerifyAllStreams shapeBuffer.Write(env.xmin); offset += 8; shapeBuffer.Write(env.ymin); offset += 8; shapeBuffer.Write(env.xmax); offset += 8; shapeBuffer.Write(env.ymax); offset += 8; // write part count shapeBuffer.Write(partCount); offset += 4; // to-do: return error if larger than 2^32 - 1 // write pointCount shapeBuffer.Write(pointCount); offset += 4; // write start indices for each part int pointIndexDelta = 0; for (int ipart = 0; ipart < partCount; ipart++) { int istart = multipathImpl.GetPathStart(ipart) + pointIndexDelta; shapeBuffer.Write(istart); offset += 4; if (bPolygon || multipathImpl.IsClosedPath(ipart)) { pointIndexDelta++; } } if (pointCount > 0) { // write xy coordinates com.epl.geometry.AttributeStreamBase positionStream = multipathImpl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.POSITION); com.epl.geometry.AttributeStreamOfDbl position = (com.epl.geometry.AttributeStreamOfDbl)positionStream; for (int ipart = 0; ipart < partCount; ipart++) { int partStart = multipathImpl.GetPathStart(ipart); int partEnd = multipathImpl.GetPathEnd(ipart); for (int i = partStart; i < partEnd; i++) { double x = position.Read(2 * i); double y = position.Read(2 * i + 1); shapeBuffer.Write(x); offset += 8; shapeBuffer.Write(y); offset += 8; } // If the part is closed, then we need to duplicate the start // point if (bPolygon || multipathImpl.IsClosedPath(ipart)) { double x = position.Read(2 * partStart); double y = position.Read(2 * partStart + 1); shapeBuffer.Write(x); offset += 8; shapeBuffer.Write(y); offset += 8; } } } // write Zs if (bExportZs) { com.epl.geometry.Envelope1D zInterval = multipathImpl.QueryInterval(com.epl.geometry.VertexDescription.Semantics.Z, 0); shapeBuffer.Write(bArcViewNaNs ? com.epl.geometry.Interop.TranslateToAVNaN(zInterval.vmin) : zInterval.vmin); offset += 8; shapeBuffer.Write(bArcViewNaNs ? com.epl.geometry.Interop.TranslateToAVNaN(zInterval.vmax) : zInterval.vmax); offset += 8; if (pointCount > 0) { if (multipathImpl._attributeStreamIsAllocated(com.epl.geometry.VertexDescription.Semantics.Z)) { com.epl.geometry.AttributeStreamOfDbl zs = (com.epl.geometry.AttributeStreamOfDbl)multipathImpl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.Z); for (int ipart = 0; ipart < partCount; ipart++) { int partStart = multipathImpl.GetPathStart(ipart); int partEnd = multipathImpl.GetPathEnd(ipart); for (int i = partStart; i < partEnd; i++) { double z = zs.Read(i); shapeBuffer.Write(bArcViewNaNs ? com.epl.geometry.Interop.TranslateToAVNaN(z) : z); offset += 8; } // If the part is closed, then we need to duplicate the // start z if (bPolygon || multipathImpl.IsClosedPath(ipart)) { double z = zs.Read(partStart); shapeBuffer.Write(z); offset += 8; } } } else { double z = com.epl.geometry.VertexDescription.GetDefaultValue(com.epl.geometry.VertexDescription.Semantics.Z); if (bArcViewNaNs) { z = com.epl.geometry.Interop.TranslateToAVNaN(z); } for (int i = 0; i < pointCount; i++) { shapeBuffer.Write(z); } offset += 8; } } } // write Ms if (bExportMs) { com.epl.geometry.Envelope1D mInterval = multipathImpl.QueryInterval(com.epl.geometry.VertexDescription.Semantics.M, 0); shapeBuffer.Write(bArcViewNaNs ? com.epl.geometry.Interop.TranslateToAVNaN(mInterval.vmin) : mInterval.vmin); offset += 8; shapeBuffer.Write(bArcViewNaNs ? com.epl.geometry.Interop.TranslateToAVNaN(mInterval.vmax) : mInterval.vmax); offset += 8; if (pointCount > 0) { if (multipathImpl._attributeStreamIsAllocated(com.epl.geometry.VertexDescription.Semantics.M)) { com.epl.geometry.AttributeStreamOfDbl ms = (com.epl.geometry.AttributeStreamOfDbl)multipathImpl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.M); for (int ipart = 0; ipart < partCount; ipart++) { int partStart = multipathImpl.GetPathStart(ipart); int partEnd = multipathImpl.GetPathEnd(ipart); for (int i = partStart; i < partEnd; i++) { double m = ms.Read(i); shapeBuffer.Write(bArcViewNaNs ? com.epl.geometry.Interop.TranslateToAVNaN(m) : m); offset += 8; } // If the part is closed, then we need to duplicate the // start m if (bPolygon || multipathImpl.IsClosedPath(ipart)) { double m = ms.Read(partStart); shapeBuffer.Write(m); offset += 8; } } } else { double m = com.epl.geometry.VertexDescription.GetDefaultValue(com.epl.geometry.VertexDescription.Semantics.M); if (bArcViewNaNs) { m = com.epl.geometry.Interop.TranslateToAVNaN(m); } for (int i = 0; i < pointCount; i++) { shapeBuffer.Write(m); } offset += 8; } } } // write Curves if (bHasCurves) { } // to-do: We'll finish this later // write IDs if (bExportIDs) { if (pointCount > 0) { if (multipathImpl._attributeStreamIsAllocated(com.epl.geometry.VertexDescription.Semantics.ID)) { com.epl.geometry.AttributeStreamOfInt32 ids = (com.epl.geometry.AttributeStreamOfInt32)multipathImpl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.ID); for (int ipart = 0; ipart < partCount; ipart++) { int partStart = multipathImpl.GetPathStart(ipart); int partEnd = multipathImpl.GetPathEnd(ipart); for (int i = partStart; i < partEnd; i++) { int id = ids.Read(i); shapeBuffer.Write(id); offset += 4; } // If the part is closed, then we need to duplicate the // start id if (bPolygon || multipathImpl.IsClosedPath(ipart)) { int id = ids.Read(partStart); shapeBuffer.Write(id); offset += 4; } } } else { int id = (int)com.epl.geometry.VertexDescription.GetDefaultValue(com.epl.geometry.VertexDescription.Semantics.ID); for (int i = 0; i < pointCount; i++) { shapeBuffer.Write(id); } offset += 4; } } } return(offset); }
public override int NumGeometries() { com.epl.geometry.MultiPath mp = (com.epl.geometry.MultiPath)GetEsriGeometry(); return(mp.GetPathCount()); }
internal virtual com.epl.geometry.Proximity2DResult MultiPathGetNearestCoordinate(com.epl.geometry.MultiPath geom, com.epl.geometry.Point2D inputPoint, bool bTestPolygonInterior, bool bCalculateLeftRightSide) { if (geom.GetType() == com.epl.geometry.Geometry.Type.Polygon && bTestPolygonInterior) { com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(); geom.QueryEnvelope2D(env); double tolerance = com.epl.geometry.InternalUtils.CalculateToleranceFromGeometry(null, env, false); com.epl.geometry.PolygonUtils.PiPResult pipResult; if (bCalculateLeftRightSide) { pipResult = com.epl.geometry.PolygonUtils.IsPointInPolygon2D((com.epl.geometry.Polygon)geom, inputPoint, 0.0); } else { pipResult = com.epl.geometry.PolygonUtils.IsPointInPolygon2D((com.epl.geometry.Polygon)geom, inputPoint, tolerance); } if (pipResult != com.epl.geometry.PolygonUtils.PiPResult.PiPOutside) { com.epl.geometry.Proximity2DResult result = new com.epl.geometry.Proximity2DResult(inputPoint, 0, 0.0); if (bCalculateLeftRightSide) { result.SetRightSide(true); } return(result); } } com.epl.geometry.SegmentIterator segIter = geom.QuerySegmentIterator(); com.epl.geometry.Point2D closest = new com.epl.geometry.Point2D(); int closestVertexIndex = -1; int closestPathIndex = -1; double closestDistanceSq = com.epl.geometry.NumberUtils.DoubleMax(); bool bRight = false; int num_candidates = 0; while (segIter.NextPath()) { while (segIter.HasNextSegment()) { com.epl.geometry.Segment segment = segIter.NextSegment(); double t = segment.GetClosestCoordinate(inputPoint, false); com.epl.geometry.Point2D point = segment.GetCoord2D(t); double distanceSq = com.epl.geometry.Point2D.SqrDistance(point, inputPoint); if (distanceSq < closestDistanceSq) { num_candidates = 1; closest = point; closestVertexIndex = segIter.GetStartPointIndex(); closestPathIndex = segIter.GetPathIndex(); closestDistanceSq = distanceSq; } else { if (distanceSq == closestDistanceSq) { num_candidates++; } } } } com.epl.geometry.Proximity2DResult result_1 = new com.epl.geometry.Proximity2DResult(closest, closestVertexIndex, System.Math.Sqrt(closestDistanceSq)); if (bCalculateLeftRightSide) { segIter.ResetToVertex(closestVertexIndex, closestPathIndex); com.epl.geometry.Segment segment = segIter.NextSegment(); bRight = (com.epl.geometry.Point2D.OrientationRobust(inputPoint, segment.GetStartXY(), segment.GetEndXY()) < 0); if (num_candidates > 1) { com.epl.geometry.OperatorProximity2DLocal.Side_helper sideHelper = new com.epl.geometry.OperatorProximity2DLocal.Side_helper(this); sideHelper.Reset(); bRight = sideHelper.Calc_side(inputPoint, bRight, geom, closestVertexIndex, closestPathIndex); } result_1.SetRightSide(bRight); } return(result_1); }
private double BruteForceMultiPathMultiPath_(com.epl.geometry.MultiPath geometryA, com.epl.geometry.MultiPath geometryB, bool geometriesAreDisjoint) { /* const */ /* const */ // It may be beneficial to have the geometry with less vertices // always be geometryA. com.epl.geometry.SegmentIterator segIterA = geometryA.QuerySegmentIterator(); com.epl.geometry.SegmentIterator segIterB = geometryB.QuerySegmentIterator(); com.epl.geometry.Envelope2D env2DSegmentA = new com.epl.geometry.Envelope2D(); com.epl.geometry.Envelope2D env2DSegmentB = new com.epl.geometry.Envelope2D(); double minSqrDistance = com.epl.geometry.NumberUtils.DoubleMax(); if (!geometriesAreDisjoint) { // Geometries might be non-disjoint. Check if they intersect // using point-in-polygon tests if (this.WeakIntersectionTest_(geometryA, geometryB, segIterA, segIterB)) { return(0.0); } } // if geometries are known disjoint, don't bother to do any tests // for polygon containment // nested while-loop insanity while (segIterA.NextPath()) { while (segIterA.HasNextSegment()) { /* const */ com.epl.geometry.Segment segmentA = segIterA.NextSegment(); segmentA.QueryEnvelope2D(env2DSegmentA); if (env2DSegmentA.SqrDistance(this.m_env2DgeometryB) > minSqrDistance) { continue; } while (segIterB.NextPath()) { while (segIterB.HasNextSegment()) { /* const */ com.epl.geometry.Segment segmentB = segIterB.NextSegment(); segmentB.QueryEnvelope2D(env2DSegmentB); if (env2DSegmentA.SqrDistance(env2DSegmentB) < minSqrDistance) { // get distance between segments double sqrDistance = segmentA.Distance(segmentB, geometriesAreDisjoint); sqrDistance *= sqrDistance; if (sqrDistance < minSqrDistance) { if (sqrDistance == 0.0) { return(0.0); } minSqrDistance = sqrDistance; } } } } segIterB.ResetToFirstPath(); } } return(System.Math.Sqrt(minSqrDistance)); }
/// <summary>Inserts a path from another multipath.</summary> /// <param name="pathIndex">The start index of the multipath to insert.</param> /// <param name="src"> /// The multipath to insert into this multipath. Can be the same /// as the multipath being modified. /// </param> /// <param name="srcPathIndex">The start index to insert the path into the multipath.</param> /// <param name="bForward">When FALSE, the points are inserted in reverse order.</param> public virtual void InsertPath(int pathIndex, com.epl.geometry.MultiPath src, int srcPathIndex, bool bForward) { m_impl.InsertPath(pathIndex, (com.epl.geometry.MultiPathImpl)src._getImpl(), srcPathIndex, bForward); }
/// <summary>Copies a path from another multipath.</summary> /// <param name="src">The multipath to copy from.</param> /// <param name="srcPathIndex">The index of the path in the the source MultiPath.</param> /// <param name="bForward">When FALSE, the points are inserted in reverse order.</param> public virtual void AddPath(com.epl.geometry.MultiPath src, int srcPathIndex, bool bForward) { m_impl.AddPath((com.epl.geometry.MultiPathImpl)src._getImpl(), srcPathIndex, bForward); }
private double BruteForceMultiPathMultiPoint_(com.epl.geometry.MultiPath geometryA, com.epl.geometry.MultiPoint geometryB, bool geometriesAreDisjoint) { /* const */ /* const */ com.epl.geometry.SegmentIterator segIterA = geometryA.QuerySegmentIterator(); com.epl.geometry.Envelope2D env2DSegmentA = new com.epl.geometry.Envelope2D(); double minSqrDistance = com.epl.geometry.NumberUtils.DoubleMax(); com.epl.geometry.Point2D inputPoint = new com.epl.geometry.Point2D(); double t = -1; double sqrDistance = minSqrDistance; /* const */ com.epl.geometry.MultiPointImpl multiPointImplB = (com.epl.geometry.MultiPointImpl)geometryB._getImpl(); int pointCountB = multiPointImplB.GetPointCount(); bool bDoPiPTest = !geometriesAreDisjoint && (geometryA.GetType() == com.epl.geometry.Geometry.Type.Polygon); while (segIterA.NextPath()) { while (segIterA.HasNextSegment()) { /* const */ com.epl.geometry.Segment segmentA = segIterA.NextSegment(); segmentA.QueryEnvelope2D(env2DSegmentA); // if multipointB has only 1 vertex then it is faster to not // test for // env2DSegmentA.distance(env2DgeometryB) if (pointCountB > 1 && env2DSegmentA.SqrDistance(this.m_env2DgeometryB) > minSqrDistance) { continue; } for (int i = 0; i < pointCountB; i++) { multiPointImplB.GetXY(i, inputPoint); if (bDoPiPTest) { // Test for polygon containment. This takes the // place of a more general intersection test at the // beginning of the operator if (com.epl.geometry.PolygonUtils.IsPointInPolygon2D((com.epl.geometry.Polygon)geometryA, inputPoint, 0) != com.epl.geometry.PolygonUtils.PiPResult.PiPOutside) { return(0.0); } } t = segmentA.GetClosestCoordinate(inputPoint, false); inputPoint.Sub(segmentA.GetCoord2D(t)); sqrDistance = inputPoint.SqrLength(); if (sqrDistance < minSqrDistance) { if (sqrDistance == 0.0) { return(0.0); } minSqrDistance = sqrDistance; } } // No need to do point-in-polygon anymore (if it is a // polygon vs polyline) bDoPiPTest = false; } } return(System.Math.Sqrt(minSqrDistance)); }
/// <summary>Adds segments from a source multipath to this MultiPath.</summary> /// <param name="src">The source MultiPath to add segments from.</param> /// <param name="srcPathIndex">The index of the path in the the source MultiPath.</param> /// <param name="srcSegmentFrom"> /// The index of first segment in the path to start adding from. /// The value has to be between 0 and /// src.getSegmentCount(srcPathIndex) - 1. /// </param> /// <param name="srcSegmentCount"> /// The number of segments to add. If 0, the function does /// nothing. /// </param> /// <param name="bStartNewPath"> /// When true, a new path is added and segments are added to it. /// Otherwise the segments are added to the last path of this /// MultiPath. /// If bStartNewPath false, the first point of the first source /// segment is not added. This is done to ensure proper connection /// to existing segments. When the source path is closed, and the /// closing segment is among those to be added, it is added also /// as a closing segment, not as a real segment. Use add_segment /// instead if you do not like that behavior. /// This MultiPath obtains all missing attributes from the src /// MultiPath. /// </param> public virtual void AddSegmentsFromPath(com.epl.geometry.MultiPath src, int srcPathIndex, int srcSegmentFrom, int srcSegmentCount, bool bStartNewPath) { m_impl.AddSegmentsFromPath((com.epl.geometry.MultiPathImpl)src._getImpl(), srcPathIndex, srcSegmentFrom, srcSegmentCount, bStartNewPath); }
// Try to find two segements that are not degenerate internal virtual bool Calc_side(com.epl.geometry.Point2D inputPoint, bool bRight, com.epl.geometry.MultiPath multipath, int vertexIndex, int pathIndex) { com.epl.geometry.SegmentIterator segIter = multipath.QuerySegmentIterator(); this.Find_analysis_pair_from_index(inputPoint, segIter, vertexIndex, pathIndex); if (this.m_i1 != -1 && this.m_i2 == -1) { // could not find a pair of segments return(this.m_bRight1); } if (this.m_i1 != -1 && this.m_i2 != -1) { if (this.m_bRight1 == this.m_bRight2) { return(this.m_bRight1); } else { // no conflicting result for the side // the conflicting result, that we are trying to resolve, // happens in the obtuse (outer) side of the turn only. segIter.ResetToVertex(this.m_i1, -1); com.epl.geometry.Segment segment1 = segIter.NextSegment(); com.epl.geometry.Point2D tang1 = segment1._getTangent(1.0); segIter.ResetToVertex(this.m_i2, -1); com.epl.geometry.Segment segment2 = segIter.NextSegment(); com.epl.geometry.Point2D tang2 = segment2._getTangent(0.0); double cross = tang1.CrossProduct(tang2); if (cross >= 0) { // the obtuse angle is on the right side return(true); } else { // the obtuse angle is on the right side return(false); } } } else { System.Diagnostics.Debug.Assert((this.m_i1 == -1 && this.m_i2 == -1)); return(bRight); } }
/// <summary>Inserts vertices from the given multipath into this multipath.</summary> /// <remarks> /// Inserts vertices from the given multipath into this multipath. All added /// vertices are connected by linear segments with each other and with the /// existing vertices. /// </remarks> /// <param name="pathIndex"> /// The path index in this multipath to insert points to. Must /// correspond to an existing path. /// </param> /// <param name="beforePointIndex"> /// The point index before all other vertices to insert in the /// given path of this multipath. This value must be between 0 and /// GetPathSize(pathIndex), or -1 to insert points at the end of /// the given path. /// </param> /// <param name="src">The source multipath.</param> /// <param name="srcPathIndex">The source path index to copy points from.</param> /// <param name="srcPointIndexFrom">The start point in the source path to start copying from.</param> /// <param name="srcPointCount">The count of points to add.</param> /// <param name="bForward">When FALSE, the points are inserted in reverse order.</param> public virtual void InsertPoints(int pathIndex, int beforePointIndex, com.epl.geometry.MultiPath src, int srcPathIndex, int srcPointIndexFrom, int srcPointCount, bool bForward) { m_impl.InsertPoints(pathIndex, beforePointIndex, (com.epl.geometry.MultiPathImpl)src._getImpl(), srcPathIndex, srcPointIndexFrom, srcPointCount, bForward); }
private static void ExportPolypathToJson(com.epl.geometry.MultiPath pp, string name, com.epl.geometry.SpatialReference spatialReference, com.epl.geometry.JsonWriter jsonWriter, System.Collections.Generic.IDictionary <string, object> exportProperties) { bool bExportZs = pp.HasAttribute(com.epl.geometry.VertexDescription.Semantics.Z); bool bExportMs = pp.HasAttribute(com.epl.geometry.VertexDescription.Semantics.M); bool bPositionAsF = false; int decimals = 17; if (exportProperties != null) { object numberOfDecimalsXY = exportProperties["numberOfDecimalsXY"]; if (numberOfDecimalsXY != null && numberOfDecimalsXY is java.lang.Number) { bPositionAsF = true; decimals = ((java.lang.Number)numberOfDecimalsXY); } } jsonWriter.StartObject(); if (bExportZs) { jsonWriter.AddPairBoolean("hasZ", true); } if (bExportMs) { jsonWriter.AddPairBoolean("hasM", true); } jsonWriter.AddPairArray(name); if (!pp.IsEmpty()) { int n = pp.GetPathCount(); // rings or paths com.epl.geometry.MultiPathImpl mpImpl = (com.epl.geometry.MultiPathImpl)pp._getImpl(); // get impl for // faster // access com.epl.geometry.AttributeStreamOfDbl zs = null; com.epl.geometry.AttributeStreamOfDbl ms = null; if (bExportZs) { zs = (com.epl.geometry.AttributeStreamOfDbl)mpImpl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.Z); } if (bExportMs) { ms = (com.epl.geometry.AttributeStreamOfDbl)mpImpl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.M); } bool bPolygon = pp is com.epl.geometry.Polygon; com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D(); for (int i = 0; i < n; i++) { jsonWriter.AddValueArray(); int startindex = pp.GetPathStart(i); int numVertices = pp.GetPathSize(i); double startx = 0.0; double starty = 0.0; double startz = com.epl.geometry.NumberUtils.NaN(); double startm = com.epl.geometry.NumberUtils.NaN(); double z = com.epl.geometry.NumberUtils.NaN(); double m = com.epl.geometry.NumberUtils.NaN(); bool bClosed = pp.IsClosedPath(i); for (int j = startindex; j < startindex + numVertices; j++) { pp.GetXY(j, pt); jsonWriter.AddValueArray(); if (bPositionAsF) { jsonWriter.AddValueDouble(pt.x, decimals, true); jsonWriter.AddValueDouble(pt.y, decimals, true); } else { jsonWriter.AddValueDouble(pt.x); jsonWriter.AddValueDouble(pt.y); } if (bExportZs) { z = zs.Get(j); jsonWriter.AddValueDouble(z); } if (bExportMs) { m = ms.Get(j); jsonWriter.AddValueDouble(m); } if (j == startindex && bClosed) { startx = pt.x; starty = pt.y; startz = z; startm = m; } jsonWriter.EndArray(); } // Close the Path/Ring by writing the Point at the start index if (bClosed && (startx != pt.x || starty != pt.y || (bExportZs && !(com.epl.geometry.NumberUtils.IsNaN(startz) && com.epl.geometry.NumberUtils.IsNaN(z)) && startz != z) || (bExportMs && !(com.epl.geometry.NumberUtils.IsNaN(startm) && com.epl.geometry.NumberUtils.IsNaN(m)) && startm != m))) { pp.GetXY(startindex, pt); // getPoint(startindex); jsonWriter.AddValueArray(); if (bPositionAsF) { jsonWriter.AddValueDouble(pt.x, decimals, true); jsonWriter.AddValueDouble(pt.y, decimals, true); } else { jsonWriter.AddValueDouble(pt.x); jsonWriter.AddValueDouble(pt.y); } if (bExportZs) { z = zs.Get(startindex); jsonWriter.AddValueDouble(z); } if (bExportMs) { m = ms.Get(startindex); jsonWriter.AddValueDouble(m); } jsonWriter.EndArray(); } jsonWriter.EndArray(); } } jsonWriter.EndArray(); if (spatialReference != null) { WriteSR(spatialReference, jsonWriter); } jsonWriter.EndObject(); }