Files
Shrlalgo.RvKits/ShrlAlgoToolkit.RevitAddins/ArchStru/WallFinishesViewModel.cs
2026-02-22 20:03:42 +08:00

312 lines
10 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.Windows;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI.Selection;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Nice3point.Revit.Toolkit.External.Handlers;
namespace ShrlAlgoToolkit.RevitAddins.RvCivil;
public partial class WallFinishesViewModel(List<WallType> wallTypes) : ObservableObject
{
private readonly ActionEventHandler wallFinishHandler = new ();
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(RevitAddins.RvCivil.WallFinishesViewModel.PlaceWallCommand))]
public partial double WallBaseOffset { get; set; }
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(RevitAddins.RvCivil.WallFinishesViewModel.PlaceWallCommand))]
private double wallHeight;
[ObservableProperty]
public partial List<WallType> WallTypes { get; set; } = wallTypes;
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(RevitAddins.RvCivil.WallFinishesViewModel.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<Wall>(), "请选择布置的墙面");
var wall = doc.GetElement(referFace) as Wall;
var face = wall.GetGeometryObjectFromReference(referFace) as Face;
var bottomFace = wall.GetAllGeometryObjects<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(
_ =>
{
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)
{
Common.Assists.LogAssist.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<Room>(), "请选择布置的房间");
var room = uidoc.Document.GetElement(refer) as Room;
var baseLevel = doc.GetElement(room.LevelId) as Level;
List<CurveLoop> curveLoops =[];
List<ElementId> walltojoin = [];
List<List<ElementId>> 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)
{
Common.Assists.LogAssist.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<Wall>(), "请选择布置的墙体");
var wall = uidoc.Document.GetElement(refer) as Wall;
var baselevel = doc.GetElement(wall.LevelId) as Level;
var bottomFace = wall.GetAllGeometryObjects<Face>().FirstOrDefault(f => f.ComputeNormal(new UV()).IsAlmostEqualTo(-XYZ.BasisZ));
var sideFaces = wall.GetAllGeometryObjects<Face>().Where(f => f.ComputeNormal(new UV()).DotProduct(XYZ.BasisZ) < 1.0e-09);
//CurveLoop loop = new CurveLoop();
List<Curve> 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(
_ =>
{
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)
{
Common.Assists.LogAssist.ToLog(ex.Message);
}
//WallUtils.AllowWallJoinAtEnd(w, 0);
//offestcurves.Add(lc);
}
},
"创建墙体饰面"
);
}
}