Kean Walmsley


  • About the Author
    Kean on Google+

April 2014

Sun Mon Tue Wed Thu Fri Sat
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30      







« Using the Microsoft Kinect SDK to capture skeleton data inside AutoCAD | Main | Displaying an AutoCAD ribbon tab contextually using .NET »

October 05, 2011

Delete “all but current” Annotation Scales on AutoCAD objects using .NET

I stumbled across this wishlist request on the forums, the other day, and thought it worth covering in a blog post.

It’s an interesting little piece of code – nothing very startling, but obviously whenever removing data you have to be a bit careful: in fact I would probably add an “are you sure?” question prior to actually removing the various annotation scales, even if the operation participates in the undo mechanism and can therefore be rolled back easily by the user.

Here’s the C# code for the AIOBJECTSCALEREMOVEOTHERS command (yes, I would normally use a slightly more succinct name, myself, such as DABC for “Delete All But Current”, but I decided to make this one more consistent with the AIOBJECTSCALEREMOVE command).

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

 

namespace AnnotationScaling

{

  public class Commands

  {

    [CommandMethod(

      "AIOBJECTSCALEREMOVEOTHERS",

      (CommandFlags.Modal | CommandFlags.UsePickSet)

     )]

    static public void RemoveAllButCurrentScale()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

      Editor ed = doc.Editor;

 

      // Get the manager object and the list of scales

 

      ObjectContextManager ocm = db.ObjectContextManager;

      ObjectContextCollection occ =

        ocm.GetContextCollection("ACDB_ANNOTATIONSCALES");

 

      // Prompt the user for objects to process (or get them

      // from the pickfirst set)

 

      PromptSelectionOptions pso = new PromptSelectionOptions();

      pso.MessageForAdding = "\nSelect annotative objects";

      PromptSelectionResult psr = ed.GetSelection(pso);

      if (psr.Status != PromptStatus.OK)

        return;

 

      // Maintain counters of objects modified and scales removed

 

      int objCount = 0, scaCount = 0;

 

      // Use a flag to check when we first modify an object

 

      bool scalesRemovedForObject = false;

 

      Transaction tr =

        doc.TransactionManager.StartTransaction();

      using (tr)

      {

        // If we can't find the current annotation scale in our

        // dictionary, we have a problem

 

        if (!occ.HasContext(db.Cannoscale.Name))

        {

          ed.WriteMessage(

            "\nCannot find current annotation scale."

          );

          return;

        }

 

        // Get the ObjectContext associated with the current

        // annotation scale

 

        ObjectContext curCtxt =

          occ.GetContext(db.Cannoscale.Name);

 

        // Check each selected object

 

        foreach (SelectedObject so in psr.Value)

        {

          // Open it for read

 

          ObjectId id = so.ObjectId;

          DBObject obj = tr.GetObject(id, OpenMode.ForRead);

 

          // Check it's annotative and has the current scale

 

          if (obj.Annotative == AnnotativeStates.True &&

              obj.HasContext(curCtxt)

            )

          {

            // Now we get it for write

 

            obj.UpgradeOpen();

 

            // Loop through the various annotation scales in

            // the drawing

 

            foreach (ObjectContext oc in occ)

            {

              // If it's on the object but not current

              // (for some reason we have to check the name

              // rather than oc == curCtxt)

 

              if (obj.HasContext(oc) &&

                  oc.Name != db.Cannoscale.Name

                )

              {

                // Remove it and increment our counter/set our

                // flag

 

                obj.RemoveContext(oc);

                scaCount++;

                scalesRemovedForObject = true;

              }

            }

 

            // Increment our counter for objects once per pass

            // and then reset the flag

 

            if (scalesRemovedForObject)

            {

              objCount++;

              scalesRemovedForObject = false;

            }

          }

        }

        tr.Commit();

 

        // Report the results

 

        ed.WriteMessage(

          "\n{0} scales removed from {1} objects.",

          scaCount, objCount

        );

      }

    }

  }

}

For fun, I went ahead and manually added the command via the CUI editor, and added it to the corresponding ribbon panel:

Our new command on the ribbon

If we then launch this command and select some annotative objects, we see that the command reports removing superfluous scales from the selected objects:

Command: AIOBJECTSCALEREMOVEOTHERS

Select annotative objects: Specify opposite corner: 4 found

Select annotative objects:

12 scales removed from 4 objects.

It should be noted that – while it’s unlikely a command this long is going to be entered at the command-line – this command does make use of the implied (aka pickfirst) selection set, should you prefer to prefer working in the noun-verb style. The ribbon item clears the pickfirst selection when launching the command, but it does work if launched via the command-line, in case.

blog comments powered by Disqus

10 Random Posts