Quantcast
Channel: All Revit API Forum posts
Viewing all articles
Browse latest Browse all 67020

Re: How to retrieve a Dimension's (segment) geometry ?

$
0
0

 thank you!

 

i implemented it in 

 

https://github.com/jeremytammik/the_building_coder_samples/blob/master/BuildingCoder/BuildingCoder/CmdGetDimensionPoints.cs

 

The entire code is:

 

    List<XYZ> GetDimensionPoints( Dimension dim )
    {
      Line dimLine = dim.Curve as Line;
      if( dimLine == null ) return null;
      List<XYZ> pts = new List<XYZ>();

      dimLine.MakeBound( 0, 1 );
      XYZ pt1 = dimLine.GetEndPoint( 0 );
      XYZ pt2 = dimLine.GetEndPoint( 1 );
      XYZ direction = pt2.Subtract( pt1 ).Normalize();
      pts.Add( pt1 );
      if( dim.Segments.Size == 0 )
      {
        pt2 = pt1.Add( direction.Multiply( (double) dim.Value ) );
        pts.Add( pt2 );
      }
      else
      {
        XYZ segmentPt0 = pt1;
        foreach( DimensionSegment seg in dim.Segments )
        {
          XYZ segmentPt1 = segmentPt0.Add( direction.Multiply( (double) seg.Value ) );
          Debug.Print( "pt  {0},  value  {1}", segmentPt1, (double) seg.Value );
          pts.Add( segmentPt1 );
          segmentPt0 = segmentPt1;
        }
      }
      return pts;
    }

    XYZ GetDimensionStartPointFirstAttempt(
      Dimension dim )
    {
      Document doc = dim.Document;

      Line dimLine = dim.Curve as Line;
      if( dimLine == null ) return null;
      dimLine.MakeBound( 0, 1 );

      XYZ dimStartPoint = null;
      XYZ pt1 = dimLine.GetEndPoint( 0 );

      // dim.Origin throws "Cannot access this method
      // if this dimension has more than one segment."
      //Debug.Assert( Util.IsEqual( pt1, dim.Origin ),
      //  "expected equal points" );

      foreach( Reference ref1 in dim.References )
      {
        XYZ refPoint = null;
        Element el = doc.GetElement( ref1.ElementId );
        GeometryObject obj = el.GetGeometryObjectFromReference(
          ref1 );

        if( obj == null )
        {
          // element is Grid or ReferencePlane or ??
          ReferencePlane refPl = el as ReferencePlane;
          if( refPl != null ) refPoint = refPl.GetPlane().Origin;
          Grid grid = el as Grid;
          if( grid != null ) refPoint = grid.Curve.GetEndPoint( 0 );
        }
        else
        {
          // reference to Line, Plane or Point?
          Line l = obj as Line;
          if( l != null ) refPoint = l.GetEndPoint( 0 );
          PlanarFace f = obj as PlanarFace;
          if( f != null ) refPoint = f.Origin;
        }

        if( refPoint != null )
        {
          //View v = doc.ActiveView;
          View v = dim.View;
          Plane WorkPlane = v.SketchPlane.GetPlane();
          XYZ normal = WorkPlane.Normal.Normalize();

          // Project the "globalpoint" of the reference onto the sketchplane

          XYZ refPtonPlane = refPoint.Subtract(
            normal.Multiply( normal.DotProduct(
              refPoint - WorkPlane.Origin ) ) );

          XYZ lineNormal = normal.CrossProduct(
            dimLine.Direction ).Normalize();

          // Project the result onto the dimensionLine

          dimStartPoint = refPtonPlane.Subtract(
            lineNormal.Multiply( lineNormal.DotProduct(
              refPtonPlane - pt1 ) ) );
        }
        break;
      }
      return dimStartPoint;
    }

    XYZ GetDimensionStartPoint(
      Dimension dim )
    {
      XYZ p = null;

      try
      {
        p = dim.Origin;
      }
      catch( Autodesk.Revit.Exceptions.ApplicationException ex )
      {
        Debug.Assert( ex.Message.Equals( "Cannot access this method if this dimension has more than one segment." ) );

        foreach( DimensionSegment seg in dim.Segments )
        {
          p = seg.Origin;
          break;
        }
      }
      return p;
    }

    public Result Execute(
      ExternalCommandData commandData,
      ref string message,
      ElementSet elements )
    {
      UIApplication uiapp = commandData.Application;
      UIDocument uidoc = uiapp.ActiveUIDocument;
      Document doc = uidoc.Document;
      Selection sel = uidoc.Selection;

      ISelectionFilter f
        = new JtElementsOfClassSelectionFilter<Dimension>();

      Reference elemRef = sel.PickObject(
        ObjectType.Element, f, "Pick a dimension" );

      Dimension dim = doc.GetElement( elemRef ) as Dimension;

      XYZ p = GetDimensionStartPoint( dim );
      List<XYZ> pts = GetDimensionPoints( dim );

      int n = pts.Count;

      Debug.Print( "Dimension origin at {0} followed "
        + "by {1} further point{2}{3} {4}",
        Util.PointString( p ), n,
        Util.PluralSuffix( n ), Util.DotOrColon( n ),
        string.Join( ", ", pts.Select(
          q => Util.PointString( q ) ) ) );

      List<double> d = new List<double>( n );
      foreach( XYZ q in pts )
      {
        d.Add( q.X - p.X );
        p = q;
      }

      Debug.Print(
        "Horizontal distances in metres: "
        + string.Join( ", ", d.Select( x =>
          Util.RealString( Util.FootToMetre( x ) ) ) ) );

      return Result.Succeeded;
    }

However, when running it in this scenario:

 

Screen Shot 2017-06-15 at 13.39.10.png

In that scenario, the current code prints:

 

Dimension origin at (0.04,-4.94,0) followed by 3 further points:
  (3.01,-4.94,0), (6.29,-4.94,0), (9.57,-4.94,0)

Horizontal distances in metres: 0.9, 1, 1

I guess that means that the '3 further points' really are the dimension points of interest.

 

The question is, what is the 'start point'?

 

Is it arbitrary?

 

In this case, it seems best to simply ignore it...

 

Thank you!

 

Cheers,

 

Jeremy

 

 

 

 


Viewing all articles
Browse latest Browse all 67020


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>