Skip to content

Instantly share code, notes, and snippets.

@pgolay
Last active July 8, 2020 04:18
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/92c085b9964f3754fab3321d11c19a27 to your computer and use it in GitHub Desktop.
Save pgolay/92c085b9964f3754fab3321d11c19a27 to your computer and use it in GitHub Desktop.
import Rhino
import scriptcontext as sc
import rhinoscriptsyntax as rs
import System
class DrawCrvCrvDeviationConduit(Rhino.Display.DisplayConduit):
def __init__(self, id1, id2, idx1, idx2):
self.textSize = 24
self.id1 = id1
self.id2 = id2
self.edgeIdx1 = idx1
self.edgeIdx2 = idx2
self.hairScale = 0
self.intSamples = 32
self.interpCrv = None
self.blnDot = True
self.lineColor = System.Drawing.Color.Blue
self.minColor = System.Drawing.Color.Green
self.maxColor = System.Drawing.Color.Red
self.m_dirty = False
self.bbox = Rhino.Geometry.BoundingBox()
self.Start()
def Calculate(self):
tol = sc.doc.ModelAbsoluteTolerance
if self.edgeIdx1 == -1:
crv1 = rs.coercecurve (self.id1)
else:
brep = rs.coercebrep(self.id1)
edge = brep.Edges[self.edgeIdx1]
crv1 = edge.ToNurbsCurve()
if self.edgeIdx2 == -1:
crv2 = rs.coercecurve (self.id2)
else:
brep = rs.coercebrep(self.id2)
edge = brep.Edges[self.edgeIdx2]
crv2 = edge.ToNurbsCurve()
info = Rhino.Geometry.Curve.GetDistancesBetweenCurves(crv1, crv2, tol)
"""
rc 0
out double maxDistance, 1
out double maxDistanceParameterA, 2
out double maxDistanceParameterB, 3
out double minDistance, 4
out double minDistanceParameterA, 5
out double minDistanceParameterB 6
If the max or min is on the end point of one of the curves,
find the closest point from that end back to the other curve and split off a subcrv to use instead.
"""
if info[0]:
dom1 = crv1.Domain
dom2 = crv2.Domain
crv2A = crv2.ClosestPoint(crv1.PointAt(dom1.Min))[1]
crv2B = crv2.ClosestPoint(crv1.PointAt(dom1.Max))[1]
domList = sorted([crv2A,crv2B])
dom2Ex = Rhino.Geometry.Interval(domList[0], domList[1])
exCrv = crv2.Trim(dom2Ex)
if exCrv is not None:
crv2 = exCrv
crv1A = crv1.ClosestPoint(crv2.PointAt(dom2.Min))[1]
crv1B = crv1.ClosestPoint(crv2.PointAt(dom2.Max))[1]
domList = sorted([crv1A,crv1B])
dom1Ex = Rhino.Geometry.Interval(domList[0], domList[1])
exCrv = crv1.Trim(dom1Ex)
if exCrv is not None:
crv1 = exCrv
pars = crv1.DivideByCount(self.intSamples,True)
self.pts = [crv1.PointAt(par) for par in pars]
self.crvPts = [crv2.PointAt(crv2.ClosestPoint(pt)[1]) for pt in self.pts]
self.Distances = []
self.Lines = []
info = Rhino.Geometry.Curve.GetDistancesBetweenCurves(crv1, crv2, tol)
if info[0]:
self.maxDist = info[1]
self.maxLoc = crv2.PointAt(info[3])
maxEndPt = crv1.PointAt(info[2])
self.minDist = info[4]
self.minLoc = crv2.PointAt(info[6])
minEndPt = crv1.PointAt(info[5])
for i in range(len(self.pts)):
self.Lines.append(Rhino.Geometry.Line(self.pts[i],self.crvPts[i]) )
for pt in self.pts:
self.bbox.Union(pt)
for pt in self.crvPts:
self.bbox.Union(pt)
self.maxLine = Rhino.Geometry.Line(self.maxLoc, maxEndPt)
self.minLine = Rhino.Geometry.Line(self.minLoc, minEndPt)
return self.maxDist,self.minDist, self.minLine, self.maxLine, self.bbox, self.Lines
def Start(self):
# Create event handlers
self.CreateEvents()
if sc.sticky.has_key('CRVDEVIATION_SAMPLES'):
self.intSamples = sc.sticky['CRVDEVIATION_SAMPLES']
if sc.sticky.has_key('CRVDEVIATION_HAIRSCALE'):
intScale = sc.sticky['CRVDEVIATION_HAIRSCALE']
self.hairScale = pow(2, intScale)/100
if sc.sticky.has_key('CRVDEVIATION_TEXT_USAGE'):
self.blnDot = sc.sticky['CRVDEVIATION_TEXT_USAGE']
# Enable conduit
self.Enabled = True
# Stop the conduit
def Stop(self):
# Remove event handlers
self.RemoveEvents()
# Disable conduit
self.Enabled = False
def CreateEvents(self):
Rhino.RhinoDoc.CloseDocument += self.OnCloseDocument
Rhino.RhinoDoc.ReplaceRhinoObject += self.OnReplaceObject
Rhino.RhinoDoc.DeleteRhinoObject += self.OnDeleteObject
Rhino.RhinoApp.Idle += self.OnIdle
# Remove Rhino event handlers
def RemoveEvents(self):
Rhino.RhinoDoc.CloseDocument -= self.OnCloseDocument
Rhino.RhinoDoc.ReplaceRhinoObject -= self.OnReplaceObject
Rhino.RhinoDoc.DeleteRhinoObject -= self.OnDeleteObject
Rhino.RhinoApp.Idle -= self.OnIdle
# RhinoDoc.ReplaceRhinoObject event handler
def OnReplaceObject(self, sender, e):
if e.ObjectId == self.id1 or e.ObjectId == self.id2 :
self.hairScale = 0
self.intSamples = 32
self.blnDot = True
if sc.sticky.has_key('CRVDEVIATION_SAMPLES'):
self.intSamples = sc.sticky['CRVDEVIATION_SAMPLES']
if sc.sticky.has_key('CRVDEVIATION_HAIRSCALE'):
intScale = sc.sticky['CRVDEVIATION_HAIRSCALE']
self.hairScale = pow(2, intScale)/100
if sc.sticky.has_key('CRVDEVIATION_TEXT_USAGE'):
self.blnDot = sc.sticky['CRVDEVIATION_TEXT_USAGE']
self.m_dirty = True
def OnDeleteObject(self, sender, e):
if e.ObjectId == self.id1 or e.ObjectId == self.id2 :
if not self.m_dirty:
self.Stop()
self.id1 = None
self.id2 = None
if sc.sticky.has_key("CurveCurveDeviationConduit"):
sc.sticky.Remove("CurveCurveDeviationConduit")
def OnIdle(self, sender, e):
if self.m_dirty == True:
self.calculate()
self.m_dirty = False
def OnCloseDocument(self, sender, e):
self.Stop()
self.id1 = None
self.id2 = None
def CalculateBoundingBox(self, e):
e.IncludeBoundingBox(self.bbox)
def DrawForeground(self, e):
self.Calculate()
for line in self.Lines:
e.Display.DrawLine(line, self.lineColor)
e.Display.DrawLine(self.maxLine, System.Drawing.Color.Aqua)
e.Display.DrawLine(self.minLine, System.Drawing.Color.Aqua)
def DrawOverlay(self, e):
self.Calculate()
#
# for line in self.Lines:
# e.Display.DrawLine(line, self.lineColor)
#
# e.Display.DrawLine(self.maxLine, System.Drawing.Color.Chartreuse)
# e.Display.DrawLine(self.minLine, System.Drawing.Color.Chartreuse)
#
if not self.blnDot:
e.Display.Draw2dText("Max " + str(round((self.maxDist),4)), System.Drawing.Color.White, self.maxLoc, True, self.textSize)
e.Display.Draw2dText("Min " + str(round((self.minDist),4)), System.Drawing.Color.White, self.minLoc, True, self.textSize)
else:
e.Display.DrawDot(self.maxLoc, "Max " + str(round((self.maxDist),4)), System.Drawing.Color.White, System.Drawing.Color.Black)
e.Display.DrawDot(self.minLoc, "Min " + str(round((self.minDist),4)), System.Drawing.Color.White, System.Drawing.Color.Black)
def DrawCrvCrvDeviation():
if sc.sticky.has_key("CurveCurveDeviationConduit"):
conduit = sc.sticky["CurveCurveDeviationConduit"]
conduit.Stop()
conduit = None
sc.sticky.Remove("CurveCurveDeviationConduit")
sc.doc.Views.Redraw()
print "Curve-Curve deviation display has been turned off."
return
while True:
blnDot = True
if sc.sticky.has_key('CRVDEVIATION_TEXT_USAGE'):
blnDot = sc.sticky['CRVDEVIATION_TEXT_USAGE']
go = Rhino.Input.Custom.GetObject()
go.GeometryFilter = Rhino.DocObjects.ObjectType.Curve|Rhino.DocObjects.ObjectType.EdgeFilter
go.SetCommandPrompt("Select two curves to test.")
opDot = Rhino.Input.Custom.OptionToggle(blnDot,"Text", "Dot")
go.AddOptionToggle("TextMode", opDot)
go.SubObjectSelect=True
crvRC = go.GetMultiple(2,2)
if ( go.CommandResult() != Rhino.Commands.Result.Success ):
return
if crvRC == Rhino.Input.GetResult.Option:
blnDot = opDot.CurrentValue
sc.sticky['CRVDEVIATION_TEXT_USAGE'] = blnDot
continue
if crvRC == Rhino.Input.GetResult.Object:
objs = [go.Object(i) for i in range(go.ObjectCount)]
ids = []
idxs = []
for obj in objs:
idxs.append(obj.GeometryComponentIndex.Index)
ids.append(obj.ObjectId)
break
# id1 = rs.GetObject("Select the first curve",filter=4, preselect=True)
# if not id1: return
# crv1 = rs.coercecurve (id1)
#
# id2 = rs.GetObject("Select the second curve",filter=4)
# if not id2: return
# crv2 = rs.coercecurve(id2)
conduit = None
conduit = DrawCrvCrvDeviationConduit( ids[0], ids[1], idxs[0], idxs[1])
sc.sticky["CurveCurveDeviationConduit"] = conduit
sc.sticky['CRVCRVDEVIATION_INPUT'] = ids
conduit.Enabled = True
sc.doc.Views.Redraw()
print "Curve-Curve deviation display is now on."
if __name__ == '__main__':DrawCrvCrvDeviation()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment