314 lines
9.8 KiB
C#
314 lines
9.8 KiB
C#
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 Sai.Toolkit.Revit.Helpers;
|
||
|
||
namespace Sai.RvKits.RvCivil;
|
||
|
||
public partial class WallFinishesViewModel(List<WallType> wallTypes) : ObservableObject
|
||
{
|
||
private readonly ActionEventHandler wallFinishHandler = new ();
|
||
|
||
[ObservableProperty]
|
||
[NotifyCanExecuteChangedFor(nameof(PlaceWallCommand))]
|
||
private double wallBaseOffset;
|
||
|
||
[ObservableProperty]
|
||
[NotifyCanExecuteChangedFor(nameof(PlaceWallCommand))]
|
||
private double wallHeight;
|
||
|
||
[ObservableProperty]
|
||
private List<WallType> 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:
|
||
|
||
/* 项目“Sai.RvKits (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(
|
||
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<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)
|
||
{
|
||
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<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(
|
||
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);
|
||
}
|
||
},
|
||
"创建墙体饰面"
|
||
);
|
||
}
|
||
}
|