How to know if an element penetrates a wall.

How to know if an element penetrates a wall.

qoreodlf37
Enthusiast Enthusiast
522 Views
5 Replies
Message 1 of 6

How to know if an element penetrates a wall.

qoreodlf37
Enthusiast
Enthusiast

Hi, I want to know if an element penetrates a wall.

qoreodlf37_0-1721116053147.png

I have tried to wall's two faces(front, back) and determin both face intersect with element solid's faces.

But result always both intersect.

bool bothFaceIntersect = false;


foreach (PlanarFace face in wallFaceList)// wall's front, back faces
{
    bool isIntersect = false;
    foreach (Face solidFace in _elementSolid.Faces)
    {
        FaceIntersectionFaceResult result = face.Intersect(solidFace);
        if (result != null && result == FaceIntersectionFaceResult.Intersecting) isIntersect = true;
    }

    if (!isIntersect)
    {
        bothFaceIntersect = false;
        break;
    }
    else bothFaceIntersect = true;
}
0 Likes
523 Views
5 Replies
Replies (5)
Message 2 of 6

Mohamed_Arshad
Advisor
Advisor

Hi @qoreodlf37 

 

    I don't know what method you have followed to get the Wall's faces, I have created a geometry algorithm for this problem, Kindly follow the below steps.

 

Steps Involved

1. Get only Exterior and Interior faces using HostObjectUtils Class .

2. Get Center Curve for the Element using Bounding Box or Location Curve or using Total Transformation create own.

3. Check whether the face intersects with the curve.

 

Code Snippet

 

Wall wall = (Wall)doc.GetElement(new ElementId(308867));
Element element1 = doc.GetElement(new ElementId(309045)); //Duct Element

//Get Front and back Face
Reference extRef = HostObjectUtils.GetSideFaces(wall, ShellLayerType.Exterior).First();
Reference intRef = HostObjectUtils.GetSideFaces(wall, ShellLayerType.Interior).First();

PlanarFace extFace = (PlanarFace)doc.GetElement(extRef).GetGeometryObjectFromReference(extRef);
PlanarFace intFace = (PlanarFace)doc.GetElement(intRef).GetGeometryObjectFromReference(intRef);

///Get Element Center Line
Curve cur1 = (element1.Location as LocationCurve).Curve;

///Get Intersection Result
///Center Line Hitting in both faces ?
if (extFace.Intersect(cur1) == SetComparisonResult.Overlap && intFace.Intersect(cur1) == SetComparisonResult.Overlap)
{
    TaskDialog.Show("Information", "Element Penetrate into the Wall");
}
else
{
    TaskDialog.Show("Information", "Element does not Penetrate into the Wall");
}

 

 

Reference GIF

Wall Element Intersection.gif

 

Hope this will Helps 🙂


Mohamed Arshad K
Software Developer (CAD & BIM)

Message 3 of 6

qoreodlf37
Enthusiast
Enthusiast

Thank you!

I tried your code, but face.Intersect(curve) always return 'Disjoint' for me.

I used face.Intersect(curve) method in my other project, then it return same things.. so I used other method.

 

So I solve this problem with this code.

double tolerance = 1e-9;

Reference extRef = HostObjectUtils.GetSideFaces(_createWall, ShellLayerType.Exterior).First();
Reference intRef = HostObjectUtils.GetSideFaces(_createWall, ShellLayerType.Interior).First();

PlanarFace extFace = (PlanarFace)_document.GetElement(extRef).GetGeometryObjectFromReference(extRef);
PlanarFace intFace = (PlanarFace)_document.GetElement(intRef).GetGeometryObjectFromReference(intRef);

Solid faceSolid1 = GeometryCreationUtilities.CreateExtrusionGeometry(extFace.GetEdgesAsCurveLoops(), extFace.FaceNormal, 0.001);
Solid oppositeFaceSolid1 = GeometryCreationUtilities.CreateExtrusionGeometry(extFace.GetEdgesAsCurveLoops(), -extFace.FaceNormal, 0.001);

Solid interSolid1 = BooleanOperationsUtils.ExecuteBooleanOperation(faceSolid1, _elementSolid, BooleanOperationsType.Intersect);
Solid oppositeInterSolid1 = BooleanOperationsUtils.ExecuteBooleanOperation(oppositeFaceSolid1, _elementSolid, BooleanOperationsType.Intersect);

Solid faceSolid2 = GeometryCreationUtilities.CreateExtrusionGeometry(intFace.GetEdgesAsCurveLoops(), intFace.FaceNormal, 0.001);
Solid oppositeFaceSolid2 = GeometryCreationUtilities.CreateExtrusionGeometry(intFace.GetEdgesAsCurveLoops(), -intFace.FaceNormal, 0.001);

Solid interSolid2 = BooleanOperationsUtils.ExecuteBooleanOperation(faceSolid2, _elementSolid, BooleanOperationsType.Intersect);
Solid oppositeInterSolid2 = BooleanOperationsUtils.ExecuteBooleanOperation(oppositeFaceSolid2, _elementSolid, BooleanOperationsType.Intersect);

bool extIntersect = interSolid1.Volume >= tolerance || oppositeInterSolid1.Volume >= tolerance;
bool intIntersect = interSolid2.Volume >= tolerance || oppositeInterSolid2.Volume >= tolerance;
Message 4 of 6

Mohamed_Arshad
Advisor
Advisor

HI @qoreodlf37 

 

   For which element you're trying to find the intersection ?


Mohamed Arshad K
Software Developer (CAD & BIM)

0 Likes
Message 5 of 6

qoreodlf37
Enthusiast
Enthusiast

a beam element from linked rvt file.

0 Likes
Message 6 of 6

cwaluga
Advocate
Advocate

Did you take the (possible) transformation of the link instance into account? Also, the Face.Intersect(face) is not implemented the way you probably think. It is rather a much too simplistic method which may or may not return correct results. At least Autodesk documented this in 2020 without fixing the actual issue. There is no good and performant replacement, which is why I always try to find ways around intersecting faces in the Revit API.

 

https://www.revitapidocs.com/2024/91f650a2-bb95-650b-7c00-d431fa613753.htm

 
This is not a general-purpose function: it only works properly for simple configurations. For other configurations, it may return an incorrect result. Some configurations for which the function might return a correct result are:
  • A planar face that fully intersects another face in a single curve, when the other face is planar or cylindrical.
  • A cylindrical face that fully intersects another face in a single curve, when the other face is planar.
0 Likes