using System.Windows; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Architecture; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Nice3point.Revit.Toolkit.External.Handlers; using ShrlAlgo.Toolkit.Core.Assist; using ShrlAlgoToolkit.Core.Assist; namespace ShrlAlgo.RvKits.RvCivil; public partial class WallFinishesViewModel(List wallTypes) : ObservableObject { private readonly ActionEventHandler wallFinishHandler = new (); [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(PlaceWallCommand))] private double wallBaseOffset; [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(PlaceWallCommand))] private double wallHeight; [ObservableProperty] private List wallTypes = 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: /* 项目“ShrlAlgoToolkit.RevitAddins (net48)”的未合并的更改 在此之前: PlaceWallFinishesByFace(uiapp, SelectedWallType, wallWidth, WallHeight, WallBaseOffset); break; 在此之后: PlaceWallFinishesByFace(uiapp, SelectedWallType, wallWidth, WallHeight, WallBaseOffset); break; */ WallFinishesViewModel.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: break; } } } catch (Autodesk.Revit.Exceptions.OperationCanceledException) { } }); } private static 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(), "请选择布置的墙面"); var wall = doc.GetElement(referFace) as Wall; var face = wall.GetGeometryObjectFromReference(referFace) as Face; var bottomFace = wall.GetAllGeometryObjects().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) { LogHelper.ToLog(ex.Message); } }, "创建墙面饰面" ); } private static void PlaceWallFinishesByRoom(UIDocument uidoc, WallType wallType, double wallWidth, double wallHeight, double wallBaseOffset) { var doc = uidoc.Document; var refer = uidoc.Selection.PickObject(ObjectType.Element, new GenericFilter(), "请选择布置的房间"); var room = uidoc.Document.GetElement(refer) as Room; var baseLevel = doc.GetElement(room.LevelId) as Level; List curveLoops =[]; List walltojoin = []; List> wallToJoinList = []; 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, wallHeight / 304.8, wallBaseOffset / 304.8, false, false ); wallCreated.get_Parameter(BuiltInParameter.WALL_ATTR_ROOM_BOUNDING).Set(1); doc.Regenerate(); //连接墙体让门窗可以剪切出来 #if REVIT2018 || REVIT2020 if (wallToJoinList[i][j].IntegerValue > 0) #elif REVIT2025 if (wallToJoinList[i][j].Value > 0) #endif { 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) { LogHelper.ToLog(ex.Message); } } //WallUtils.AllowWallJoinAtEnd(w, 0); //offsetCurves.Add(lc); } } }, "创建房间墙饰面" ); } private static void PlaceWallFinishesByWall(UIDocument uidoc, WallType wallType, double wallWidth, double wallHeight, double wallBaseOffset) { var doc = uidoc.Document; var refer = uidoc.Selection.PickObject(ObjectType.Element, new GenericFilter(), "请选择布置的墙体"); var wall = uidoc.Document.GetElement(refer) as Wall; var baselevel = doc.GetElement(wall.LevelId) as Level; var bottomFace = wall.GetAllGeometryObjects().FirstOrDefault(f => f.ComputeNormal(new UV()).IsAlmostEqualTo(-XYZ.BasisZ)); var sideFaces = wall.GetAllGeometryObjects().Where(f => f.ComputeNormal(new UV()).DotProduct(XYZ.BasisZ) < 1.0e-09); //CurveLoop loop = new CurveLoop(); List curs = []; 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, wallHeight / 304.8, wallBaseOffset / 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) { LogHelper.ToLog(ex.Message); } //WallUtils.AllowWallJoinAtEnd(w, 0); //offestcurves.Add(lc); } }, "创建墙体饰面" ); } }