Drawing and detecting an elliptical arc

I’m interested in drawing elliptical arcs (i.e. parts of ellipses) in Rhino. Currently, I’ve tried splitting an ellipse into four parts (not necessarily into quadrants), like so:

e%20arc

However, upon checking the object type and using IsEllipse, IsArc in rhinoscriptsyntax, I get some unexpected results:

rs.IsEllipse: True
rs.IsArc: False

which means I can’t sense that it’s an arc, and that it still registers as an ellipse. What would be a surefire way to generate an elliptical arc that Rhino can sense, and how do I check if a curve geometry is an elliptical arc using RhinoPython / Rhinoscriptsyntax / Rhino common? Would I need to do some math bits first in order to check if it is elliptical?

That seems correct - it is not an arc, it is an ellipse segment… An arc is a true single radius object.

Thanks @Helvetosaur, that clears things up.

Any suggestions then for how to draw a ‘true’ elliptical arc? I.e. an ‘elliptical segment’ with start and end points not equivalent to each other. Or would arcs in this case only be circular arcs?

The RhinoCommon method Curve.TryGetEllipse() works to detect if the curve is an elliptical arc:

def isEllipse(crv_id, tol=0.01):
    crv = rs.coercecurve(crv_id)
    success, ellipse = crv.TryGetEllipse(tol)
    return success

Constructing one is a little trickier, depending on what your constraints are. Does creating a circular arc and scaling it non-uniformly work well enough for you?

Thanks for the suggestion. Upon testing, it appears to still identify both ellipses and elliptical arcs as ellipses, so I’d need to constrain it a bit more for arcs. As for issues:

  • Unfortunately, it also identifies circular arcs as ellipses (which I know is technically correct, since circles are ellipses where focus 1 == focus 2 == center and so on). Any suggestions for a further constraint that uses Rhino Common or Rhinoscriptsyntax? I’ve developed my own checking function for circles vs. ellipses that distinguishes between the two, but would like to know if Rhino already has something similar (as it makes life a lot easier).

  • How do I reconstruct an elliptical arc using Rhino Common and rhinoscriptsyntax, and what information do I need? This will affect which data about elliptical arc I will be storing. I am aware of AddArc3Pt, AddArc, AddArcPtTanpt, but these appear to be primarily for circular arcs.

Also, yes, constructing one from a non-uniformly scaled circular arc (as well as cutting an ellipse up) seems to work. I’ll post some results here once I have something more conclusive.

Not sure if I’m missing something else here, but isn’t the only difference between ellipses and elliptical arcs the fact that the former is a closed curve? i.e. rs.IsCurveClosed() or the RhinoCommon method .IsClosed() .

Similarly if you have an Ellipse structure from TryGetEllipse(), just compare their Radius1 and Radius2 properties (within a certain tolerance) to check if it is a circle / circular arc.
http://developer.rhino3d.com/api/RhinoCommon/html/T_Rhino_Geometry_Ellipse.htm

As for constructing elliptical arcs, a convenient way to do so for smaller angular spans is by directly specifying the degree-2 rational Bezier form via 3 control points and varying the weight of the middle point.

Here’s a quick grasshopper definition to demonstrate it:
construct_elliptical_arc.gh (6.4 KB)

(Note that the position of the middle point defines the start and end tangents of the curve)

Also see https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/NURBS/RB-conics.html for the geometrical understanding of how and why this works.

Yeahp, figured that out eventually, but thanks for the suggestions.

This is definitely useful since I will be trying to implement drawing elliptical arcs in Grasshopper later on, but would there be a way to carry it out using only the RhinoPython editor?

Yes it is definitely possible- looks like rhinoscriptsyntax does not expose any methods that allow you to edit control point weights directly, so you will have to work with RhinoCommon types.

Check out the NurbsCurve class, in particular NurbsCurve.Create() and NurbsCurve.Points.SetWeight().

Hi @Bianchi,

Here is a simple example of creating an ellipse with Python:

import Rhino
import scriptcontext

plane = Rhino.Geometry.Plane.WorldXY
x_radius = 10.0
y_radius = 5.0
ellipse = Rhino.Geometry.Ellipse(plane, x_radius, y_radius)
if ellipse.IsValid:
    nurb = ellipse.ToNurbsCurve()
    if nurb.IsValid:
        scriptcontext.doc.Objects.AddCurve(nurb)
        scriptcontext.doc.Views.Redraw()

test_ellipse.gh (6.8 KB)

– Dale

1 Like

Hi @dale,

Thanks for the suggestion. I’ve managed to get this working up to a certain point, and right now I’m stuck with trimming off the bits of the curve outside the elliptical arc’s domain. Do you have any suggestions for how to do this using Trim or Split?

To illustrate, I’m trying to get arcs that look like this:
elliptical%20arc

My current solution is to generate the ellipse, then turn it into a Nurbs Curve and try to trim/split it from there. However, I’ve tried Split, but it doesn’t give back the elliptical arc as per my original start and end points. I also think I might not be using Trim correctly, as I get the following error:

Message: expected CurveEnd, got float

If Trim is the better solution, what kind of data type should I be using for the interval input of rs.TrimCurve? (I’m able to get the start and end point coordinates of my elliptical arc.)

Hi @Bianchi,

I’ve modified the script to include trimming

test_ellipse.gh (12.1 KB)

Let me know if this helps.

– Dale

Yes, this is exactly what I was trying to do! Thanks @dale!