Skip to content

Instantly share code, notes, and snippets.

@pgolay
Last active March 26, 2020 16:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pgolay/f345a3bd65d33ae3c49167e80fcf65d3 to your computer and use it in GitHub Desktop.
Save pgolay/f345a3bd65d33ae3c49167e80fcf65d3 to your computer and use it in GitHub Desktop.
import rhinoscriptsyntax as rs
import Rhino
import scriptcontext as sc
import math
import System
def CalculateTargets(Grevs, srf, crv):
pi = math.pi
tPlanes = []
pPlanes = []
tLines = []
for pt in Grevs:
sPar = srf.ClosestPoint(pt)
tPlane = srf.FrameAt(sPar[1], sPar[2])[1]
cPar = crv.ClosestPoint(pt)
parRC,sParU, sParV = srf.ClosestPoint(pt)
vecNorm = srf.NormalAt(sParU, sParV)
crvPlane = crv.PerpendicularFrameAt(cPar[1])[1]
tVec = Rhino.Geometry.Vector3d(tPlane.ZAxis)
tVec.Rotate(pi/2,crvPlane.ZAxis)
tLine = Rhino.Geometry.Line(pt, pt+tVec)
#sc.doc.Objects.AddLine(tLine)
tPlanes.append(tPlane)
tLines.append(tLine)
pPlanes.append(Rhino.Geometry.Plane(pt, tVec, vecNorm))
return tPlanes, tLines, pPlanes
def CustomGetPoint(plane, Grevs, srf, crv, vecNorm, tangent, tPlanes, tLines, pPlanes):
pass
pi = math.pi
valid = False
# Color to use when drawing dynamic lines
line_color = System.Drawing.Color.FromArgb(255,0,0)
arc_color = System.Drawing.Color.FromArgb(240,240,240)
vecTan = tangent.To - tangent.From
vecTan.Unitize()
#if flip: vecTan.Reverse()
normal = Rhino.Geometry.Line(plane.Origin, plane.Origin + vecNorm)
units = rs.UnitSystemName()
if units == "millimeter":
units = " mm"
elif units == "inch":
units = " in"
elif units == "meter":
units = " M"
elif units == "foot":
" ft"
elif units == "centimeter":
units = " cm"
def GetPointDynamicDrawFunc( sender, args ):
current_point = args.CurrentPoint
#tPlanes, tLines, pPlanes = CalculateTargets(Grevs, srf, crv)
xform = args.Viewport.GetTransform(Rhino.DocObjects.CoordinateSystem.World, Rhino.DocObjects.CoordinateSystem.Screen)
lType = Rhino.Geometry.LoftType.Normal
uPt = Rhino.Geometry.Point3d.Unset
mat = Rhino.Display.DisplayMaterial(System.Drawing.Color.CornflowerBlue, .5)
tracking = Rhino.Geometry.Line(plane.Origin, args.CurrentPoint)
vecDir = args.CurrentPoint-plane.Origin
#circlePlane = Rhino.Geometry.Plane(plane.Origin, tanPt, args.CurrentPoint)
angle = Rhino.Geometry.Vector3d.VectorAngle(vecTan, vecDir, plane)
# print angle
angleDeg = round(Rhino.RhinoMath.ToDegrees(angle),2)
if angleDeg == 360: angleDeg = 0
drawAngle = angle
planePar, U, V = plane.ClosestParameter(current_point)
if planePar:
if V < 0:
pass
#angleDeg = - angleDeg
elif V > 0:
pass
#drawAngle = (2*pi)-angle
distance = round(plane.Origin.DistanceTo(args.CurrentPoint), 3)
lineCrvs = [Rhino.Geometry.LineCurve(Grevs[0], Grevs[0] + vecDir)]
lines = [Rhino.Geometry.Line(Grevs[0], Grevs[0]+ vecDir)]
targs = [Grevs[0]+vecDir]
x = len(Grevs)
for n in range(1,len(Grevs)):
testVec = (tLines[n].To - tLines[n].From)*vecDir.Length #local Tangent vector
testVec.Rotate( angle, pPlanes[n].ZAxis)
targ = Grevs[n]+testVec
targs.append(targ)
lines.append(Rhino.Geometry.Line(Grevs[n], targ))
lineCrvs.append(Rhino.Geometry.LineCurve(Grevs[n], targ))
for line in lines:
args.Display.DrawLine(line,System.Drawing.Color.Red, 1)
#preview lofts
preview_loft = False
lofts = Rhino.Geometry.Brep.CreateFromLoft(lineCrvs, uPt, uPt, lType, False)
if len(lofts) > 0:
preview_loft = True
brep = lofts[0]
loft = brep.Faces[0].ToNurbsSurface()
#vecTan is a line tangent to the surface
tanPt = plane.Origin +(vecTan*distance)
pass
#plane is pPlanes[0] (perp planes on input curve
circlePlane = Rhino.Geometry.Plane(plane.Origin, tanPt, args.CurrentPoint)
circle = Rhino.Geometry.Circle(plane, args.CurrentPoint.DistanceTo(plane.Origin))
arc = Rhino.Geometry.Arc(circle, drawAngle)
#tracking = Rhino.Geometry.Line(current_point, plane.Origin)
# sc.doc.Objects.AddLine(tracking)
# sc.doc.Objects.AddArc(arc)
arc_mid = arc.MidPoint
#mid_pt = Rhino.Geometry.Point3d.Interpolate(current_point, plane.Origin, .5)
mid_pt = plane.Origin+(vecDir/2)
mid_pt.Transform(xform)
arc_mid.Transform(xform)
current_point.Transform(xform)
screen_point = Rhino.Geometry.Point2d(current_point.X+16, current_point.Y)
screen_mid = Rhino.Geometry.Point2d(mid_pt.X, mid_pt.Y)
screen_arc_mid = Rhino.Geometry.Point2d(arc_mid.X + 16, arc_mid.Y)
#args.Display.DrawLine(tracking, arc_color,1)
args.Display.Draw2dText(str(angleDeg)+ " deg", System.Drawing.Color.Black, screen_arc_mid, False, 16)
args.Display.Draw2dText(str(distance)+ units, System.Drawing.Color.Black, screen_mid, False, 16)
#args.Display.DrawCircle(circle, arc_color, 2)
args.Display.DrawArc( arc, arc_color, 2)
args.Display.DrawLine(plane.Origin, args.CurrentPoint, line_color, 2)
args.Display.DrawLine(plane.Origin, tanPt, System.Drawing.Color.LightSlateGray, 2)
if preview_loft:
args.Display.DrawBrepShaded(brep, mat)
args.Display.DrawBrepWires(brep, System.Drawing.Color.Black, 0 )
constraint = None
dist = None
angleConstraint = None
while True:
flipAngle=False
deformable = False
if sc.sticky.has_key ("DEFORMABLE_FIN"):
deformable = sc.sticky["DEFORMABLE_FIN"]
finAngle = 10
if sc.sticky.has_key('FIN_ANGLE'):
finAngle = sc.sticky['FIN_ANGLE']
gp = Rhino.Input.Custom.GetPoint()
gp.DynamicDraw += GetPointDynamicDrawFunc
gp.AcceptNumber(True, True)
gp.AcceptNothing(True)
gp.SetBasePoint(plane.Origin, True)
opLinear = Rhino.Input.Custom.OptionToggle(deformable,"No","Yes")
gp.AddOptionToggle("Deformable", opLinear)
if dist is not None:
gp.ConstrainDistanceFromBasePoint(dist)
gp.SetCommandPrompt("Set fin depth and direction")
if constraint is None:
gp.SetCommandPrompt("Set fin depth and angle")
gp.Constrain( plane, False)
gp.AddOption("Normal")
gp.AddOption("Tangent")
gp.AddOption("Angle")
elif constraint == 2:
gp.Constrain( normal )
elif constraint == 3:
gp.Constrain( tangent )
if angleConstraint is not None:
gp.AddOption("FlipAngle")
angleVec = Rhino.Geometry.Vector3d(vecTan)
angleVec.Rotate(angleConstraint, plane.ZAxis)
angleLine = Rhino.Geometry.Line(plane.Origin+angleVec , plane.Origin)
gp.Constrain( angleLine )
rc = gp.Get()
if ( gp.CommandResult() != Rhino.Commands.Result.Success ):
return
if rc==Rhino.Input.GetResult.Point:
pass
pt = gp.Point()
#sc.doc.Objects.AddPoint(pt)
#angle = (tangent.To-tangent.From).VectorAngle(gp.Point-plane.Origin)
angle = Rhino.Geometry.Vector3d.VectorAngle((tangent.To-tangent.From),(pt - plane.Origin),plane)
return pt, deformable, angle
elif rc == Rhino.Input.GetResult.Number:
dist = gp.Number()
continue
elif rc == Rhino.Input.GetResult.Nothing:
dist = None
elif rc == Rhino.Input.GetResult.Option:
if 4 > gp.OptionIndex() > 1:
constraint = gp.OptionIndex()
if gp.OptionIndex() == 4:
ga = Rhino.Input.Custom.GetNumber()
ga.SetCommandPrompt("Fin angle")
ga.SetLowerLimit(-180, False)
ga.SetUpperLimit(180, False)
ga.SetDefaultNumber(finAngle)
ga.Get()
if ga.CommandResult()!=Rhino.Commands.Result.Success:
return ga.CommandResult()
finAngle = ga.Number()
angleConstraint = Rhino.RhinoMath.ToRadians(finAngle)
sc.sticky['FIN_ANGLE'] = finAngle
if gp.OptionIndex() == 5:
flipAngle=True
angleConstraint = -angleConstraint
flipAngle=False
deformable = opLinear.CurrentValue
sc.sticky["DEFORMABLE_FIN"] = deformable
continue
def TangentIsInterior(brep,srf, plane1, idx, crv):
testPt1 = plane1.Origin + plane1.XAxis
tempVec = Rhino.Geometry.Vector3d(plane1.XAxis)
tempVec.Reverse()
testPt2 = plane1.Origin + tempVec
parRC, parU, parV = srf.ClosestPoint(testPt1)
if parRC:
inFace1 = brep.Faces[idx].IsPointOnFace(parU, parV)
parRC, parU, parV = srf.ClosestPoint(testPt2)
if parRC:
inFace2 = brep.Faces[idx].IsPointOnFace(parU, parV)
if inFace1 != inFace2:
return True
return False
def FinSimple():
sr4 = False
version = Rhino.RhinoApp.Version.ToString()
if int(version.split(".")[0]) < 7 and int(version.split(".")[1])< 4:
sr4= True
pi = math.pi
uPt = Rhino.Geometry.Point3d.Unset
blnEdge = False
crvInput = rs.GetObject("Select a curve or surface edge.", 4, preselect=True, subobjects=True)
if not crvInput:return
brepId = crvInput.ObjectId
edgeIdx = crvInput.GeometryComponentIndex.Index
if edgeIdx != -1:
brep = crvInput.Brep()
if brep.Faces.Count>1:
srfInfo = rs.GetObject("Select the base surface.", 8,subobjects=True)
if not srfInfo: return
brepId = srfInfo.ObjectId
idx = srfInfo.GeometryComponentIndex.Index
srf = brep.Faces[idx].ToNurbsSurface()
else:
srf = brep.Faces[0].ToNurbsSurface()
idx = 0
crv = brep.Edges[edgeIdx].ToNurbsCurve()
if not sr4:
crvId = sc.doc.Objects.AddCurve(crv)
blnEdge = True
else:
crvId = crvInput.ObjectId
crv = sc.doc.Objects.Find(crvId).Geometry
srfId = rs.GetObject("Select the base surface.", 8)
if not srfId: return
brep = sc.doc.Objects.Find(srfId).Geometry
idx =0
srf = sc.doc.Objects.Find(srfId).Geometry.Faces[0].ToNurbsSurface()
crv = crv.ToNurbsCurve()
crv.Domain = Rhino.Geometry.Interval(0, crv.GetLength())
Grevs = crv.GrevillePoints()
tPlanes, tLines, pPlanes = CalculateTargets(Grevs, srf, crv)
parRC, sParU, sParV = srf.ClosestPoint(Grevs[0])
vecNorm = srf.NormalAt(sParU, sParV)
normal = Rhino.Geometry.Line(Grevs[0], tPlanes[0].Origin + tPlanes[0].ZAxis)
plane1 = Rhino.Geometry.Plane(Grevs[0], tLines[0].To - tLines[0].From, tPlanes[0].ZAxis)
#sc.doc.Objects.AddLine(normal)
#sc.doc.Objects.AddLine(tLines[0])
circ = Rhino.Geometry.Circle(pPlanes[0], 10)
#sc.doc.Objects.AddCircle(circ)
flip = TangentIsInterior(brep, srf, plane1, idx, crv)
inputs = CustomGetPoint(plane1, Grevs, srf, crv, vecNorm, tLines[0], tPlanes, tLines, pPlanes)
if not inputs:
if blnEdge and crvId: rs.DeleteObject(crvId)
return
pt, deformable, angle= inputs
#print angle
pass
targs = []
targs.append(pt)
vecDir = pt - Grevs[0]
for n in range(1,len(Grevs)):
testVec = (tLines[n].To - tLines[n].From)*vecDir.Length #local Tangent vector
testVec.Rotate( angle, pPlanes[n].ZAxis)
targs.append(Grevs[n]+testVec)
#rs.AddPoints(targs)
if sr4:
#Loft type
type = 2
if deformable:
type = 0
sc.doc.Objects.UnselectAll()
crvCopy = rs.CopyObject(crvId)
rs.EnableRedraw(False)
rs.SelectObject(crvCopy)
rs.Command("EditPtOn")
locs = rs.ObjectGripLocations(crvCopy, targs)
rs.AddLoftSrf([crvCopy,crvId], loft_type = type)
rs.DeleteObject(crvCopy)
else:
#Loft type
type = Rhino.Geometry.LoftType.Straight
if deformable:
type = Rhino.Geometry.LoftType.Normal
#crv.Simplify(Rhino.Geometry.CurveSimplifyOptions.All, .001, sc.doc.ModelAngleToleranceRadians)
crv2 = crv.DuplicateCurve()
if crv2.SetGrevillePoints(targs):
loft = Rhino.Geometry.Brep.CreateFromLoft([crv,crv2], uPt, uPt, type, False)
if loft:
if loft[0].IsValid:
sc.doc.Objects.AddBrep(loft[0])
else:
print "Unable to create the fin surface. Try splitting closed loops into two pieces."
if blnEdge:
if rs.IsObject(crvId):
rs.DeleteObject(crvId)
rs.EnableRedraw(True)
if __name__ == "__main__": FinSimple()
@pgolay
Copy link
Author

pgolay commented Jul 22, 2019

Added user definable angle. Might need some work...

@pgolay
Copy link
Author

pgolay commented Mar 26, 2020

Added a fix to run cleanly in V7/WIP

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment