Revit Importing Geometry As Triangulated

hi, I’m having an intriguing problem, which I am wondering if anyone can weigh in on. Certain breps in Rhino are being translated into triangulated geometry when brought over into Revit using “Sample 2” from the Github repo.

After examining all of the geometry closely, I think it may have to do with the edge or vertex tolerances. For example, this comes over fine:

polysurface
ID: 5229c582-c234-4a11-bea6-83ac1f43c034 (44180)
Object name: (not named)
Layer name: Box Metal
Render Material:
source = from layer
index = -1
Geometry:
Valid polysurface.
Closed solid polysurface with 6 surfaces.
Edge Tally:
12 manifold edges
Edge Tolerances: all 0
Vertex Tolerances: all 0
Render mesh: 6 fast meshes 24 vertices 8 polygons
Analysis mesh: none present

But this ends up triangulated:

polysurface
ID: 00445753-311e-4bc7-88c7-c183bc393123 (26297)
Object name: (not named)
Layer name: Box 1
Render Material:
source = from obj
index = 690
Geometry:
Invalid polysurface.
Closed solid polysurface with 6 surfaces.
Edge Tally:
12 manifold edges
Edge Tolerances: 0 to 0.0010581
median = 8.72066e-05 average = 0.00030539
Vertex Tolerances: 3.35858e-05 to 0.00105916
median = 8.72938e-05 average = 0.000316833
Render mesh: 6 fast meshes 24 vertices 8 polygons
Analysis mesh: none present
Geometry UserData:
UserData ID: 3B7FB506-437C-431e-B1D7-93C4CBFF417F
Plug-in: Rhino
description: Gumball grip frame
saved in file: yes
copy count: 20

For visual reference, “A” is what a triangulated brep looks like. “B” is what that same Brep looks like if it is exploded and brought into Revit as individual surfaces (I moved the surfaces apart a little to illustrate). Running join on the surfaces after exploding them results in “A” again. If I extrude one of the exploded surfaces, I get “C” which is the desired (clean) result.

For now, I’m working on an additional component to contribute to the RIR github, which will check the tolerances of breps, to help identify ones which may need reconstruction…

Also, I think I may have found the code responsible for creating the triangulated version, it seems be there as a fallback for if the preferred method fails. In Convert.cs at line 438:

else
{
// Emergency result as a mesh
var mp = MeshingParameters.Default;
mp.MinimumEdgeLength = Revit.VertexTolerance;
mp.ClosedObjectPostProcess = true;
mp.JaggedSeams = false;

var brepMesh = new Rhino.Geometry.Mesh();
brepMesh.Append(Rhino.Geometry.Mesh.CreateFromBrep(brep, mp));

foreach(var g in brepMesh.ToHost())
yield return g;
}

I have a working node that checks for this issue (if anyone would like it, let me know and I can put it on Github). However, I think I found a bug while developing it, see the screenshot below. Initially the referenced geometry previews normally, but after checking IsValid on the object, if IsValid is false, then that geometry will no longer preview at all…

A - One referenced Brep (where IsValid = False)
B - One referenced Brep (where IsValid = True)
C - Tries to preview the invalid Breps (fails)
D - Tries to preview the valid Breps (succeeds)
E - Shows info about B
F - Shows info about A
G - Revit Directshape made from B
H - Revit DirectShape made from A (triangulates regardless of whether IsValid is checked)

Grasshopper file is here:
Modified Sample2.ghx (2.5 MB)

This is the code inside SolveInstance, it basically just checks for IsValid, because invalid breps seem to be causing the triangulation issue.

protected override void SolveInstance(IGH_DataAccess DA)
{
  var geometryList = new List<Rhino.Geometry.GeometryBase>();
  DA.GetDataList(0, geometryList);

  IEnumerable<Rhino.Geometry.GeometryBase> geometryEn = geometryList;

  List<GeometryBase> goodGeometry = new List<GeometryBase>();
  List<GeometryBase> badGeometry = new List<GeometryBase>();
  List<string> debug = new List<string>();

  if (geometryEn != null)
  {

    //DEBUG
    debug.Add("geometryEn contains: " + geometryEn.Count().ToString() + " items");
    debug.Add("-----------------------");
    int x = 0;
    //DEBUG

    foreach (var geo in geometryEn)
    {
      if (geo.IsValid)
      {
        goodGeometry.Add(geo);
      }
      else
      {
        badGeometry.Add(geo);
      }

      //DEBUG
      //var result = geometryEn.ToHost();
      debug.Add("geometryEn[" + x + "] class is: " + geo.GetType().ToString());
      debug.Add("geometryEn[" + x + "] isValid: " + geo.IsValid.ToString());
      debug.Add("geometryEn[" + x + "] ObjectType is: " + geo.ObjectType.ToString());
      //debug.Add("geometryEn[" + x + "] type is: " + geo.IsSolid.ToString());
      //debug.Add("geometryEn[" + x + "] type is: " + geo.IsManifold.ToString());
      debug.Add("-----------------------");
      x++;
      //DEBUG

    }//end foreach

  } //end if

  DA.SetDataList(0, goodGeometry);
  DA.SetDataList(1, badGeometry);
  DA.SetDataList(2, debug);
}//end SolveInstance

Thanks for test and share your conclusions here!!