Create Dimension between Two Lines

Another one of those recurring questions: how to create dimensioning.

I took the opportunity to highlight how to search the samples, find a solution, and apply a correction to RevitLookup yourself.

You have the code.

May the Force be with you.

Question: I tried to create detail drawings programmatically using the ItemFactoryBase NewDimension method.

I am creating detail lines in the drafting view based the on the geometry wall elements and would like to use Revit dimensioning to insert measurements into the detail drawings.

How do I obtain the reference for the detail lines of a drafting view to be able to call the NewDimension method?

I am sure that this is possible, since I can create dimension lines in a drafting view using the dimension line commands on the Annotate ribbon.

Answer: Whenever you are faced with a question like this, please always begin by studying the three main official sources of information:

  • The Revit API help file RevitAPI.chm.
  • The online wikihelp Revit

    API Developer’s Guide
    .
  • The Revit SDK sample source code.

Normally, when researching an issue like this myself, I perform a global search across the entire project in the SDKSamples2013.sln solution.

This time, happily, I extended it to the entire samples directory instead, including RevitLookup.
To tell the truth, I even searched my whole hard disk for all C# files containing NewDimension, because there were not that many in total.

This turned up the following hits in the Revit SDK folder (copy and paste to an editor to see the truncated lines):


C:...SDKRevitLookupCSTestTestElements.cs(1255):               //        m_revitApp.ActiveUIDocument.Document.Create.NewDimension(dimension.View, line, dimension.References, dimension.DimensionType);
C:...SDKRevitLookupCSTestTestElements.cs(1470):            m_revitApp.ActiveUIDocument.Document.Create.NewDimension(m_revitApp.ActiveUIDocument.Document.ActiveView,
C:...SDKRevitLookupCSTestTestElements.cs(1475):            m_revitApp.ActiveUIDocument.Document.FamilyCreate.NewDimension(m_revitApp.ActiveUIDocument.Document.ActiveView,
C:...SDKRevitLookupCSUtilsElements.cs(272):            Dimension dimensionClone = app.ActiveUIDocument.Document.Create.NewDimension(dimension.View, line, dimension.References);
C:...SDKSamplesCreateDimensionsCSCommand.cs(213):                    Dimension newDimension = doc.Create.NewDimension(
C:...SDKSamplesCreateDimensionsCSCommand1.cs(219):                    Dimension newDimension = doc.Create.NewDimension(
C:...SDKSamplesFamilyCreationWindowWizardCSCreateDimension.cs(31):    /// The class allows users to create dimension using Document.FamilyCreate.NewDimension() function
C:...SDKSamplesFamilyCreationWindowWizardCSCreateDimension.cs(91):            dim = m_document.FamilyCreate.NewDimension(view, line, refArray);
C:...SDKSamplesFamilyCreationWindowWizardCSCreateDimension.cs(125):            dim = m_document.FamilyCreate.NewDimension(view, line, refArray);
C:...SDKSamplesFamilyCreationWindowWizardCSCreateDimension.cs(160):            dim = m_document.FamilyCreate.NewDimension(view, line, refArray);

The very first of those, in the RevitLookup test framework, looks like it should answer your question right away:


  XYZ location1 = GeomUtils.kOrigin;
  XYZ location2 = new XYZ( 20.0, 0.0, 0.0 );
  XYZ location3 = new XYZ( 0.0, 20.0, 0.0 );
  XYZ location4 = new XYZ( 20.0, 20.0, 0.0 );
 
  Curve curve1 = m_revitApp.Application.Create
    .NewLine( location1, location2, true );
 
  Curve curve2 = m_revitApp.Application.Create
    .NewLine( location3, location4, true );
 
  DetailCurve dCurve1 = null;
  DetailCurve dCurve2 = null;
 
  if( !doc.IsFamilyDocument )
  {
    dCurve1 = doc.Create.NewDetailCurve(
      doc.ActiveView, curve1 );
 
    dCurve2 = doc.Create.NewDetailCurve(
      doc.ActiveView, curve2 );
  }
  else
  {
    if( null != doc.OwnerFamily
      && null != doc.OwnerFamily.FamilyCategory )
    {
      if( !doc.OwnerFamily.FamilyCategory.Name
        .Contains( "Detail" ) )
      {
        MessageBox.Show(
          "Please make sure you open a detail based family template.",
          "RevitLookup", MessageBoxButtons.OK,
          MessageBoxIcon.Information );
 
        return;
      }
    }
    dCurve1 = doc.FamilyCreate.NewDetailCurve(
      doc.ActiveView, curve1 );
 
    dCurve2 = doc.FamilyCreate.NewDetailCurve(
      doc.ActiveView, curve2 );
  }
 
  Line line = m_revitApp.Application.Create.NewLine(
    location2, location4, true );
 
  ReferenceArray refArray = new ReferenceArray();
 
  refArray.Append( dCurve1.GeometryCurve.Reference );
  refArray.Append( dCurve2.GeometryCurve.Reference );
 
  if( !doc.IsFamilyDocument )
  {
    doc.Create.NewDimension(
      doc.ActiveView, line, refArray );
  }
  else
  {
    doc.FamilyCreate.NewDimension(
      doc.ActiveView, line, refArray );
  }

I tried running this sample command by selecting the ribbon tab Add-Ins > Revit Lookup > Test Framework… > Object Hierarchy > APIObject > Element > Dimension > OK.

That calls the DimensionHardWired method to do the job.

Unfortunately, it throws an exception saying “Attempt to modify the model outside of transaction”.

I fixed it by adding the following lines right at the beginning of the method:


  using( Transaction tx = new Transaction( doc ) )
  {
    tx.Start( "DimensionHardWired" );

Obviously, I need to commit the transaction and close the using statement at the end again:


    tx.Commit();
  }

Now is successfully completes with the following result:

New dimension

You can also look at two The Building Coder samples creating wall dimensioning, either by

iterating over the wall faces
to
pick the two suitable ones, or using

FindReferencesByDirection to shoot a ray
and
find them directly.

They both retrieve the geometry references from the wall faces, and not from a simple detail line, though.

All together, this should provide more than enough to solve your issue.

Accessing the Path of a Family Document from the Family Instance

Before closing, here is pointer to a cool discovery by Saikat Bhattacharya: if you try to find the family document of a family instance and go through the path family instance > family symbol > family > document, you end up at the document containing the family instance.
If you are actually after the family document defining the instance, you need to go through the EditFamily method instead.
More details on

accessing the path of a family document from an instance
.


Comments

20 responses to “Create Dimension between Two Lines”

  1. Hi..Jeremy
    I trying to retreive dimension points from revit dimension. I am able to get orgin and direction from dimension.curve property and the curve is unbounded. How can I get the exact points for a Linear dimension?
    Thanks

  2. Dear Sangsen,
    I would assume that you go through the Dimension.References property.
    After all, that is what is driving the dimension element.
    Please show me your final solution, if it works, since this would be worth a blog post, I think :-)
    Thank you!
    Cheers, Jeremy.

  3. Hi Jeremy..
    Thanks for your response.
    I tried with Dimension.References property. But I am not getting global point / UV point only getting referencing elementId.
    Is it possible to get exact points from reference? Because I have to pump exact dimension points to another appln.
    Thanks

  4. Dear Sangsen,
    Have you ever heard the abbreviation RTFM?
    Sorry to put it so bluntly, but I believe this is appropriate, for the nonce.
    Please take a look at the Revit API help file RevitAPI.chm, read the description of the Reference.GlobalPoint property, and let us know whether that helps. Thank you!
    Cheers, Jeremy.

  5. Hi.. Jeremy
    In earlier comment itself I mentioned that Reference.GlobalPoint and UVPoint properties are null. Thatswhy I am asking you jeremy.
    Fully gone through Revit API.chm.I am not got any correct solution.
    I can create dimension from origin and direction of dimension curve for plan view. In section view only i got some incorrect values.

  6. LeeJaeYoung Avatar
    LeeJaeYoung

    Hi..Jeremy
    Grid lineGrida = document.Create.NewGrid(geomLine);
    Grid lineGridb = document.Create.NewGrid(geomLine);
    SketchPlane skplane = findSketchPlane(document, XYZ.BasisZ);
    if (null == skplane)
    {
    Plane geometryPlane = creApp.NewPlane(XYZ.BasisZ, XYZ.Zero);
    skplane = document.Create.NewSketchPlane(geometryPlane);
    }
    ReferenceArray ra = new ReferenceArray();
    ra.Append(lineGrida.Curve.Reference); –> this is error.
    ra.Append(lineGridb.Curve.Reference); –> this is error.
    start = new XYZ(0, 15, 0);
    end = new XYZ(10, 15, 0);
    line = creApp.NewLine(start, end, true);
    Dimension dim = document.Create.NewDimension(document.ActiveView, line, ra);
    i want two grid line dimension but i don’t know.
    I want your advice. please
    thank you

  7. LeeJaeYoung Avatar
    LeeJaeYoung

    i try location -curve-reference
    location get_point(0) – curver…..

  8. LeeJaeYoung Avatar
    LeeJaeYoung

    Curve linecu = lineGrida.Curve;
    message += lineGrida.IsCurved; –> fault
    Line linea = linecu as Line;
    message += “\nLine’s Length: ” + linea.Length; —> this is error.
    message += “\nStart point: ” + XYZToString(linecu.get_EndPoint(0));
    message += “; End point: ” + XYZToString(linecu.get_EndPoint(1));
    TaskDialog.Show(“Grid”, message);

  9. LeeJaeYoung Avatar
    LeeJaeYoung

    error message “object reference not set to an instance of an object”

  10. LeeJaeYoung Avatar
    LeeJaeYoung

    i test this
    Curve curve = lineGrida.Curve;
    if (null == curve)
    {
    TaskDialog.Show(“Grid”, “Error”);
    }
    but curve is null.
    i don’t know.

  11. Dear LeeJaeYoung,
    So, the grid curve is null, is it? How sad. Have you tried retrieving its location?
    Cheers, Jeremy.

  12. LeeJaeYoung Avatar
    LeeJaeYoung

    yes, I did
    Location locationline = lineGrida.Location;
    message += “:” + locationline.ToString();
    TaskDialog.Show(“Grid”, message);
    “Grid : Autodesk.Revit.DB.Location”
    but I want to have Reference
    LocationCurve locationcurve = locationline.curve as LocationCurve;
    if (null == locationcurve)
    {
    TaskDialog.Show(“Grid”, “Error111”);
    }
    always I see “Error111”
    i try public void GetInfo_Grid(Grid grid)
    in revitapi sample code
    location is true but get_point,curve,location curve error
    i don’t know my mistake.
    i need your advice. i am beginner. please

  13. LeeJaeYoung Avatar
    LeeJaeYoung

    hahaha
    my mistake is transaction.Start()
    i think TransactionMode.Automatic don’t need transaction.Start()
    Curve linecu = lineGrida.Curve is error.
    have a nice day

  14. Dear LeeJaeYoung,
    Congratulations!
    Yes, indeed.
    Also, automatic mode is discouraged nowadays:
    http://thebuildingcoder.typepad.com/blog/2012/05/read-only-and-automatic-transaction-modes.html
    Cheers, Jeremy.

  15. Hi Jeremy, I’m making an AssemblyInstance an then with the with the AssemblyViewUtils.CreateDetailSection() method I created a View. Once the view is created I tried to create the dimension using the CropBox as reference to obtained the location point.
    Something like the example
    XYZ location1 = new XYZ(views[0].CropBox.Min.X, views[0].CropBox.Min.Y, 0.0d),
    location2 = new XYZ(views[0].CropBox.Max.X, views[0].CropBox.Min.Y, 0.0d),
    location3 = new XYZ(views[0].CropBox.Min.X, views[0].CropBox.Max.Y, 0.0d),
    location4 = new XYZ(views[0].CropBox.Max.X, views[0].CropBox.Max.Y, 0.0d);
    Curve bottomCurve = revDef.RevitUiApp.Application.Create.NewLine(location1, location2, true),
    topCurve = revDef.RevitUiApp.Application.Create.NewLine(location3, location4, true),
    leftCurve = revDef.RevitUiApp.Application.Create.NewLine(location1, location3, true),
    rightCurve = revDef.RevitUiApp.Application.Create.NewLine(location2, location4, true);
    But when I called the Create.NewDimension no matter wich points I choose to make the line The direction is (0,-1,0) or (0,1,0) and I get exception “The direction of dimension is invalid” The view I’m using is not the activeView, is one created in CreateDetailSection().
    Thanks, have a nice day

  16. williams espinosa Avatar
    williams espinosa

    Jeremy
    Funciona muy bien
    Gracias!!

  17. Dear Williams,
    Estoy contento que te puedo ayudar. Gracias. Buena suerte.
    Cheers, Jeremy.

  18. Dear Jeremy,
    Unable to build below code as .NewLine is missing in 2014 Revit API.
    Curve curve1 = m_revitApp.Application.Create.NewLine( location1, location2, true );
    Thanks.

  19. Dear James,
    It is now Line.Create.
    Cheers, Jeremy.

  20. Thanks Jeremy.

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading