Files

312 lines
10 KiB
C#
Raw Permalink Normal View History

2024-09-22 11:05:41 +08:00
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;
2025-04-24 20:56:44 +08:00
namespace ShrlAlgoToolkit.RevitAddins.RvCivil;
2024-09-22 11:05:41 +08:00
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; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
2025-04-24 20:56:44 +08:00
[NotifyCanExecuteChangedFor(nameof(RevitAddins.RvCivil.WallFinishesViewModel.PlaceWallCommand))]
2024-09-22 11:05:41 +08:00
private double wallHeight;
[ObservableProperty]
public partial List<WallType> WallTypes { get; set; } = wallTypes;
2024-09-22 11:05:41 +08:00
[ObservableProperty]
2025-04-24 20:56:44 +08:00
[NotifyCanExecuteChangedFor(nameof(RevitAddins.RvCivil.WallFinishesViewModel.PlaceWallCommand))]
2024-09-22 11:05:41 +08:00
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:
2025-04-24 20:56:10 +08:00
/* ShrlAlgoToolkit.RevitAddins (net48)
2024-09-22 11:05:41 +08:00
:
2024-12-22 10:26:12 +08:00
PlaceWallFinishesByFace(uiapp, SelectedWallType, wallWidth, WallHeight, WallBaseOffset);
2024-09-22 11:05:41 +08:00
break;
:
2024-12-22 10:26:12 +08:00
PlaceWallFinishesByFace(uiapp, SelectedWallType, wallWidth, WallHeight, WallBaseOffset);
2024-09-22 11:05:41 +08:00
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(
_ =>
2024-09-22 11:05:41 +08:00
{
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)
{
2026-02-21 16:31:24 +08:00
Common.Assists.LogAssist.ToLog(ex.Message);
2024-09-22 11:05:41 +08:00
}
},
"创建墙面饰面"
);
}
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)
{
2026-02-21 16:31:24 +08:00
Common.Assists.LogAssist.ToLog(ex.Message);
2024-09-22 11:05:41 +08:00
}
}
//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(
_ =>
2024-09-22 11:05:41 +08:00
{
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)
{
2026-02-21 16:31:24 +08:00
Common.Assists.LogAssist.ToLog(ex.Message);
2024-09-22 11:05:41 +08:00
}
//WallUtils.AllowWallJoinAtEnd(w, 0);
//offestcurves.Add(lc);
}
},
"创建墙体饰面"
);
}
}