Best Techniques for DisplayConduit Caching of Breps and Text

Hi, All:
For context, I am working on interference elimination between a spindle/cutter and a work piece. There are numerous algorithms available from which to detect interference, but the program must iterate the spindle/cutter out of the interference state by rotational adjustment. In addition to code efficiency, I find that visual inspection of the “attack angle” improves my confidence that selected algorithm is doing its job in all areas of the work piece. For simplification, the work piece is meshed, and the attack angle is determined by the normal vector from the mesh face in addition to angular adjustment when required. From the screen grabs below, the mesh faces that need angular adjustment are converted to Breps and displayed in red.

The respective mesh face number is also displayed to isolate errant interference calculations. (I hope to learn about transparency, but that isn’t top of mind just now.)

Given the context, though there are a number of posts regarding DisplayConduit and the use of caching or “buckets” to improve the frame rate of Rhino viewports, I am still struggling to implement the swiftest algorithm.

For the Brep faces that signify angular adjustment, the DisplayConduit class is inherited by the VIZ_Evalute class, and has a property of a List<RhinoList>. (These are a list of lists of Breps as there are 13 milling levels in this example. The less curved Breps have fewer or no interference faces.)

2023-07-01_20-18-06

    public static List<RhinoList<Brep>>? CachedIntFerBreps { get; set; }

The milling level to display is selected from the List< RhinoLists> by the LvlBrepMeshNo integer and drawn within the PreDrawObjects event. A similar pattern is used when displaying the mesh face numbers.

        protected override void PreDrawObjects(DrawEventArgs e)
             if (MathParams.Viz_IntFerFaces)
            {
                    List<RhinoList<Brep>> IntFers = CachedIntFerBreps;
                    RhinoList<Brep> intFerFaces = IntFers[GetParams.LvlBrepMeshNo];

                foreach(Brep face in intFerFaces)
                {
                    DisplayMaterial BrepMat3 = new DisplayMaterial();
                    BrepMat3.Transparency = .2;
                    BrepMat3.Diffuse = System.Drawing.Color.Red;
                    e.Display.DrawBrepShaded(face, BrepMat3);
                }
            }

It seems obvious that a foreach loop within the PreDrawObjects event delays output of the viewport frame. The question is how to make the display faster as Rhino is pushing events to the DisplayConduit with every mouse motion in the viewport.

Options I have considered are:

  1. Before reaching PreDrawObjects event, create a mesh that includes Mesh, Brep faces and the mesh face numbers for each milling level. To have a preconstructed “thing” to draw, this seems the fastest, but the “thing” will take some time to create. However, during an evaluation cycle, each milling level only needs to be created once. Not sure how to make such a mesh but I am willing to try.

  2. Push the face Breps and face numbers to an Array, and then use Span to iterate the array within the PreDrawObject event.

A face Brep seems is a heavy object to display in multiples, would a DrawSurface method be faster?

Can an object be create that holds all three elements: mesh, Brep, and face numbers, and an instance of that object be displayed with the DrawObject method? (A separate instance for each milling level.)

Would appreciate any advise and examples.
Thanks,
Dave

Dear @David_Saylor

I just cross-read your long topic:

my guesses:

  • use meshes instead of Breps - Breps need to be meshed
  • you might even use a single mesh with unjoinend / partial joined faces
  • create the material BrepMat3 only once, outside the loop or as field of the class / Displayconduit
  • handling nested List<RhinoList<Brep>> might also be a bottleneck.

Visual Studio gives several tools to measure performance: Profiling
… maybe a startingpoint to identify the bottlenecks.

or have a look at this topic

Hi, Tom_P,

Thanks for offering your remarks after the long read. I was able to print out the code for both the DisplayConduit and DisplayPipeline classes using VS2022 debug tools. A brief overview shows that the DisplayPipeline class has undocumented methods to consider, such as, DisplaySurface(), DisplayPolygon(), DisplayPolyline(), and DisplayObject(). Despite my coding progress being slow as cold molasses, I am going to work though your much appreciated suggestions. Profiling will come later. I am interested in macro improvements just now.

  1. For the intended use explained in my topic, I don’t need shaded Breps to recognize which projection from mesh faces cause interference between the spindle/cutter and the workpiece. A “lighter” geometry object like a surface, a filled polygon, or a wire thickened polyline might due just fine.
  2. I am not sure how to create a separate mesh with just the interference faces. More research! It seems efficient to drape one mesh over another.
  3. I agree with the issue of materials, create once, use many times.
  4. From my current level of C# understanding, a List of RhinoLists make for easy collection types. However, considering the list lengths are already already determined for each milling level, the DisplayConduit should function faster using arrays. The Rhinocommon code for the classes mentioned above suggests that array collection types are preferred. I will create the arrays from the lists before attempting to invoke any draw method. Might this be considered “caching”?

I can see that I am trying to built a watch when a sundial will due. I will report back my finding(s).
As always, additional suggestions and code examples are much appreciated.
Dave