How to get detailed geometry information efficiently

I draw a Ellipse and get below geometry information via button “Details”. Geometry gotten from api is NurbsCurve, it can be determined as Ellipse by IsEllipse. But class Ellipse only contains radius, but similar text can be gotten via “RhinoObject.Description()”. Furthermore it is not sure has performance issue to use this method if this method calculate realtime and then return result.

Geometry:
    Valid curve.
    Ellipse
      radii = 8, 3
      focal distance = 7.4162
      foci = (31.4162,-4,0), (16.5838,-4,0)
      center = (24,-4,0)
      normal = (0,0,1)
      start = (32,-4,0)
      end = (32,-4,0)
      degree = 2
      control points: rational, count=9
      knots: non-uniform, domain = 0 to 6.28319
      clamped at start and end
    Geometry UserData:
      UserData ID: 2544A64E-220D-4d65-B8D4-611BB57B46C7
      Plug-in: Rhino
        description: RhinoCommon UserDictionary
        saved in file: no
        copy count: 1

Hi @RyanZhou,

Rhino does not have an Ellipse object. Rather, it can create NURBS curves that have the properties of ellipses.

You can use the Curve.TryGetEllipse method to try getting the Ellipse structure. This provides much of the information, such as radii, foci, etc., that you’ve listed above. The rest of the details comes from the NurbsCurve itself.

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
  var rc = RhinoGet.GetOneObject("Select curve", false, ObjectType.Curve, out var objref);
  if (rc == Result.Success && null != objref)
  {
    var curve = objref.Curve();
    if (null != curve)
    {
      if (curve is NurbsCurve nurbs_curve)
      {
        if (nurbs_curve.TryGetEllipse(out var ellipse))
        {
          // TODO: query ellipse
        }
        // TODO: query NURBS curve
      }
    }
  }
  return Result.Success; 
}

Not sure I’ve answered your question…

– Dale

Thanks for your explanation.
Take “foci” and “center” for example, how to get them from Ellipse or NurbsCurve?

Hi @RyanZhou,

The center of an ellipse is just the origin of the ellipse’s plane:

Point3d center = ellipse.Plane.Origin;

There isn’t a method exposed that will return the ellipse’s foci. I’ve logged an item so we can get this added.

https://mcneel.myjetbrains.com/youtrack/issue/RH-67116

In the mean time here are some extension methods you can use:

public static class EllipseExtensionMethods
{
  public static double FocalDistance(this Ellipse e)
  {
    double rc = RhinoMath.UnsetValue;
    if (e.IsValid)
    {
      double[] radius = new double[] { e.Radius1, e.Radius2 };
      int i = (Math.Abs(radius[0]) >= Math.Abs(radius[1])) ? 0 : 1;
      double a = Math.Abs(radius[i]);
      double b = a > 0.0 ? Math.Abs(radius[1 - i]) / a : 0.0;
      rc = a * Math.Sqrt(1.0 - b * b);
    }
    return rc;
  }

  public static bool Foci(this Ellipse e, out Point3d F1, out Point3d F2)
  {
    bool rc = false;
    F1 = F2 = Point3d.Unset;
    if (e.IsValid)
    {
      double f = e.FocalDistance();
      Vector3d majorAxis = (e.Radius1 >= e.Radius2) ? e.Plane.XAxis : e.Plane.YAxis;
      F1 = e.Plane.Origin + f * majorAxis;
      F2 = e.Plane.Origin - f * majorAxis;
      rc = true;
    }
    return rc;
  }

  public static Point3d Center(this Ellipse e)
  {
    Point3d rc = Point3d.Unset;
    if (e.IsValid)
      rc = e.Plane.Origin;
    return rc;
  }
}

– Dale

Thanks for your sample code, it is very helpful.

What i want is getting CSG similar information from Rhino, and then importing to other platforms, otherwise, just mesh with less information.
For example a ball, i want to get center and radius or information like below, but only get Brep from api.

Geometry:
    Valid surface.
    closed surface.
      Surface of Revolution
        U = angular parameter, V = curve parameter
        "U": Periodic  (0 <= U <= 45.3087)
        "V":  (-11.3272 <= V <= 11.3272)
        Axis of revolution: (2,-3,0) to (2,-3,1)
        Angles: from 0 radians (0 degrees) to 6.28319 radians (360 degrees).
        Revolute:
          Arc
            start = (2,-3,-7.2111)
            end = (2,-3,7.2111)
            center = (2,-3,0)
            radius = 7.2111
            angle = 180 degrees

For acquiring minimal data needed to define the geometry, it may be better to use the various TryGet… methods of Geometry.Curve and Geometry.Surface and this code for boxes (PythonScript equivalent of IsBox and BoxPoints? - #2 by dale). If a shape is found, use its properties. Any additional data that the other CAD system requires would just have to be calculated, like what Dale provided for an Ellipse. This may also be the case for Cylinders and Cones so that their Height values reflect the referenced Breps.

It may be more convinient to get geometry directly, developers will not waste extra time to find how to get geometry and be away from repeated code like “if(try) else(try)”. Furthermore, method “Description” already return geometry information text, it should be easy to convert to structured geometry definition, right?

I believe that some of the information is calculated in real time, and by using the TryGet… methods yourself, you can specify the tolerance to find the shapes, and double type values can be obtained from the results.