public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
var uiapp = commandData.Application;
var uidoc = uiapp.ActiveUIDocument;
var doc = uidoc.Document;
var selectedWalls = uidoc
.Selection
.GetElementIds()
.Select(doc.GetElement)
.OfType<Wall>()
.ToList();
if (selectedWalls.Count != 2)
{
message = "Необходимо выбрать 2 стены";
return Result.Failed;
}
var intersectionPoint = GetWallsIntersectionPoint(selectedWalls[0], selectedWalls[1]);
if (intersectionPoint == null)
{
message = "Не найдена точка пересечения стен";
return Result.Failed;
}
using (var transaction = new Transaction(doc, "trim or extend walls"))
{
transaction.Start();
if (selectedWalls.Any(selectedWall => !TrimOrExtendWallToPoint(selectedWall, intersectionPoint)))
{
message = "Ожидается, что стены прямые";
return Result.Failed;
}
transaction.Commit();
}
// проверим на всякий случай, что Revit эти стенки объединил
var wallLocationCurve = ((LocationCurve) selectedWalls[0].Location);
var wallJoinsIds = wallLocationCurve
.get_ElementsAtJoin(0).OfType<Element>()
.Union(wallLocationCurve.get_ElementsAtJoin(1).OfType<Element>())
.Select(x => x.Id)
.ToList();
var areSelectedWallJoined = selectedWalls
.Select(x => wallJoinsIds.Contains(x.Id))
.Aggregate(true, (result, elem) => result && elem);
if (!areSelectedWallJoined)
{
message = "Стенки не объединены!";
return Result.Failed;
}
return Result.Succeeded;
}
private XYZ GetWallsIntersectionPoint(Wall firstWall, Wall secondWall)
{
var firstCurve = ((LocationCurve) firstWall.Location).Curve.Clone();
firstCurve.MakeUnbound();
var secondCurve = ((LocationCurve)secondWall.Location).Curve.Clone();
secondCurve.MakeUnbound();
IntersectionResultArray intersectionResults;
if (firstCurve.Intersect(secondCurve, out intersectionResults) != SetComparisonResult.Overlap)
return null;
return intersectionResults.get_Item(0).XYZPoint;
}
private bool TrimOrExtendWallToPoint(Wall wall, XYZ point)
{
var wallLocationCurve = (LocationCurve) wall.Location;
var wallLine = wallLocationCurve.Curve as Line;
if (wallLine == null)
return false;
var wallStart = (wallLine.GetEndPoint(0) - point).GetLength() >
(wallLine.GetEndPoint(1) - point).GetLength()
? wallLine.GetEndPoint(0)
: wallLine.GetEndPoint(1);
var newWallLine = Line.CreateBound(wallStart, point);
wallLocationCurve.Curve = newWallLine;
return true;
}