Files
SzmediTools/Szmedi.RvKits/Civil/WallFinishesViewModel.cs
2025-09-16 16:06:41 +08:00

318 lines
13 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Linq;
using System.Windows;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Nice3point.Revit.Toolkit.External.Handlers;
namespace Szmedi.RvKits.Civil;
public partial class WallFinishesViewModel : ObservableObject
{
public WallFinishesViewModel(List<WallType> wallTypes)
{
this.wallTypes = wallTypes;
wallFinishHandler = new ActionEventHandler();
}
private readonly ActionEventHandler wallFinishHandler;
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(PlaceWallCommand))]
private double wallBaseOffset;
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(PlaceWallCommand))]
private double wallHeight = 200;
[ObservableProperty]
private List<WallType> wallTypes;
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(PlaceWallCommand))]
private WallType selectedWallType;
public PlacementType PlaceType { get; set; }
private bool CanPlaceWallFinish()
{
return SelectedWallType != null && WallHeight > 0 && WallHeight > WallBaseOffset;
}
[RelayCommand(CanExecute = nameof(CanPlaceWallFinish))]
private void PlaceWall()
{
wallFinishHandler.Raise(uiapp =>
{
var uidoc = uiapp.ActiveUIDocument;
var doc = uidoc.Document;
var wallWidth = SelectedWallType.Width;
try
{
while (true)
{
switch (PlaceType)
{
case PlacementType.ByFace:
PlaceWallFinishesByFace(uidoc, SelectedWallType, wallWidth, WallHeight, WallBaseOffset);
break;
case PlacementType.ByWall:
PlaceWallFinishesByWall(uidoc, SelectedWallType, wallWidth, WallHeight, WallBaseOffset);
break;
case PlacementType.ByRoom:
var rooms = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Rooms);
if (!rooms.Any())
{
MessageBox.Show("项目中当前没有房间", "温馨提示");
//message = "项目中当前没有房间";
}
PlaceWallFinishesByRoom(uidoc, SelectedWallType, wallWidth, WallHeight, WallBaseOffset);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException) { }
});
}
private void PlaceWallFinishesByFace(UIDocument uidoc, WallType wallType, double wallWidth, double height, double baseOffset)
{
var doc = uidoc.Document;
var referFace = uidoc.Selection.PickObject(ObjectType.Face, new GenericFilter<Wall>(), "请选择布置的墙面");
var wall = doc.GetElement(referFace) as Wall;
var face = wall!.GetGeometryObjectFromReference(referFace) as Face;
var bottomFace = wall.GetGeometryObjects<Face>().FirstOrDefault(f => f.ComputeNormal(new UV()).IsAlmostEqualTo(-XYZ.BasisZ));
if (bottomFace == null)
{
return;
}
var baseLevel = doc.GetElement(wall.LevelId) as Level;
face.Intersect(bottomFace, out var intersectCurve);
doc.Invoke(
ts =>
{
var curve = intersectCurve.CreateOffset(wallWidth / 2, XYZ.BasisZ).CreateReversed();
var wallCreated = Wall.Create(doc, curve, wallType.Id, baseLevel!.Id, height / 304.8, baseOffset / 304.8, false, false);
doc.Regenerate();
try
{
if (wallCreated.WallType.Kind == WallKind.Stacked)
{
foreach (var wallId in wallCreated.GetStackedWallMemberIds())
{
var stackedWall = doc.GetElement(wallId) as Wall;
JoinGeometryUtils.JoinGeometry(doc, wall, stackedWall);
}
}
else
{
JoinGeometryUtils.JoinGeometry(doc, wall, wallCreated);
}
//JoinGeometryUtils.JoinGeometry(doc, wall, wallCreated);
}
catch (Exception ex)
{
LogAssists.WriteLog(ex.Message);
}
},
"创建墙面饰面"
);
}
private void PlaceWallFinishesByRoom(UIDocument uidoc, WallType wallType, double wallWidth, double heightOfWall, double baseOffsetOfWall)
{
var doc = uidoc.Document;
var refer = uidoc.Selection.PickObject(ObjectType.Element, new GenericFilter<Room>(), "请选择布置的房间");
var room = uidoc.Document.GetElement(refer) as Room;
var baseLevel = doc.GetElement(room!.LevelId) as Level;
List<CurveLoop> curveLoops = new();
List<ElementId> wallToJoin = new();
List<List<ElementId>> wallToJoinList = new();
var opts = new SpatialElementBoundaryOptions();
//{
// SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish
//};
//BuiltInCategory builtInCategory = (BuiltInCategory)walltype.Category.ViewId.IntegerValue;
//if (walltype.Kind == WallKind.Stacked)
//{
// var li = walltype.GetSubelements();
// walltype.get
//}
//if (walltype.Kind == WallKind.Basic)
//{
// var compounds = walltype.GetCompoundStructure();
// for (int i = 0; i < compounds.LayerCount; i++)
// {
// offest += compounds.GetWidth();
// }
//}
var segementsList = room.GetBoundarySegments(opts);
if (segementsList != null)
{
foreach (var boundarySegments in segementsList)
{
CurveLoop curveLoop = new();
foreach (var boundarySegment in boundarySegments)
{
curveLoop.Append(boundarySegment.GetCurve());
wallToJoin.Add(boundarySegment.ElementId);
}
wallToJoinList.Add(wallToJoin);
curveLoops.Add(curveLoop);
}
}
doc.Invoke(
ts =>
{
var options = ts.GetFailureHandlingOptions();
FailuresPreProcessor failuresProcessor = new();
options.SetFailuresPreprocessor(failuresProcessor);
ts.SetFailureHandlingOptions(options);
//Plane plane = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, new XYZ());
//var mc = doc.Create.NewModelCurveArray(array, SketchPlane.Create(doc, plane));
for (var i = 0; i < curveLoops.Count; i++)
{
//切线方向叉乘参数中的向量,内侧叉乘-z
var curveLoopOffset = CurveLoop.CreateViaOffset(curveLoops[i], wallWidth / 2, -XYZ.BasisZ);
for (var j = 0; j < curveLoopOffset.Count(); j++)
{
var curve = curveLoopOffset.ElementAt(j);
////c的方向叉乘参数中的向量内侧叉乘-z
//var lc = c.CreateOffset(100 / 304.8, -XYZ.BasisZ);
//var x = curve.ComputeDerivatives(0.5, true).BasisX.CrossProduct(-XYZ.BasisZ).Normalize() * 100 / 304.8;
//var mc = doc.Create.NewModelCurve(lc, SketchPlane.Create(doc, plane));
//var mc = doc.Create.NewModelCurve(c, SketchPlane.Create(doc, plane));
var wallCreated = Wall.Create(
doc,
curve,
wallType.Id,
baseLevel.Id,
heightOfWall / 304.8,
baseOffsetOfWall / 304.8,
false,
false
);
wallCreated.get_Parameter(BuiltInParameter.WALL_ATTR_ROOM_BOUNDING).Set(1);
doc.Regenerate();
//连接墙体让门窗可以剪切出来
if (wallToJoinList[i][j].IntegerValue > 0)
{
var elemToJoin = doc.GetElement(wallToJoinList[i][j]);
try
{
if (wallCreated.WallType.Kind == WallKind.Stacked)
{
foreach (var wallid in wallCreated.GetStackedWallMemberIds())
{
var stackedWall = doc.GetElement(wallid) as Wall;
JoinGeometryUtils.JoinGeometry(doc, elemToJoin, stackedWall);
}
}
else
{
JoinGeometryUtils.JoinGeometry(doc, elemToJoin, wallCreated);
}
}
catch (Exception ex)
{
LogAssists.WriteLog(ex.Message);
}
}
//WallUtils.AllowWallJoinAtEnd(w, 0);
//offsetCurves.Add(lc);
}
}
},
"创建房间墙饰面"
);
}
private void PlaceWallFinishesByWall(UIDocument uidoc, WallType wallType, double wallWidth, double heightOfWall, double baseOffsetOfWall)
{
var doc = uidoc.Document;
var refer = uidoc.Selection.PickObject(ObjectType.Element, new GenericFilter<Wall>(), "请选择布置的墙体");
var wall = uidoc.Document.GetElement(refer) as Wall;
var baseLevel = doc.GetElement(wall.LevelId) as Level;
var bottomFace = wall.GetGeometryObjects<Face>().FirstOrDefault(f => f.ComputeNormal(new UV()).IsAlmostEqualTo(-XYZ.BasisZ));
var sideFaces = wall.GetGeometryObjects<Face>().Where(f => f.ComputeNormal(new UV()).DotProduct(XYZ.BasisZ) < 1.0e-09);
//CurveLoop loop = new CurveLoop();
List<Curve> curs = new();
foreach (var sideFace in sideFaces)
{
bottomFace.Intersect(sideFace, out var intersectCurve);
curs.Add(intersectCurve);
//ModelCurve ml = doc.Create.NewModelCurve(cur, doc.ActiveView.SketchPlane);
//loop.Append(cur);
}
//var loop = CurveLoop.Create(curs);
//var offestcurveloop = CurveLoop.CreateViaOffset(loop, wallwidth / 2, XYZ.BasisZ);
doc.Invoke(
ts =>
{
for (var i = 0; i < curs.Count; i++)
{
var curve = curs.ElementAt(i).CreateOffset(wallWidth / 2, -XYZ.BasisZ);
var wallCreated = Wall.Create(
doc,
curve,
wallType.Id,
baseLevel.Id,
heightOfWall / 304.8,
baseOffsetOfWall / 304.8,
false,
false
);
doc.Regenerate();
try
{
if (wallCreated.WallType.Kind == WallKind.Stacked)
{
foreach (var wallId in wallCreated.GetStackedWallMemberIds())
{
var stackedWall = doc.GetElement(wallId) as Wall;
JoinGeometryUtils.JoinGeometry(doc, wall, stackedWall);
}
}
else
{
JoinGeometryUtils.JoinGeometry(doc, wall, wallCreated);
}
//JoinGeometryUtils.JoinGeometry(doc, wall, wallCreated);
}
catch (Exception ex)
{
LogAssists.WriteLog(ex.Message);
}
//WallUtils.AllowWallJoinAtEnd(w, 0);
}
},
"创建墙体饰面"
);
}
}