Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Create a Curve when only the Start Point, End Point & Radius is Known

11 REPLIES 11
SOLVED
Reply
Message 1 of 12
Anonymous
4804 Views, 11 Replies

Create a Curve when only the Start Point, End Point & Radius is Known

Hello

 

I am attempting to create a Curve (Elipse, Arc, CylindricalHelix, doesn't really matter). But I only know the following properties of the curve:

 

  • The start point (XYZ) of the curve
  • The end point (XYZ) of the curve
  • The radius of the curve

There aren't any functions that can create an Arc using this information AFAIK. There are only the following functions:

 

  • Arc Create(XYZ end0, XYZ end1, XYZ pointOnArc)
  • Arc Create(Plane plane, double radius, double startAngle, double endAngle)
  • Arc Create(XYZ center, double radius, double startAngle, double endAngle, XYZ xAxis, XYZ yAxis)

Do you know how I could create an Arc (or Elipse, CylindricalHelix) using the above functions and the information I know about the arc (start, end and radius)?

 

I've tried creating an Arc using the first function Arc Create(XYZ end0, XYZ end1, XYZ pointOnArc) and then setting the Arcs radius property after but it turns out that an Arcs radius property is read only so this doesn't work.
Any advice or suggestions on how I could produce my arc in the Revit APIT would be extremely appreciated.

11 REPLIES 11
Message 2 of 12
Anonymous
in reply to: Anonymous

Technically speaking, 2 points and a radius are not enough to define a unique arc as there are up to 4 possible arcs that will fit for any plane of reference. Test this yourself by drawing 2 circles of the same size that overlap each other and then draw a line between the 2 intersecting points. Each side of the line will contain 2 arcs that have the same end points and radius.

 

You can get away with it if you firstly adopt the convention that all arcs are to be drawn in the same direction from start to end (say, anticlockwise) when looking at them in the negative z direction of the target plane and secondly that you always want either the arc with included angle of less than or equal to 180 degrees or the larger arc of over 180°.

 

That aside, your best option is to calculate a point that lies on the arc and use the 3 points method that you have already used, but this time you will be giving it the correct 3rd point and there will be no need to attempt changing the radius afterwards. We will use the anti-clockwise convention as that is what Revit also uses, we will also assume that the smaller arc is desired.

 

Here is a little bit of code I just whipped up for you, I have done some minimal testing and it appears to be working fine. I have assumed that you have the 3 following variables already defined and in scope: XYZ end0, XYZ end1 and Double radius. I have also assumed that the arc lies on a plane with a normal vector of XYZ.BasisZ

 

Double sagitta = radius - Math.Sqrt(Math.Pow(radius, 2.0) - Math.Pow((end1 - end0).GetLength() / 2.0, 2.0)); 

XYZ midPointOfChord = (end0 + end1) / 2.0;

XYZ midPointOfArc = midPointOfChord + Transform.CreateRotation(XYZ.BasisZ, Math.PI / 2.0).OfVector((end0 - end1).Normalize().Multiply(sagitta));

Arc myArc = Arc.Create(end0, end1, midPointOfArc);

 

If you want the larger arc, simply change the sagitta calculation to be 'radius +' instead of 'radius -'.

 

If you aren't familiar with the mathematics used to calculate arcs I would suggest heading over to Math Open Reference

 

Message 3 of 12
Anonymous
in reply to: Anonymous

Thanks for your detailed reply 🙂 Its very much appreciated

 

I am importing data (3d Lines) from another CAD program into Revit. And the data only specifies the arcs start, end and radius. I'll give yor advice a go and see how I go.

Message 4 of 12
Anonymous
in reply to: Anonymous

No problems, I've just recently been doing some work on line-based families with arc location lines so it was all fresh in my head.

 

I think you may have some issues acheiving what you are after though, the solution I gave will only really work accurately for 2D data unless you also plug in the correct normal vector (axis) of each arc, basically everywhere that I have used XYZ.BasisZ would need to be replaced with the correct normal vector.

 

From the data you have it is not possible to determine the correct orientation of the arcs. You will need either a 3rd point on the arc provided for you (which would solve all your problems), or a normal vector of the target plane. Are you sure that there isn't any other information exported for arcs? If not, then the exporter isn't doing a very good job.

 

A possible solution then could be to see if you can first tesselate the arcs in the source software and then export just the straight line data. You could then rebuild the arcs from the lines as they will give you enough points to define a plane, but the trick would be knowing which lines belong to an arc and which don't. To solve this you could export 2 sets of data, one with tesselation and one without and then mtach the end points found in the tesselated data against the other set to determine whether you need to build an arc or not.

 

Ok, I'll stop rambling now. Long story short: you need more data!

 

Edit: I just had the thought that if you have a mixture of arcs and lines and the lines are always tangent to the arcs, you could use the lines each side of an arc to calculate the correct plane.

Message 5 of 12
Anonymous
in reply to: Anonymous

Yes I have a series of strings (strings of vertices) that I am importing. The string is made of segments (Arc, Line or Point segments). So I have 'the lines each side of the arc' as you say

 

Heres the data I am importing into Revit (so a segment with a radius of zero means the segment is a Line otherwise its an Arc):

<string_super>
    <name>22.5</name>
    <chainage>0</chainage>
    <breakline>line</breakline>
    <colour>green</colour>
    <style>1</style>
    <time_created>23-Oct-2013 23:45:46</time_created>
    <time_updated>23-Oct-2013 23:45:46</time_updated>
    <data_3d>
      <p>-896.15376506 330.85993976 null</p>
      <p>-484.5 141.5 null</p>
      <p>-484.5 141.5 null</p>
      <p>-232.5 -49.5 null</p>
      <p>-232.5 -49.5 null</p>
      <p>-79.22003012 -10.17816265 null</p>
    </data_3d>
    <radius_data>
      0 0 321.33149289 0 0 0
    </radius_data>
    <major_data>
      f f f f f f
    </major_data>
  </string_super>

 

 

Message 6 of 12
Anonymous
in reply to: Anonymous

Well that data is actually 2D (null z-value) so you should be fine unless you also encounter data with z-values.

 

I plugged that data into the code above with the addition of some simple line creation stuff and got the following chain of curves. Does this look like the source geometry? Image Link If so then you are good to go Smiley Happy

 

Message 7 of 12
Anonymous
in reply to: Anonymous

There's a workaround for this issue if you feel like just drawing it out:

 

 

Draw a line from your point A to point B.

 

Draw a circle with a radius equal to the arc you're trying to create.

 

Move the line such that the centrepoint of the line is at the centrepoint of the circle.

 

Draw a perpendicular line from each of the endpoints of the line to intersect the edge of the circle.

 

The part of the circle between those two lines is your desired arc.

 

 

It's a bit circuitous, but it works.

Message 8 of 12
AndrewButenko
in reply to: Anonymous

Hi Scott!

 

I try use your code. I translate it to vb. Your code have innacuracy. I fix it. 

 

 Dim ar As Arc = Crv
        Dim radius As Double = ar.Radius




        Dim sagitta As Double = radius - Math.Sqrt(Math.Pow(radius, 2.0) - Math.Pow((p1 - p0).GetLength() / 2.0, 2.0))

        Dim midPointOfChord As XYZ = (p0 + p1) / 2.0

        Dim midPointOfArc As XYZ = midPointOfChord + Transform.CreateRotation(XYZ.BasisZ, Math.PI / 2.0).OfVector((p1 - p0).Normalize().Multiply(sagitta))

        If Math.Round((midPointOfArc - ar.Center).GetLength, 5) = Math.Round(ar.Radius, 5) Then
            Return Arc.Create(p0, p1, midPointOfArc)
        Else
            midPointOfArc = midPointOfArc - 2 * Transform.CreateRotation(XYZ.BasisZ, Math.PI / 2.0).OfVector((p1 - p0).Normalize().Multiply(sagitta))
            Return Arc.Create(p0, p1, midPointOfArc)
        End If
Message 9 of 12

Dear Andrew,

 

Your if clause uses the arc center. Where does that come from? We only have radius, start and end point given.

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 10 of 12
jeremytammik
in reply to: Anonymous

Dear Scott,

 

Thank you for the very nice solution and explanation.

 

I added it to The Building Coder samples as well, in C#, like this:

 

https://github.com/jeremytammik/the_building_coder_samples/compare/2018.0.137.0...2018.0.137.1

 

    /// <summary>
    /// Create an arc in the XY plane from a given
    /// start point, end point and radius. 
    /// </summary>
    public static Arc CreateArc2dFromRadiusStartAndEndPoint( 
      XYZ ps, 
      XYZ pe, 
      double radius, 
      bool largeSagitta = false )
    {
      // https://forums.autodesk.com/t5/revit-api-forum/create-a-curve-when-only-the-start-point-end-point-amp-radius-is/m-p/7830079

      XYZ midPointChord = 0.5 * ( ps + pe );
      XYZ v = pe - ps;
      double d = 0.5 * v.GetLength(); // half chord length

      // Small and large circle sagitta:
      // http://www.mathopenref.com/sagitta.html

      double s = largeSagitta
        ? radius + Math.Sqrt( radius * radius - d * d ) // sagitta large
        : radius - Math.Sqrt( radius * radius - d * d ); // sagitta small

      XYZ midPointArc = midPointChord 
        + Transform.CreateRotation( XYZ.BasisZ, 0.5 * Math.PI )
          .OfVector( v.Normalize().Multiply( s ) );

      return Arc.Create( ps, pe, midPointArc );
    }

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 11 of 12
jeremytammik
in reply to: Anonymous

I edited this discussion and summarised the results for posterity:

 

http://thebuildingcoder.typepad.com/blog/2018/03/create-2d-arc-and-filter-for-intersecting-elements....

 

Many thanks again to Scott!

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 12 of 12

Dear Jeremy!

 

You are right. I found this topic to solution my task. In my task i have arc and two points on  arc  🙂 .  

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Customer Advisory Groups


Rail Community