Rhino 8 HiddenLineDrawing - Issue with OccludingSectionOption

Hello Everybody, maybe @rajaa ?

I’m trying to get a custom version of Make2D running via HiddenLineDrawing and I managed to get out visible lines, even cut by a plane. Already pretty nice!
Now I want the clipped away parts to be occluded as in the new V8 clipping planes when a background color is set. I found OccludingSectionOption in HiddenLineDrawingParameters and occluding_sections toggles when adding geometry - and I imagined I could occlude clipped away parts that way.
But whichever values I set these parameters to I always get all visible lines including the ones I want to stay hidden. Did I understand something wrong here?

I also noticed that HiddenLineDrawingSegment.Visibility.Clipped never seems to return any curves - shouldn’t it return the curves that are clipped away by the plane?

This is my code:

import Rhino

getObject = Rhino.Input.Custom.GetObject()
getObject.GeometryFilter = Rhino.DocObjects.ObjectType.Brep
getObject.GetMultiple(1, 0)
if getObject.ObjectCount != 0:
    geometryRefs = getObject.Objects()

geometry = []
for geometryRef in geometryRefs:
    geometry.append(geometryRef.Geometry())

hiddenLineDrawingParameters = Rhino.Geometry.HiddenLineDrawingParameters()
viewNumber = Rhino.RhinoDoc.ActiveDoc.NamedViews.FindByName("01")
view = Rhino.RhinoDoc.ActiveDoc.NamedViews[viewNumber]
viewport = view.Viewport
plane = Rhino.Geometry.Plane(viewport.TargetPoint, viewport.CameraX, viewport.CameraY)
hiddenLineDrawingParameters.SetViewport(viewport)
hiddenLineDrawingParameters.Flatten = True
for geometryItem in geometry:
    hiddenLineDrawingParameters.AddGeometry(geometryItem, None, True)
hiddenLineDrawingParameters.AddClippingPlane(plane)
hiddenLineDrawingParameters.OccludingSectionOption = True
hiddenLineDrawingParameters.AbsoluteTolerance = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance


hiddenLineDrawing = Rhino.Geometry.HiddenLineDrawing.Compute(hiddenLineDrawingParameters, True)
#hiddenLineDrawing.RejoinCompatibleVisible()

for segment in hiddenLineDrawing.Segments:
    if segment.SegmentVisibility == Rhino.Geometry.HiddenLineDrawingSegment.Visibility.Visible:
        Rhino.RhinoDoc.ActiveDoc.Objects.AddCurve(segment.CurveGeometry.DuplicateCurve())

And this is the Rhino file I use it with (on Layer 03 you can see what is created using my code…):
240328_CustomMake2D.3dm (381.6 KB)
240328_CustomMake2D.py (1.4 KB)

Can anyone tell me what I’m doing wrong or how I could get the desired result?
Thank you!

@rajaa - is this something you can help with?

1 Like

Hi @romio82
When you pass a geometry to the HLD, you need to also pass if it is cut by a clipping plane. So instead of using
hiddenLineDrawingParameters.AddGeometry(...),
you should use
hiddenLineDrawingParameters.AddGeometryAndPlanes(...)

You still need to pass the clipping planes to the HLDParameters, as you do, but only once per clipping plane.

Let me know how that works for you

1 Like

Hey @rajaa,

thanks a lot for your hint! Now the cuty work as expected.
I have to admit that I never before used a System.Collections.Generic.List in python before so I had to do a small research to find out how to pass the planes to hiddenLineDrawingParameters.AddGeometryAndPlanes(...) but finally I got it working :sweat_smile:

Now I went a little further and tried to add multiple clipping planes to my HLD and I came across a strange behaviour that seems to me like a bug in the HLD calculation. Please correct me if I’m missing something!!

I have a simple scene with a sphere and a named view that I tahe for HLD calculation.

Step 1:
If I let the ball be cut by the standard WorldXY plane and the World XZ plane, everything works as expected. The sphere is cut by the two planes, only a quarter of it stays visible.

Step 2:
If I now start to rotate the second (XZ) plane around the World Z axis, something seems to be breaking in the HLD calculation and now the sphere is drawn only cut by the first (XY) plane.

Step 3:
To reassure myself thet the rotated plane should work, I took the first one out of the HLD calculation. Now the sphere is correctly drawn cut by the rotated XZ plane.

To illustrate, here is a screenshot with the output of the three steps:

Here is the script:

import Rhino
import System

# First Step: degreesToRotateWorldXZ = 0, usePlane1 = True => Everything works as expected. The output is the Ball cut by two clipping planes.
# Second Step: degreesToRotateWorldXZ = -30, usePlane1 = True => Now the ball appears only to be cut by the XY Plane. The rotated XZ plan doesn't cut.
# Third Step: degreesToRotateWorldXZ = -30, usePlane1 = False => If the XY plane is taken out and only the rotated XZ plane is used, everything seems fine. The ball is cut by the rotated XZ plane.
# Conclusion: One by one, both of the planes seem to cut as expected. Only if used together and only if the second one is rotated out of plain XZ, things seem to brake and only the first plane is used.

degreesToRotateWorldXZ = -30
usePlane1 = False

# Define clipping planes to use
planes = []
plane1 = Rhino.Geometry.Plane.WorldXY

plane2 = Rhino.Geometry.Plane.WorldZX
plane2.Rotate(Rhino.RhinoMath.ToRadians(degreesToRotateWorldXZ), Rhino.Geometry.Vector3d(0,0,1))

# Add planes to the list
if usePlane1:
    planes.append(plane1)
planes.append(plane2)

# Define plane list for use in HiddenLineDrawing
planeList = System.Collections.Generic.List[Rhino.Geometry.Plane]()
for plane in planes:
    planeList.Add(plane)

# Get Objects to Draw
getObject = Rhino.Input.Custom.GetObject()
getObject.GeometryFilter = Rhino.DocObjects.ObjectType.Brep
getObject.GetMultiple(1, 0)
if getObject.ObjectCount != 0:
    geometryRefs = getObject.Objects()

geometry = []
for geometryRef in geometryRefs:
    geometry.append(geometryRef.Geometry())

# Prepare HiddenLineDrawingParameters
hiddenLineDrawingParameters = Rhino.Geometry.HiddenLineDrawingParameters()
viewNumber = Rhino.RhinoDoc.ActiveDoc.NamedViews.FindByName("01")
view = Rhino.RhinoDoc.ActiveDoc.NamedViews[viewNumber]
viewport = view.Viewport
plane = Rhino.Geometry.Plane(viewport.TargetPoint, viewport.CameraX, viewport.CameraY)
hiddenLineDrawingParameters.SetViewport(viewport)
hiddenLineDrawingParameters.Flatten = True
for object in geometry:
    hiddenLineDrawingParameters.AddGeometryAndPlanes(object, None, True, planeList)
for plane in planes:
    hiddenLineDrawingParameters.AddClippingPlane(plane)
hiddenLineDrawingParameters.OccludingSectionOption = True
hiddenLineDrawingParameters.AbsoluteTolerance = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance

# Calculate HiddenLineDrawing
hiddenLineDrawing = Rhino.Geometry.HiddenLineDrawing.Compute(hiddenLineDrawingParameters, True)

# Add computed segments to the ObjectTable
for segment in hiddenLineDrawing.Segments:
    if segment.SegmentVisibility == Rhino.Geometry.HiddenLineDrawingSegment.Visibility.Visible:
        Rhino.RhinoDoc.ActiveDoc.Objects.AddCurve(segment.CurveGeometry.DuplicateCurve())

And finally the Rhino file I used as well as the script file:
240331_CustomMake2D_TwoClippingPlanes.3dm (284.3 KB)
240331_CustomMake2D_TwoClippingPlanes.py (2.7 KB)

It would be great if you could have a look to see what’s happening there. Thank you!

What version of Rhino are you using, and what service release?

I’m on Rhino 8 SR6. I have updates for Service Release Candidates active, the installed version is 8.6.24086.11001.

1 Like

[Editied]
I’m debugging your code now… Thank you for providing full description and examples.
HLD handles rotated planes correctly using the same HLD classes you are using (except that the clipping plane actually exist in the document, which should not be an issue, unless you hit a corner case when only one clipping plane can be handled in this case)…

I’ll see if I can find where the problem is

Thank you @rajaa,
I’m curious to see where the issue comes from… And I hope it’s not a stupid bug I didn’t see :slight_smile:
As the clipping planes in the script only exist “virtually” as planes, the corner case shouldn’t be the issue, right? Still, it would be interesting to understand what exactely this corner case is because I intended to use my script with “real” document-based clipping planes as well.

One more thing I discovered inbetween: It makes a difference in the result if I switch the AddGeometryAndPlanes-Parameter “occluding_sections” to False.
So if I change line 54 in my script to

hiddenLineDrawingParameters.AddGeometryAndPlanes(object, None, False, planeList)

the result I expected (a quarter of a sphere, cut by WorldXY and the rotated XZ) is drawn, just “hollow”, without the filling.
Does this observation maybe help with finding the issue?
Thanks for your efforts!

Yes, this appears to be the issue… I create a report for @GregArden to look into here…

Great, thank you @rajaa!
Looking forward to a fixed HLD :slightly_smiling_face:

When I thought about your last comment with these corner cases I came across another thing:
Shouldn’t the remainings of a shpere cut by the World XY plane as ClippingPlane be the upper half of the sphere? As the Normal of World XY goes upwards the Clipping Plane should also look upwards or am I missing something there?
If I add that XY plane to the Documet via Rhino.RhinoDoc.ActiveDoc.Objects.AddClippingPlane I get a ClippingPlane that clips away the lower part of the sphere - as expected.
What I get drawn from HLD is the upper half of the sphere being clipped away. So it seems like it flips the plane.
Can you repeat that? And is it intended to use the flipped plane?

Yes, it was set up that way, and I know it feels a bit counter intuitive.

OK, I guess we can live with that… :smiley:
Thanks for the information!

Your tests worked fine in the the current developer build. I fixed some major clipping plane issues a couple weeks ago. Could you please test with the 8.7 service release candidate that should be coming out next week. Please let me know if this fixes your problems.

2 Likes

Thank you for that info and for those fixes, @GregArden !
Just checked my test with the first 8.7 service release from yesterday and everything works as expected. Thank you!