Hello,
I’m working on a Display Conduit script in Python 3 that works for block instances as well.
My issue is that I can get the Block nested geometry to show in the conduit but it is not drawing in the foreground like the rest of my object types.
You can see that Meshes (M), Breps (B), and Curves (C) are all showing correctly but the BI (exploded breps, curves, etc.) are having z.fighting issues with the parent/non-exploded block.
Thank you all for any guidance you can provide!
Here’s the code, it’s a hybrid of the C# @menno provided here and the explode block sample code that @dale provided [here] adapted for Python 3(RhinoCommon nested instances - #2 by dale):
Rhino Test File:
test_file.3dm (3.4 MB)
Python Code:
import Rhino
import scriptcontext as sc
import rhinoscriptsyntax as rs
from System.Drawing import Color
class PreviewAttributes:
def __init__(self):
self.ObjectColor = Color.Black
self.ColorSource = Rhino.DocObjects.ObjectColorSource.ColorFromObject
self.WireDensity = 1
self.LayerIndex = -1
self.CurveThickness = 5
self.PointStyle = Rhino.Display.PointStyle.ControlPoint
self.PointPixels = 3
self.TextColor = Color.White
@staticmethod
def Selected():
attr = PreviewAttributes()
attr.ObjectColor = Color.BlueViolet # Default is Color.Yellow
attr.ColorSource = Rhino.DocObjects.ObjectColorSource.ColorFromObject
attr.TextColor = Color.Black
return attr
@staticmethod
def New():
attr = PreviewAttributes()
attr.ColorSource = Rhino.DocObjects.ObjectColorSource.ColorFromLayer
attr.LayerIndex = sc.doc.Layers.CurrentLayer.LayerIndex
return attr
@staticmethod
def Warning():
attr = PreviewAttributes()
attr.ObjectColor = Color.Red
attr.ColorSource = Rhino.DocObjects.ObjectColorSource.ColorFromObject
attr.TextColor = Color.White
return attr
class PreviewDisplayConduit(Rhino.Display.DisplayConduit):
def __init__(self):
super(PreviewDisplayConduit, self).__init__()
self._objects = {}
self._exploded_geometries = []
def AddObject(self, obj, attributes):
if obj:
self._objects[obj] = attributes
def ClearObjects(self):
self._objects.clear()
self._exploded_geometries.clear()
def DrawForeground(self, e):
self._exploded_geometries.clear()
for obj, attr in self._objects.items():
color = attr.ObjectColor
material = Rhino.Display.DisplayMaterial(color)
if attr.ColorSource == Rhino.DocObjects.ObjectColorSource.ColorFromLayer:
layer = sc.doc.Layers[attr.LayerIndex]
color = layer.Color
if isinstance(obj, Rhino.Geometry.Curve):
e.Display.DrawCurve(obj, color, attr.CurveThickness)
elif isinstance(obj, Rhino.Geometry.Brep):
e.Display.DrawBrepShaded(obj, material)
# e.Display.DrawBrepWires(obj, color, attr.WireDensity)
elif isinstance(obj, Rhino.Geometry.Point):
e.Display.DrawPoint(obj.Location, attr.PointStyle, attr.PointPixels, color)
elif isinstance(obj, Rhino.Geometry.Mesh):
e.Display.DrawMeshWires(obj, color)
elif isinstance(obj, Rhino.Geometry.TextDot):
e.Display.DrawDot(obj.Point, obj.Text, color, attr.TextColor)
elif isinstance(obj, Rhino.Geometry.InstanceReferenceGeometry):
# Explode Block Geometry Here
self.ExplodeBlockHelper(e, obj, attr, Rhino.Geometry.Transform.Identity)
else:
Rhino.RhinoApp.WriteLine("Obj Type Is: " + str(obj))
# Draw exploded geometries after processing all objects
for geom, attr in self._exploded_geometries:
color = attr.ObjectColor
material = Rhino.Display.DisplayMaterial(color)
if attr.ColorSource == Rhino.DocObjects.ObjectColorSource.ColorFromLayer:
layer = sc.doc.Layers[attr.LayerIndex]
color = layer.Color
if isinstance(geom, Rhino.Geometry.Curve):
e.Display.DrawCurve(geom, color, attr.CurveThickness)
elif isinstance(geom, Rhino.Geometry.Brep):
e.Display.DrawBrepShaded(geom, material)
elif isinstance(geom, Rhino.Geometry.Point):
e.Display.DrawPoint(geom.Location, attr.PointStyle, attr.PointPixels, color)
elif isinstance(geom, Rhino.Geometry.Mesh):
e.Display.DrawMeshWires(geom, color)
elif isinstance(geom, Rhino.Geometry.TextDot):
e.Display.DrawDot(geom.Point, geom.Text, color, attr.TextColor)
def ExplodeBlockHelper(self, e, iref, attr, xform):
idef = sc.doc.InstanceDefinitions.FindId(iref.ParentIdefId)
if idef is None:
return False
xform = xform * iref.Xform
do_xform = xform.IsValid and not xform.Equals(Rhino.Geometry.Transform.Identity)
objects = idef.GetObjects()
for obj in objects:
if obj is None:
continue
if isinstance(obj, Rhino.DocObjects.InstanceObject):
# Explode any nested instances...
self.ExplodeBlockHelper(e, obj.Geometry, attr, xform)
continue
geom = obj.Geometry.Duplicate()
if do_xform:
if xform.SimilarityType == Rhino.Geometry.TransformSimilarityType.NotSimilarity:
if not geom.MakeDeformable() and isinstance(geom, Rhino.Geometry.Curve):
geom = geom.ToNurbsCurve()
if not geom.Transform(xform):
continue
if xform.SimilarityType == Rhino.Geometry.TransformSimilarityType.OrientationReversing:
if isinstance(geom, Rhino.Geometry.Brep):
geom.Flip()
elif isinstance(geom, Rhino.Geometry.Mesh):
geom.Flip(True, True, True)
self._exploded_geometries.append((geom, attr))
def CalculateBoundingBox(self, e):
bbox = Rhino.Geometry.BoundingBox()
for obj in self._objects.keys():
bbox.Union(obj.GetBoundingBox(True))
e.IncludeBoundingBox(bbox)
def PreviewObjects():
selected_objects = rs.GetObjects("Select objects to preview")
if not selected_objects:
return
conduit = PreviewDisplayConduit()
attr = PreviewAttributes.Selected()
for obj_id in selected_objects:
rhino_obj = rs.coercegeometry(obj_id)
conduit.AddObject(rhino_obj, attr)
conduit.Enabled = True
sc.doc.Views.Redraw()
rs.GetString("Press Enter to end preview")
conduit.Enabled = False
conduit.ClearObjects()
sc.doc.Views.Redraw()
if __name__ == "__main__":
PreviewObjects()