Code Red > .NET

Selection Set by Fence

(1/2) > >>

kdub_nz:

Some days you have so much fun you forget about the wonderful sun shining outside

kdub_nz:
During a discussion elsewhere about a month ago I mistakenly thought that a Fence selection did not keep the SelectionSet in order of selection.
That, combined with the OP's requirement for being able to multi-select and force the selectionset to retain a specific order, led to a play day for me.

This could probably be combined with a keyword trap to allow single selections as well as Fence selections to be added to the SelectionSet .. but it would probably get messy.

Just to prove I was wrong about the Selection set (not) being ordered : ...


edit kdub: spelling police :)

kdub_nz:
Some Code


--- Code - C#: ---    public class Commands    {        [CommandMethod("TEST", CommandFlags.Modal)]        public void Test()        {            Active.Editor.WriteMessage(" Get on with it !!");        }         /// <summary>SelectionSet with filter by Fence.</summary>        // This command does a simple selection and ignores all         // entities other than red circles.        [CommandMethod("SSetF", CommandFlags.Modal)]        public void SSGetFilterByFence()        {            // DxfCode.Start (equal to 0) - This is for 'Entity Name'            // DxfCode.Color is for ACI color - 1 = Red            TypedValue[] filterValues = new[] {                new TypedValue((int)DxfCode.Start, "CIRCLE"),                new TypedValue((int)DxfCode.Color, 1)            };            SelectionFilter selectionFilter = new SelectionFilter(filterValues);             Active.WriteMessage("\nFence point: (Enter when Done)");            Point3dCollection pointCollection = InteractivePolyLine.CollectPointsInteractive();             if (pointCollection.Count != 0) {                try {                    SelectionSet ss;                    PromptSelectionResult selectionResult = Active.Editor.SelectFence(pointCollection, selectionFilter);                    if (selectionResult.Status == PromptStatus.OK) {                        ss = selectionResult.Value;                        if (ss != null) {                            Active.WriteMessage($"\nThe SelectionSet has {ss.Count} entities.");                            OutputCircleData(ss);                        }                        else {                            Active.WriteMessage("\nThe SelectionSet has null value");                        }                    }                    else { Active.WriteMessage("\nFence selection failed!"); }                 }                catch (System.Exception ex) {                    Active.WriteMessage(Environment.NewLine + ex.ToString());                }            }        }          /// <summary>SelectionSet with filter.</summary>        // This command does a simple selection and ignores all         // entities other than red circles.        // Use any of the conventional selection Keywords at the commandLine         [CommandMethod("SSetA", CommandFlags.Modal)]        public void SSGetFilterAnyMeans()        {            // DxfCode.Start (equal to 0) - This is for 'Entity Name'            // DxfCode.Color is for ACI color - 1 = Red            TypedValue[] filterValues = new[] {                new TypedValue((int)DxfCode.Start, "CIRCLE"),                new TypedValue((int)DxfCode.Color, 1)            };            SelectionFilter selectionFilter = new SelectionFilter(filterValues);             // Set the selection options            PromptSelectionOptions selectionOptions = new PromptSelectionOptions {                MessageForAdding = "Select Red Circles by Any means:",                AllowDuplicates = true            };             // Make the selection:            PromptSelectionResult selectionResult = Active.Editor.GetSelection(selectionOptions, selectionFilter);             if (!(selectionResult.Status == PromptStatus.OK))                return;             SelectionSet ss = selectionResult.Value;            OutputCircleData(ss);        }         /// <summary>Outputs the circle data.</summary>        /// <param name="ss">The SelectionSet of Circles.</param>        private void OutputCircleData(SelectionSet ss)        {            ObjectId[] idarray = ss.GetObjectIds();            // start a transaction            using (Transaction tr = Active.Database.TransactionManager.StartTransaction()) {                try {                    foreach (var id in idarray) {                        var circle = (Circle)tr.GetObject(id, OpenMode.ForRead, true);                        Active.WriteMessage(                            $"\nYou selected: {circle.GetType().FullName} with Radius = {circle.Radius }");                    }                }                finally {                    tr.Dispose();                }            }        }  


--- Code - C#: ---    /// <summary>    /// Provides easy access to several "active" objects in the     /// AutoCAD runtime environment.    /// Thanks to : Scott McFarlane - Programming AutoCAD with C#: Best Practices    /// </summary>    public static class Active    {        public static Document Document => cadApp.DocumentManager.MdiActiveDocument;        public static Database Database => Document.Database;        public static Editor Editor => Document.Editor;         public static void WriteMessage(            string message)            => Editor.WriteMessage(message);         public static void WriteMessage(            string message, params object[] parameter)            => Editor.WriteMessage(message, parameter);    }      /// <summary></summary>    /// <seealso cref="Autodesk.AutoCAD.Runtime.IExtensionApplication" />    public class Initialization : IExtensionApplication    {        public void Initialize()        {            cadApp.Idle += OnIdle;        }         private void OnIdle(object sender, EventArgs e)        {            var doc = Active.Document;            if (doc != null) {                cadApp.Idle -= OnIdle;                Active.WriteMessage("\nSelectionTesting loaded.\n");                Active.WriteMessage("Enter \"TEST\" at the CommandLine.\n");                Active.WriteMessage("Enter \"SSetA\" at the CommandLine to Select Red Circles\n");                Active.WriteMessage("Enter \"SSetF\" at the CommandLine to Select Red Circles by FENCE\n");            }        }         public void Terminate()        { }    } 
The  CollectPointsInteractive() method is also used by
        [CommandMethod("TestPOLY", CommandFlags.Modal)]
        public void InteractivePolylineTest()
       

--- Code - C#: ---    public class InteractivePolyLine    {        /// <summary>Collects the points interactively, Temporarily joining vertexes.</summary>        /// <returns>Point3dCollection</returns>        public static Point3dCollection CollectPointsInteractive()        {            Point3dCollection pointCollection = new Point3dCollection();            Color color = Active.Database.Cecolor;            PromptPointOptions pointOptions = new PromptPointOptions("\nSelect vertex: ") {                AllowNone = true            };             // Get the start point            PromptPointResult pointResult = Active.Editor.GetPoint(pointOptions);            while (pointResult.Status == PromptStatus.OK) {                pointCollection.Add(pointResult.Value);                 // Select subsequent points                pointOptions.UseBasePoint = true;                pointOptions.BasePoint = pointResult.Value;                pointResult = Active.Editor.GetPoint(pointOptions);                if (pointResult.Status == PromptStatus.OK) {                    // Draw a temporary segment                    Active.Editor.DrawVector(                      pointCollection[pointCollection.Count - 1], // start point                      pointResult.Value,          // end point                      color.ColorIndex,                      false);                     // highlighted?                }            }            if (pointResult.Status == PromptStatus.None) {                return pointCollection;            }            else {                return new Point3dCollection();            }        }         /// <summary> Generates an interactive Polyline.</summary>        [CommandMethod("TestPOLY", CommandFlags.Modal)]        public void InteractivePolylineTest()        {            Point3dCollection pointCollection = CollectPointsInteractive();             if (pointCollection.Count != 0) {                // Get the current UCS                Matrix3d ucs = Active.Editor.CurrentUserCoordinateSystem;                Point3d origin = new Point3d(0, 0, 0);                Vector3d normal = new Vector3d(0, 0, 1).TransformBy(ucs);                 // Create a temporary plane                Plane plane = new Plane(origin, normal);                 // Create the polyline                Polyline pline = new Polyline(pointCollection.Count) {                    Normal = normal                };                foreach (Point3d pt in pointCollection) {                    pline.AddVertexAt(pline.NumberOfVertices,                    plane.ParameterOf(pt.TransformBy(ucs)),                    0, 0, 0                    );                }                 // Add the polyline to modelspace                using (Transaction tr = Active.Database.TransactionManager.StartTransaction()) {                    var bt = (BlockTable)tr.GetObject(Active.Database.BlockTableId, OpenMode.ForRead);                     var btrMS = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);                     ObjectId plineId = btrMS.AppendEntity(pline);                    tr.AddNewlyCreatedDBObject(pline, true);                    tr.Commit();                     Active.WriteMessage("\nPolyline entity is: " + plineId.ToString());                }            }            Active.Editor.Regen();        }    }  

MickD:
I know it's a throwback to vba but I have used ThisDrawing (or ThisDrg for short) in the same way you have used Active, it just seems to read well :)

kdub_nz:

--- Quote from: MickD on July 07, 2019, 12:51:11 AM ---I know it's a throwback to vba but I have used ThisDrawing (or ThisDrg for short) in the same way you have used Active, it just seems to read well :)

--- End quote ---

I like it too Mick
.. but not because it reminds me of VBA :)

I'm getting into the habit of using it without conciously forcing it. That was difficult after years of declaring and assigning the values over and over and over again. Intellisence saves the typing.

As an aside, I've noticed I'm using longer variable names that read better ( for me) ie: reducing the use of abbreviations for variables (except for the regularly accepted ones ; tr, bt, id, ent etc.
I find it makes code easier for me to read when I come back to it ... I don't need to pause mentally to expand/translate abbreviations.

Navigation

[0] Message Index

[#] Next page

Go to full version