A MultiPolygon is a MultiSurface whose elements are Polygons.
Inheritance: GeometryCollection
        public static void PositionMultiPolygon(CALayer shape, MultiPolygon multiPolygon, IStyle style, IViewport viewport)
        {
            var shapeLayer = shape as CAShapeLayer;
            var path = multiPolygon.ToUIKit(viewport);
            //var frame = ConvertBoundingBox (multiPolygon.GetBoundingBox(), viewport);
            shapeLayer.Path = path.CGPath;
            //shape.Frame = frame;
            /*
            if (viewport.Resolution > MinResolution || viewport.Resolution < MaxResolution) {
                //recalculate
                var newImage = RenderMultiPolygonOnLayer (multiPolygon, style, viewport);

                shape.Contents = newImage.Contents;
                shape.Frame = newImage.Frame;

                var resolution = ZoomHelper.ClipResolutionToExtremes (Resolutions, viewport.Resolution);

                MinResolution = ZoomHelper.ZoomOut (Resolutions, resolution);
                MaxResolution = ZoomHelper.ZoomIn (Resolutions, resolution);

            } else {
                //reposition Geometry
                var frame = ConvertBoundingBox (multiPolygon.GetBoundingBox(), viewport);
                var newFrame = new RectangleF (frame.X, (frame.Y), frame.Width, frame.Height);

                shape.Frame = newFrame;
                //shape.Frame = frame;
            }
            */
        }
        public void RenderGeometry(MultiPolygon multiPolygon, IStyle style, IFeature feature, IViewport viewport)
        {
            if (_bgWorker == null)
                _bgWorker = new BackgroundWorker();
            /*
            while (_bgWorker.IsBusy) {
                Thread.Sleep (00001);
            }
            */
            _bgWorker.RunWorkerCompleted += (sender, e) =>
                {
                    var layer = e.Result as CALayer;

                    if (layer != null)
                    {
                        var styleKey = style.GetHashCode().ToString();
                        feature[styleKey] = layer;
                    }
                };

            _bgWorker.DoWork += delegate(object sender, DoWorkEventArgs e)
                {
                    var layer = RenderImage(multiPolygon, style, viewport);
                    e.Result = layer;
                };

            _bgWorker.RunWorkerAsync();
        }
Exemple #3
0
        /// <summary>
        ///     Return a copy of this geometry
        /// </summary>
        /// <returns>Copy of Geometry</returns>
        public new MultiPolygon Clone()
        {
            var geoms = new MultiPolygon();

            foreach (var polygon in Polygons)
            {
                geoms.Polygons.Add(polygon.Clone());
            }
            return(geoms);
        }
        private static CALayer RenderImage(MultiPolygon multiPolygon, IStyle style, IViewport viewport)
        {
            var geom = new CAShapeLayer();

            if (!(style is VectorStyle)) throw new ArgumentException("Style is not of type VectorStyle");
            var vectorStyle = style as VectorStyle;

            float strokeAlpha = (float)vectorStyle.Outline.Color.A / 255;
            float fillAlpha = (float)vectorStyle.Fill.Color.A / 255;
            var strokeColor = new CGColor(new CGColor(vectorStyle.Outline.Color.R, vectorStyle.Outline.Color.G,
                                                      vectorStyle.Outline.Color.B), strokeAlpha);
            var fillColor = new CGColor(new CGColor(vectorStyle.Fill.Color.R, vectorStyle.Fill.Color.G,
                                                    vectorStyle.Fill.Color.B), fillAlpha);

            geom.StrokeColor = strokeColor;
            geom.FillColor = fillColor;
            geom.LineWidth = (float)vectorStyle.Outline.Width;

            var bbRect = GeometryRenderer.ConvertBoundingBox(multiPolygon.GetBoundingBox(), viewport);
            var offset = new CoreGraphics.CGPoint((int)bbRect.GetMinX(), (int)bbRect.GetMinY());

            GeometryExtension.OffSet = offset;

            var path = multiPolygon.ToUIKit(viewport);
            var frame = new CGRect(0, 0, (int)((float)bbRect.GetMaxX() - (float)bbRect.GetMinX()), (int)((float)bbRect.GetMaxY() - (float)bbRect.GetMinY()));
            var size = frame.Size;

            geom.Path = path.CGPath;

            UIGraphics.BeginImageContext((CGSize)size);

            var context = UIGraphics.GetCurrentContext();

            context.SetBlendMode(CGBlendMode.Multiply);
            geom.RenderInContext(context);

            var image = UIGraphics.GetImageFromCurrentImageContext();
            var imageTile = new CALayer { Contents = image.CGImage, Frame = frame };

            return imageTile;
        }
        public static CALayer RenderMultiPolygonOnLayer(MultiPolygon multiPolygon, IStyle style, IViewport viewport)
        {
            var tile = new CAShapeLayer();

            if (!(style is VectorStyle)) throw new ArgumentException("Style is not of type VectorStyle");
            var vectorStyle = style as VectorStyle;

            var strokeAlpha = (float)vectorStyle.Outline.Color.A / 255;
            var fillAlpha = (float)vectorStyle.Fill.Color.A / 255;

            var strokeColor = new CGColor(new CGColor(vectorStyle.Outline.Color.R, vectorStyle.Outline.Color.G,
                vectorStyle.Outline.Color.B), strokeAlpha);
            var fillColor = new CGColor(new CGColor(vectorStyle.Fill.Color.R, vectorStyle.Fill.Color.G,
                vectorStyle.Fill.Color.B), fillAlpha);

            var path = multiPolygon.ToUIKit(viewport);

            tile.StrokeColor = strokeColor;
            tile.FillColor = fillColor;
            tile.LineWidth = (float)vectorStyle.Outline.Width;
            tile.Path = path.CGPath;

            return tile;
        }
        /// <summary>
        /// This method produces instances of type <see cref="Mapsui.Geometries.MultiPolygon"/>.
        /// </summary>
        /// <returns>The created geometries</returns>
        internal override Collection<Geometry> CreateGeometries(Features features)
        {
            IPathNode multiPolygonNode = new PathNode(Gmlns, "MultiPolygon", (NameTable) XmlReader.NameTable);
            IPathNode multiSurfaceNode = new PathNode(Gmlns, "MultiSurface", (NameTable) XmlReader.NameTable);
            IPathNode multiPolygonNodeAlt = new AlternativePathNodesCollection(multiPolygonNode, multiSurfaceNode);
            IPathNode polygonMemberNode = new PathNode(Gmlns, "polygonMember", (NameTable) XmlReader.NameTable);
            IPathNode surfaceMemberNode = new PathNode(Gmlns, "surfaceMember", (NameTable) XmlReader.NameTable);
            IPathNode polygonMemberNodeAlt = new AlternativePathNodesCollection(polygonMemberNode, surfaceMemberNode);
            IPathNode linearRingNode = new PathNode(Gmlns, "LinearRing", (NameTable) XmlReader.NameTable);
            var labelValue = new string[1];
            bool geomFound = false;

            try
            {
                // Reading the entire feature's node makes it possible to collect label values that may appear before or after the geometry property
                while ((FeatureReader = GetSubReaderOf(XmlReader, null, FeatureNode)) != null)
                {
                    while (
                        (GeomReader =
                         GetSubReaderOf(FeatureReader, labelValue, multiPolygonNodeAlt, polygonMemberNodeAlt)) != null)
                    {
                        var multiPolygon = new MultiPolygon();
                        GeometryFactory geomFactory = new PolygonFactory(GeomReader, FeatureTypeInfo);
                        Collection<Geometry> polygons = geomFactory.CreateGeometries(features);

                        foreach (Polygon polygon in polygons)
                            multiPolygon.Polygons.Add(polygon);

                        Geoms.Add(multiPolygon);
                        geomFound = true;
                    }
                    if (geomFound) features.Add(CreateFeature(Geoms[Geoms.Count - 1], FeatureTypeInfo.LableField, labelValue[0]));
                    geomFound = false;
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError("An exception occured while parsing a multi-polygon geometry: " + ex.Message);
                throw;
            }

            return Geoms;
        }
Exemple #7
0
        /// <summary>
        /// Writes a multipolygon.
        /// </summary>
        /// <param name="mp">The mulitpolygon to be written.</param>
        /// <param name="bWriter">Stream to write to.</param>
        /// <param name="byteorder">Byte order</param>
        private static void WriteMultiPolygon(MultiPolygon mp, BinaryWriter bWriter, WkbByteOrder byteorder)
        {
            //Write the number of polygons.
            WriteUInt32((uint) mp.Polygons.Count, bWriter, byteorder);

            //Loop on the number of polygons.
            foreach (Polygon poly in mp.Polygons)
            {
                //Write polygon header
                bWriter.Write((byte) byteorder);
                WriteUInt32((uint) WKBGeometryType.WKBPolygon, bWriter, byteorder);
                //Write each polygon.
                WritePolygon(poly, bWriter, byteorder);
            }
        }
 public static void Render(Graphics graphics, MultiPolygon pols, Brush brush, Pen pen, IViewport viewport)
 {
     foreach (var t in pols.Polygons)
         PolygonRenderer.DrawPolygon(graphics, t, brush, pen, viewport);
 }
Exemple #9
0
 /// <summary>
 /// Converts a MultiPolygon to &lt;MultiPolygon Tagged
 /// Text&gt; format, then Appends it to the writer.
 /// </summary>
 /// <param name="multiPolygon">The MultiPolygon to process</param>
 /// <param name="writer">The output stream writer to Append to.</param>
 private static void AppendMultiPolygonTaggedText(MultiPolygon multiPolygon, StringWriter writer)
 {
     writer.Write("MULTIPOLYGON ");
     AppendMultiPolygonText(multiPolygon, writer);
 }
Exemple #10
0
        /// <summary>
        /// Reads and parses the geometry with ID 'oid' from the ShapeFile
        /// </summary>
        /// <remarks><see cref="FilterDelegate">Filtering</see> is not applied to this method</remarks>
        /// <param name="oid">Object ID</param>
        /// <returns>geometry</returns>
        private Geometry ReadGeometry(uint oid)
        {
            brShapeFile.BaseStream.Seek(GetShapeIndex(oid) + 8, 0); //Skip record number and content length
            ShapeType type = (ShapeType) brShapeFile.ReadInt32(); //Shape type
            if (type == ShapeType.Null)
                return null;
            if (_ShapeType == ShapeType.Point || _ShapeType == ShapeType.PointM || _ShapeType == ShapeType.PointZ)
            {
                Point tempFeature = new Point();
                return new Point(brShapeFile.ReadDouble(), brShapeFile.ReadDouble());
            }
            else if (_ShapeType == ShapeType.Multipoint || _ShapeType == ShapeType.MultiPointM ||
                     _ShapeType == ShapeType.MultiPointZ)
            {
                brShapeFile.BaseStream.Seek(32 + brShapeFile.BaseStream.Position, 0); //skip min/max box
                MultiPoint feature = new MultiPoint();
                int nPoints = brShapeFile.ReadInt32(); // get the number of points
                if (nPoints == 0)
                    return null;
                for (int i = 0; i < nPoints; i++)
                    feature.Points.Add(new Point(brShapeFile.ReadDouble(), brShapeFile.ReadDouble()));

                return feature;
            }
            else if (_ShapeType == ShapeType.PolyLine || _ShapeType == ShapeType.Polygon ||
                     _ShapeType == ShapeType.PolyLineM || _ShapeType == ShapeType.PolygonM ||
                     _ShapeType == ShapeType.PolyLineZ || _ShapeType == ShapeType.PolygonZ)
            {
                brShapeFile.BaseStream.Seek(32 + brShapeFile.BaseStream.Position, 0); //skip min/max box

                int nParts = brShapeFile.ReadInt32(); // get number of parts (segments)
                if (nParts == 0)
                    return null;
                int nPoints = brShapeFile.ReadInt32(); // get number of points

                int[] segments = new int[nParts + 1];
                //Read in the segment indexes
                for (int b = 0; b < nParts; b++)
                    segments[b] = brShapeFile.ReadInt32();
                //add end point
                segments[nParts] = nPoints;

                if ((int) _ShapeType%10 == 3)
                {
                    MultiLineString mline = new MultiLineString();
                    for (int LineID = 0; LineID < nParts; LineID++)
                    {
                        LineString line = new LineString();
                        for (int i = segments[LineID]; i < segments[LineID + 1]; i++)
                            line.Vertices.Add(new Point(brShapeFile.ReadDouble(), brShapeFile.ReadDouble()));
                        mline.LineStrings.Add(line);
                    }
                    if (mline.LineStrings.Count == 1)
                        return mline[0];
                    return mline;
                }
                else //(_ShapeType == ShapeType.Polygon etc...)
                {
                    //First read all the rings
                    List<LinearRing> rings = new List<LinearRing>();
                    for (int RingID = 0; RingID < nParts; RingID++)
                    {
                        LinearRing ring = new LinearRing();
                        for (int i = segments[RingID]; i < segments[RingID + 1]; i++)
                            ring.Vertices.Add(new Point(brShapeFile.ReadDouble(), brShapeFile.ReadDouble()));
                        rings.Add(ring);
                    }
                    bool[] IsCounterClockWise = new bool[rings.Count];
                    int PolygonCount = 0;
                    for (int i = 0; i < rings.Count; i++)
                    {
                        IsCounterClockWise[i] = rings[i].IsCCW();
                        if (!IsCounterClockWise[i])
                            PolygonCount++;
                    }
                    if (PolygonCount == 1) //We only have one polygon
                    {
                        Polygon poly = new Polygon();
                        poly.ExteriorRing = rings[0];
                        if (rings.Count > 1)
                            for (int i = 1; i < rings.Count; i++)
                                poly.InteriorRings.Add(rings[i]);
                        return poly;
                    }
                    else
                    {
                        MultiPolygon mpoly = new MultiPolygon();
                        Polygon poly = new Polygon();
                        poly.ExteriorRing = rings[0];
                        for (int i = 1; i < rings.Count; i++)
                        {
                            if (!IsCounterClockWise[i])
                            {
                                mpoly.Polygons.Add(poly);
                                poly = new Polygon(rings[i]);
                            }
                            else
                                poly.InteriorRings.Add(rings[i]);
                        }
                        mpoly.Polygons.Add(poly);
                        return mpoly;
                    }
                }
            }
            else
                throw (new ApplicationException("Shapefile type " + _ShapeType.ToString() + " not supported"));
        }
 public static void DrawMultiPolygon(Graphics graphics, MultiPolygon pols, Brush brush, Pen pen, IViewport viewport)
 {
     foreach (Polygon t in pols.Polygons)
         DrawPolygon(graphics, t, brush, pen, viewport);
 }
Exemple #12
0
        /// <summary>
        /// Reads and parses the geometry with ID 'oid' from the ShapeFile
        /// </summary>
        /// <remarks><see cref="FilterDelegate">Filtering</see> is not applied to this method</remarks>
        /// <param name="oid">Object ID</param>
        /// <returns>geometry</returns>
        // ReSharper disable once CyclomaticComplexity // Fix when changes need to be made here
        private Geometry ReadGeometry(uint oid)
        {
            _brShapeFile.BaseStream.Seek(GetShapeIndex(oid) + 8, 0); //Skip record number and content length
            var type = (ShapeType)_brShapeFile.ReadInt32(); //Shape type
            if (type == ShapeType.Null)
                return null;
            if (_shapeType == ShapeType.Point || _shapeType == ShapeType.PointM || _shapeType == ShapeType.PointZ)
            {
                return new Point(_brShapeFile.ReadDouble(), _brShapeFile.ReadDouble());
            }
            if (_shapeType == ShapeType.Multipoint || _shapeType == ShapeType.MultiPointM ||
                _shapeType == ShapeType.MultiPointZ)
            {
                _brShapeFile.BaseStream.Seek(32 + _brShapeFile.BaseStream.Position, 0); //skip min/max box
                var feature = new MultiPoint();
                int nPoints = _brShapeFile.ReadInt32(); // get the number of points
                if (nPoints == 0)
                    return null;
                for (int i = 0; i < nPoints; i++)
                    feature.Points.Add(new Point(_brShapeFile.ReadDouble(), _brShapeFile.ReadDouble()));

                return feature;
            }
            if (_shapeType == ShapeType.PolyLine || _shapeType == ShapeType.Polygon ||
                _shapeType == ShapeType.PolyLineM || _shapeType == ShapeType.PolygonM ||
                _shapeType == ShapeType.PolyLineZ || _shapeType == ShapeType.PolygonZ)
            {
                _brShapeFile.BaseStream.Seek(32 + _brShapeFile.BaseStream.Position, 0); //skip min/max box

                int nParts = _brShapeFile.ReadInt32(); // get number of parts (segments)
                if (nParts == 0)
                    return null;
                int nPoints = _brShapeFile.ReadInt32(); // get number of points

                var segments = new int[nParts + 1];
                //Read in the segment indexes
                for (int b = 0; b < nParts; b++)
                    segments[b] = _brShapeFile.ReadInt32();
                //add end point
                segments[nParts] = nPoints;

                if ((int)_shapeType % 10 == 3)
                {
                    var mline = new MultiLineString();
                    for (int lineId = 0; lineId < nParts; lineId++)
                    {
                        var line = new LineString();
                        for (int i = segments[lineId]; i < segments[lineId + 1]; i++)
                            line.Vertices.Add(new Point(_brShapeFile.ReadDouble(), _brShapeFile.ReadDouble()));
                        mline.LineStrings.Add(line);
                    }
                    if (mline.LineStrings.Count == 1)
                        return mline[0];
                    return mline;
                }
                else //(_ShapeType == ShapeType.Polygon etc...)
                {
                    //First read all the rings
                    var rings = new List<LinearRing>();
                    for (int ringId = 0; ringId < nParts; ringId++)
                    {
                        var ring = new LinearRing();
                        for (int i = segments[ringId]; i < segments[ringId + 1]; i++)
                            ring.Vertices.Add(new Point(_brShapeFile.ReadDouble(), _brShapeFile.ReadDouble()));
                        rings.Add(ring);
                    }
                    var isCounterClockWise = new bool[rings.Count];
                    int polygonCount = 0;
                    for (int i = 0; i < rings.Count; i++)
                    {
                        isCounterClockWise[i] = rings[i].IsCCW();
                        if (!isCounterClockWise[i])
                            polygonCount++;
                    }
                    if (polygonCount == 1) //We only have one polygon
                    {
                        var poly = new Polygon { ExteriorRing = rings[0] };
                        if (rings.Count > 1)
                            for (int i = 1; i < rings.Count; i++)
                                poly.InteriorRings.Add(rings[i]);
                        return poly;
                    }
                    else
                    {
                        var mpoly = new MultiPolygon();
                        var poly = new Polygon { ExteriorRing = rings[0] };
                        for (var i = 1; i < rings.Count; i++)
                        {
                            if (!isCounterClockWise[i])
                            {
                                mpoly.Polygons.Add(poly);
                                poly = new Polygon(rings[i]);
                            }
                            else
                                poly.InteriorRings.Add(rings[i]);
                        }
                        mpoly.Polygons.Add(poly);
                        return mpoly;
                    }
                }
            }

            throw (new ApplicationException("Shapefile type " + _shapeType.ToString() + " not supported"));
        }
 public static XamlShapes.Path RenderMultiPolygon(MultiPolygon geometry, IStyle style, IViewport viewport)
 {
     if (!(style is VectorStyle)) throw new ArgumentException("Style is not of type VectorStyle");
     var vectorStyle = style as VectorStyle;
     XamlShapes.Path path = CreatePolygonPath(vectorStyle, viewport.Resolution);
     path.Data = geometry.ToXaml();
     path.RenderTransform = new XamlMedia.MatrixTransform { Matrix = CreateTransformMatrix1(viewport) };
     return path;
 }
 /// <summary>
 /// Return a copy of this geometry
 /// </summary>
 /// <returns>Copy of Geometry</returns>
 public new MultiPolygon Clone()
 {
     var geoms = new MultiPolygon();
     foreach (Polygon polygon in polygons)
         geoms.Polygons.Add(polygon.Clone());
     return geoms;
 }
        private static MultiPolygon CreateWKBMultiPolygon(BinaryReader reader, WkbByteOrder byteOrder)
        {
            // Get the number of Polygons.
            var numPolygons = (int) ReadUInt32(reader, byteOrder);

            // Create a new array for the Polygons.
            var polygons = new MultiPolygon();

            // Loop on the number of polygons.
            for (int i = 0; i < numPolygons; i++)
            {
                // read polygon header
                reader.ReadByte();
                ReadUInt32(reader, byteOrder);

                // TODO: Validate type

                // Create the next polygon and add it to the array.
                polygons.Polygons.Add(CreateWKBPolygon(reader, byteOrder));
            }

            //Create and return the MultiPolygon.
            return polygons;
        }
        /// <summary>
        /// Creates a <see cref="MultiPolygon"/> using the next token in the stream.
        /// </summary>
        /// <param name="tokenizer">tokenizer over a stream of text in Well-known Text
        /// format. The next tokens must form a MultiPolygon.</param>
        /// <returns>a <code>MultiPolygon</code> specified by the next token in the 
        /// stream, or if if the coordinates used to create the <see cref="Polygon"/>
        /// shells and holes do not form closed linestrings.</returns>
        private static MultiPolygon ReadMultiPolygonText(WktStreamTokenizer tokenizer)
        {
            var polygons = new MultiPolygon();
            string nextToken = GetNextEmptyOrOpener(tokenizer);
            if (nextToken == "EMPTY")
                return polygons;

            Polygon polygon = ReadPolygonText(tokenizer);
            polygons.Polygons.Add(polygon);
            nextToken = GetNextCloserOrComma(tokenizer);
            while (nextToken == ",")
            {
                polygon = ReadPolygonText(tokenizer);
                polygons.Polygons.Add(polygon);
                nextToken = GetNextCloserOrComma(tokenizer);
            }
            return polygons;
        }
Exemple #17
0
        protected override List<IGeometry> GetGeometries()
        {
            List<IGeometry> res = new List<IGeometry>();
            MultiPolygon mult = new MultiPolygon();
            Polygon poly = new Polygon();
            mult.Polygons.Add(poly);
            int current = 0;

            for (int i = 0; i < _points.Count; i++)
            {

                Point p = _currentProjection.Project(_points[i].X, _points[i].Y);
                if (p == null)
                {
                    return null;
                }
                if (poly.ExteriorRing.Vertices.Count == 0)
                {
                    poly.ExteriorRing.Vertices.Add(p);
                }
                else
                {
                    var prev = _currentProjection.Inverse(poly.ExteriorRing.Vertices.LastOrDefault().X, poly.ExteriorRing.Vertices.LastOrDefault().Y);

                    if (Math.Abs(prev.X - _points[i].X) > 180)
                    {

                        double x1 = prev.X >= 0 ? 180 : -180;
                        double x2 = -x1;
                        double y = prev.Y + (_points[i].Y - prev.Y) * Math.Abs(x1 - prev.X) / (Math.Abs(_points[i].X - x2) + Math.Abs(x1 - prev.X));
                        var p1 = _currentProjection.Project(x1, y);
                        if (p1 != null)
                        {
                            poly.ExteriorRing.Vertices.Add(p1);
                        }
                        else
                        {
                            return null;
                        }
                        if (mult.Polygons.Count >= 2 && Math.Abs(mult.Polygons[current - 1].ExteriorRing.EndPoint.X - _points[i].X) < 180)
                        {
                            current--;

                            poly = mult.Polygons[current];
                        }
                        else
                        {
                            current++;
                            poly = new Polygon();
                            mult.Polygons.Add(poly);
                        }
                        var p2 = _currentProjection.Project(x2, y);
                        if (p2 != null)
                        {
                            poly.ExteriorRing.Vertices.Add(p2);
                        }
                        else
                        {
                            return null;
                        }
                        poly.ExteriorRing.Vertices.Add(p);
                    }
                    else
                    {
                        poly.ExteriorRing.Vertices.Add(p);
                    }
                }

            }

            if (mult.Polygons.Count > 1)
            {
                res.Add(mult);
            }
            res.Add(poly);
            return res;
        }
Exemple #18
0
 /// <summary>
 /// Converts a MultiPolygon to &lt;MultiPolygon Text&gt; format, then Appends to it to the writer.
 /// </summary>
 /// <param name="multiPolygon">The MultiPolygon to process.</param>
 /// <param name="writer">The output stream to Append to.</param>
 private static void AppendMultiPolygonText(MultiPolygon multiPolygon, StringWriter writer)
 {
     if (multiPolygon == null || multiPolygon.IsEmpty())
         writer.Write("EMPTY");
     else
     {
         writer.Write("(");
         for (int i = 0; i < multiPolygon.Polygons.Count; i++)
         {
             if (i > 0)
                 writer.Write(", ");
             AppendPolygonText(multiPolygon[i], writer);
         }
         writer.Write(")");
     }
 }
Exemple #19
0
 /// <summary>
 ///     Return a copy of this geometry
 /// </summary>
 /// <returns>Copy of Geometry</returns>
 public new MultiPolygon Clone()
 {
     var geoms = new MultiPolygon();
     foreach (var polygon in Polygons)
     {
         geoms.Polygons.Add(polygon.Clone());
     }
     return geoms;
 }