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 ListThen the use of the class in custom command. There are 2 commands: one shows trace line, while the other does not:_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; } } } }
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.
2 comments:
Hi Yuan,
Looking at this code again. I ran to an other glitch. If you selected 1 or more points. And you hit the Esc button. The user gets prompted on the commandline the command was canceld. This is how AutoCAD works. But in your code you check if the array is not emtpy, if not the commandline will still prompt the number of selected points.
Where in your code will be the best place to check is promptstatus is canceld en then clear the array of points.
Kind regards,
Irvin
Post a Comment