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);
 }
Example #2
0
 /// <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);
 }
Example #3
0
 /// <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);
 }
Example #4
0
 /// <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);
 }
Example #5
0
 /// <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);
 }
Example #6
0
 /// <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();
        }