Some explanations. To make things simple, I decide to draw a polyline with multiple segments (e.g. with more than 2 vertices) so that every other segment is visible; also, the Overrule would only apply to polylines that are on certain layer; and the Overrule itself can be turn on or off, regardless if there is other custom Overrule taking effect.
Here is the code:
using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.Runtime;using Autodesk.AutoCAD.DatabaseServices;using Autodesk.AutoCAD.EditorInput;using Autodesk.AutoCAD.Geometry;using Autodesk.AutoCAD.GraphicsInterface; [assembly: CommandClass(typeof(HidePartialPLine.MyCommands))] namespace HidePartialPLine{ public class MyCommands { private const string OR_LAYER="Overruled_PLine"; private static MyPLineOverrule _myOR=null; [CommandMethod("MyOR")] public static void ToggleMyOverrule() { Document dwg = Application.DocumentManager.MdiActiveDocument; Editor ed = dwg.Editor; if (_myOR==null) { _myOR=new MyPLineOverrule(); _myOR.StartOverrule(); ed.WriteMessage("\nMyPLineOverrule is on.\n"); } else { if (!_myOR.OverruleOn) { _myOR.StartOverrule(); ed.WriteMessage("\nMyPLineOverrule is on.\n"); } else { _myOR.StopOverrule(); ed.WriteMessage("\nMyPLineOverrule is off.\n"); } } } [CommandMethod("SetOR")] public static void SetMyOverruleToPolyline() { Document dwg = Application.DocumentManager.MdiActiveDocument; Editor ed = dwg.Editor; ObjectId id = SelectPolyline(ed); if (id == ObjectId.Null) { ed.WriteMessage("\n*Cancel*\n"); return; } SetPolylineLayer(id, OR_LAYER, dwg.Database); } #region private methods private static ObjectId SelectPolyline(Editor ed) { PromptEntityOptions opt=new PromptEntityOptions("\nPick a polyline"); opt.SetRejectMessage("You must pick a polyline. "); opt.AddAllowedClass( typeof(Autodesk.AutoCAD.DatabaseServices.Polyline),true); PromptEntityResult res=ed.GetEntity(opt); if (res.Status==PromptStatus.OK) { return res.ObjectId; } else { return ObjectId.Null; } } private static void SetPolylineLayer( ObjectId entId, string layerName, Database db) { using (Transaction tran = db.TransactionManager.StartTransaction()) { Entity ent = (Entity)tran.GetObject(entId, OpenMode.ForRead); if (ent.Layer.ToUpper() != OR_LAYER.ToUpper()) { ent.UpgradeOpen(); ent.Layer = OR_LAYER; } tran.Commit(); } } #endregion } public class MyPLineOverrule : DrawableOverrule { private const string OR_LAYER = "Overruled_PLine"; private bool _overruling=false; private bool _oldOverruling=false; public MyPLineOverrule() { _overruling=false; } public bool OverruleOn { get { return _overruling; } } public void StartOverrule() { _overruling=true; _oldOverruling = Overrule.Overruling; Overrule.AddOverrule(RXObject.GetClass( typeof(Autodesk.AutoCAD.DatabaseServices.Polyline)), this, false); //Set custom filter, so that code in overriden IsApplicable() //will run to do the filtering this.SetCustomFilter(); Overrule.Overruling=true; Application.DocumentManager.MdiActiveDocument.Editor.Regen(); } public void StopOverrule() { _overruling = false; //Cause Overrule redraw the polyline to its original shape //before the overrule is stopped Application.DocumentManager.MdiActiveDocument.Editor.Regen(); Overrule.RemoveOverrule(RXObject.GetClass( typeof(Autodesk.AutoCAD.DatabaseServices.Polyline)), this); Overrule.Overruling=_oldOverruling; } #region Override overrule methods public override bool IsApplicable(RXObject overruledSubject) { //Only apply this overrule to polyline on layer "Overruled_PLine" Entity ent=overruledSubject as Entity; return ent.Layer.ToUpper() == OR_LAYER.ToUpper(); } public override bool WorldDraw(Drawable drawable, WorldDraw wd) { Autodesk.AutoCAD.DatabaseServices.Polyline pl = drawable as Autodesk.AutoCAD.DatabaseServices.Polyline; //If the polyline only has one segment, draw itself if (pl.NumberOfVertices < 3) { return base.WorldDraw(drawable, wd); } if (_overruling) { //Get polyline's vertices Point3d[] pts = new Point3d[pl.NumberOfVertices]; for (int i = 0; i < pl.NumberOfVertices; i++) { pts[i] = pl.GetPoint3dAt(i); } //Draw every other segement int n = 0; while (n < pts.Length) { wd.Geometry.WorldLine(pts[n], pts[n + 1]); n += 2; } return true; } else { return base.WorldDraw(drawable, wd); } } #endregion }}The code pretty much explains itself. To test the code, I started AutoCAD, created a layer named as "Overruled_PLine". Then I drew a few polylines on layer 0. After the code being "netload"ed, I can toggle MyPLineOverrule on/off. When it is on, move polyline to layer "Overruled_PLine" will make the segments of a polyline visible/invisible alternately.
The effect can be watched in this video clip.

1 comment:
Loved reaading this thanks
Post a Comment