using System.ComponentModel.DataAnnotations; 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 BricksFinishesViewModel : ObservableValidator { public BricksFinishesViewModel() { //ErrorsChanged += BricksFinishesViewModel_ErrorsChanged; finishesHandler = new ActionEventHandler(); PavementLength = 600; PavementWidth = 600; PavementGap = 2; WallBaseOffset = 0; PavementThickness = 2; PanelName = "铺砖"; } //~BricksFinishesViewModel() //{ // ErrorsChanged -= BricksFinishesViewModel_ErrorsChanged; //} //private void BricksFinishesViewModel_ErrorsChanged(object sender, System.ComponentModel.DataErrorsChangedEventArgs e) //{ // MessageBox.Show(GetErrors().FirstOrDefault().ErrorMessage, "错误", MessageBoxButton.OK, MessageBoxImage.Error); //} private readonly ActionEventHandler finishesHandler; [ObservableProperty] public partial bool ByRoom { get; set; } //边界限具有缝隙 [ObservableProperty] public partial bool IsEdgeExistGap { get; set; } [Required(ErrorMessage = "不可为空")] [Attributes.IsNumeric] [Attributes.Minimum(10.0)] [ObservableProperty] [NotifyDataErrorInfo] public partial double PavementWidth { get; set; } //public double PavementWidth //{ // get => pavementWidth; // set => SetProperty(ref pavementWidth, value, true); //} [Required(ErrorMessage = "不可为空")] [Attributes.IsNumeric] [ObservableProperty] [NotifyDataErrorInfo] public partial double WallBaseOffset { get; set; } // public double WallBaseOffset //{ // get => wallBaseOffset; // set => SetProperty(ref wallBaseOffset, value, true); //} [Required(ErrorMessage = "不可为空")] [Attributes.IsNumeric] [Attributes.Minimum(1.0)] [ObservableProperty] [NotifyDataErrorInfo] public partial double PavementThickness { get; set; } // public double PavementThickness //{ // get => pavementThickness; // set => SetProperty(ref pavementThickness, value, true); //} [Required(ErrorMessage = "不可为空")] [Attributes.IsNumeric] [Attributes.Minimum(10.0)] [ObservableProperty] [NotifyDataErrorInfo] public partial double PavementLength { get; set; } // public double PavementLength //{ // get => pavementLength; // set => SetProperty(ref pavementLength, value, true); //} [Required(ErrorMessage = "不可为空")] [Attributes.IsNumeric] [Attributes.Minimum(1.0)] [ObservableProperty] [NotifyDataErrorInfo] public partial double PavementGap { get; set; } // public double PavementGap //{ // get => pavementGap; // set => SetProperty(ref pavementGap, value, true); //} [Required(ErrorMessage = "不可为空")] [MinLength(1)] [ObservableProperty] [NotifyDataErrorInfo] public partial string PanelName { get; set; } // public string PanelName //{ // get => panelName; // set // { // SetProperty(ref panelName, value, true); // PlaceBricksCommand.NotifyCanExecuteChanged(); // } //} private static CurtainSystemType SetCurtainSystemType(Document doc, double length, double width, double gap, double thickness, string panelName) { var curtainSystemTypeCollector = new FilteredElementCollector(doc) .OfClass(typeof(CurtainSystemType)) .OfCategory(BuiltInCategory.OST_CurtaSystem) .Cast() .ToList(); var panelTypeCollector = new FilteredElementCollector(doc) .OfClass(typeof(PanelType)) .OfCategory(BuiltInCategory.OST_CurtainWallPanels) .Cast() .ToList(); var curtainWallMullionsTypeCollector = new FilteredElementCollector(doc) .OfClass(typeof(MullionType)) .OfCategory(BuiltInCategory.OST_CurtainWallMullions) .Cast() .ToList(); CurtainSystemType curtainSystemType = null; PanelType panelType = null; MullionType mullionType = null; var curtainSystemTypeName = $"铺砖-{length}mm x {width}mm"; var panelTypeName = panelName; var mullionTypeName = $"{gap}mm x {thickness}mm"; //创建嵌板类型 try { var defaultPanelType = panelTypeCollector.FirstOrDefault(); panelType = defaultPanelType.Duplicate(panelTypeName) as PanelType; } catch (Autodesk.Revit.Exceptions.ArgumentException) { foreach (var t in panelTypeCollector) { if (t.Name == panelTypeName) { panelType = t; break; } } } panelType?.get_Parameter(BuiltInParameter.CURTAIN_WALL_SYSPANEL_THICKNESS).Set(thickness / 304.8); //嵌板偏移 panelType?.get_Parameter(BuiltInParameter.CURTAIN_WALL_SYSPANEL_OFFSET).Set(0); //创建竖挺类型 try { var defaultMullionType = curtainWallMullionsTypeCollector.FirstOrDefault( m => m.FamilyName.Contains("矩形") || m.FamilyName.Contains("Rectangular") ); mullionType = defaultMullionType.Duplicate(mullionTypeName) as MullionType; } catch (Autodesk.Revit.Exceptions.ArgumentException) { foreach (var t in curtainWallMullionsTypeCollector) { if (t.Name == mullionTypeName) { mullionType = t; break; } } } //设置参数 mullionType?.get_Parameter(BuiltInParameter.RECT_MULLION_WIDTH1).Set(gap / 304.8 / 2); mullionType?.get_Parameter(BuiltInParameter.RECT_MULLION_WIDTH2).Set(gap / 304.8 / 2); mullionType?.get_Parameter(BuiltInParameter.RECT_MULLION_THICK).Set(thickness / 304.8); //创建幕墙系统类型 try { var defaultCurtainSystemType = curtainSystemTypeCollector.FirstOrDefault(); curtainSystemType = defaultCurtainSystemType.Duplicate(curtainSystemTypeName) as CurtainSystemType; } catch (Autodesk.Revit.Exceptions.ArgumentException) { foreach (var t in curtainSystemTypeCollector) { if (t.Name == curtainSystemTypeName) { curtainSystemType = t; break; } } } //mullionType.get_Parameter(BuiltInParameter.MULLION_OFFSET).Set(0); //mullionType.get_Parameter(BuiltInParameter.MULLION_OFFSET).Set(thickness / 304.8 ); curtainSystemType?.get_Parameter(BuiltInParameter.SPACING_LAYOUT_1).Set(1); curtainSystemType?.get_Parameter(BuiltInParameter.SPACING_LAYOUT_2).Set(1); //panelType.get_Parameter(BuiltInParameter.CURTAIN_WALL_SYSPANEL_OFFSET).Set(-thickness / 304.8 / 2); curtainSystemType?.get_Parameter(BuiltInParameter.SPACING_LENGTH_1).Set((width + gap) / 304.8); curtainSystemType?.get_Parameter(BuiltInParameter.SPACING_LENGTH_2).Set((length + gap) / 304.8); if (mullionType != null && panelType != null) { curtainSystemType?.get_Parameter(BuiltInParameter.AUTO_PANEL).Set(panelType.Id); curtainSystemType?.get_Parameter(BuiltInParameter.AUTO_MULLION_INTERIOR_GRID1).Set(mullionType.Id); curtainSystemType?.get_Parameter(BuiltInParameter.AUTO_MULLION_INTERIOR_GRID2).Set(mullionType.Id); } curtainSystemType?.get_Parameter(BuiltInParameter.CURTAINGRID_ADJUST_BORDER_1).Set(1); curtainSystemType?.get_Parameter(BuiltInParameter.CURTAINGRID_ADJUST_BORDER_2).Set(1); //curtainSystemType.get_Parameter(BuiltInParameter.AUTO_MULLION_BORDER1_GRID1).Set(mullionType.ViewId); //curtainSystemType.get_Parameter(BuiltInParameter.AUTO_MULLION_BORDER1_GRID2).Set(mullionType.ViewId); //curtainSystemType.get_Parameter(BuiltInParameter.AUTO_MULLION_BORDER2_GRID1).Set(mullionType.ViewId); //curtainSystemType.get_Parameter(BuiltInParameter.AUTO_MULLION_BORDER2_GRID2).Set(mullionType.ViewId); return curtainSystemType; } /// /// 获取偏移量 /// /// UV平面坐标系 /// 拾取的起铺点 /// private static double[,] GetOffset(List coord, XYZ start) { var origin = coord[0]; //var insterIntersectionResult = line.ProjectOf(origin); //var project = insterIntersectionResult?.XYZPoint; //var dis = insterIntersectionResult?.DistanceX; //var uDirection = XYZ.Zero; //var vDirection = XYZ.Zero; //bool lineIsU = false; double uoffest; double voffest; var p = start - origin; //u轴进行的偏移实际是v轴沿着u轴的偏移值,故应相反设置偏移值 //因为轴的模长度为1,所以直接等于p在轴上的投影长度 uoffest = p.DotProduct(coord[1]); //if (coord[1].CrossProduct(p).Z < 0) //{ // uoffest = -uoffest; //} voffest = p.DotProduct(coord[2]); //if (coord[2].CrossProduct(p).Z < 0) //{ // voffest = -voffest; //} //if (coord[1].CrossProduct(line.Direction).IsAlmostEqualTo(XYZ.Zero)) //{ // uoffest = coord[1].DotProduct(p) * coord[1]; // voffest = coord[2].DotProduct(p) * coord[2]; // ////得到起铺点相对幕墙系统原点的偏移量 // //double offest = default; // //if ((start - origin).Normalize().IsAlmostEqualTo(coord[1])) // //{ // // offest = (start - origin).GetLength(); // //} // //else // //{ // // offest = -(start - origin).GetLength(); // //} // //result.Add(coord[1], offest);//u // //if ((project - origin).Normalize().IsAlmostEqualTo(coord[2])) // //{ // // offest = (project - origin).GetLength(); // //} // //else // //{ // // offest = -(project - origin).GetLength(); // //} // //result.Add(coord[2], offest);//v //} //else if (coord[2].CrossProduct(line.Direction).IsAlmostEqualTo(XYZ.Zero)) //{ // isInvert = true; // uoffest = coord[2].DotProduct(p) * coord[2]; // voffest = coord[1].DotProduct(p) * coord[1]; // //double offest = default; // //if ((project - origin).Normalize().IsAlmostEqualTo(coord[1])) // //{ // // offest = (project - origin).GetLength(); // //} // //else // //{ // // offest = -(project - origin).GetLength(); // //} // //result.Add(coord[1], offest);//v // //if ((start - origin).DotProduct(coord[1]) > 0) // //{ // // offest = (start - origin).GetLength(); // //} // //else // //{ // // offest = -(start - origin).GetLength(); // //} // //result.Add(coord[1], offest);//v //} ////if (project != null) ////{ //// var offset = project.DistanceTo(start); //// //判断正方向还是反方向 //// if ((start - project).Normalize().IsAlmostEqualTo(-coord[1])) //// { //// offset = -offset; //// } //// //var direction = XYZ.BasisZ.CrossProduct(pl.FaceNormal); //// //if (direction.IsAlmostEqualTo(line.Direction)) //// //{ //// // offset = xyz.DistanceTo(startPoint) * 304.8; //// //} //// //else //// //{ //// // offset = xyz.DistanceTo(endPoint) * 304.8; //// //} //// //offset = x; //// var n = Math.Floor(offset / interval); //// offset -= Math.Floor(n) * interval; //// return offset; ////} //if (voffest == null || uoffest == null) //{ // return null; //} return new[,] { { uoffest, voffest } }; } private static FaceArray GetFaceArray(Document doc, List curveLoops, out DirectShape ds) { FaceArray array = new(); var solid = GeometryCreationUtilities.CreateExtrusionGeometry(curveLoops, -XYZ.BasisZ, 10.0); ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_Mass)); ds?.AppendShape(new List { solid }); foreach (Face face in solid.Faces) { var pf = face as PlanarFace; if (pf.FaceNormal.IsAlmostEqualTo(XYZ.BasisZ)) { array.Append(face); break; } } return array; } /// /// 获取最终幕墙系统坐标 /// /// /// /// /// /// private static List GetCoordinateSystem(Document doc, FaceArray array, Line line, out Rotation rotation) { var curtainSystemTypeCollector = new FilteredElementCollector(doc) .OfClass(typeof(CurtainSystemType)) .OfCategory(BuiltInCategory.OST_CurtaSystem); XYZ origin = null; XYZ u = null; XYZ v = null; rotation = null; using (Transaction trans = new(doc, "获取坐标系")) { trans.Start(); if (curtainSystemTypeCollector.FirstOrDefault() is CurtainSystemType defaultCurtainSystemType) { defaultCurtainSystemType.get_Parameter(BuiltInParameter.SPACING_LAYOUT_1).Set(2); defaultCurtainSystemType.get_Parameter(BuiltInParameter.SPACING_LAYOUT_2).Set(2); var curtainSystem = doc.Create.NewCurtainSystem(array, defaultCurtainSystemType); //编号 curtainSystem.get_Parameter(BuiltInParameter.SPACING_NUM_DIVISIONS_1).Set(1); curtainSystem.get_Parameter(BuiltInParameter.SPACING_NUM_DIVISIONS_2).Set(1); //对正 curtainSystem.get_Parameter(BuiltInParameter.SPACING_JUSTIFICATION_1).Set(2); curtainSystem.get_Parameter(BuiltInParameter.SPACING_JUSTIFICATION_2).Set(2); // curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ORIGIN_1).Set(0); curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ORIGIN_2).Set(0); doc.Regenerate(); origin = GetOrigin(doc, curtainSystem, out u, out v); var list = new List { origin, u, v }; //获取旋转角度 rotation = GetRotation(list, line); //设置旋转角 curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ANGLE_1).Set(rotation.Radian); curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ANGLE_2).Set(rotation.Radian); //得到转换后的角度 doc.Regenerate(); origin = GetOrigin(doc, curtainSystem, out u, out v); } trans.RollBack(); //trans.Commit(); } return [origin, u, v]; } /// /// 得到旋转角度 /// /// /// /// private static Rotation GetRotation(List coordSystem, Line line) { var radian1 = coordSystem[1].AngleTo(line.Direction); Rotation rotation1 = new() { Radian = radian1, Direction = line.Direction, Orientation = Orientation.U, CoordSystemAxis = coordSystem[1] }; var radian2 = coordSystem[1].AngleTo(-line.Direction); Rotation rotation2 = new() { Radian = radian2, Direction = -line.Direction, Orientation = Orientation.U, CoordSystemAxis = coordSystem[1] }; var radian3 = coordSystem[2].AngleTo(line.Direction); Rotation rotation3 = new() { Radian = radian3, Direction = line.Direction, Orientation = Orientation.V, CoordSystemAxis = coordSystem[2] }; var radian4 = coordSystem[2].AngleTo(-line.Direction); Rotation rotation4 = new() { Radian = radian4, Direction = -line.Direction, Orientation = Orientation.V, CoordSystemAxis = coordSystem[2] }; List rotations = [rotation1, rotation2, rotation3, rotation4]; var rotation = rotations.OrderBy(r => r.Radian).First(); if (rotation.CoordSystemAxis.CrossProduct(rotation.Direction).Z < 0) { rotation.Radian = -rotation.Radian; } return rotation; //double radian; ////grid2的轴向单位向量 ////在平面 //if (pl.FaceNormal.IsAlmostEqualTo(XYZ.BasisZ)) //{ // var perpendicularVector = line.Direction.CrossProduct(XYZ.BasisZ); // if (perpendicularVector.Y < 0) // { // perpendicularVector = -perpendicularVector; // } // radian = perpendicularVector.X > 0 ? -perpendicularVector.AngleTo(XYZ.BasisY) : perpendicularVector.AngleTo(XYZ.BasisY); // //angle = radian * 180 / Math.PI; // if (Math.Abs(Math.Round(radian, MidpointRounding.AwayFromZero) - Math.PI / 2) < 0.0001) // { // radian = 0; // } //} //else//在垂直面 //{ // radian = 0; //} //return radian; } private static void CreateCurtainSystemByFace( UIDocument uidoc, double length, double width, double gap, double thickness, double wallBaseOffset, string panelName, bool isEdgeExistGap ) { var doc = uidoc.Document; var faceReference = uidoc.Selection.PickObject(ObjectType.Face, "请选择铺贴的面"); var element = doc.GetElement(faceReference); double baseHeight = default; double height = default; doc.InvokeGroup( _ => { if (element is Wall) { doc.Invoke( _ => { //顶部约束 var topConstraint = element.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).AsElementId(); if (topConstraint == ElementId.InvalidElementId) //未连接 { //无连接高度 height = element.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).AsDouble(); element.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).Set(height - (wallBaseOffset / 304.8)); } baseHeight = element.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).AsDouble(); element.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(baseHeight + (wallBaseOffset / 304.8)); }, "设置墙底部高度" ); } var face = element.GetGeometryObjectFromReference(faceReference) as Face; var pl = face as PlanarFace; if (pl == null) { return; } double radian = 0; double actualU = 0; double actualV = 0; FaceArray array = new(); array.Append(face); var referEdge = uidoc.Selection.PickObject(ObjectType.Edge, new EdgeFilter(element), "请选择对齐的边"); var xyz = uidoc.Selection.PickPoint( ObjectSnapTypes.Intersections | ObjectSnapTypes.Endpoints | ObjectSnapTypes.Centers | ObjectSnapTypes.Midpoints | ObjectSnapTypes.Points | ObjectSnapTypes.Nearest | ObjectSnapTypes.Perpendicular | ObjectSnapTypes.WorkPlaneGrid | ObjectSnapTypes.Quadrants | ObjectSnapTypes.Tangents, "请选择起铺点" ); var edgeObj = element.GetGeometryObjectFromReference(referEdge) as Edge; //var ourterEdgeArray = face.EdgeLoops.get_Item(0); if (edgeObj != null && edgeObj.AsCurve() is Line) { var line = edgeObj.AsCurve() as Line; var coordinateSystem = GetCoordinateSystem(doc, array, line, out var rotation); var startPoint = line!.GetEndPoint(0); var endPoint = line.GetEndPoint(1); var start = line.Project(xyz).XYZPoint; var totalLength = start.DistanceTo(startPoint) + start.DistanceTo(endPoint); //判断点是否在直线上 if (totalLength - line.Length > 0.0001) { MessageBox.Show("选择点不在对齐的边上", "错误"); return; } radian = rotation.Radian; var uv = GetOffset(coordinateSystem, start); if (uv != null) { //原始起铺点基于幕墙系统原点平面uv偏移量 var intervalU = (length + gap) / 304.8; var intervalV = (width + gap) / 304.8; var n = Math.Floor(uv[0, 0] / intervalU); var m = Math.Floor(uv[0, 1] / intervalV); if (isEdgeExistGap) { actualU = uv[0, 0] - (n * intervalU); actualV = uv[0, 1] - (m * intervalV); } else { actualU = uv[0, 0] - (n * intervalU) - (gap / 2 / 304.8); actualV = uv[0, 1] - (m * intervalV) - (gap / 2 / 304.8); } } } CurtainSystem curtainSystem = null; //doc.Regenerate(); doc.Invoke( _ => { var curtainSystemType = SetCurtainSystemType(doc, length, width, gap, thickness, panelName); curtainSystem = doc.Create.NewCurtainSystem(array, curtainSystemType); curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ANGLE_1).Set(radian); curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ANGLE_2).Set(radian); doc.Regenerate(); curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ORIGIN_1).Set(actualU); curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ORIGIN_2).Set(actualV); curtainSystem.get_Parameter(BuiltInParameter.SPACING_JUSTIFICATION_1).Set(2); curtainSystem.get_Parameter(BuiltInParameter.SPACING_JUSTIFICATION_2).Set(2); ElementTransformUtils.MoveElement(doc, curtainSystem.Id, pl.FaceNormal * thickness / 304.8 / 2); }, "创建幕墙系统" ); if (element is Wall) { doc.Invoke( _ => { element.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(baseHeight); var topConstraint = element.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).AsElementId(); if (topConstraint == ElementId.InvalidElementId) //未连接 { //无连接高度 element.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).Set(height); } }, "设置墙偏移" ); } if (curtainSystem != null) { doc.Invoke(_ => { var iterator = curtainSystem.CurtainGrids.ForwardIterator(); iterator.MoveNext(); var grid = iterator.Current as CurtainGrid; var panels = grid!.GetPanelIds().Select(id => doc.GetElement(id) as Panel); var area = width / 304.8 * length / 304.8; var errorPanels = from panel in panels where panel!.get_Parameter(BuiltInParameter.HOST_AREA_COMPUTED).AsDouble() < area / 4 select panel; foreach (var panel in errorPanels) { var overrideGraphicSettings = doc.ActiveView.GetElementOverrides(panel.Id); overrideGraphicSettings.SetProjectionLineColor(new Color(255, 0, 0)); //在当前视图下设置,其它视图保持原来的 doc.ActiveView.SetElementOverrides(panel.Id, overrideGraphicSettings); doc.Regenerate(); } }); } }, "创建饰面" ); //CreateCurtainSystem(length, width, gap, thickness, angle, offset, doc, curveLoops, pl.FaceNormal); //var xyz = referEdge.GlobalPoint; //if (angle > Math.PI / 2) //{ // angle -= Math.PI; // if (perpendicularVector.Y>0) // { // angle -= Math.PI / 2 ; // } // else // { // angle = Math.PI / 2 - angle; // } //} } private static void CreateCurtainSystemByRoom(UIDocument uidoc, double length, double width, double gap, double thickness, string panelName) { var doc = uidoc.Document; var rooms = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Rooms); if (!rooms.Any()) { MessageBox.Show("项目中当前没有房间", "提示", MessageBoxButton.OK, MessageBoxImage.Stop); return; } var refer = uidoc.Selection.PickObject(ObjectType.Element, new GenericFilter(), "请选择铺贴的房间"); var room = doc.GetElement(refer) as Room; List curveLoops = []; var opts = new SpatialElementBoundaryOptions(); var segmentsList = room!.GetBoundarySegments(opts); if (segmentsList != null) { foreach (var boundarySegments in segmentsList) { CurveLoop curveLoop = new(); foreach (var boundarySegment in boundarySegments) { curveLoop.Append(boundarySegment.GetCurve()); } curveLoops.Add(curveLoop); } } doc.Invoke( _ => { //double angle = 0; var array = GetFaceArray(doc, curveLoops, out var ds); var curtainSystemType = SetCurtainSystemType(doc, length, width, gap, thickness, panelName); var curtainSystem = doc.Create.NewCurtainSystem(array, curtainSystemType); curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ANGLE_1).Set(0); curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ANGLE_2).Set(0); curtainSystem.get_Parameter(BuiltInParameter.SPACING_JUSTIFICATION_1).Set(2); curtainSystem.get_Parameter(BuiltInParameter.SPACING_JUSTIFICATION_2).Set(2); curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ORIGIN_1).Set(0); curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ORIGIN_2).Set(0); if (ds != null) { doc.Delete(ds.Id); } ElementTransformUtils.MoveElement(doc, curtainSystem.Id, XYZ.BasisZ * thickness / 304.8 / 2); }, "创建铺贴饰面" ); //CreateCurtainSystem(length, width, gap, thickness, angle, offset, doc, curveLoops, XYZ.BasisZ); } [RelayCommand] private void PlaceBricks() { finishesHandler.Raise(uiapp => { var uidoc = uiapp.ActiveUIDocument; try { if (ByRoom) { CreateCurtainSystemByRoom(uidoc, PavementLength, PavementWidth, PavementGap, PavementThickness, PanelName); } else { CreateCurtainSystemByFace( uidoc, PavementLength, PavementWidth, PavementGap, PavementThickness, WallBaseOffset, PanelName, IsEdgeExistGap ); } } catch (Autodesk.Revit.Exceptions.OperationCanceledException) { } }); } private static XYZ GetOrigin(Document doc, CurtainSystem curtainSystem, out XYZ u, out XYZ v) { XYZ origin = null; var iterator = curtainSystem.CurtainGrids.ForwardIterator(); iterator.MoveNext(); var grid = iterator.Current as CurtainGrid; var uLineId = grid.GetUGridLineIds().FirstOrDefault(); var vLineId = grid.GetVGridLineIds().FirstOrDefault(); var uLine = doc.GetElement(uLineId) as CurtainGridLine; var vLine = doc.GetElement(vLineId) as CurtainGridLine; var l1 = uLine.FullCurve as Line; u = l1.Direction; var l2 = vLine.FullCurve as Line; v = l2.Direction; var result = l1.Intersect(l2, out var resultArray); if (result != SetComparisonResult.Disjoint) { if (!resultArray.IsEmpty) { origin = resultArray.get_Item(0).XYZPoint; } } return origin; } } public class EdgeFilter : ISelectionFilter { public EdgeFilter(Element preElement) { element = preElement; } private readonly Element element; public bool AllowElement(Element elem) { return element.Id == elem.Id; } public bool AllowReference(Reference reference, XYZ position) { return true; } }