internal static Geometry MakeFishnetPolygon(Polygon inputPoly)
        {
            Envelope envPoly  = inputPoly.Extent;
            var      interval = GetFishnetIntervalDistance(envPoly);
            var      pb       = new PolygonBuilder(inputPoly.SpatialReference)
            {
                HasZ = true
            };

            for (var dX = envPoly.XMin; dX < envPoly.XMax + interval; dX += interval)
            {
                for (var dY = envPoly.YMin; dY < envPoly.YMax + interval; dY += interval)
                {
                    var cutEnv = EnvelopeBuilder.CreateEnvelope(dX, dY, dX + interval, dY + interval, envPoly.SpatialReference);
                    if (GeometryEngine.Instance.Intersects(cutEnv, inputPoly))
                    {
                        var addPolygonPart = GeometryEngine.Instance.Clip(inputPoly, cutEnv) as Polygon;
                        if (addPolygonPart.Area < 0)
                        {
                            System.Diagnostics.Debug.WriteLine($@"area: {addPolygonPart.Area}");
                        }
                        pb.AddPart(addPolygonPart.Points);
                    }
                }
            }
            return(pb.ToGeometry());
        }
예제 #2
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(Polygon mp, BinaryWriter bWriter, WkbByteOrder byteorder)
        {
            //Write the number of polygons.
            WriteUInt32((uint)mp.Parts.Count, bWriter, byteorder);

            //Loop on the number of polygons.
            for (var i = 0; i < mp.Parts.Count; i++)
            {
                var poly = mp.Parts[i];

                //create a polygon and remember its orientation
                var singlePolygon = new PolygonBuilder(poly);

                var exteriorRingOrientation = Algorithms.IsCcw(poly);

                //Add any interior rings
                while (++i < mp.Parts.Count && Algorithms.IsCcw(mp.Parts[i]) != exteriorRingOrientation)
                {
                    singlePolygon.AddPart(mp.Parts[i]);
                }

                //Write polygon header
                bWriter.Write((byte)byteorder);
                WriteUInt32((uint)WkbGeometryType.WkbPolygon, bWriter, byteorder);
                //Write each polygon.
                WritePolygon(singlePolygon.ToGeometry(), bWriter, byteorder);
            }
        }
예제 #3
0
        public static Graphic NewDonut(double x, double y, double innerRadius, double outerRadius)
        {
            double[] px = new double[NUM];
            double[] py = new double[NUM];
            GeometryAlgorithms.CircleToPoints(x, y, outerRadius, NUM, px, py, AngleDirection.CounterClockwise);

            Esri.ArcGISRuntime.Geometry.PointCollection pc = new Esri.ArcGISRuntime.Geometry.PointCollection();
            for (int i = 0; i < NUM; i++)
            {
                MapPoint p = new MapPoint(px[i], py[i]);
                pc.Add(p);
            }
            pc.Add(pc[0]);

            PolygonBuilder polygon = new PolygonBuilder(pc);

            GeometryAlgorithms.CircleToPoints(x, y, innerRadius, NUM, px, py, AngleDirection.Clockwise);
            pc = new Esri.ArcGISRuntime.Geometry.PointCollection();
            for (int i = 0; i < NUM; i++)
            {
                MapPoint p = new MapPoint(px[i], py[i]);
                pc.Add(p);
            }
            pc.Add(pc[0]);
            polygon.AddPart(pc);

            Graphic g = new Graphic();

            g.Geometry = polygon.ToGeometry();
            return(g);
        }
        public void SystemSpatialGeometryConvertPolygonToMultiPolygon()
        {
            PolygonBuilder pb = new PolygonBuilder(SpatialReferences.Wgs84);

            pb.AddPart(new MapPoint[] { new MapPoint(0, 0), new MapPoint(1, 1), new MapPoint(1, 0) });
            pb.AddPart(new MapPoint[] { new MapPoint(10, 10), new MapPoint(10, 11), new MapPoint(11, 11), new MapPoint(11, 10) });
            var pl = pb.ToGeometry();
            var g  = pl.ToSystemSpatialGeometry();

            Assert.IsNotNull(g);
            Assert.IsInstanceOfType(g, typeof(System.Spatial.GeometryMultiPolygon));
            var p = (System.Spatial.GeometryMultiPolygon)g;

            Assert.AreEqual(2, p.Polygons.Count);
            Assert.AreEqual(1, p.Polygons[0].Rings.Count);
            Assert.AreEqual(1, p.Polygons[1].Rings.Count);
            Assert.AreEqual(SpatialReferences.Wgs84.Wkid, p.CoordinateSystem.EpsgId);
        }
        public void SystemSpatialGeometryConvertPolygonToPolygon()
        {
            PolygonBuilder pb = new PolygonBuilder(SpatialReferences.Wgs84);

            pb.AddPart(new MapPoint[] { new MapPoint(56, 67), new MapPoint(90, 10), new MapPoint(78, 89) });
            var pl = pb.ToGeometry();
            var g  = pl.ToSystemSpatialGeometry();

            Assert.IsNotNull(g);
            Assert.IsInstanceOfType(g, typeof(System.Spatial.GeometryPolygon));
            var p = (System.Spatial.GeometryPolygon)g;

            Assert.AreEqual(1, p.Rings.Count);
            Assert.AreEqual(4, p.Rings[0].Points.Count);
            Assert.AreEqual(SpatialReferences.Wgs84.Wkid, p.CoordinateSystem.EpsgId);
        }
예제 #6
0
        private static Polygon CreateWkbPolygon(BinaryReader reader, WkbByteOrder byteOrder)
        {
            // Get the Number of rings in this Polygon.
            var numRings = (int)ReadUInt32(reader, byteOrder);

            Debug.Assert(numRings >= 1, "Number of rings in polygon must be 1 or more.");

            var polygonBuilder = new PolygonBuilder(CreateWkbLinearRing(reader, byteOrder));

            // Create a new array of linearrings for the interior rings.
            for (var i = 0; i < numRings - 1; i++)
            {
                polygonBuilder.AddPart(CreateWkbLinearRing(reader, byteOrder));
            }
            // Create and return the Poylgon.
            return(polygonBuilder.ToGeometry());
        }
        /// <summary>
        ///     Creates a Polygon 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 &lt;Polygon Text&gt;.
        /// </param>
        /// <param name="exteriorRingCcw"></param>
        /// <param name="exteriorRingCcwSpecified"></param>
        /// <returns>
        ///     Returns a Polygon specified by the next token
        ///     in the stream
        /// </returns>
        /// <remarks>
        ///     ParseException is thown if the coordinates used to create the Polygon
        ///     shell and holes do not form closed linestrings, or if an unexpected
        ///     token is encountered.
        /// </remarks>
        private static Polygon ReadPolygonText(WktStreamTokenizer tokenizer, bool exteriorRingCcw = false,
                                               bool exteriorRingCcwSpecified = false)
        {
            var nextToken = GetNextEmptyOrOpener(tokenizer);

            if (nextToken == "EMPTY")
            {
                throw new Exception("Empty Polygon");
            }

            var exteriorRing = GetCoordinates(tokenizer);


            IEnumerable <MapPoint> firstRing;

            // Exterior ring.  Force it to be CW/CCW to match the first exterior ring of the multipolygon, if it is part of a multipolygon
            if (exteriorRingCcwSpecified)
            {
                firstRing = Algorithms.IsCcw(exteriorRing) != exteriorRingCcw?Reverse(exteriorRing) : exteriorRing;
            }
            else
            {
                firstRing = exteriorRing;
            }

            var polygonBuilder = new PolygonBuilder(firstRing);

            nextToken = GetNextCloserOrComma(tokenizer);
            while (nextToken == ",")
            {
                //Add holes
                var interiorRing  = GetCoordinates(tokenizer);
                var correctedRing = interiorRing;
                // Make sure interior rings go in the opposite direction of the exterior rings
                if (Algorithms.IsCcw(interiorRing) == exteriorRingCcw)
                {
                    correctedRing = Reverse(interiorRing);
                }
                polygonBuilder.AddPart(correctedRing); //interior rings
                nextToken = GetNextCloserOrComma(tokenizer);
            }
            return(polygonBuilder.ToGeometry());
        }
예제 #8
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(Polygon multiPolygon, StringWriter writer)
        {
            if (multiPolygon == null || multiPolygon.Parts.Count == 0)
            {
                writer.Write("EMPTY");
            }
            else
            {
                writer.Write("(");

                var outerRing = true;
                if (multiPolygon.Parts.Count > 0)
                {
                    outerRing = Algorithms.IsCcw(multiPolygon.Parts[0]);
                }
                for (var i = 0; i < multiPolygon.Parts.Count; i++)
                {
                    if (i > 0)
                    {
                        writer.Write(", ");
                    }

                    var singlePolygon = new PolygonBuilder(multiPolygon.Parts[i]);

                    //Add any interior rings
                    for (var j = i + 1; j < multiPolygon.Parts.Count; j++)
                    {
                        // It is an interior ring if the clockwise direction is opposite of the first ring
                        if (Algorithms.IsCcw(multiPolygon.Parts[j]) == outerRing)
                        {
                            break;
                        }

                        singlePolygon.AddPart(multiPolygon.Parts[j]);
                        i++;
                    }

                    AppendPolygonText(singlePolygon.ToGeometry(), writer);
                }
                writer.Write(")");
            }
        }
        /// <summary>
        /// Returns a polygon with a range fan(circular ring sector - like a donut wedge or wiper blade swipe with inner and outer radius)
        /// from the input parameters
        /// Input Angles must be 0-360 degrees
        /// </summary>
        public static Geometry ConstructRangeFan(MapPoint centerPoint,
                                                 double innerDistanceInMapUnits, double outerDistanceInMapUnits,
                                                 double horizontalStartAngleInBearing, double horizontalEndAngleInBearing,
                                                 SpatialReference sr, double incrementAngleStep = 1.0)
        {
            // Check inputs
            if ((centerPoint == null) || (sr == null) ||
                (innerDistanceInMapUnits < 0.0) || (outerDistanceInMapUnits < 0.0) ||
                (horizontalStartAngleInBearing < 0.0) || (horizontalStartAngleInBearing > 360.0) ||
                (horizontalEndAngleInBearing < 0.0) || (horizontalEndAngleInBearing > 360.0))
            {
                return(null);
            }

            // Tricky - if angle cuts across 360, need to adjust for this case (ex. Angle: 270->90)
            if (horizontalStartAngleInBearing > horizontalEndAngleInBearing)
            {
                horizontalStartAngleInBearing = -(360.0 - horizontalStartAngleInBearing);
            }

            double deltaAngle = Math.Abs(horizontalStartAngleInBearing - horizontalEndAngleInBearing);

            // if full circle(or greater), return donut section with inner/outer rings
            if ((deltaAngle == 0.0) || (deltaAngle >= 360.0))
            {
                // Just add 2 concentric circle buffers
                PolygonBuilder donutPb = new PolygonBuilder();

                EllipticArcSegment circularArcOuter =
                    EllipticArcBuilder.CreateEllipticArcSegment((Coordinate2D)centerPoint,
                                                                outerDistanceInMapUnits, esriArcOrientation.esriArcClockwise, sr);

                donutPb.AddPart(new List <Segment> {
                    circularArcOuter
                });

                if (innerDistanceInMapUnits > 0.0)
                {
                    EllipticArcSegment circularArcInner =
                        EllipticArcBuilder.CreateEllipticArcSegment((Coordinate2D)centerPoint,
                                                                    innerDistanceInMapUnits, esriArcOrientation.esriArcCounterClockwise, sr);

                    donutPb.AddPart(new List <Segment> {
                        circularArcInner
                    });
                }

                return(donutPb.ToGeometry());
            }

            // Otherwise if range fan, construct that
            var points = new List <MapPoint>();

            MapPoint startPoint = null;

            if (innerDistanceInMapUnits <= 0.0)
            {
                startPoint = centerPoint;
                points.Add(startPoint);
            }

            double minAngle = Math.Min(horizontalStartAngleInBearing, horizontalEndAngleInBearing);
            double maxAngle = Math.Max(horizontalStartAngleInBearing, horizontalEndAngleInBearing);

            // don't let this create more than 360 points per arc
            if ((deltaAngle / incrementAngleStep) > 360.0)
            {
                incrementAngleStep = deltaAngle / 360.0;
            }

            // Draw Outer Arc of Ring
            // Implementation Note: because of the unique shape of this ring,
            // it was easier to manually create these points than use EllipticArcBuilder
            for (double angle = minAngle; angle <= maxAngle; angle += incrementAngleStep)
            {
                double cartesianAngle = (450 - angle) % 360;
                double angleInRadians = cartesianAngle * (Math.PI / 180.0);
                double x = centerPoint.X + (outerDistanceInMapUnits * Math.Cos(angleInRadians));
                double y = centerPoint.Y + (outerDistanceInMapUnits * Math.Sin(angleInRadians));

                MapPoint pointToAdd = MapPointBuilder.CreateMapPoint(x, y, sr);
                points.Add(pointToAdd);

                if (startPoint == null)
                {
                    startPoint = pointToAdd;
                }
            }

            if (innerDistanceInMapUnits > 0.0)
            {
                // Draw Inner Arc of Ring - if inner distance set
                for (double angle = maxAngle; angle >= minAngle; angle -= incrementAngleStep)
                {
                    double cartesianAngle = (450 - angle) % 360;
                    double angleInRadians = cartesianAngle * (Math.PI / 180.0);
                    double x = centerPoint.X + (innerDistanceInMapUnits * Math.Cos(angleInRadians));
                    double y = centerPoint.Y + (innerDistanceInMapUnits * Math.Sin(angleInRadians));

                    points.Add(MapPointBuilder.CreateMapPoint(x, y, sr));
                }
            }

            // close Polygon
            points.Add(startPoint);

            PolygonBuilder pb = new PolygonBuilder();

            pb.AddPart(points);

            return(pb.ToGeometry());
        }
예제 #10
0
        public static Graphic NewDonut(double x, double y, double innerRadius, double outerRadius)
        {
            double[] px = new double[NUM];
            double[] py = new double[NUM];
            GeometryAlgorithms.CircleToPoints(x, y, outerRadius, NUM, px, py, AngleDirection.CounterClockwise);

            Esri.ArcGISRuntime.Geometry.PointCollection pc = new Esri.ArcGISRuntime.Geometry.PointCollection();
            for (int i = 0; i < NUM; i++)
            {
                MapPoint p = new MapPoint(px[i], py[i]);
                pc.Add(p);
            }
            pc.Add(pc[0]);

            PolygonBuilder polygon = new PolygonBuilder(pc);

            GeometryAlgorithms.CircleToPoints(x, y, innerRadius, NUM, px, py, AngleDirection.Clockwise);
            pc = new Esri.ArcGISRuntime.Geometry.PointCollection();
            for (int i = 0; i < NUM; i++)
            {
                MapPoint p = new MapPoint(px[i], py[i]);
                pc.Add(p);
            }
            pc.Add(pc[0]);
            polygon.AddPart(pc);

            Graphic g = new Graphic();
            g.Geometry = polygon.ToGeometry();
            return g;
        }
예제 #11
0
        public static async Task <Polygon> DrawPolygonAsync(SceneView sceneView, System.Threading.CancellationToken cancellationToken)
        {
            var            tcs            = new TaskCompletionSource <Polygon>();
            PolygonBuilder polygonBuilder = new PolygonBuilder(sceneView.SpatialReference);

            polygonBuilder.AddPart(new MapPoint[] { });
            var     sketchlayer    = CreateSketchLayer(sceneView);
            Graphic polygonGraphic = new Graphic()
            {
                Symbol = DefaultFillSymbol
            };
            Graphic lineMoveGraphic = new Graphic()
            {
                Symbol = DefaultLineMoveSymbol
            };

            sketchlayer.Graphics.AddRange(new Graphic[] { polygonGraphic, lineMoveGraphic });
            Action cleanupEvents = SetUpHandlers(sceneView,
                                                 (p) => //On mouse move move completion line around
            {
                if (p != null && polygonBuilder.Parts.Count > 0 && polygonBuilder.Parts[0].Count > 0)
                {
                    lineMoveGraphic.Geometry = new Polyline(new MapPoint[]
                    {
                        polygonBuilder.Parts[0].Last().EndPoint,
                        p,
                        polygonBuilder.Parts[0].First().StartPoint
                    });
                }
            },
                                                 (p) => //On tap add a vertex
            {
                if (p != null)
                {
                    polygonBuilder.AddPoint(p);
                    if (polygonBuilder.Parts.Count > 0 && polygonBuilder.Parts[0].Count > 0)
                    {
                        polygonGraphic.Geometry  = polygonBuilder.ToGeometry();
                        lineMoveGraphic.Geometry = null;
                    }
                }
            },
                                                 (p) => //View tapped - completes task and returns point
            {
                tcs.SetResult(polygonBuilder.ToGeometry());
            });
            Action cleanup = () =>
            {
                cleanupEvents();
                sceneView.GraphicsOverlays.Remove(sketchlayer);
            };

            cancellationToken.Register(() => tcs.SetCanceled());

            Polygon result = null;

            try
            {
                result = await tcs.Task;
            }
            finally
            {
                cleanup();
            }

            return(result);
        }