internal static Geometry MakeFishnetPolygon(Polygon inputPoly) { Envelope envPoly = inputPoly.Extent; var interval = GetFishnetIntervalDistance(envPoly); var pb = new PolygonBuilderEx(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 = EnvelopeBuilderEx.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()); }
protected override void OnClick() { QueuedTask.Run(async() => { //get sketch geometry var sketchGeom = await MapView.Active.GetCurrentSketchAsync(); //return if the sketch doesn't have enough points for its geometry type if ((sketchGeom.GeometryType == GeometryType.Polygon && sketchGeom.PointCount < 3) || (sketchGeom.GeometryType == GeometryType.Polyline && sketchGeom.PointCount < 2)) { return; } //get the sketch as a point collection var pointCol = ((Multipart)sketchGeom).Points; //get the last point in the sketch based on its geometry type var lastSketchPoint = pointCol[(sketchGeom.GeometryType == GeometryType.Polygon) ? pointCol.Count - 2 : pointCol.Count - 1]; //build a geometry with the last sketch point and set the sketch if (sketchGeom.GeometryType == GeometryType.Polygon) { //sketch polygons need two points for the initial feedback to work var sketchPoly = new PolygonBuilderEx(new[] { lastSketchPoint, lastSketchPoint }, AttributeFlags.None); await MapView.Active.SetCurrentSketchAsync(sketchPoly.ToGeometry()); } else { var sketchPolyline = new PolylineBuilderEx(new[] { lastSketchPoint }, AttributeFlags.None); await MapView.Active.SetCurrentSketchAsync(sketchPolyline.ToGeometry()); } }); }
private static Geometry GetGeometryFromBuffer(byte[] geomBuffer, SpatialReference sr) { var geomType = GetGeometryType(geomBuffer); switch (geomType) { case GeometryType.Point: { int offset = 4; double x = DoubleWithNaN(BitConverter.ToDouble(geomBuffer, offset)); offset += 8; double y = DoubleWithNaN(BitConverter.ToDouble(geomBuffer, offset)); var mp = MapPointBuilderEx.FromEsriShape(geomBuffer, sr); //System.Diagnostics.Debug.WriteLine($@"x: {x} = {mp.X} y: {y} = {mp.Y}"); return(mp); } case GeometryType.Polyline: { var line = PolylineBuilderEx.FromEsriShape(geomBuffer, sr); return(line); } case GeometryType.Polygon: { var poly = PolygonBuilderEx.FromEsriShape(geomBuffer, sr); return(poly); } } return(null); }
/// <summary> /// The methods retrieves the outer ring(s) of the input polygon. /// This method must be called on the MCT. Use QueuedTask.Run. /// </summary> /// <param name="inputPolygon">Input Polygon.</param> /// <returns>The outer most (exterior, clockwise) ring(s) of the polygon. If the input is null or empty, a null pointer is returned.</returns> /// <remarks>This method must be called on the MCT. Use QueuedTask.Run.</remarks> public Polygon GetOutermostRings(Polygon inputPolygon) { if (inputPolygon == null || inputPolygon.IsEmpty) { return(null); } // create a polygonbuilder - ensure it has the same spatial reference as the source polygon var outerRings = new PolygonBuilderEx(inputPolygon.SpatialReference); List <Polygon> internalRings = new List <Polygon>(); // explode the parts of the polygon into a list of individual geometries var parts = MultipartToSinglePart(inputPolygon); // get an enumeration of clockwise geometries (area > 0) ordered by the area var clockwiseParts = parts.Where(geom => ((Polygon)geom).Area > 0).OrderByDescending(geom => ((Polygon)geom).Area); // for each of the exterior rings foreach (var part in clockwiseParts) { // add the first (the largest) ring into the internal collection if (internalRings.Count == 0) { internalRings.Add(part as Polygon); } // use flag to indicate if current part is within the already selection polygons bool isWithin = false; foreach (var item in internalRings) { if (GeometryEngine.Instance.Within(part, item)) { isWithin = true; } } // if the current polygon is not within any polygon of the internal collection // then it is disjoint and needs to be added to if (isWithin == false) { internalRings.Add(part as Polygon); } } // now assemble a new polygon geometry based on the internal polygon collection foreach (var ring in internalRings) { outerRings.AddParts(ring.Parts); } // return the final geometry of the outer rings return(outerRings.ToGeometry()); }
private Task OnBeforeSketchCompletedEvent(BeforeSketchCompletedEventArgs arg) { //replace curved sketch segments with straight segments //return if sketch geometry is not polygon or polyline if (!(arg.Sketch.GeometryType == GeometryType.Polyline || arg.Sketch.GeometryType == GeometryType.Polygon)) { return(Task.CompletedTask); } var sketchMP = arg.Sketch as Multipart; //if the sketch doesnt have curves then return if (!sketchMP.HasCurves) { return(Task.CompletedTask); } //itterate through each sketch part var newParts = new List <List <Segment> >(); foreach (var sketchPart in sketchMP.Parts) { //itterate through each sketch segment var newSegments = new List <Segment>(); foreach (var sketchSegment in sketchPart) { if (sketchSegment.IsCurve) { newSegments.Add(LineBuilderEx.CreateLineSegment(sketchSegment.StartPoint, sketchSegment.EndPoint)); } else { newSegments.Add(sketchSegment); } } newParts.Add(newSegments); } //create the new sketch geometry based on sketch type and set back on the sketch if (arg.Sketch.GeometryType == GeometryType.Polyline) { var polyline = PolylineBuilderEx.CreatePolyline(newParts, AttributeFlags.None); arg.SetSketchGeometry(polyline); } else { var polygon = PolygonBuilderEx.CreatePolygon(newParts, AttributeFlags.None); arg.SetSketchGeometry(polygon); } return(Task.CompletedTask); }
/// <summary> /// Create a circular polygon around a mappoint for with a radius in pixels. /// </summary> /// <param name="mapPoint">Center of the circle as a mappoint.</param> /// <param name="pixels">Circle radius in screen pixels.</param> /// <returns>A polygon geometry.</returns> private Polygon CreateSearchPolygon(MapPoint mapPoint, int pixels) { //get search radius var screenPoint = MapView.Active.MapToScreen(mapPoint); var radiusScreenPoint = new System.Windows.Point((screenPoint.X + pixels), screenPoint.Y); var radiusMapPoint = MapView.Active.ScreenToMap(radiusScreenPoint); var searchRadius = GeometryEngine.Instance.Distance(mapPoint, radiusMapPoint); //build a search circle geometry var cent = new Coordinate2D(mapPoint); var searchGeom = EllipticArcBuilderEx.CreateCircle(cent, searchRadius, ArcOrientation.ArcClockwise, MapView.Active.Map.SpatialReference); var searchPB = new PolygonBuilderEx(new[] { searchGeom }, AttributeFlags.None); return(searchPB.ToGeometry()); }
protected override void OnClick() { QueuedTask.Run(() => { //Get all the graphics layers in the map var allGraphicsLayers = MapView.Active?.Map?.GetLayersAsFlattenedList().OfType <GraphicsLayer>(); if (allGraphicsLayers.Count() == 0) { return; } //Get the geometry of the map's extent var geometry = PolygonBuilderEx.CreatePolygon(MapView.Active.Extent); //Keep adding the elements to the selection MapView.Active.SelectElements(geometry, SelectionCombinationMethod.Add); }); }
protected override void OnClick() { QueuedTask.Run(() => { //creates a crowd planning zone var cpLayer = MapView.Active.Map.FindLayers("CrowdPlanning").FirstOrDefault() as FeatureLayer; var geom = MapView.Active.Extent.Expand(0.1, 0.1, true); var poly = new PolygonBuilderEx(geom).ToGeometry(); //create an edit operation and execute var editOp = new EditOperation(); editOp.Name = "Create crowd plan"; editOp.Create(cpLayer, poly); editOp.Execute(); }); }
/// <summary> /// Copy the elements to an offset location /// </summary> /// <param name="graphicsLayer"></param> /// <param name="elements"></param> internal static void CustomCopyElements(this GraphicsLayer graphicsLayer, IEnumerable <Element> elements) { if (elements.Count() == 0) { return; } //Copy the elements. var copyElements = graphicsLayer.CopyElements(elements); //Iterate through the elements to move the anchor point for the copy. foreach (var element in copyElements) { var elementPoly = PolygonBuilderEx.CreatePolygon(element.GetBounds()); var pointsList = elementPoly.Copy2DCoordinatesToList(); element.SetAnchorPoint(pointsList[1]); } }
private Geometry Buffer(Geometry geom, esriGeometryType shapeType, double margin, MaskKind maskKind, bool isAnno = false) { var poly_outline = geom as Polygon; if (poly_outline.HasCurves) { poly_outline = GeometryEngine.Instance.DensifyByDeviation(geom, 0.1 * margin) as Polygon; } if (margin > 0.0) { if (maskKind == MaskKind.Box || maskKind == MaskKind.ConvexHull) { //strip out interior polygons var ext_poly = PolygonBuilderEx.CreatePolygon(poly_outline.GetExteriorRings(true), AttributeFlags.None); var joins = maskKind == MaskKind.Box ? LineJoinType.Miter : LineJoinType.Bevel; var buff_out = GeometryEngine.Instance.GraphicBuffer(ext_poly, margin, joins, LineCapType.Butt, 4, 0.05 * margin, 64); poly_outline = GeometryEngine.Instance.Generalize(buff_out, 0.01 * margin) as Polygon; } else { var buff_out = GeometryEngine.Instance.Buffer(poly_outline, margin); if (maskKind == MaskKind.ExactSimplified) { poly_outline = GeometryEngine.Instance.Generalize(buff_out, 0.05 * margin) as Polygon; } else { poly_outline = buff_out as Polygon; } } } //simplify if needed //return GeometryEngine.Instance.SimplifyAsFeature(poly_outline); return(poly_outline); }
protected override Task <bool> OnSketchCompleteAsync(Geometry geometry) { if (ActiveElementContainer == null) { Task.FromResult(true); } if (Module1.SelectedSymbol == null) { return(Task.FromResult(true)); } return(QueuedTask.Run(() => { ICollection <Segment> segments = null; (geometry as Polygon).GetAllSegments(ref segments); if (segments.Count == 0) { return false; } var ellipticalArcSegment = segments.First() as EllipticArcSegment; //If this cast fails, this is not an ellipse if (ellipticalArcSegment == null) { return false; } var ellipsePolygon = PolygonBuilderEx.CreatePolygon(segments); var ge = ElementFactory.Instance.CreateTextGraphicElement (this.ActiveElementContainer, TextType.EllipseParagraph, ellipsePolygon, Module1.SelectedSymbol as CIMTextSymbol); //The new text graphic element has been created //We now switch to Pro's out of box "esri_layouts_inlineEditTool" //This will allow inline editing of the text //This tool will work on graphics on both map view and layouts FrameworkApplication.SetCurrentToolAsync("esri_layouts_inlineEditTool"); return true; })); }
/// <summary> /// Called when the sketch finishes. This is where we will create the sketch operation and then execute it. /// </summary> /// <param name="geometry">The geometry created by the sketch.</param> /// <returns>A Task returning a Boolean indicating if the sketch complete event was successfully handled.</returns> protected override Task <bool> OnSketchCompleteAsync(Geometry geometry) { if (CurrentTemplate == null || geometry == null) { return(Task.FromResult(false)); } return(QueuedTask.Run(() => { //build a circular arc var cent = new Coordinate2D(geometry as MapPoint); var circleEAB = EllipticArcBuilderEx.CreateCircle(cent, Radius, ArcOrientation.ArcClockwise, MapView.Active.Map.SpatialReference); // find the source layer and determine whether polyline/polygon. Create the appropriate shape var lyr = CurrentTemplate.Layer as BasicFeatureLayer; Geometry circleGeom = null; if (lyr.ShapeType == esriGeometryType.esriGeometryPolygon) { circleGeom = PolygonBuilderEx.CreatePolygon(new[] { circleEAB }, AttributeFlags.None); } else { circleGeom = PolylineBuilderEx.CreatePolyline(circleEAB, AttributeFlags.None); } // Create an edit operation var createOperation = new EditOperation(); createOperation.Name = string.Format("Create circular {0}", CurrentTemplate.Layer.Name); createOperation.SelectNewFeatures = true; // Queue feature creation createOperation.Create(CurrentTemplate, circleGeom); // Execute the operation return createOperation.ExecuteAsync(); })); }
protected override Task <bool> OnSketchCompleteAsync(Geometry geometry) { if (ActiveElementContainer == null) { Task.FromResult(true); } if (Module1.SelectedSymbol == null) { return(Task.FromResult(true)); } return(QueuedTask.Run(() => { var centerPt = ((Polygon)geometry).Extent.CenterCoordinate; double circleArea = ((Polygon)geometry).Extent.Area; double radius = Math.Sqrt(circleArea / Math.PI); var circle = EllipticArcBuilderEx.CreateCircle(centerPt, radius, ArcOrientation.ArcClockwise); List <Segment> circleSegments = new List <Segment>() { circle }; var circlePolygon = PolygonBuilderEx.CreatePolygon(circleSegments); var ge = ElementFactory.Instance.CreateTextGraphicElement (this.ActiveElementContainer, TextType.CircleParagraph, circlePolygon, Module1.SelectedSymbol as CIMTextSymbol, "Text" ); //The new text graphic element has been created //We now switch to Pro's out of box "esri_layouts_inlineEditTool" //This will allow inline editing of the text //This tool will work on graphics on both map view and layouts FrameworkApplication.SetCurrentToolAsync("esri_layouts_inlineEditTool"); return true; })); }
protected override void OnClick() { QueuedTask.Run(() => { var allGraphicLayers = MapView.Active.Map.GetLayersAsFlattenedList().OfType <GraphicsLayer>(); foreach (var gl in allGraphicLayers) { var selElements = gl.GetSelectedElements(); if (selElements.Count == 0) { continue; } //Move the element up foreach (var selElement in selElements) { var elementPoly = PolygonBuilderEx.CreatePolygon(selElement.GetBounds()); var pointsList = elementPoly.Copy2DCoordinatesToList(); selElement.SetAnchorPoint(pointsList[1]); } } return(true); }); }
/// <summary> /// This method takes an input multi part geometry and breaks the parts into individual standalone geometries. /// This method must be called on the MCT. Use QueuedTask.Run. /// </summary> /// <param name="inputGeometry">The geometry to be exploded into the individual parts.</param> /// <returns>An enumeration of individual parts as standalone geometries. The type of geometry is maintained, i.e. /// if the input geometry is of type Polyline then each geometry in the return is of type Polyline as well. /// If the input geometry is of type Unknown then an empty list is returned.</returns> /// <remarks>This method must be called on the MCT. Use QueuedTask.Run.</remarks> public IEnumerable <Geometry> MultipartToSinglePart(Geometry inputGeometry) { // list holding the part(s) of the input geometry List <Geometry> singleParts = new List <Geometry>(); // check if the input is a null pointer or if the geometry is empty if (inputGeometry == null || inputGeometry.IsEmpty) { return(singleParts); } // based on the type of geometry, take the parts/points and add them individually into a list switch (inputGeometry.GeometryType) { case GeometryType.Envelope: singleParts.Add(inputGeometry.Clone() as Envelope); break; case GeometryType.Multipatch: singleParts.Add(inputGeometry.Clone() as Multipatch); break; case GeometryType.Multipoint: var multiPoint = inputGeometry as Multipoint; foreach (var point in multiPoint.Points) { // add each point of collection as a standalone point into the list singleParts.Add(point); } break; case GeometryType.Point: singleParts.Add(inputGeometry.Clone() as MapPoint); break; case GeometryType.Polygon: var polygon = inputGeometry as Polygon; foreach (var polygonPart in polygon.Parts) { // use the PolygonBuilder turning the segments into a standalone // polygon instance singleParts.Add(PolygonBuilderEx.CreatePolygon(polygonPart)); } break; case GeometryType.Polyline: var polyline = inputGeometry as Polyline; foreach (var polylinePart in polyline.Parts) { // use the PolylineBuilder turning the segments into a standalone // polyline instance singleParts.Add(PolylineBuilderEx.CreatePolyline(polylinePart)); } break; case GeometryType.Unknown: break; default: break; } return(singleParts); }
protected override async Task <bool> OnSketchCompleteAsync(Geometry geometry) { // get the embedded control var vm = this.EmbeddableControl as ChooseTemplateViewModel; if (vm == null) { return(false); } // ensure there's a template chosen if (vm.SelectedTemplate == null) { vm.ShowMessage("Please choose a layer and template"); return(false); } // clear any message vm.ClearMessage(); var template = vm.SelectedTemplate; BasicFeatureLayer templateLayer = template.Layer as BasicFeatureLayer; if (templateLayer == null) { return(false); } bool result = await QueuedTask.Run(() => { // find the target feature from the geometry click var targetFeatures = MapView.Active.GetFeatures(geometry); if ((targetFeatures == null) || (targetFeatures.ToDictionary().Keys.Count == 0)) { return(false); } // we will use the first feature returned var targetLayer = targetFeatures.ToDictionary().Keys.First(); var targetOID = targetFeatures[targetLayer][0]; // At 2.4, EditOperation.TransferAttributes method is one of the few functions which honors the field mapping. // The only method signature for EditOperation.TransferAttributes requires a source and target feature // So our workflow will be // 1. Create a temporary feature using the chosen template and empty geometry // 2. Call TransferAttributes from the temporary feature to the target feature // 3. Delete the temporary feature // build an empty geometry according to the correct template layer type Geometry emptyGeometry = null; switch (templateLayer.ShapeType) { case esriGeometryType.esriGeometryPoint: emptyGeometry = MapPointBuilderEx.CreateMapPoint(); break; case esriGeometryType.esriGeometryPolyline: emptyGeometry = PolylineBuilderEx.CreatePolyline(); break; case esriGeometryType.esriGeometryPolygon: emptyGeometry = PolygonBuilderEx.CreatePolygon(); break; } // some other geometry type if (emptyGeometry == null) { return(false); } // create the temporary feature using the empty geometry var op = new EditOperation(); op.Name = "Transfer attributes from template"; // note Create signature.. we are interested in the new ObjectID var rowToken = op.Create(template, emptyGeometry); // execute var opResult = op.Execute(); // if create was successful if (opResult) { var newObjectID = rowToken.ObjectID.Value; // chain to create a new operation var opChain = op.CreateChainedOperation(); // transfer the attributes between the temporary feature and the target feature opChain.TransferAttributes(templateLayer, newObjectID, targetLayer, targetOID); // and now delete the temporary feature opChain.Delete(templateLayer, newObjectID); opResult = opChain.Execute(); } return(opResult); }); return(result); }