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()); }
/// <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); } }
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); }
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 <Polygon Text>. /// </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()); }
/// <summary> /// Converts a MultiPolygon to <MultiPolygon Text> 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()); }
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 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); }