Get a Solid of Door or Window opening in Wall
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
How to get a Solid of Door or Window Opening inserted in Wall ?
From the <orange wall> we need to get the <green volume> obtained as a result of installing the <blue door>
I wrote a code restoring the geometry of the wall to subtract the current geometry with holes from it. If there is a Sketch in the wall, then I get an extrusion through the profile, orientation and thickness of the wall. If SketchId = -1, then through the upper and lower surface of the wall. This code works well, and handles all cases at the moment. I have a suspicion that this will not always be the case. Is there a way to get a similar Solid collection with binding to Doors and Windows, but having a simpler and more reliable implementation? After all, we see a cut-out cavity on the screen, how can we get it easier? The option of editing the families of doors and windows with the addition of extrusion inside them disappears, because they are in a linked file, which is also updated frequently (we get a new architecture file from a third-party organization several times a week)
public static Dictionary<Element, Solid> GetGeometry(Document Doc)
{
List<Element> listHosted = new List<Element>();
listHosted.AddRange(new FilteredElementCollector(Doc).OfCategory(BuiltInCategory.OST_Doors).WhereElementIsNotElementType());
listHosted.AddRange(new FilteredElementCollector(Doc).OfCategory(BuiltInCategory.OST_Windows).WhereElementIsNotElementType());
List<Solid> listSolid = new List<Solid>();
foreach (Wall wall in new FilteredElementCollector(Doc).OfClass(typeof(Wall)).WhereElementIsNotElementType())
{
foreach (GeometryObject gObj in wall.get_Geometry(new Options()))
{
Solid sldObj = gObj as Solid;
if (sldObj != null && sldObj.Volume > 0)
{
PlanarFace pFaceUp = null;
PlanarFace pFaceDown = null;
foreach (Face fc in sldObj.Faces)
{
PlanarFace pFc = (PlanarFace)fc;
if (pFc.FaceNormal.IsAlmostEqualTo(new XYZ(0, 0, 1)))
{
if (pFaceUp == null)
pFaceUp = pFc;
else if (pFaceUp.Origin.Z < pFc.Origin.Z)
pFaceUp = pFc;
}
else if (pFc.FaceNormal.IsAlmostEqualTo(new XYZ(0, 0, -1)))
{
if (pFaceDown == null)
pFaceDown = pFc;
else if (pFaceDown.Origin.Z > pFc.Origin.Z)
pFaceDown = pFc;
}
}
if (pFaceUp != null && pFaceDown != null)
{
CurveLoop curveLoop;
XYZ dir;
double dist;
if (wall.SketchId.IntegerValue == -1)
{
curveLoop = pFaceUp.GetEdgesAsCurveLoops()[0];
XYZ pProj = G.Project(pFaceUp.Origin, pFaceDown.Origin, pFaceDown.FaceNormal);
dir = (pProj - pFaceUp.Origin).Normalize();
dist = pFaceUp.Origin.DistanceTo(pProj);
}
else
{
Sketch sketch = (Sketch)Doc.GetElement(wall.SketchId);
dir = wall.Orientation;
dist = wall.Width;
Transform tran = Transform.CreateTranslation(dir.Negate() * (dist / 2));
List<Line> listLine = new List<Line>();
foreach (Curve curve in sketch.Profile.get_Item(0))
listLine.Add(Line.CreateBound(tran.OfPoint(curve.GetEndPoint(0)), tran.OfPoint(curve.GetEndPoint(1))));
curveLoop = new CurveLoop();
foreach (Line line in listLine)
curveLoop.Append(line);
}
if (curveLoop == null || curveLoop.IsOpen() || dir == null || dist < 0)
continue;
Solid sldExtrus = GeometryCreationUtilities.CreateExtrusionGeometry(new CurveLoop[] { curveLoop }, dir, dist);
if (sldExtrus != null && sldExtrus.Volume > 0)
{
Solid sldDif = BooleanOperationsUtils.ExecuteBooleanOperation(sldExtrus, sldObj, BooleanOperationsType.Difference);
if (sldDif != null && sldDif.Volume > 0)
listSolid.AddRange(SolidUtils.SplitVolumes(sldDif));
}
}
}
}
}
Dictionary<Element, Solid> dictElemSolid = new Dictionary<Element, Solid>();
foreach (Element elem in listHosted)
{
Location loc = elem.Location;
if (loc == null)
continue;
XYZ pElem = ((LocationPoint)loc).Point;
Solid sldNear = null;
double distLast = -1;
foreach (Solid sld in listSolid)
{
double dist = pElem.DistanceTo(sld.ComputeCentroid());
if (distLast == -1)
distLast = dist;
else if (dist <= distLast && dist < 10)
{
distLast = dist;
sldNear = sld;
}
}
// G.ShapeBySolid(Doc, sldNear);
dictElemSolid.Add(elem, sldNear);
}
return dictElemSolid;
}