Cut Revit Solid with Civil Surface

Hello Dynamo Friends :slight_smile:

I would like to get the geometry of a Civil surface to dynamo for revit so I can use it to cut Revit solids.
Here are my results so far.

With CivilConnection I can get the Civil Surface to Dynamo Revit. No big deal.

I can get points of the surface and build a topography in Dynamo Revit.
This will not represent the Civil Topography correct, to increase the quality I will may use much more points in the future, by just creating as many sample points in civil as I want.

I tried to create a mesh and thicken it with the help of MeshToolkit. In hopes of getting a solid.

Turns out this just gives me a mesh and not a solid, and a mesh is pretty useless for what I want to do, so I need another approach.

I had to get rid of unnecessary points because Dynamo couldnĀ“t deal with the number of elements anymore, so I tested for intersection with my Revit Solid and build a new topo.

And now i build faces from the mesh.

I can build a polysurface from the surfaces and as a last step I tried to surface.thicken to get my desired ā€œtopo solidā€ that I want to cut with my revit solid. But I get the error:

[
  An error occurred: Unable to compute thickened face : INCONSISTENT_ORIENTATION -- Faces in shell have inconsistent orientation
   at Autodesk.LibG.Surface.thicken(Double thickness, Boolean both_sides)
   at Autodesk.LibG.SurfaceHost.Thicken(Double thickness, Boolean bothSides)
   at Autodesk.DesignScript.Geometry.Surface.Thicken(Double thickness, Boolean both_sides)
]

So IĀ“m not sure how to create a solid from the polysurface. I tried to create a python code to test and correct the orientation of the faces but it didnĀ“t work out.

As IĀ“m pretty sure there have to be better methods for what I want to achiev, IĀ“m asking for help and appreciate any suggestions on this topic.

Kind Regards!

I am not sure how to do what your are after and am too busy to take on such an exploration this week, butā€¦

If memory serves this is the third ā€˜Civil to Revitā€™ topic youā€™ve asked about in around as many days.

Not that there is a problem with asking questions about a generic process (it helps the community grow as ideas are surfaced), but something more specific about the end goals is likely going to get you better results.

Asking something along the lines of ā€œI have a surface in Civil 3D which I need to intersect with a solid geometry of a ____ in Revit with so that I can ______. How would you go about this?ā€ and providing a small sample dataset will likely be more effective at getting you where you want to be.

Here is a solution, I maybe adding another one in the future and IĀ“m interested if someone has other solutions.

Task:

Fit a concrete block (Revit generic model, grey) to a topography (Civil 3D Surface, green)

Workflow:

  • Get Surface.Triangles in Civil 3D and save in dynamo file with data.remember
  • Call the Triangles in Revit and transform to project coordinate system
  • Extrude Triangles in -z direction with Curve.ExtrudeAsSolid
  • Test for intersections between concrete block solid and Triangle solids with Geometry.DoesIntersect
  • Use Solid.DifferenceAll to remove Triangle solids from main solid
  • Remove unnecessary stuff with Solid.Separate and create DirectShape

1 Like

Things that did not work out:

Looking how other people do that i found 2 resources.

  1. Dealing withTopography in Dynamo

  2. Wall follow topography

They create polysurfaces. This did not work out for me because i could not use the polysurface for anything. I could not extrude it or use it to split my solid. The topography is so big and complex it always lead to errors because auf the direction of the faces and so on. Thats why i decided to just extrude every single triangle itself.

I could not create a FreeForm because SAT is returning Mesh geometry:

My goal was to create a nice family with a FreeForm but the solid is too complex an could not meet the criteria. Here you can read about the limitations:

Causes:
Not supported geometry - thin, circle-based, and long extrusions could not be created in Revit.

https://www.autodesk.com/support/technical/article/caas/sfdcarticles/sfdcarticles/Dynamo-node-FamilyType-ByGeometry-is-unable-to-create-family-types-in-Revit.html

Trying to create a free form directly in a family document did not work out. Dynamo and Revit Solids are not easy convertible to each other, a workaround is to export the dyn solid to SAT and import it. Unfortunately this does not work if the SAT file gets to complex. In that case it will be retrieved as a mesh and not a solid when importing it back to dynamo, and a mesh is useless for my task.

So using a DirectShape is the only thing I could get working, sadly :confused:

ItĀ“s annoying that a DirectShape will not be listed in a material takeoff as soon as it is too complex.

Python code

As the core nodes were failing or did take too long for the calculations of the 100k elements i had to use a few python nodes.

Extrude Polycurves:

import clr

clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import Vector

polycurves = IN[0]

polycurves = polycurves if isinstance(polycurves, list) else [polycurves]

vector = Vector.ByCoordinates(0, 0, 1)  # Z-direction

extruded_geometry = []

for polycurve in polycurves:
    try:
        extruded_geometry.append(polycurve.ExtrudeAsSolid(vector, -10))
    except:
        pass

OUT = extruded_geometry

Intersect Solids:

import clr

clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

def solids_intersect(solid1, solid2):
    try:
        intersection = Solid.Intersect(solid1, solid2)

        if intersection:
            return True
    except:
        pass
    return False

input_solid = IN[0]
list_of_solids = IN[1]

intersecting_solids = []

for solid in list_of_solids:
    if solids_intersect(input_solid, solid):
        intersecting_solids.append(solid)

OUT = intersecting_solids

Solid Difference:
As Solid.DifferenceAll was failing if a single element fail and Solid.Difference did take forever i built this combination. Here the solids are grouped and every group is differenced with Solid.DifferenceAll, if a group fails the elements will be differenced with Solid.Difference. You have to experiment with group size.

import Autodesk.DesignScript.Geometry as geom

def subtract_solids(main_solid, solids_to_subtract, group_size=20):

    if main_solid is None or main_solid.Volume <= 0:
        return "Invalid main solid."

    solid_groups = [solids_to_subtract[i:i+group_size] for i in range(0, len(solids_to_subtract), group_size)]
    
    for group in solid_groups:
        valid_group = [s for s in group if s is not None and s.Volume > 0]
        try:
            main_solid = geom.Solid.DifferenceAll(main_solid, valid_group)
        except Exception:
            # If DifferenceAll fails, subtract solids one by one
            for solid in valid_group:
                try:
                    main_solid = geom.Solid.Difference(main_solid, solid)
                except Exception:
                    continue
            
    return main_solid  

main_solid = IN[0]
solids_to_subtract = IN[1]

result_solid = subtract_solids(main_solid, solids_to_subtract)

OUT = result_solid

Solid.Faces was also pretty useful to modify the solid in the end.

import clr

clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import Solid

ds_solid = IN[0]

def extract_faces_from_dynamo_solid(ds_solid):
    if isinstance(ds_solid, Solid):
        faces = ds_solid.Faces
        return faces
    else:
        return "Input is not a Dynamo Solid."

OUT = extract_faces_from_dynamo_solid(ds_solid)
2 Likes