Creating and overriding AutoCAD dimension styles using .NET

A request came in by email during last week's vacation:

I have been looking around to find a way about creating Dimension Style Overrides, but have not really had any success at anything yet. I have created program in which I do create several dimension styles, but I just keep getting lost with the overrides.

This seemed like a really good topic to cover, so this post contains some simple code that to create a dimension style and two nearly-identical linear dimensions: both use our newly-created dimension style but the second of the two also contains some Dimension Style Overrides, which we attach to the dimension via Extended Entity Data (XData).

Here's the C# code:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.Runtime;

 

namespace DimStyleOverrideTest

{

  public class Commands

  {

    [CommandMethod("ODS")]

    public void OverrideDimensionStyle()

    {

      Database db =

        HostApplicationServices.WorkingDatabase;

 

      Transaction tr =

        db.TransactionManager.StartTransaction();

      using (tr)

      {

        // Open our dimension style table to add our

        // new dimension style

 

        DimStyleTable dst =

          (DimStyleTable)tr.GetObject(

            db.DimStyleTableId, OpenMode.ForWrite

          );

 

        // Create our new dimension style

 

        DimStyleTableRecord dstr =

          new DimStyleTableRecord();

        dstr.Dimtad = 2;

        dstr.Dimgap = 0.3;

        dstr.Name = "MyStyle";

 

        // Add it to the dimension style table

 

        ObjectId dsId = dst.Add(dstr);

        tr.AddNewlyCreatedDBObject(dstr, true);

 

        // Now create two identical dimensions, one

        // next to the other, using our dimension

        // style

 

        AlignedDimension ad1 =

          new AlignedDimension(

            Point3d.Origin,

            new Point3d(5.0, 0.0, 0.0),

            new Point3d(2.5, 2.0, 0.0),

            "Standard dimension",

            dsId

          );

 

        // The only thing we change is the text string

 

        AlignedDimension ad2 =

          new AlignedDimension(

            new Point3d(5.0, 0.0, 0.0),

            new Point3d(10.0, 0.0, 0.0),

            new Point3d(7.5, 2.0, 0.0),

            "Overridden dimension",

            dsId

          );

 

        /*

 

        Now we'll add dimension overrides for DIMTAD

        and DIMGAP via XData

 

        Dimension variable group codes are:

 

          DIMPOST     3

          DIMAPOST    4

          DIMSCALE   40

          DIMASZ     41

          DIMEXO     42

          DIMDLI     43

          DIMEXE     44

          DIMRND     45

          DIMDLE     46

          DIMTP      47

          DIMTM      48

          DIMTOL     71

          DIMLIM     72

          DIMTIH     73

          DIMTOH     74

          DIMSE1     75

          DIMSE2     76

          DIMTAD     77

          DIMZIN     78

          DIMAZIN    79

          DIMTXT    140

          DIMCEN    141

          DIMTSZ    142

          DIMALTF   143

          DIMLFAC   144

          DIMTVP    145

          DIMTFAC   146

          DIMGAP    147

          DIMALTRND 148

          DIMALT    170

          DIMALTD   171

          DIMTOFL   172

          DIMSAH    173

          DIMTIX    174

          DIMSOXD   175

          DIMCLRD   176

          DIMCLRE   177

          DIMCLRT   178

          DIMADEC   179

          DIMDEC    271

          DIMTDEC   272

          DIMALTU   273

          DIMALTTD  274

          DIMAUNIT  275

          DIMFRAC   276

          DIMLUNIT  277

          DIMDSEP   278

          DIMATMOVE 279

          DIMJUST   280

          DIMSD1    281

          DIMSD2    282

          DIMTOLJ   283

          DIMTZIN   284

          DIMALTZ   285

          DIMALTTZ  286

          DIMUPT    288

          DIMATFIT  289

          DIMTXSTY  340

          DIMLDRBLK 341

          DIMBLK    342

          DIMBLK1   343

          DIMBLK2   344

          DIMLWD    371

          DIMLWE    372

 

        Variables have different types: these can be found in

        the ObjectARX Reference - search for "Dimension Style

        Overrides"

 

        */

 

        ResultBuffer rb =

          new ResultBuffer(

            new TypedValue[8]{

              new TypedValue(

                (int)DxfCode.ExtendedDataRegAppName, "ACAD"

              ),

              new TypedValue(

                (int)DxfCode.ExtendedDataAsciiString, "DSTYLE"

              ),

              new TypedValue(

                (int)DxfCode.ExtendedDataControlString, "{"

              ),

              new TypedValue(

                (int)DxfCode.ExtendedDataInteger16, 77  // DIMTAD

              ),

              new TypedValue(

                (int)DxfCode.ExtendedDataInteger16, 4   // Below

              ),

              new TypedValue(

                (int)DxfCode.ExtendedDataInteger16, 147 // DIMGAP

              ),

              new TypedValue(

                (int)DxfCode.ExtendedDataReal, 0.5      // Larger

              ),

              new TypedValue(

                (int)DxfCode.ExtendedDataControlString, "}"

              )

            }

          );

 

        // Set the XData on our object

 

        ad2.XData = rb;

        rb.Dispose();

 

        // Now let's open the current space and add our two

        // dimensions

 

        BlockTableRecord btr =

          (BlockTableRecord)tr.GetObject(

            db.CurrentSpaceId,

            OpenMode.ForWrite

          );

 

        btr.AppendEntity(ad1);

        btr.AppendEntity(ad2);

 

        tr.AddNewlyCreatedDBObject(ad1, true);

        tr.AddNewlyCreatedDBObject(ad2, true);

 

        // And commit the transaction, of course

 

        tr.Commit();

      }

    }

  }

}

When we NETLOAD our application and run the ODS command, we see that two dimensions are created in the current space:

A dimension with style and another overridden

I won't spend time on the specifics of the various dimension variables you can override using this mechanism – I'm sure many (if not most) of you know much more about AutoCAD's dimension mechanism than I – but I have included the list of the various dimension variables' group codes in a comment in the above code. For more information regarding the specific types of these variables – and their ranges, if applicable – I suggest searching for "Dimension Style Override" in the ObjectARX Reference.

Update

OK, I missed the obvious on this one (as does happen from time-to-time, as regular readers will by now be aware). Rather than setting the overrides directly via XData, there are handy properties belonging to the dimension's managed interface that do this for you. Very cool. So we can reduce the code to the following:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.Runtime;

 

namespace DimStyleOverrideTest

{

  public class Commands

  {

    [CommandMethod("ODS")]

    public void OverrideDimensionStyle()

    {

      Database db =

        HostApplicationServices.WorkingDatabase;

 

      Transaction tr =

        db.TransactionManager.StartTransaction();

      using (tr)

      {

        // Open our dimension style table to add our

        // new dimension style

 

        DimStyleTable dst =

          (DimStyleTable)tr.GetObject(

            db.DimStyleTableId, OpenMode.ForWrite

          );

 

        // Create our new dimension style

 

        DimStyleTableRecord dstr =

          new DimStyleTableRecord();

        dstr.Dimtad = 2;

        dstr.Dimgap = 0.3;

        dstr.Name = "MyStyle";

 

        // Add it to the dimension style table

 

        ObjectId dsId = dst.Add(dstr);

        tr.AddNewlyCreatedDBObject(dstr, true);

 

        // Now create two identical dimensions, one

        // next to the other, using our dimension

        // style

 

        AlignedDimension ad1 =

          new AlignedDimension(

            Point3d.Origin,

            new Point3d(5.0, 0.0, 0.0),

            new Point3d(2.5, 2.0, 0.0),

            "Standard dimension",

            dsId

          );

 

        // The only thing we change is the text string

 

        AlignedDimension ad2 =

          new AlignedDimension(

            new Point3d(5.0, 0.0, 0.0),

            new Point3d(10.0, 0.0, 0.0),

            new Point3d(7.5, 2.0, 0.0),

            "Overridden dimension",

            dsId

          );

 

        // Isn't this easier?

 

        ad2.Dimtad = 4;

        ad2.Dimgap = 0.5;

 

        // Now let's open the current space and add our two

        // dimensions

 

        BlockTableRecord btr =

          (BlockTableRecord)tr.GetObject(

            db.CurrentSpaceId,

            OpenMode.ForWrite

          );

 

        btr.AppendEntity(ad1);

        btr.AppendEntity(ad2);

 

        tr.AddNewlyCreatedDBObject(ad1, true);

        tr.AddNewlyCreatedDBObject(ad2, true);

 

        // And commit the transaction, of course

 

        tr.Commit();

      }

    }

  }

}

I managed to forget to name the style in the previous example, so I've gone ahead and fixed that in both sets of code.

And it turns out that the original question may actually have been about something different, so I'm now going to go away and look at that (and will create a new post, as needed).

24 responses to “Creating and overriding AutoCAD dimension styles using .NET”

  1. me.yahoo.com/a/7KY44PV62oiOHtk Avatar
    me.yahoo.com/a/7KY44PV62oiOHtk

    Please forgive my ignorance, but is there something wrong with using the DimXxxxx properties of the Dimension managed wrapper to set dimension overrides?

    If we give it a nanosecond's thought, what else would the DimXxxxx properties of the Dimension type do?

    I take it you can guess who this is.

  2. Actually there's nothing wrong with using them: in my haste to understand (and replicate) how it was done from ObjectARX, I missed the obvious.

    And trust me: I thought about it for at least a couple of microseconds. 🙂

    I could probably guess who this is, but then again, why spend the energy when I clearly have a post to go and fix?

    Kean

  3. "in my haste to understand (and replicate) how it was done from ObjectARX, I missed the obvious."

    Sorry, not sure I follow.

    It's essentially the same in native ObjectARX (see dbdimvar.h).

  4. OK, let me change that...

    "in my haste, I missed the obvious."

    Is that better? <sigh>

    Kean

  5. Hi Kean,
    where can i find max sizes for DxfCode.ExtendedData... types ? I'm trying to use DxfCode.ExtendedDataBinaryChunk but it looks 255 is max size ?!

  6. Hi Eug,

    Xdata is limited to 16K per object, but this is a shared limit, so individual applications should be careful about attaching large chunks. If you'd going to go anywhere over 1-2K, I suggest adding Xrecords into the object's extension dictionary, instead.

    Regards,

    Kean

  7. sylvesp@hotmail.com Avatar
    sylvesp@hotmail.com

    Could somebody please tell me how to force a graphics update, using the .net api, on a Dimension object after changing one of it's properties?
    After I change the object property, the graphics on the screen does not change although the property palette shows the new color "Red" for the "Dim line color"
    The dim line shows still as green though 🙁

    using (Transaction trans = acadDoc.TransactionManager.StartTransaction())
    {
    Dimension dimObject = trans.GetObject(objId, OpenMode.ForWrite) as Dimension;
    dimObject.Dimclrd = Color.FromColorIndex(ColorMethod.ByAci, 1);

    trans.Commit();
    }

    dimObject.Draw() doesn't seem to help either.

    Thanks
    Peter

  8. Long time, no hear, Peter! 🙂

    Please do post your questions on the AutoCAD .NET Discussion Group, as this blog isn't really a support forum.

    Regards,

    Kean

  9. sylvesp@hotmail.com Avatar
    sylvesp@hotmail.com

    Hi Kean!

    Indeed... long time no hear! Hope you are doing well.
    Thanks for your feedback.
    I've posted the question to the .Net Discussion Group.

    Regards,
    Peter

  10. Jorge Gutierrez Avatar
    Jorge Gutierrez

    The dimensions are "no associative". How to create associative dimensions with dot net?

    Thanks,

  11. We introduced an associative dimension API in AutoCAD 2009, but I'm pretty sure it's ObjectARX (C++) only, right now.

    For now you can either fire commands to create a dimension associatively or include a C++ component in your application.

    Kean

  12. Gerrit van Diepen Avatar
    Gerrit van Diepen

    Hi Kean,

    Is there a way to get the boundingbox of a dimensiontext?

    I created a dimensionroutine and I want put the dimensiontext in a upper position if the created dimension is near the last dimension.

    With the boudingbox I hope to calculate if the dimensiontext fits between the two dimensionblocks.

    Kind regards,

    Gerrit

  13. Hi Gerrit,

    This post should be helpful - I'm pretty sure I had it working with dimensions (although it's exploding to get at the information).

    Regards,

    Kean

  14. jaroslaw.szajbe@gmail.com Avatar
    jaroslaw.szajbe@gmail.com

    Hello!

    I want to create new Dimension Style in C++.
    I can create AcDbDimStyleTableRecord, but i don't know how set for example height of text?

    Best regards
    Jarek

  15. Hello Jarek,

    Please post your support questions via ADN or to the appropriate discussion forum.

    Thank you,

    Kean

  16. Hi I have a drawing with various blocks which are not at 0 elevation. these blocks have dimensions associated with them. Now i want to move everything to 0 elevation. I did all this. I changed even the elevation property of dimension to zero. But still I can see some points which are associated with dimensions with non-zero z coordinate. I think these are end points of extension lines as list command in dimensions are showing non zero z coordinates. Is there any way that i can change these points to 0 z value?

    1. I suggest finding a problematic property and changing the its value via the user interface, and then writing some code to find and modify them programmatically.

      Kean

      1. Kean,
        What I want to do is this. I have a rectangle whose elevation is 50. Then i change the elevation to 100 and I am dimensioning the rectangle at that elevation. Now i want to bring all the elements to 0 elevation. What should i do for this? I want to do it programmatically. I tried changing the text position property and the dim block position property. nothing works.

        1. This is the method i wrote for doing what i mentioned above, but without any success.
          private void FlattenDimension(Database db, Editor ed)
          {
          try
          {
          TypedValue[] tvs = new TypedValue[]
          {
          new TypedValue((int)DxfCode.Operator,"<or"), new="" typedvalue((int)dxfcode.start,"dimension"),="" new="" typedvalue((int)dxfcode.operator,"or="">")
          };

          SelectionFilter sf = new SelectionFilter(tvs);
          PromptSelectionResult psr = ed.SelectAll(sf);

          if (psr.Value.Count > 0)
          {
          Transaction tr = db.TransactionManager.StartTransaction();

          using (tr)
          {
          foreach (SelectedObject so in psr.Value)
          {
          RotatedDimension dim = (RotatedDimension)tr.GetObject(so.ObjectId, OpenMode.ForWrite);

          if (dim.Elevation != 0)
          dim.Elevation = 0;

          Point3d textPoint = dim.TextPosition;

          if (textPoint.Z != 0)
          {
          dim.TextPosition = new Point3d(textPoint.X, textPoint.Y, 0);
          }

          Point3d blockPoint = dim.DimBlockPosition;

          if (blockPoint.Z != 0)
          {
          Vector3d acVec3d = blockPoint.GetVectorTo(new Point3d(blockPoint.X, blockPoint.Y, 0));
          dim.DimBlockPosition.TransformBy(Matrix3d.Displacement(acVec3d));
          }

          }

          tr.Commit();
          }
          }

          //ed.WriteMessage("Z changed for {0} rotated dimensions.\n", changedCount);
          }
          catch (System.Exception e)
          {
          ed.WriteMessage(e.Message + " error 10\n");
          return;
          }
          }

          1. Kean Walmsley Avatar

            Dickins,

            I really don't have time to debug code for people, unless it's a problem in code I've posted.

            As this is really a support question, please post it to the ADN team or the AutoCAD .NET Discussion Group.

            (If you haven't already tried it, you might want to check the FLATTEN command, to see if that's of any use to you.)

            Kean

  17. Hello.
    Is it possible to have alighned dimension horizontally or vertically? If not hat can you advise how to have horizontal dimension between two points with different "Y" (.NET)? Is there only way to have rotated dimension and calculate everytime the angle? Is tehre easier way?

    Thank you.

    With best regards.

  18. How do we set the Annotative Scale for Dimensions?

    1. Kean Walmsley Avatar

      Sorry, I don't have time to provide support. Please post your support questions to the relevant online forum.

      Thanks,

      Kean

      1. Sure Kean. No Problem.

Leave a Reply to Jorge Gutierrez Cancel reply

Your email address will not be published. Required fields are marked *