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); }
/// <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); }
/// <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>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); }
/// <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); }
/// <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); }
/// <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); }
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++; } }
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); }
// 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 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(); }