HiddenLine Drawing

Hello I have been using the following code for creating a hiddenLine drawing based on the examples I have found within this forum.


Rhino.RhinoDoc doc = Rhino.RhinoDoc.ActiveDoc;

        HiddenLineDrawingParameters _HLDparam = new HiddenLineDrawingParameters();

        Rhino.Display.RhinoViewport VP = new Rhino.Display.RhinoViewport();
        VP.SetToPlanView(P.Origin, P.XAxis, P.YAxis, true);

        doc.Views.ActiveView.ActiveViewport.SetToPlanView(P.Origin, P.XAxis, P.YAxis, true);

        _HLDparam.AbsoluteTolerance = doc.ModelAbsoluteTolerance;
        _HLDparam.IncludeHiddenCurves = false;
        _HLDparam.IncludeTangentEdges = false;
        _HLDparam.IncludeTangentSeams = false;
        _HLDparam.Flatten = true;

        // add Geometry to hiddenLineDrawingObject...
        for (int i = 0; i < geom.Length; i++)
            _HLDparam.AddGeometry(geom[i], i);

        HiddenLineDrawing Drawing = HiddenLineDrawing.Compute(_HLDparam, true);

        List<Curve> _curves = new List<Curve>();
        List<ObjectAttributes> _objAtt = new List<ObjectAttributes>();
        int objIndex = -1;
        foreach (Rhino.Geometry.HiddenLineDrawingSegment seg in Drawing.Segments)

            switch (seg.SegmentVisibility)
                case HiddenLineDrawingSegment.Visibility.Visible:
                case HiddenLineDrawingSegment.Visibility.Clipped:
                case HiddenLineDrawingSegment.Visibility.Unset:
                case HiddenLineDrawingSegment.Visibility.Duplicate:
                case HiddenLineDrawingSegment.Visibility.Projecting:
                        objIndex = (int)seg.ParentCurve.SourceObject.Tag;
                case HiddenLineDrawingSegment.Visibility.Hidden:

        Transform HLtW = new Transform();
        Drawing.WorldToHiddenLine.TryGetInverse(out HLtW);
        Transform final = Transform.PlanarProjection(P) * HLtW;

So what I get is not very satisfying, Top: Code Result, Buttom: Make2D result…
Any suggestions?

@rajaa, can you assist?

For the moment I found a bit of a work around simply converting the Brep into a Mesh (tried converting to surfaces before but that was even uglier), however this increases computation time and the result is not pleasing:

Hi @richard_schaffranek
Are you using clipping planes? Looks like intersection curves between the clipping planes and your geometry are being omitted. Check the sample I shared in this link, and let me know if you still have a problem:

Hello @Rajaa,

no I am never calling the function AddClippingPlane(), I am constructing a Viewport from scratch (and for visualisation, I am also change the current Rhino Viewport to the same view). See initial post. And I also have been following the HLDParam in my debugging session, it never shows up with clipping planes.

Can you share the example geometry you have, so I can run with your code at my end?

Send a private message.

1 Like

Just a quick question, is the hidden line drawing using the graphic card? I am running the code on a laptop with a dual graphic card and I am not so sure which of the both the C# code is accessing if so…

@dale I’m not sure I know the answer to this question. Can you help here?

Hidden line drawing as in “technical display” does use the GPU. Hidden line drawing as in the results produced from Make2d are computed on the CPU

In your code:
" VP.SetToPlanView(P.Origin, P.XAxis, P.YAxis, true);"
Where do you get the “P” from?

Also, the “geom”, is it a list of all geometry in the doc?
Also, you have “_Att” in “_objAtt.Add(_Att[objIndex]);”, is this the list of attributes of your doc objects? I did the following to get the 2, but still not sure what “P” is:

      var go = new GetObject();

      // Get Objects in document to compute Make2D calculation on
      go.SetCommandPrompt("Select objects to Make2D");
      go.GeometryFilter = ObjectType.Point | ObjectType.PointSet | ObjectType.Curve | ObjectType.Surface |
                          ObjectType.PolysrfFilter | ObjectType.Mesh | ObjectType.Annotation | ObjectType.TextDot |
      go.GroupSelect = true;
      go.GetMultiple(1, 0);
      if (go.CommandResult() != Result.Success)
        return go.CommandResult();
      var obj_refs = go.Objects();
      List<GeometryBase> geom = new List<GeometryBase>();
      List<ObjectAttributes> _Att = new List<ObjectAttributes>();
      for (int i = 0; i < obj_refs.Length; i++)


no actually the code is within a function. None of the object are actually within the active document.
There is an array of GeometryBase (Brep) and for each Brep an Attribute specifiying the layer of each Line segment that I add to Rhino later in the Code.

Porpuse is to create an underlying drawing of a 3D Steal Object which should be bended from a 2D lasercut based on refference points, that is why the acctual 3D geometry is never exported to Rhino.

The plane P is also some plane that is passed into the function. This should be any possible plane.
But for the given case it is actually WorldXY, WorldXZ, WorldYZ with a different ORIGIN.

Complete function is called rom a Grashopper component within its bake methode (don’t know if this playes a roll)

Thanks for looking into it.

I’m getting the correct answer at my end. I’ll send you the result model I’m getting and the code in a direct message

After seeing your code, the reason why you are getting what appears to be a bug in the HLD is because your lofted surfaces are not split at the kinks. After creating your lofted surface, you need to do the following:


That should fix it. The reason why it worked for you after baking the geometry, is that Rhino does verify if a brep has kinks within the document tolerances and does split when adding to the document.


Thx that is very very helpful. Are there any thoughts on it why this is not done directly when lofting?

Because I think I like the beauty of it having a continuous surface with a 90 degree Knick but if I then can’ t get it into Rhino why ?

I mean theoretically I could construct a box from a surface?

Hi @richard_schaffranek,

The default behavior of Rhino is to split kinky surfaces when they are added to the document. Most users don’t want to deal with kinky surfaces because they can cause problems down stream.

If you want to add kinky surfaces to the document, you’ll need to write C# or Python script that calls this version of ObjectTable.AddBrep and pass a False value for the splitKinkySurfaces parameter.

– Dale