Wish: Set CPlane by center, center, plane

Just wondering if there is a way to set a CPlane by temporarily switching to center Osnap (just for this particular command) and then snapping to center, then to another center, then pick a planar surface, so that the origin of the new CPlane will be sitting in the middle between the two center points projected from the planar surface, even if the planar surface is not equally oriented to the two centers? To make it easier to understand, here is a sample image and a 3dm file.
Set CPlane by surface plane, then midpoint between centers.3dm (299.6 KB)

This is very usable for design of machine parts for CNC-milling, but it could be handy for any other application, as well.


At the moment I use a custom macro that does something similar, except that it works by picking the planar surface initially, then picking the two centers, then manually snapping to the middle of the temporary line, then picking the Z-elevation for the CPlane. All this is a bit cumbersome and requires more mouse clicks than necessary.
“Set CPlane by surface plane, then midpoint between centers”

'_CPlane _Object _Pause _Line _Center _Pause _Center _Pause
_SelLast _CPlane _Mid _Pause delete
_Pause _CPlane _Elevation

This requires picking planar surface 3, then center of surface 1, then center of surface 2, then the middle between both centers, then adjusting the elevation by snapping to surface 3 (or any other surface).


An alternative shorter version of the macro could be used if additional adjustment of the elevation is not needed:
“Set CPlane by surface center, surface center and midpoint”

'_CPlane _Object _Pause _Line _Center _Pause _Center _Pause
_SelLast _CPlane _Mid _Pause delete

This requires picking surface 1, then center of surface 1, then center of surface 2, then the middle between both centers.


Ideally, a more intelligent way to execute that would require just the following 3 mouse clicks:

  1. Pick center number 1.
  2. Pick center number 2.
  3. Pick planar surface. Then Rhino automatically places the origin of the new CPlane along the planar surface so that its projected Z-vector aligns in the middle between the two centers.

The tricky part is that this also must orient the X-axis along the line between the two centers. My macros don’t take this into account, because the XY orientation is assigned to the target surface instead… You can test this shortcoming of my macros with this file consisting inclined parts:
Set CPlane by surface plane, then midpoint between centers (the macros can’t align the X-axis along the 2 centers).3dm (303.7 KB)

See if this is doing what you want:

import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc


def getplane():
    pt1 = rs.GetPoint("select center 1")
    if not pt1:
        return

    pt2 = rs.GetPoint("select center 2")
    if not pt2:
        return
    plane = sc.doc.Views.ActiveView.ActiveViewport.ConstructionPlane()
    pt1 = plane.ClosestPoint(pt1)
    pt2 = plane.ClosestPoint(pt2)
    vecX = Rhino.Geometry.Vector3d.Subtract(Rhino.Geometry.Vector3d(pt2), Rhino.Geometry.Vector3d(pt1))
    if vecX.Length <= Rhino.RhinoMath.Epsilon:
        return
    vecX.Unitize()
    vecY = Rhino.Geometry.Vector3d.CrossProduct(plane.ZAxis, vecX)
    plane.XAxis = vecX
    plane.YAxis = vecY
    plane.Origin = (pt1+pt2)/2
    sc.doc.Views.ActiveView.ActiveViewport.SetConstructionPlane(plane)
getplane()

Hi @Gijs ! Thanks for the help. I can’t run this code for some reason. I always struggle with these codes. Is there a tutorial how to convert them into a PY script for linking from a folder? :smiley:

getplanebetweencenters.py (783 Bytes)

1 Like
  1. Rhino 8 and above: run Scripteditor
  2. or in Rhino 7 and below, run EditPythonScript,
  3. use the copy button to copy the code
  4. paste into a new pythonscript
  5. run/save
1 Like

you can also copy paste the code into an empty txt file and change the suffix to .py

1 Like

Thanks for the explanation.
By the way, that script does not work in my Rhino 7. When I click the second center, the command stops and nothing happens… Is there something specific to make it run properly? Pre-selection or anything else?

This is in Rhino 7:

That’s weird. It’s not clanging the CPlane in my Rhino 7.

did you try it in the file you sent in the perspective viewport?
Can you try this diagnose version and post back what you get in the commandline?

getplanebetweencenters_diagnose.py (873 Bytes)

1 Like

I figured out that your script actually moves the CPlane along the XY coordinates of the current CPlane until it reaches the middle point of the two centers, and also rotates the plane along the Z-axis to set the X-axis inline with the two centers. However, the idea is to be able to set a totally new CPlane orientation (either read from the first center’s plane or by picking a planar surface) so that its Z-axis will be projected to the middle between the two centers.


Here is a video that compares both the script and my macro:

My macro does the job, but it takes extra mouse clicks to do so. Your script works in the intended way once I place a macro to set the CPlane on the target surface in front of it. It looks this way and takes just 3 mouse clicks:
'_CPlane _Object _Pause _-RunPythonScript "D:\PROGRAMI\Rhinoceros 7\Добавки\CPlane between centers\getplanebetweencenters.py"
I named this compound command as “Set CPlane by surface, then middle between centers”.
Set CPlane by surface, then middle between centers

Your script is handy in other situations when the intent is to preserve the current CPlane, so I will use both versions of these. :slight_smile: Thank you for the great job!

I named the command using your script as “Set CPlane in middle between centers”.


As for the diagnose script, below is the warning message that shows up upon running it:

---------------------------
Exception Occured
---------------------------
Message: unexpected token ')'

  File "D:\PROGRAMI\Rhinoceros 7\Добавки\CPlane between centers\getplanebetweencenters_diagnose.py", line 29

    sc.doc.Views.ActiveView.ActiveViewport.SetConstructionPlane(plane))

                                                                      ^

SyntaxError: unexpected token ')'
---------------------------
OK   
---------------------------

sorry for the extra ) typo, I updated the script above.

if you want the plane to align to the first circle, you can use this script
first select a circular curve or edge, second select a point
getplanebetweencenters2.py (943 Bytes)

1 Like

Wow, this new script caused my Gumball to disappear! I can’t bring it back… Not sure what’s happening.

Apart from that, it’s great that the script now works with just two mouse clicks! :slight_smile: Hopefully there will be a fix for Gumball.

EDIT: The only way to bring back the Gumball is to change the CPlane. Weird…

hmm, looks like I am doing some forbidden stuff in that code, I suspect the CPlane I am creating is not 100% valid.
Pls try the updated script above. Sorry for the inconvenience!

1 Like

Now it works just as expected! :slight_smile: Great job! Thank you for the effort! This should be a native command in Rhino!

Ooops, I just figured out that it will orient the CPlane relative to the two centers instead of preserving the plane of the initially clicked circle. This is a problem when the two circles are not on the same plane. Is it possible to set the CPlane parallel to the initially picked circle?

You can test this by picking circles #1 and #4 from this updated test file:
Set CPlane by surface plane, then midpoint between centers.3dm (383.4 KB)

@Rhino_Bulgaria See updated script

1 Like