OK, so I made my first PythonScript attempting to extend Rhino’s std SetPt
command.
The idea is to be able to set multiple points at once using a another object (Curve or Surface) as a “template” for where to move the Control Point positions. Each Point to be moved/pulled needs a matching “template” point to guide it’s target position.
The command allows for window selecting of Control Points.
In its first version it is recommended to select entire rows of Control Points, not only individual Points (use SetPt
for that). The current version of the script tends to swap directions if not entire point rows are selected. The number of template target points must not be less than the pull points.
SetPtMulti
can set 1, 2 or 3 directions (just like the original SetPt
command) which then are applied for each Pull-Target pair.
SetPtMulti
has been briefly tested to support matches of the following object types :
- Curve -> Curve control points
- Curve -> Surface control points
- Surface to Surface control points
- Surface to Curve control points
Video Clip
Below a 1.2 min video clip demonstrating how the command is used in its first version. If you have any suggestions, or want to contribute to extend and enhance the script, just let me know.
Video clip :
The Script (R0.9). Let the code review begin! ( ):
import rhinoscriptsyntax as rs
# ------------------------------------------------------------------
# Rolf Lampa, 2016 Rev 0.9
# SetPtMulti is intended as an extended version of Rhino's std SetPt
# command. It sets multiple points to corresponding target points in
# pairs.
# Command line options to set: X, Y, Z, All, or Cancel
# -------------------------------------------------------------------
def SetPtMulti():
def ExitProc(SelObj1=None, SelObj2=None):
if SelObj1:
rs.EnableObjectGrips(SelObj1, False) # Hide Control points
if SelObj2:
rs.EnableObjectGrips(SelObj2, False) # Hide Control points
#rs.GetObjects() # clear selection
# ------------------------------------------------------------------
# MAIN
# ------------------------------------------------------------------
# CONST
X = 0
Y = 1
Z = 2
ALL = 3
CANCEL = 4
# Select Object to Modify
moveObj = rs.GetObject("Select object to Move", filter=4+8, select=True) # Curve, Surface
if not moveObj:
return
rs.EnableObjectGrips(moveObj) # Show Control points
moveObjIsSurface = rs.IsSurface(moveObj)
# TARGET
targetObj = rs.GetObject("Select Target object", filter=4+8, select=True) # Curve, Surface
if not targetObj:
ExitProc(moveObj, None)
return
targetObjIsSurface = rs.IsSurface(targetObj)
# Get POINTS to Move
msg1 = "Select Points to Pull :"
unsorted = rs.GetObjectGrips(message=msg1, select=True)
if not unsorted:
ExitProc(moveObj, None)
return
# SORT
unsorted.sort(key = lambda g : g[1])
movePoints = unsorted
# Target POINTS
msg1="Select target Points :"
rs.EnableObjectGrips(targetObj) # Show Control points
unsorted = rs.GetObjectGrips(message=msg1, select=True)
if not unsorted:
ExitProc(moveObj, None)
return
# SORT
unsorted.sort(key = lambda g : g[1])
trgPoints = unsorted
if not trgPoints:
return
# Points to move (grips) must be less or equal to target points.
if len(movePoints) > len(trgPoints):
rs.MessageBox("Number of points to move must be less or equal to target points!", buttons=16, title="Warning")
return
# DIRECTIONS select :
uvn_params = ("X", "No", "Yes"), ("Y", "No", "Yes"), ("Z", "No", "Yes"), ("All", "No", "Yes"), ("Cancel", "No", "Yes")
uvn_directions = rs.GetBoolean("Directions to modify:", uvn_params, (False, False, False, False, False) )
if uvn_directions[CANCEL]:
ExitProc(moveObj, targetObj)
return
elif (not (uvn_directions[X] or uvn_directions[Y] or uvn_directions[Z])
and (not uvn_directions[ALL])):
rs.MessageBox("No directions was selected! Try again.", buttons=64, title="Ops!")
ExitProc(moveObj, targetObj)
return
# Set directions, individually (x,y,z) or "all" :
is_valid_options = False
if uvn_directions[ALL]:
uvn_directions[X] = True
uvn_directions[Y] = True
uvn_directions[Z] = True
is_valid_options = True
else:
for val in uvn_directions:
if not is_valid_options and val:
is_valid_options = True
break
if not is_valid_options:
rs.MessageBox("No directions was selected! Try again.", buttons=64, title="Ops!")
return
# Move any pairs of points between any object type
# (surface to curve, curve to curve,
# curve to surface or surface to surface
#rs.EnableRedraw(False) # Lock screen
i = 0
for grip in movePoints:
# Get points
obj, ix, movePt = grip
obj, trgIx, trgPt = trgPoints[i] # trgPoints[i][2]
# Copy target's pts to the object to be moved
if uvn_directions[X]:
movePt[X] = trgPt[X]
if uvn_directions[Y]:
movePt[Y] = trgPt[Y]
if uvn_directions[Z]:
movePt[Z] = trgPt[Z]
if moveObjIsSurface:
rs.ObjectGripLocation(moveObj, ix, movePt)
else:
rs.ObjectGripLocation(moveObj, ix, movePt)
# next movePt
i += 1
ExitProc(moveObj, targetObj)
rs.EnableRedraw(True)
SetPtMulti()
// Rolf