Cut a polygon with line,Any tool?

Aug 24, 2014 at 6:00 AM
Hi,
I have found a piece of c# code that cuts a polygon using arcobject,Is there any similar tools that I can use it in dotspatial?

Here is that class I mentioned but I can not understand how it is working :(
 #region IEngineEditTask Implementations
    public void Activate(ESRI.ArcGIS.Controls.IEngineEditor editor, ESRI.ArcGIS.Controls.IEngineEditTask oldTask)
    {      
        if (editor == null)
          return;

        //Initialize class member variables.
        m_engineEditor = editor;
        m_editSketch = editor as IEngineEditSketch;
        m_editSketch.GeometryType = esriGeometryType.esriGeometryPolyline;
        m_editLayer = m_editSketch as IEngineEditLayers;

        //Wire editor events.        
        ((IEngineEditEvents_Event)m_editSketch).OnTargetLayerChanged += new IEngineEditEvents_OnTargetLayerChangedEventHandler(OnTargetLayerChanged);
        ((IEngineEditEvents_Event)m_editSketch).OnCurrentTaskChanged += new IEngineEditEvents_OnCurrentTaskChangedEventHandler(OnCurrentTaskChanged);
    }

    public void Deactivate()
    {
      //Stop listening for editor events.
      ((IEngineEditEvents_Event)m_engineEditor).OnTargetLayerChanged -= OnTargetLayerChanged;
      ((IEngineEditEvents_Event)m_engineEditor).OnCurrentTaskChanged -= OnCurrentTaskChanged;

      //Release object references.
      m_engineEditor = null;
      m_editSketch = null;
      m_editLayer = null;
    }

    public string GroupName
    {
      get
      {
        return "Modify Tasks";
      }
    }

    public string Name
    {
      get
      {
        return "Cut Polygons Without Selection (C#)";
      }
    }

    //This method is not expected to be fired since we have unregistered from the event in Deactivate
    public void OnCurrentTaskChanged()
    {
      UpdateSketchToolStatus();
    }

    public void OnTargetLayerChanged()
    {
      UpdateSketchToolStatus();
    }

    public void OnDeleteSketch()
    { 
    }
    
    public void OnFinishSketch()
    {
      if (m_editSketch == null)
        return;

      bool hasCutPolygons = false;

      //Change the cursor to be hourglass shape.
      System.Windows.Forms.Cursor.Current = Cursors.WaitCursor;

      try
      {
        //Get the geometry that performs the cut from the edit sketch.
        IGeometry cutGeometry = m_editSketch.Geometry;

        //The sketch geometry is simplified to deal with a multi-part sketch as well
        //as the case where the sketch loops back over itself.
        ITopologicalOperator2 topoOperator = cutGeometry as ITopologicalOperator2;
        topoOperator.IsKnownSimple_2 = false;
        topoOperator.Simplify();

        //Create the spatial filter to search for features in the target feature class.
        //The spatial relationship we care about is whether the interior of the line 
        //intersects the interior of the polygon.
        ISpatialFilter spatialFilter = new SpatialFilterClass();
        spatialFilter.Geometry = m_editSketch.Geometry;
        spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;

        //Find the polygon features that cross the sketch.
        IFeatureClass featureClass = m_editLayer.TargetLayer.FeatureClass;
        IFeatureCursor featureCursor = featureClass.Search(spatialFilter, false);

        //Only do work if there are features that intersect the edit sketch.
        IFeature origFeature = featureCursor.NextFeature();
        if (origFeature != null)
        {
          //Check the first feature to see if it is ZAware and if it needs to make the
          //cut geometry ZAware.
          IZAware zAware = origFeature.Shape as IZAware;
          if (zAware.ZAware)
          {
            zAware = cutGeometry as IZAware;
            zAware.ZAware = true;
          }

          ArrayList comErrors = new ArrayList();       
            
          //Start an edit operation so we can have undo/redo.
          m_engineEditor.StartOperation();

          //Cycle through the features, cutting with the sketch.
          while (origFeature != null)
          {
            try
            { 
              //Split the feature. Use the IFeatureEdit::Split method which ensures
              //the attributes are correctly dealt with.
              IFeatureEdit featureEdit = origFeature as IFeatureEdit;
              //Set to hold the new features that are created by the Split.            
              ISet newFeaturesSet = featureEdit.Split(cutGeometry);

              //New features have been created.
              if (newFeaturesSet != null)
              {
                newFeaturesSet.Reset();
                hasCutPolygons = true;
              }
            }
            catch (COMException comExc)
            {
                comErrors.Add(String.Format("OID: {0}, Error: {1} , {2}",origFeature.OID.ToString(), comExc.ErrorCode,comExc.Message));
            }
            finally
            {
              //Continue to work on the next feature if it fails to split the current one.
              origFeature = featureCursor.NextFeature();
            }
          }
          //If any polygons were cut, refresh the display and stop the edit operation.
          if (hasCutPolygons)
          {
            //Clear the map's selection.
            m_engineEditor.Map.ClearSelection();

            //Refresh the display including modified layer and any previously selected component. 
            IActiveView activeView = m_engineEditor.Map as IActiveView;
            activeView.PartialRefresh(esriViewDrawPhase.esriViewGeography | esriViewDrawPhase.esriViewGeoSelection, null, activeView.Extent);

            //Complete the edit operation.
            m_engineEditor.StopOperation("Cut Polygons Without Selection");
          }
          else
          {
            m_engineEditor.AbortOperation();
          }

          //report any errors that have arisen while splitting features
          if (comErrors.Count > 0)
          {
            StringBuilder stringBuilder = new StringBuilder("The following features could not be split: \n", 200);
            foreach (string comError in comErrors)
            {
              stringBuilder.AppendLine(comError);
            }

            MessageBox.Show(stringBuilder.ToString(), "Cut Errors");
          }
        }
      }
      catch (Exception e)
      {
        MessageBox.Show("Unable to perform the cut task.\n" + e.Message);
        m_engineEditor.AbortOperation();
      }
      finally
      {
        //Change the cursor shape to default.
        System.Windows.Forms.Cursor.Current = Cursors.Default;
      }
    }

    public string UniqueName
    {
      get
      {
        return "CutPolygonsWithoutSelection_CS_CutPolygonsWithoutSelection_CSharp";
      }
    }
    #endregion

    #region IEngineEditTask private methods
    private void UpdateSketchToolStatus()
    {
      if (m_editLayer == null)
        return;

      //Only enable the sketch tool if there is a polygon target layer.
      if (m_editLayer.TargetLayer.FeatureClass.ShapeType != esriGeometryType.esriGeometryPolygon)
        m_editSketch.GeometryType = esriGeometryType.esriGeometryNull;
      else
        //Set the edit sketch geometry type to be esriGeometryPolyline.
        m_editSketch.GeometryType = esriGeometryType.esriGeometryPolyline;
    }
    #endregion

  }
}
Aug 24, 2014 at 10:58 PM
Edited Aug 24, 2014 at 11:12 PM
I used

success = DotSpatial.Tools.ClipPolygonWithLine.Accurate_ClipPolygonWithLine(ref poly, ref line, ref result);

hope this helps

have a look in the DotSpatial.Plugins.ShapeEditor this show all you need to know about editing plugins. I have nodified this for my purposes and created a function to cut a polygon with a line.

Here is the overridden method
class AddFence : EditableMap
    {
        public AddFence(IMap map) : base(map) { }
        /// <summary>
        /// Finish the shape.
        /// </summary>
        /// <param name="sender">The object sender.</param>
        /// <param name="e">An empty EventArgs class.</param>
        public override void FinishPolyLine(object sender, EventArgs e)
        {
            if (_coordinates.Count < 2) { return;}
            if (Layer.DataSet != null && !Layer.DataSet.IsDisposed)
            {
                IFeature f = new Feature(FeatureType.Line,_coordinates);

                List<IFeature> paddockSelect = Spatial.Extensions.IsWithin(Layer.DataSet, Spatial.Extensions.CentroidCoordinate(f));
                if (paddockSelect != null && paddockSelect.Any())
                {
                    Layer.EditMode = true;
                    Layer.Symbology.SuspendEvents();

                    IFeatureSet result = new FeatureSet();
                    IFeature paddock = paddockSelect[0].Copy();
                    //DotSpatial.Tools.ClipPolygonWithLine.FindIntersectionTolerance = 100;
                    bool success = false;
                    try
                    {
                        success = DotSpatial.Tools.ClipPolygonWithLine.Accurate_ClipPolygonWithLine(ref paddock, ref f,
                            ref result);
                    }
                    catch (Exception ex)
                    {
                        paddock = paddock.Buffer(0);
                        success = DotSpatial.Tools.ClipPolygonWithLine.Accurate_ClipPolygonWithLine(ref paddock, ref f,
                            ref result);
                    }
                    finally
                    {
                        if (success)
                        //if (DotSpatial.Tools.ClipPolygonWithLine.Fast_ClipPolygonWithLine(ref paddock, ref f, ref result))
                        {
                            paddock = MappingLayer.EditFeature(paddockSelect[0], result.Features, result.Features.First().BasicGeometry);

                        }

                        ValidateMap();

                        _fenceAdded = true;
                    }
                    
                }
            }
            base.FinishPolyLine(sender, e);
            
        }

        
    }
Aug 25, 2014 at 8:58 PM
Hi,Thank you very much for your help.But I noticed that this calss is not a map function or somthing like that,so how can I use this?
Is this a part of shapeeditor.dll?I looked at it and It can creat lined but I don't know how to use your class :(
Aug 25, 2014 at 11:42 PM
Sorry about not giving enough of the code

EditableMap inherits from SnappableMapFunction which inherits from MapFunction

And EditableMap was hacked out of AddShapeFunction in th DotSpatial.Plugins.ShapeEditor directory of the source code.

Have limited space here so can't paste code. If you would like my source I can put it somewhere (suggestion welcome?)

I'm sure once you check the code in the DotSpatial source you will probably come up with something much better than the cut/paste coding I have done.
Aug 26, 2014 at 4:51 AM
Thanks my friend,I just want to get some idea how to do that,some how I am new with dotspatial and I am learning ,Is it possible to share it in dropbox or even google doc?
I will try to use the code you provided with shapeditor but if I could not do that I want to get ideas from your source code.
Thanks very much
Aug 28, 2014 at 5:49 AM
I have put a chunk of code on DropBox
DropBox Link
Aug 28, 2014 at 6:24 AM
Thank you very much for your help
Aug 28, 2014 at 8:33 AM
I have notice in your code this part is unknown
List<IFeature> paddockSelect = Spatial.Extensions.IsWithin(Layer.DataSet, DotSpatial.Extensions.CentroidCoordinate(f));
Spatial.Ectentions is in which assembely?
Aug 28, 2014 at 6:14 PM
I used this code in case of finding within polygons with line but it returns false.so List is empty always .where is my mistake?
     private List<IFeature> IsWithin(IFeatureSet featureSet, IFeature centroidpoint)
        {
            List<IFeature> list = new List<IFeature>();
            for (int i = 0; i < featureSet.Features.Count; i++)
            {
                if (featureSet.Features[i].Within(centroidpoint))
                {
                   
                    list.Add(featureSet.Features[i]);
                }
            }
            return list;
      
            
        }
Is there any way to add attribute tables to result?I tried but it does not look good :(
Developer
Aug 28, 2014 at 6:25 PM
Try to use intersects instead of within. Within finds only features that lay completely inside of centroidpoint. If centroidpoint is a point or line there is no way a polygon can lay within.
Aug 28, 2014 at 6:37 PM
Hi Jany_
I used
f.Centroid()
for IFeature centroidpoint in this function.I'll try your suggestion now and report the results
Aug 28, 2014 at 6:50 PM
Hi Jany_
Thanks for your help.It worked great,I used this code in case of cutting polygon,It works fine at the first time.but if I use it for second time it removes some part of base polygon.I tried to save polygons without any intersect and add them to result featureset. this seems to work only for one part lines and it removes parts of polygon if I draw a two part line (for example a V shaped line cause this problem)
Do you have any suggestions to fix this problem?
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Windows.Forms;

using DotSpatial.Controls;
using DotSpatial.Data;
using DotSpatial.Symbology;
using DotSpatial.Topology;

using Point = System.Drawing.Point;


namespace LandManagment
{
    class AddFence : shapeEditor.AddShapeFunction
    {
        private int ownerID{get;set;}
        List<IFeature> withoutintersect = new List<IFeature>();
        public AddFence(IMap map, int owner_ID) : base(map) { this.ownerID = owner_ID; }
        /// <summary>
        /// Finish the shape.
        /// </summary>
        /// <param name="sender">The object sender.</param>
        /// <param name="e">An empty EventArgs class.</param>
        public override void FinishShape(object sender, EventArgs e)
        {
            if (_coordinates.Count < 2) { return;}
            if (Map.Layers[0].DataSet != null && !Map.Layers[0].DataSet.IsDisposed)
            {
                IFeature f = new Feature(FeatureType.Line,_coordinates);
                Layer = Map.GetPolygonLayers().First();

                List<IFeature> paddockSelect = IsWithin(Map.GetPolygonLayers().First().DataSet, f);
                if (paddockSelect != null && paddockSelect.Any())
                {
                    Layer.EditMode = true;
                    Layer.Symbology.SuspendEvents();

                    IFeatureSet result = new FeatureSet();
                    IFeature paddock = paddockSelect[0].Copy();
                    //DotSpatial.Tools.ClipPolygonWithLine.FindIntersectionTolerance = 100;
                    bool success = false;
                    try
                    {
                        success = DotSpatial.Tools.ClipPolygonWithLine.Accurate_ClipPolygonWithLine(ref paddock, ref f,
                            ref result);
                    }
                    catch (Exception ex)
                    {
                        paddock = paddock.Buffer(0);
                        success = DotSpatial.Tools.ClipPolygonWithLine.Accurate_ClipPolygonWithLine(ref paddock, ref f,
                            ref result);
                    }
                    finally
                    {
                        if (success)
                        //if (DotSpatial.Tools.ClipPolygonWithLine.Fast_ClipPolygonWithLine(ref paddock, ref f, ref result))
                        {
                            foreach (var fe in withoutintersect)
                            {

                                result.AddFeature(fe);
                            }
                            result.DataTable = new DataTable();
                            //result.DataTable.Columns.Add(new DataColumn("کد بهره بردار", typeof(int)));
                            result.Projection = DotSpatial.Projections.ProjectionInfo.FromEpsgCode(Properties.Settings.Default.UTMCode);
                            result.Features[0].DataRow.Table.Columns.Add(new DataColumn("کد بهره بردار", typeof(int)));
                            foreach (var fe in result.Features)
                            {
                               // fe.DataRow.Table.Columns.Add(new DataColumn("کد بهره بردار", typeof(int)));
                                fe.DataRow.BeginEdit();
                                fe.DataRow[0] = ownerID;
                                fe.DataRow.EndEdit();
                            }

                            result.Projection=Map.Projection;
                            
                            //paddock = MappingLayer.EditFeature(paddockSelect[0], result.Features, result.Features.First().BasicGeometry);

                        }

                        ValidateMap();

                        _fenceAdded = true;

                        Map.Layers.Clear();
                        Map.Layers.Add(result);
                        Map.ZoomToMaxExtent();
                    }

                }
            }
            base.FinishShape(sender, e);
            
        }

        private List<IFeature> IsWithin(IFeatureSet featureSet, IFeature centroidpoint)
        {
            List<IFeature> list = new List<IFeature>();
            for (int i = 0; i < featureSet.Features.Count; i++)
            {
                if (featureSet.Features[i].Intersects(centroidpoint))
                {

                    list.Add(featureSet.Features[i]);
                }
                else
                {

                    withoutintersect.Add(featureSet.Features[i]);
                }
            }
            return list;
      
            
        }


        protected override void OnActivate()
        {


            FeatureType featureType = FeatureType.Line;


            _featureSet = new FeatureSet(featureType);
           
            base.OnActivate();
        }

        
    }
}