Ask for Sketch from user

531
5
04-19-2018 02:28 PM
MKa
by
Occasional Contributor III

After drawing a polygon on my map.  i am required to get a direction Polyline from the user.  In ArcObjects, I was able to accomplish this like the following.  This would give me a line that a user drew that represented a "direction"

                IActiveView activeView = pDocument.ActiveView;
                IScreenDisplay screenDisplay = activeView.ScreenDisplay;

                string cursorLocation = ProMapSettings.AssemblyDirectory + @ProMapSettings.CursorFileLocation + "RowDirection.cur";
                bool cursorLocationExists = File.Exists(cursorLocation);
                if (cursorLocationExists)
                {
                    System.Windows.Forms.Cursor newCursor = new System.Windows.Forms.Cursor(cursorLocation);
                    System.Windows.Forms.Cursor.Current = newCursor;
                }

                screenDisplay.StartDrawing(screenDisplay.hDC, (System.Int16)esriScreenCache.esriNoScreenCache);

                IGeometry lineGeom = new PolylineClass();
                IRubberBand rubberBand = new RubberLineClass();
                if (rubberBand.TrackExisting(screenDisplay, null, lineGeom))
                {
                    lineGeom = rubberBand.TrackNew(screenDisplay, null) as IPolyline;
                }
                screenDisplay.FinishDrawing();

                polyline = (IPolyline)lineGeom;

In ArcGIS Pro, i understand how to create overlays and use map tools to create features, but can't quite figure out how to get a drawing from a user from within the code.  If there was a way I could trigger a MapTool that would be great too, but can't quite figure out how to get that to work and wait for it in code.  I want something like this.

//I need something like this to work, and then get result back to use the geometry                            
AddOverlayTool adt = new AddOverlayTool(RowLine);
Polyline mPolyline = await adt.startSketch();

//Then I use that line to get the angle and do more work                            
if (!mPolyline.IsNullOrEmpty())


0 Kudos
5 Replies
MKa
by
Occasional Contributor III

I am trying to trigger a MapTool from my code now.  This will allow me to draw a line that is my direction line that I need.  But I can't seem to get it to work.  I don't know what i am missing.  I keep getting the exception "Cannot set sketch from inactive tool". 

1st I am making a MapTool class

    internal class AddRowDirectionTool : MapTool
    {

        private IDisposable _graphic = null;
        private CIMLineSymbol _lineSymbol = null;
        public AddRowDirectionTool()
        {
            IsSketchTool = true;
            SketchType = SketchGeometryType.Line;
            SketchOutputMode = SketchOutputMode.Map;

            Module.GfxAddRowDirectionTool = this;
        }

        public async Task startSketch(Geometry inGeometry)
        {
            await StartSketchAsync();
            await SetCurrentSketchAsync(inGeometry); 
        }
    }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

2nd I make the reference in the module to the class

        private AddRowDirectionTool m_gfxAddRowDirectionTool;
        public static AddRowDirectionTool GfxAddRowDirectionTool
        {
            get
            {
                return Current?.m_gfxAddRowDirectionTool;
            }
            set
            {
                if (Current != null)
                    Current.m_gfxAddRowDirectionTool = value;
            }
        }

3rd I make the DAML entry for this class

        <tool id="GFXModule_PairTool" caption="Add Row Direction" className="xxxxyyyzzz.Attributes.Model.AddRowDirectionTool" keytip="AddRow"  loadOnClick="true" smallImage="Images\Rings32.png" largeImage="Images\Rings32.png" condition="esri_mapping_mapPane">
          <tooltip heading="Add Row Direction">
            Add Row Direction<disabledText />
          </tooltip>
        </tool>‍‍‍‍‍

4th In my code where i want to use the tool I do this and get the error "Cannot set sketch from inactive tool"

     //Here is where I load an instance and call it
     AddRowDirectionTool adt = new AddRowDirectionTool();
         
     //I call my function Start Sketch               
     await adt.startSketch(RowLine);‍‍‍‍


‍‍‍‍     //It gives me the error when I try and set the geometry in the start sketch function
     await SetCurrentSketchAsync(inGeometry);

     //But even If i skip over that line and just do this
     await StartSketchAsync();

     //It doesn't wait for my sketch to be created

I know I am missing something simple.  Please Advise

0 Kudos
CharlesMacleod
Esri Regular Contributor

Even though your constructor is public you should never call it. Framework will instantiate an instance of your tool when it is activated. It can be activated via clicking on the button on the UI or in code via: FrameworkApplication.SetCurrentToolAsync("GFXModule_PairTool")

Here is a code sequence which is kind of what you are after:

internal class Activate_Tool : Button
  {
    protected override void OnClick()
    {
      FrameworkApplication.SetCurrentToolAsync("ModifySketch_MapTool1");
    }
  }

internal class MapTool1 : MapTool
  {
    public MapTool1()
    {
      IsSketchTool = true;
      SketchType = SketchGeometryType.Line;
      SketchOutputMode = SketchOutputMode.Map;
    }

    protected override async Task OnToolActivateAsync(bool active)
    {
      var extent = MapView.Active.Extent;
      var center = extent.Center;
      var delta = extent.Width / 10.0;

      await StartSketchAsync();
      var polyLine = await QueuedTask.Run(() =>
      {
        var segment = LineBuilder.CreateLineSegment(
            new Coordinate2D { X = extent.Center.X - delta, Y = extent.Center.Y - delta },
            new Coordinate2D { X = extent.Center.X + delta, Y = extent.Center.Y + delta },
            MapView.Active.Map.SpatialReference);
        return PolylineBuilder.CreatePolyline(segment);
      });

      this.SetCurrentSketchAsync(polyLine);
    }

    protected override Task<bool> OnSketchCompleteAsync(Geometry geometry)
    {
      return base.OnSketchCompleteAsync(geometry);
    }
  }
MKa
by
Occasional Contributor III

That does work in setting the tool to the Line, but I need to do this in my code and get the result.  Like I did in ArcObjects.  Immediatly after my Feature was created, I wanted a line that represents the Row direction of this polygon (Agriculture field).  I basically prompted the user from code to draw a line direction.

                IGeometry lineGeom = new PolylineClass();
                IRubberBand rubberBand = new RubberLineClass();
                if (rubberBand.TrackExisting(screenDisplay, null, lineGeom))
                {
                    lineGeom = rubberBand.TrackNew(screenDisplay, null) as IPolyline;
                }
                screenDisplay.FinishDrawing();
0 Kudos
CharlesMacleod
Esri Regular Contributor

The finished sketch is returned to you in the OnSketchCompleteAsync callback.

0 Kudos
MKa
by
Occasional Contributor III

My Code doesn't seem to wait for the sketch from the user?  I call the SetCurrentToolAsync function and i can see that it initiates the tool.  But It just blows right by this line of code after i call it.  I think I am missing something to get the drawing.  My code cannot proceed until I get the drawing from the user.

await FrameworkApplication.SetCurrentToolAsync("XYX_RowTool");

0 Kudos