Average between two planes

Hi does anyone know a way to create a plane based on the average of two other planes?

I’m look for a way to build circles along a curve that have perfect angle between two segments.

Average.gh (7.3 KB)

Pufferfish plugin has tween planes.


You can do it natively by averaging vectors (average component)

1 Like

Extract the z-axis vectors of both planes and add them together. Since the axis vectors have unit length this will give you the average direction. You can then create a new plane using the same origin point and the new averages z-axis. This will result in potentially different x and y directions, but for circles maybe that doesn’t matter.

1 Like

or just create a curve and take perpendicular frames at the kinks…
planes2.gh (9.7 KB)

1 Like

Careful with this - averaging the XYZ vectors of two planes does not give their average plane!

averagePlane.gh (15.6 KB)

You can always get from one plane to another with a translation and a rotation about a single axis. This script uses Rhino’s quaternion class to find that rotation axis. Note how when you compare the Y axis of the average plane found this way with the Y axes of the 2 input planes it forms an equal angle with each of them, whereas this is not the case for the plane you get from just averaging the basis vectors separately.


Thanks guys!!

Not necessarily. Like @DanielPiker suggests you will want to use Quaternions. Pufferfish tween planes has Quaternions built in.

One main issue with simply averaging is Gimbal lock (try averaging two planes which x or y axis directly oppose each other, you will see the plane will just flip when it goes past halfway).

Check this video for some interesting test with Quaternions using drones.

1 Like

Thanks guys for all the comments, Puffer Fish worked great!
I also solved the next step of my project from your example of deconstructing angles from the planes!


Thank you for posting this Example! I was completely unfamiliar with Quaternions before this! For the sake of a learning exercise, I took a shot at converting your C# component to python. While I still am WAY out of my depth in regards to quaternions… What I ended up learning was how to use clr.StrongBox (or clr.Reference…both of which don’t autocomplete and took some digging to find!), to mimic C# out parameters! Reference mentioned here: (thanks @AndersDeleuran and @piac for posting that info!)

For the sake of completing the learning exercise, I thought I would share my results. Below is an un-optimized python implementation of your c# component. (Rhino 6, SDK mode). Please note that this was just a learning exercise and may not follow python/ironpython best practices. The one thing I got stuck on was recasting(?) the axis vector from a StrongBox Vector3d, back to a “regular” Vector3d.
"expected Vector3d, got StrongBox[Vector3d] in line 51
(Workaround is noted in code.)

from ghpythonlib.componentbase import executingcomponent as component
import Grasshopper, GhPython
import System
import Rhino
import clr
import math

class Tween2Planes(component):
    def RunScript(self, P1, P2, t):
        # always declare output variables
        a = None
        b = None
        c = None

        #Quaternion Rotation
        q = Rhino.Geometry.Quaternion.Rotation(P1, P2)
        # using StrongBox/Reference to mimic C# out parameters
        angle = clr.Reference[System.Double]()
        axis = clr.Reference[Rhino.Geometry.Vector3d]()
        # this returns the angle and axis, in C# it would be q.GetRotation(out angle, out axis);
        q.GetRotation(angle, axis)

        #when using axis, was getting error "expected Vector3d, got StrongBox[Vector3d] in line 51
        #workaround was to make new vector.  I didn't know how to "recast?" back as non-strongbox vector?
        axis2 = Rhino.Geometry.Vector3d(axis.X, axis.Y, axis.Z)
        OutputPlane = P1
        angle = float(angle) - 2 * math.pi if float(angle) > math.pi else float(angle)
        OutputPlane.Rotate(t * angle, axis2, OutputPlane.Origin)
        Translation = Rhino.Geometry.Vector3d(P2.Origin - P1.Origin)
        OutputPlane.Translate(Translation * t)
        #set values for output params
        a = OutputPlane
        b = angle
        c = axis2
        # return outputs:
        return a, b, c

I overly commented the code in the attached file for those that may be interested.
Quaternion_strongbox_GHpy.gh (11.1 KB)

Rhino ver: (6.9.18261.20431, 09/18/2018)