000

Picking Points With Visual Aid

.
Again, this article was prompted with the discussion in the same thread from Autodesk's .NET discussion here.

As we all know, using PromptPointOptions with Editor.GetPoint(), one can use its properties UseBasePoint and BasePoint tp let AutoCAD show a rubber band line while picking points.

Some times, there are many points to pick, and user may want to have certain visual hint showing the points he/she has picked during the picking process. It may also be helpful to show a trace line follow the order of the points being picked.

Here is the code I do it, in a class called "PickPoints":

using System.Collections.Generic;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;

namespace PickPointWithVisualSpot
{
public class PickPoints
{
private Document _dwg;
private Editor _editor;
private List _points = null;
private List _circles = null;

private bool _drawPline = false;
private Polyline _pline = null;

private int _color = 1;
private double _radius = 0.1;

public PickPoints(Document dwg)
{
_dwg = dwg;
_editor = _dwg.Editor;
}

public Point3d[] PickedPoints
{
get
{
if (_points == null)
return null;
else
return _points.ToArray();
}
}

public void DoPick(bool drawTraceLine)
{
try
{
//Pick first point
Point3d pt;
if (!PickFirstPoint(out pt)) return;

_drawPline = drawTraceLine;

_points = new List();
_circles = new List();

_points.Add(pt);

//Crate visual at the point
CreateCircle(pt);

while (true)
{
if (!PickNextPoint()) break;
}
}
catch { }
finally
{
//Clear Transient graphics
if (_circle != null)
{

if (_circles.Count > 0)
{
foreach (Circle c in _circles)
{
TransientManager.CurrentTransientManager.
EraseTransient(c, new IntegerCollection());

c.Dispose();
}
}

_circles.Clear();
_circles = null;
}

ClearTraceLine();
}
}

private bool PickFirstPoint(out Point3d pt)
{
pt = new Point3d();

PromptPointOptions opt =
new PromptPointOptions("\nPick start point: ");
PromptPointResult res = _editor.GetPoint(opt);
if (res.Status == PromptStatus.OK)
{
pt = res.Value;
return true;
}
else
{
return false;
}
}

private bool PickNextPoint()
{
PromptPointOptions opt=
new PromptPointOptions("\nPick next point: ");
opt.UseBasePoint=true;
opt.BasePoint=_points[_points.Count-1];
if (_points.Count>2)
{
opt.Keywords.Add("Close");
opt.AppendKeywordsToMessage=true;
}

PromptPointResult res=_editor.GetPoint(opt);
if (res.Status==PromptStatus.OK)
{
_points.Add(res.Value);

CreateCircle(res.Value);

if (_points.Count > 1 && _drawPline )
{
DrawTraceLine();
}

return true;
}
else if (res.Status==PromptStatus.Keyword)
{
return false;
}
else
{
return false;
}
}

private void CreateCircle(Point3d pt)
{
Circle c = new Circle();
c.Center = pt;
c.Radius = _radius;
c.ColorIndex = _color;
c.Highlight();

TransientManager.CurrentTransientManager.AddTransient(c,
TransientDrawingMode.Highlight,128, new IntegerCollection());

_circles.Add(c);
}

private void DrawTraceLine()
{
ClearTraceLine();

_pline = new Polyline(_points.Count);

for (int i = 0; i < _points.Count; i++)
{
Point2d p = new Point2d(_points[i].X, _points[i].Y);
_pline.AddVertexAt(i, p, 0.0, 0.0, 0.0);
}

_pline.ColorIndex = _color;

TransientManager.CurrentTransientManager.AddTransient(_pline,
TransientDrawingMode.Highlight, 128, new IntegerCollection());
}

private void ClearTraceLine()
{
if (_pline != null)
{
TransientManager.CurrentTransientManager.
EraseTransient(_pline, new IntegerCollection());

_pline.Dispose();
_pline = null;
}
}
}
}
Then the use of the class in custom command. There are 2 commands: one shows trace line, while the other does not:

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;

[assembly: CommandClass(typeof(PickPointWithVisualSpot.MyCommand))]

namespace PickPointWithVisualSpot
{
public class MyCommand
{
[CommandMethod("MyPick1", CommandFlags.Session)]
public static void RunThisMethod1()
{
Document dwg = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;

PickPoints pick = new PickPoints(dwg);

pick.DoPick(false);
if (pick.PickedPoints != null)
{
dwg.Editor.WriteMessage("\nMyCommand executed: {0} points picked.", pick.PickedPoints.Length);
}
else
{
dwg.Editor.WriteMessage("\n*Cancelled*");
}
}

[CommandMethod("MyPick2", CommandFlags.Session)]
public static void RunThisMethod2()
{
Document dwg = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;

PickPoints pick = new PickPoints(dwg);

pick.DoPick(true);
if (pick.PickedPoints != null)
{
dwg.Editor.WriteMessage("\nMyCommand executed: {0} points picked.", pick.PickedPoints.Length);
}
else
{
dwg.Editor.WriteMessage("\n*Cancelled*");
}
}
}
}

See this video clip for the code's behaviour.

Note: thanks to Irvin who prompted a bug in the "PickPoints" class' DoPick() method in the try...finally{...} block. I have corrected in red.

Blog Archive