Maths behind Plane.FitPlaneToPoints method

Hello,
Is it possible to get some theoretical background on how Plane.FitPlaneToPoints method calculates the approximate plane?
Thank you in advance.

Edit: One complete solution in R (notice also that different methods vary in both speed and accuracy):
http://www.ilikebigbits.com/2017_09_25_plane_from_points_2.html

But if I would try to make a red-neck solution I would split up the area in strips (or slices) of points in two directions. Then run FitLine (also a least squares method) on the slices, and make an average of the slice-lines. In both directions. At last, from the two resulting (perpendicular) lines, take the cross product to get the plane Normal.

// Rolf

1 Like

Thank you for link and explanation Rolf!
Do you mind providing a small example? I am wondering how would I approximate creation of the lines in case the points aren’t lying in a single plane?

Hello,

After some time I am getting back to this topic.

For some reason the Plane.FitPlaneToPoints method is unpredictable.

I have planar rectangle labeled as ply1 in the screenshot:

Taking its corner points and running the The Plane.FitPlaneToPoints method returns the following plane (origin, {XAxis}, {YAxis}, {ZAxis}):

0,0,0
{-1,0,0}
{0,1,0}
{0,0,-1}

If I move the same rectangle a bit from the world origin, but still in the X+,Y+ domain, the Plane.FitPlaneToPoints yields a different plane:

0,0,0
{1,0,0}
{0,1,0}
{0,0,1}

Is this a bug?
I was using Plane.FitPlaneToPoints on Rhino 5 as well, and it took me some time to realize that the this behavior happens in Rhino 6, but not in Rhino5.
I would understand if the Plane.FitPlaneToPoints would return two different planes if rectangles are located in different parts of the World XY plane, but in this case, they are both in X+,Y+ domain.
Here is an example code and attached .3dm rectangles:

import rhinoscriptsyntax as rs

ids = rs.GetObjects("select ply1, ply2 rectangles")

for id in ids:
    pts = list(rs.CurveEditPoints(id))
    plane = rs.PlaneFitFromPoints(pts[:-1]) # "pts[:-1]" remove the last pt
    print plane.Origin
    print "{%s}" % plane.XAxis
    print "{%s}" % plane.YAxis
    print "{%s}" % plane.ZAxis
    print "--------"

planes.3dm (204.5 KB)

@dale, @stevebaer, any help would be appreciated

Hi @djordje,

No, this isn’t a bug, as the correct plane is calculated. The plane fitter isn’t always going to orient the plane to your liking - what you’re seeing, however. But that isn’t the purpose of the tool.

In the case of planar curves, you should be using Curve.TryGetPlane.

– Dale

1 Like

Thank you @dale,
My apologies for the taking me too long to reply.

I noticed that “Curve.TryGetPlane” always returns a plane oriented in a way which ‘makes’ the curve’s direction to be counter-clock wise.
Example:

succ, crv_pln = crv.TryGetPlane(tol)
crvOrientation = crv.ClosedCurveOrientation(crv_pln)  # always counter-clockwise

Is this correct, or did I misunderstand it?

Hi @djordje,

The direction of a planar curve does control the normal direction of the curve’s plane.

– Dale

Hi @dale,
Thank you.
Does normal direction of curve’s plane, always point to the side where curve’s orientation is counter-clockwise:


Is this Rhino’s convention?
Because I always seem to get “counter-clockwise” from:

succ, crv_pln = crv.TryGetPlane(tol)
crvOrientation = crv.ClosedCurveOrientation(crv_pln)  # always counter-clockwise

Yes, the plane is calculated from the tangent direction of the curve.

– Dale

1 Like

This thread might also help: