Hi All,
I am trying to break a selected wall at every intersection on it. For this, the logic I have is to copy the actual wall as many times as the number of intersections and reassign the location curves to connect two consecutive intersections. If anyone has a better logic, please advise.
It is working fine except for two issues.
1. The walls after spliting are not joined correctly
2. The doors on the wall id getting deleted. This is happenning because when we adjust the location curve, the door goes outside the wall. Thats Ok, but there should be a copy of the same door on every copied wall. So, atleast one should remain on that segment of the wall. That however, is not happenning.
Note: I have an extension method to copy the wall, which has the CopyElement method is called.
Here is that SplitWall method;
public static List<ElementId> SplitWall(Wall wall)
{
Document doc = wall.Document;
List<ElementId> copiedWalls = new List<ElementId>();
// Get all intersection points
List<XYZ> intersectionPoints = GetWallsIntersectionPoints(wall)
.OrderBy(p => wall.StartPoint().DistanceTo(p))
.ToList();
intersectionPoints.Add(
new XYZ(
wall.EndPoint().X,
wall.EndPoint().Y,
wall.EndPoint().Z
)
);
if (intersectionPoints.Count > 0)
{
using (Transaction trans = new Transaction(doc, "Modify Wall"))
{
trans.Start();
// Modify the given wall to start from its start point and end at the first intersection point
LocationCurve wallCurve = wall.Location as LocationCurve;
if (wallCurve != null)
{
//WallUtils.DisallowWallJoinAtEnd(wall, 0);
//WallUtils.DisallowWallJoinAtEnd(wall, 1);
wallCurve.Curve = Line.CreateBound(wallCurve.Curve.GetEndPoint(0), intersectionPoints[0]);
}
Wall wallForCopy = wall.Copy(doc) as Wall;
XYZ lastPoint = intersectionPoints[0];
List<Wall> newWalls = new List<Wall>() { wall};
for (int i = 1; i < intersectionPoints.Count; i++)
{
if (lastPoint.IsAlmostEqualTo(intersectionPoints[i]) == false)
{
Wall currentWall = wallForCopy.Copy(doc) as Wall;
newWalls.Add(currentWall);
LocationCurve wc = currentWall.Location as LocationCurve;
WallUtils.DisallowWallJoinAtEnd(currentWall, 0);
WallUtils.DisallowWallJoinAtEnd(currentWall, 1);
wc.Curve = Line.CreateBound(lastPoint, intersectionPoints[i]);
lastPoint = intersectionPoints[i];
}
}
foreach (var w in newWalls)
{
WallUtils.AllowWallJoinAtEnd(w, 1);
WallUtils.AllowWallJoinAtEnd(w, 0);
}
doc.Delete(wallForCopy.Id);
trans.Commit();
}
}
return copiedWalls;
}
Here is how I get all the intersection points;
private static List<XYZ> GetWallsIntersectionPoints(Wall wall)
{
Document doc = wall.Document;
List<XYZ> intersectingPoints = new List<XYZ>();
LocationCurve wallCurve = wall.Location as LocationCurve;
Options options = new Options();
options.ComputeReferences = true;
options.IncludeNonVisibleObjects = true;
GeometryElement wallGeometry = wall.get_Geometry(options);
foreach (GeometryObject geomObj in wallGeometry)
{
Solid solid = geomObj as Solid;
if (solid != null)
{
FilteredElementCollector intersectingWallsCollector = new FilteredElementCollector(doc)
.OfClass(typeof(Wall))
.WherePasses(new ElementIntersectsSolidFilter(solid));
foreach (Wall intersectingWall in intersectingWallsCollector)
{
if (intersectingWall.Id != wall.Id)
{
LocationCurve intersectingWallCurve = intersectingWall.Location as LocationCurve;
if (intersectingWallCurve != null)
{
SetComparisonResult result = wallCurve.Curve.Intersect(intersectingWallCurve.Curve, out IntersectionResultArray intersectionResults);
if (result == SetComparisonResult.Overlap)
{
foreach (IntersectionResult intersectionResult in intersectionResults)
{
XYZ p = intersectionResult.XYZPoint;
if (
p.IsAlmostEqualTo(wall.StartPoint()) ||
p.IsAlmostEqualTo(wall.EndPoint())
)
{
continue;
}
intersectingPoints.Add(p);
}
}
}
}
}
}
}
return intersectingPoints;
}
Kindle see the images attached. How to fix this...?
Hi All,
I am trying to break a selected wall at every intersection on it. For this, the logic I have is to copy the actual wall as many times as the number of intersections and reassign the location curves to connect two consecutive intersections. If anyone has a better logic, please advise.
It is working fine except for two issues.
1. The walls after spliting are not joined correctly
2. The doors on the wall id getting deleted. This is happenning because when we adjust the location curve, the door goes outside the wall. Thats Ok, but there should be a copy of the same door on every copied wall. So, atleast one should remain on that segment of the wall. That however, is not happenning.
Note: I have an extension method to copy the wall, which has the CopyElement method is called.
Here is that SplitWall method;
public static List<ElementId> SplitWall(Wall wall)
{
Document doc = wall.Document;
List<ElementId> copiedWalls = new List<ElementId>();
// Get all intersection points
List<XYZ> intersectionPoints = GetWallsIntersectionPoints(wall)
.OrderBy(p => wall.StartPoint().DistanceTo(p))
.ToList();
intersectionPoints.Add(
new XYZ(
wall.EndPoint().X,
wall.EndPoint().Y,
wall.EndPoint().Z
)
);
if (intersectionPoints.Count > 0)
{
using (Transaction trans = new Transaction(doc, "Modify Wall"))
{
trans.Start();
// Modify the given wall to start from its start point and end at the first intersection point
LocationCurve wallCurve = wall.Location as LocationCurve;
if (wallCurve != null)
{
//WallUtils.DisallowWallJoinAtEnd(wall, 0);
//WallUtils.DisallowWallJoinAtEnd(wall, 1);
wallCurve.Curve = Line.CreateBound(wallCurve.Curve.GetEndPoint(0), intersectionPoints[0]);
}
Wall wallForCopy = wall.Copy(doc) as Wall;
XYZ lastPoint = intersectionPoints[0];
List<Wall> newWalls = new List<Wall>() { wall};
for (int i = 1; i < intersectionPoints.Count; i++)
{
if (lastPoint.IsAlmostEqualTo(intersectionPoints[i]) == false)
{
Wall currentWall = wallForCopy.Copy(doc) as Wall;
newWalls.Add(currentWall);
LocationCurve wc = currentWall.Location as LocationCurve;
WallUtils.DisallowWallJoinAtEnd(currentWall, 0);
WallUtils.DisallowWallJoinAtEnd(currentWall, 1);
wc.Curve = Line.CreateBound(lastPoint, intersectionPoints[i]);
lastPoint = intersectionPoints[i];
}
}
foreach (var w in newWalls)
{
WallUtils.AllowWallJoinAtEnd(w, 1);
WallUtils.AllowWallJoinAtEnd(w, 0);
}
doc.Delete(wallForCopy.Id);
trans.Commit();
}
}
return copiedWalls;
}
Here is how I get all the intersection points;
private static List<XYZ> GetWallsIntersectionPoints(Wall wall)
{
Document doc = wall.Document;
List<XYZ> intersectingPoints = new List<XYZ>();
LocationCurve wallCurve = wall.Location as LocationCurve;
Options options = new Options();
options.ComputeReferences = true;
options.IncludeNonVisibleObjects = true;
GeometryElement wallGeometry = wall.get_Geometry(options);
foreach (GeometryObject geomObj in wallGeometry)
{
Solid solid = geomObj as Solid;
if (solid != null)
{
FilteredElementCollector intersectingWallsCollector = new FilteredElementCollector(doc)
.OfClass(typeof(Wall))
.WherePasses(new ElementIntersectsSolidFilter(solid));
foreach (Wall intersectingWall in intersectingWallsCollector)
{
if (intersectingWall.Id != wall.Id)
{
LocationCurve intersectingWallCurve = intersectingWall.Location as LocationCurve;
if (intersectingWallCurve != null)
{
SetComparisonResult result = wallCurve.Curve.Intersect(intersectingWallCurve.Curve, out IntersectionResultArray intersectionResults);
if (result == SetComparisonResult.Overlap)
{
foreach (IntersectionResult intersectionResult in intersectionResults)
{
XYZ p = intersectionResult.XYZPoint;
if (
p.IsAlmostEqualTo(wall.StartPoint()) ||
p.IsAlmostEqualTo(wall.EndPoint())
)
{
continue;
}
intersectingPoints.Add(p);
}
}
}
}
}
}
}
return intersectingPoints;
}
Kindle see the images attached. How to fix this...?
I did something similar in the past, and this is how I did it:
1. Saving the joining status at both end points for all collided walls and disable them via LocationCurve class.
2. Determine intersection point to create wall segment, which you did fine, also.
3. Set the joining status back to those wall. This should solve about 80% of the cases, but the difficult cases when the regarding drawing direction, minimum length or room boundary can be tricky and still remains.
4. Determine which door still belongs to the original wall, which I assume you had modified to make it the first segment, and which door doesn't. Calculate the location point of the later ones and create similar door with their new hosts, which are the new segment they belong to. Otherwise, those doors will be outside of their host and you will receive the mentioned error.
Keep in mind that this is what I did with Revit 2019, there might be other or even better way to do it. Hope this helps in some ways.
I did something similar in the past, and this is how I did it:
1. Saving the joining status at both end points for all collided walls and disable them via LocationCurve class.
2. Determine intersection point to create wall segment, which you did fine, also.
3. Set the joining status back to those wall. This should solve about 80% of the cases, but the difficult cases when the regarding drawing direction, minimum length or room boundary can be tricky and still remains.
4. Determine which door still belongs to the original wall, which I assume you had modified to make it the first segment, and which door doesn't. Calculate the location point of the later ones and create similar door with their new hosts, which are the new segment they belong to. Otherwise, those doors will be outside of their host and you will receive the mentioned error.
Keep in mind that this is what I did with Revit 2019, there might be other or even better way to do it. Hope this helps in some ways.
Can't find what you're looking for? Ask the community or share your knowledge.