Skip to content

Instantly share code, notes, and snippets.

@pgolay
Last active July 9, 2018 15:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pgolay/0bdacb2ffb45cda7f2054688f26745e4 to your computer and use it in GitHub Desktop.
Save pgolay/0bdacb2ffb45cda7f2054688f26745e4 to your computer and use it in GitHub Desktop.
import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc
import System.Guid
import math
def GetMarkerOptions(crvLength):
while True:
num = 0
if sc.sticky.has_key("SEW_START_NUMBER"):
num = sc.sticky["SEW_START_NUMBER"]
prefix = None
if sc.sticky.has_key("SEW_NUMBER_PREFIX"):
prefix = sc.sticky["SEW_NUMBER_PREFIX"]
addNum = True
if sc.sticky.has_key("ADD_SEW_NUMBERS"):
addNum = sc.sticky["ADD_SEW_NUMBERS"]
dblSize = 1
if sc.sticky.has_key("SEAM_MARKER_SIZE"):
dblSize = sc.sticky["SEAM_MARKER_SIZE"]
divLen = 1
if sc.sticky.has_key("SEW_DIV_LENGTH"):
divLen = sc.sticky["SEW_DIV_LENGTH"]
divNum = 5
if sc.sticky.has_key("SEW_DIV_NUM"):
divNum = sc.sticky["SEW_DIV_NUM"]
mode = False
if sc.sticky.has_key("SEW_DIV_MODE"):
mode = sc.sticky["SEW_DIV_MODE"]
go = Rhino.Input.Custom.GetOption()
go.AcceptNothing(True)
strGo = "Edge length is " + str(crvLength) + " Press Enter to accept the current settings."
go.SetCommandPrompt(strGo)
go.AcceptNumber(True, True)
opSize = Rhino.Input.Custom.OptionDouble(dblSize)
opNum = Rhino.Input.Custom.OptionInteger(num)
opDivLen = Rhino.Input.Custom.OptionDouble(divLen)
opDivNum = Rhino.Input.Custom.OptionInteger(divNum)
opMode = Rhino.Input.Custom.OptionToggle(mode, "Number", "Length")
opAddNum = Rhino.Input.Custom.OptionToggle(addNum, "No", "Yes")
go.AddOptionToggle("Mode",opMode)
go.AddOptionInteger("CurrentNumber", opNum)
go.AddOptionDouble("MarkerSize", opSize)
#Decide what division option to add
if mode:
go.AddOptionDouble("DivisionLength", opDivLen)
else:
go.AddOptionInteger("DivisionNumber", opDivNum)
go.AddOptionToggle("Numbers", opAddNum)
result = go.Get()
if( go.CommandResult() != Rhino.Commands.Result.Success ):
return False, mode,dblSize,num,divLen,divNum, addNum
if result == Rhino.Input.GetResult.Number:
divNum = int(go.Number())
sc.sticky["SEW_DIV_NUM"] = divNum
continue
if result == Rhino.Input.GetResult.Nothing:
sc.sticky["SEW_START_NUMBER"]= num
return True, mode,dblSize,num,divLen,divNum, addNum
if result == Rhino.Input.GetResult.Option:
mode = opMode.CurrentValue
dblSize = opSize.CurrentValue
num = opNum.CurrentValue
divLen = opDivLen.CurrentValue
divNum = opDivNum.CurrentValue
addNum = opAddNum.CurrentValue
sc.sticky["ADD_SEW_NUMBERS"] = addNum
sc.sticky["SEW_NUMBER"] = num
sc.sticky["SEW_START_NUMBER"]= num
sc.sticky["SEAM_MARKER_SIZE"] = dblSize
sc.sticky["SEW_DIV_LENGTH"] = divLen
sc.sticky["SEW_DIV_NUM"] = divNum
sc.sticky["SEW_DIV_MODE"] = mode
continue
def EdgeDivider():
pi = math.pi
count = 0
startNum = 0
if sc.sticky.has_key("SEW_START_NUMBER"):
startNum = sc.sticky["SEW_START_NUMBER"]
def PlanarSrfFilter(rhObject, geometry, componentIndex):
return geometry.Brep.Surfaces[0].IsPlanar()
while count < 2:
count +=1
grp = rs.AddGroup()
edgeStr = "Select an edge to mark near starting end."
if count > 1:
edgeStr = "Select the second edge near the starting end."
#Get the edge to divide
ge = Rhino.Input.Custom.GetObject()
ge.GeometryFilter = Rhino.DocObjects.ObjectType.EdgeFilter
ge.SetCustomGeometryFilter(PlanarSrfFilter)
ge.SetCommandPrompt(edgeStr)
rc = ge.Get()
if( ge.CommandResult() != Rhino.Commands.Result.Success ):
return
if rc == Rhino.Input.GetResult.Object:
objref = ge.Object(0)
pPt = objref.SelectionPoint()
e = objref.Geometry()
brep = e.Brep
face = brep.Faces[0]
brepPlane = brep.Surfaces[0].TryGetPlane()[1]
eCrv = e.ToNurbsCurve()
if count == 1: crvLength = round(eCrv.GetLength(), 3)
#Get the options for dividing and marking the edges
if count == 1:
RC, mode,dblSize,num,divLen,divNum,addNum = GetMarkerOptions(crvLength)
if not RC: return
if count > 1:
if sc.sticky.has_key("SEW_START_NUMBER"):
num = sc.sticky["SEW_START_NUMBER"]
if not eCrv: return
#start counting from the picked end of the curve
eDom = eCrv.Domain
x = eCrv.ClosestPoint(pPt)
if eCrv.ClosestPoint(pPt)[1]>eDom.Mid:
eCrv.Reverse()
#print "Reversed"
#Set the right kind of curve division
if mode:#Use length of division
pars = eCrv.DivideByLength(divLen, True)
else: #Use number of divisions
pars = eCrv.DivideByCount(divNum, True)
#Intersect a circle with the brep plane to get two points marking the ends of the hash mark
for i in range(len(pars)):
pt = eCrv.PointAt(pars[i])
rc, plane = eCrv.PerpendicularFrameAt(pars[i])
circle = Rhino.Geometry.Circle(plane, dblSize)
ppp = Rhino.Geometry.Intersect.Intersection.CurvePlane(circle.ToNurbsCurve(), brepPlane, .001)
p1 = ppp[0].PointA
p2 = ppp[1].PointA
hashMark = Rhino.Geometry.LineCurve(p1,p2)
#if numbering is asked for by the user, get the correct plane etc, and add number-shaped curves.
if addNum: #Numbering enabled
directionsMatch=False
srf = face.DuplicateSurface()
if p2.DistanceTo( brep.ClosestPoint(p2)) < .001:
vecY = hashMark.TangentAtEnd
tPt = p2
else:
vecY = hashMark.TangentAtStart
vecY.Reverse()
tPt = p1
srfRc,parU, parV = srf.ClosestPoint(tPt)
planeRc, tPlane = srf.FrameAt(parU, parV)
planeAxis = Rhino.Geometry.Vector3d(tPlane.ZAxis)
planeAxis.Reverse()
vecX= Rhino.Geometry.Vector3d(vecY)
vecX.Rotate( pi/2,planeAxis)
tPlane = Rhino.Geometry.Plane(tPlane.Origin,vecX,vecY)
tPlane.Origin = pt
if Rhino.Geometry.Vector3d.VectorAngle(eCrv.TangentAtStart, tPlane.XAxis) < pi/2:
directionsMatch=True
text = Rhino.Geometry.Curve.CreateTextOutlines(str(num),"Arial", .9*dblSize,0,True,tPlane,.8*dblSize, tolerance=.001)
#TEXT = Rhino.Geometry.TextEntity()
#TEXT.Plane = tPlane
#TEXT.Text = str(num)
#TEXT.Justification= Rhino.Geometry.TextJustification.BottomLeft
#TEXT.FontIndex = sc.doc.Fonts.FindOrCreate("Arial",False, False)
#sc.doc.Objects.AddText(TEXT)
if text:
textBB = Rhino.Geometry.BoundingBox()
for txtCrv in text:
textBB.Union(txtCrv.GetBoundingBox(tPlane))
pass
corners = textBB.GetCorners()
pToP = Rhino.Geometry.Transform.PlaneToPlane(Rhino.Geometry.Plane.WorldXY,tPlane)
for u in range(8):
corners[u] = pToP*corners[u]
tempPt = corners[1]
if directionsMatch:
if count > 1:
if i > 0:
xXform = (pt-corners[1])*1.1
#TEXT.Justification= Rhino.Geometry.TextJustification.BottomRight
else:
xXform = None
#TEXT.Justification= Rhino.Geometry.TextJustification.BottomLeft
else:
if i > 0:
xXform = (pt-corners[1])*1.1
#TEXT.Justification= Rhino.Geometry.TextJustification.BottomRight
else:
xXform = None
#TEXT.Justification= Rhino.Geometry.TextJustification.BottomLeft
else:
if count > 1:
if i < len(pars)-1:
xXform = (pt-corners[1])*1.1
#TEXT.Justification= Rhino.Geometry.TextJustification.BottomRight
else:
xXform = None
#TEXT.Justification= Rhino.Geometry.TextJustification.BottomLeft
else:
if 0< i < len(pars)-1:
xXform = None
#TEXT.Justification= Rhino.Geometry.TextJustification.BottomLeft
elif i == len(pars)-1 :
xXform = None
#TEXT.Justification= Rhino.Geometry.TextJustification.BottomLeft
elif i == 0:
xXform = (pt-corners[1]).Length*eCrv.TangentAtStart*1.1
#TEXT.Justification= Rhino.Geometry.TextJustification.BottomRight
#xXform.Reverse()
yXform = tPlane.YAxis*.1*dblSize
tempIds = []
#tPlane.Rotate( pi, tPlane.ZAxis)
#TEXT.Plane = tPlane
#TEXT.Justification= Rhino.Geometry.TextJustification.TopRight
#sc.doc.Objects.AddText(TEXT)
for txtCrv in text:
if xXform is not None: txtCrv.Translate(xXform)
txtCrv.Translate(yXform)
tempIds.append(sc.doc.Objects.AddCurve(txtCrv))
rs.AddObjectsToGroup(tempIds, rs.AddGroup())
rs.AddObjectsToGroup(tempIds, grp)
addId = System.Guid.NewGuid()
crvId = sc.doc.Objects.AddCurve(hashMark)
rs.AddObjectToGroup(crvId, grp)
rs.SetUserText(crvId, "SeamMarkerId", str(addId))
addId = None
if addNum: num += 1
sc.sticky["SEW_NUMBER"] = num
sc.doc.Objects.UnselectAll()
sc.doc.Views.Redraw()
sc.sticky["SEW_START_NUMBER"] = num
if __name__ == "__main__": EdgeDivider()
@pgolay
Copy link
Author

pgolay commented Jul 5, 2018

Changed to selecting only edges, and added filter for edges of planar breps

@pgolay
Copy link
Author

pgolay commented Jul 6, 2018

Fixed text placement bugs, added grouping.

@pgolay
Copy link
Author

pgolay commented Jul 9, 2018

Commented out one last reference to 'TEXT' to match the others.

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