ThinkGeo.com    |     Documentation    |     Premium Support

Editing rectangular polygons

I have polygon shapes on my map that I want to have the user size (rectangles but not necessarily flat on the X/Y axis).  Is there any way to set the edit overlay so that when I drag a control point on the corner the adjacent control points move so that the rectangular shape remains rather than just having the single control point move?


Thanks



David,


This is an advanced requirement. We can achieve this by write our won EditInterativeOverlay logic.


 Following is the code basically we write according to your requirement, and you can modify it if you want.
 

public class CustomerEditInteractiveOverlay : EditInteractiveOverlay
    {
        private ResizeMode resizeMode;

        public CustomerEditInteractiveOverlay()
        {
        }

        public ResizeMode ResizeMode
        {
            get { return resizeMode; }
            set { resizeMode = value; }
        }

        protected override Feature AddVertexCore(Feature targetFeature, PointShape targetPointShape, double searchingTolerance)
        {
            return new Feature();
        }

        protected override IEnumerable<Feature> CalculateResizeControlPointsCore(Feature feature)
        {
            Collection<Feature> resizeControlPoints = new Collection<Feature>();
            
            PolygonShape polygonShape = feature.GetShape() as PolygonShape;
            if (polygonShape != null)
            {
                foreach (Vertex vertex in polygonShape.OuterRing.Vertices)
                {
                    resizeControlPoints.Add(new Feature(vertex, feature.Id));
                }
            }

            return resizeControlPoints;
        }

        protected override Feature ResizeFeatureCore(Feature sourceFeature, PointShape sourceControlPoint, PointShape targetControlPoint)
        {
            Feature editedFeature = new Feature();

            PolygonShape polygonShape = sourceFeature.GetShape() as PolygonShape;
           
            int fixedPointIndex = GetFixedPointIndex(polygonShape, sourceControlPoint);

            PointShape fixedPointShape = new PointShape(polygonShape.OuterRing.Vertices[fixedPointIndex]);

            if (resizeMode == ResizeMode.OnePointFixed)
            {
                RectangleShape newRectangleShape = new LineShape(new Vertex[] { new Vertex(fixedPointShape), new Vertex(targetControlPoint) }).GetBoundingBox();
                editedFeature = new Feature(newRectangleShape.GetWellKnownBinary(), sourceFeature.Id, sourceFeature.ColumnValues);

                if (!string.Equals(polygonShape.GetBoundingBox().GetWellKnownText(), polygonShape.GetWellKnownText()))
                {
                    editedFeature = base.ResizeFeatureCore(sourceFeature, sourceControlPoint, targetControlPoint);
                }
            }
            else
            {
                editedFeature = base.ResizeFeatureCore(sourceFeature, sourceControlPoint, targetControlPoint);
            }

            return editedFeature;
        }

        private int GetFixedPointIndex(PolygonShape sourcePolygonShape, PointShape sourceControlPointShape)
        {
            int index = 0;
            for (int i = 0; i < sourcePolygonShape.OuterRing.Vertices.Count; i++)
            {
                Vertex vertex = sourcePolygonShape.OuterRing.Vertices[i];
                if (Math.Abs(vertex.X - sourceControlPointShape.X) <= 10E-6 && Math.Abs(vertex.Y - sourceControlPointShape.Y) <= 10E-6)
                {
                    index = i;
                    break;
                }
            }
            int fixedPointIndex = 0;
            if (index <= 2)
            {
                fixedPointIndex = index + 2;
            }
            else
            {
                fixedPointIndex = index - 2;
            }

            return fixedPointIndex;
        }
    }

    public enum ResizeMode
    {
        Default = 0,
        Standard = 1,
        OnePointFixed = 2
    }

Based on this CustomerEditInteractiveOverlay, We can use it in the following way.



  winformsMap1.MapUnit = GeographyUnit.DecimalDegree;
            winformsMap1.BackgroundOverlay.BackgroundBrush = new GeoSolidBrush(GeoColor.GeographicColors.ShallowOcean);

            //ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(@"..\..\..\..\..\PostsData\Countries02.shp", ShapeFileReadWriteMode.ReadOnly);
            //worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.Country1;
            //worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;

            //LayerOverlay worldOverlay = new LayerOverlay();
            //worldOverlay.Layers.Add("WorldLayer", worldLayer);
            //winformsMap1.Overlays.Add("WorldOverlay", worldOverlay);

            CustomerEditInteractiveOverlay customerEditOverlay = new CustomerEditInteractiveOverlay();
            customerEditOverlay.ResizeMode = ResizeMode.OnePointFixed;
            winformsMap1.EditOverlay = customerEditOverlay;

            winformsMap1.ZoomLevelSnapping = ZoomLevelSnappingMode.None;
            winformsMap1.CurrentExtent = new RectangleShape(-180, 90, 180, -90);

            winformsMap1.Refresh();

Any queries just let me know.


 
Thanks.
 
Yale.

 



Thanks.  That put me on the trail. 



Cool, I also want to extend EditInteractiveOverlay, this is really good example. 
 Thank Yale.

David & James, 
  
 Thanks for your words. Any more questions just let me know. 
  
 Yale 


What a great example, thanks from me, Yale. I have a couple of questions on it, please. 
  
 1) In my application, the user has already selected the feature she wants to edit when I copy it into the EditInteractiveOverlay, so how can I put the new feature into an edit mode right away, rather than making the user select it again? 
  
 2) Is there already a mechanism for the user to signal she is done editing, or must I provide one (and if it’s the latter, do you have an example I can re-use)? 
  
 Thank you, 
  
 Janene McCrillis 
 Wireless Seismic

Janene, 
   
             1. there are two ways to to edit a feature. One is using mouse to select it as you already know; the other one is to add this feature to EditInteractiveOverlay directly. There is an InMemoryFeatureLayer called EditShapeLayer in EditInteractiveOverlay, you can add the features to the InternalFeatures property of it. 
  
             2. It will raise an event when each operation (such rotate, drag, add vertex etc) start or end.  I think you can use the end event as the signal of done editing.  
  
 Thanks, 
  
 Ben

Hi Ben, thanks for the reply.


My first question was more aimed at the question of how to put a feature into editing mode automatically, so the control points for editing are available to the user without making her select the feature a 2nd time. I'm adding my current code below, please let me know where I need to add or change something to show the feature ready to be edited:


 



            RectangleShape newRectangleShape = currentlySelectedFeature.GetBoundingBox() as RectangleShape;

            lineSegmentEditOverlay.Lock.EnterWriteLock();
            try {
                lineSegmentEditOverlay.EditShapesLayer.InternalFeatures.Add(new Feature(newRectangleShape));
                lineSegmentEditOverlay.CalculateAllControlPoints();
            } finally {
                lineSegmentEditOverlay.Lock.ExitWriteLock();
            }

            wpfMap1.Refresh();

 


 


I'm still working on this, so any help would be appreciated. Thanks!


Janene McCrillis


Wireless Seismic



Hi Janene,


I think this block of code is enough, the control points will show on the map after executing these codes and you can edit the feature directly by the control points without nothing more operation.
There is a simple sample in the attachment to show you how it works base on the CustomerEditInteractiveOverlay in this post.
Any more questions please let us know.
Thanks,
sun

1283-Post5822Demo.zip (11.5 KB)

Hi Sun, 
  
 The map is still not entering edit mode automatically - the user still has to select the feature again to edit it. It is also not refreshing automatically when the feature is removed, in spite of many calls to wpfMap.refresh() 
  
 JAnene 
  


Janene,


I think you could use the event TrackEnded to implement the functionality, try the attachment sample, and hope it helps.
 
Any more questions just feel free to let me know.
 
Thanks.
 
Yale

1296-Post5822_Wpf_sample.zip (14.1 KB)

 


Guys,
 
We create a sample in our Code Community shows how to edit rectangles.
code.thinkgeo.com/projects/s...rectangles
 
Thanks
James