using System.Diagnostics; using Autodesk.Revit.DB; using Autodesk.Revit.UI.Selection; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Nice3point.Revit.Toolkit.External.Handlers; namespace ShrlAlgoToolkit.RevitAddins.RvView { public partial class QuickViewSectionViewModel : ObservableObject { private readonly ActionEventHandler handler = new(); [ObservableProperty] public partial bool IsParallel { get; set; } = true; private readonly List viewSections = []; [RelayCommand] private void DeleteViewSection() { handler.Raise( uiapp => { var uidoc = uiapp.ActiveUIDocument; var doc = uidoc.Document; doc.Invoke( _ => { for (var i = viewSections.Count - 1; i >= 0; i--) { var view = viewSections[i]; if (view.IsValidObject) { var uiView = uidoc.GetOpenUIViews().FirstOrDefault(ui => ui.ViewId == view.Id); uiView?.Close(); viewSections.Remove(view); doc.Delete(view.Id); } } }, "删除快速剖面"); }); } [RelayCommand] private void CreateViewSection() { handler.Raise( uiapp => { var uidoc = uiapp.ActiveUIDocument; var doc = uidoc.Document; //var element = uidoc.SelectObject(new FuncFilter(elem => elem.GetCurve() is Line)); var placeProjectPoint = XYZ.Zero; Line locLine = null; XYZ lookDirection = null; var depth = 4.0; double baseLength = 4.0; Element element; if (IsParallel) { var refer = uidoc.Selection .PickObject( ObjectType.PointOnElement, new FuncFilter(elem => elem.GetCurve() is Line), "请选择前进方向起点(剖面看向将会在前进方向左侧)"); var refer1 = uidoc.Selection .PickObject( ObjectType.PointOnElement, new FuncFilter(elem => elem.Id == refer.ElementId), "请选择前进方向终点(剖面看向将会在前进方向左侧)"); element = doc.GetElement(refer); var startPointPicked = refer.GlobalPoint; var startProjectPoint = element.GetCurve().Project(startPointPicked).XYZPoint; //终点投影 var forwardPointPicked = refer1.GlobalPoint; var forwardProjectPoint = element.GetCurve().Project(forwardPointPicked).XYZPoint; //前进方向 var d = forwardProjectPoint - startProjectPoint; //剖面宽度、跨度 baseLength = d.GetLength(); //左侧 lookDirection = XYZ.BasisZ.CrossProduct(forwardProjectPoint - startProjectPoint).Normalize(); //中点,向查看方向反向移动,用于平行剖面的放置 placeProjectPoint = (forwardProjectPoint + startProjectPoint) / 2 - lookDirection; } else { var refer = uidoc.Selection .PickObject( ObjectType.PointOnElement, new FuncFilter(elem => elem.GetCurve() is Line), "请选择放置剖面位置"); var refer1 = uidoc.Selection .PickObject( ObjectType.PointOnElement, new FuncFilter(elem => elem.Id == refer.ElementId), "剖面看向方向和相对剖面放置的深度"); element = doc.GetElement(refer); //正交剖面的放置位置 var placePointPicked = refer.GlobalPoint; placeProjectPoint = element.GetCurve().Project(placePointPicked).XYZPoint; //深度的投影 var lookPointPicked = refer1.GlobalPoint; var lookProjectPoint = element.GetCurve().Project(lookPointPicked).XYZPoint; depth = placeProjectPoint.DistanceTo(lookProjectPoint); //if (locLine.Direction.IsAlmostEqualTo((lookPointPicked - startPointPicked).Normalize())) //{ //} lookDirection = (lookProjectPoint - placeProjectPoint).Normalize(); } locLine = element.GetCurve() as Line; #region 选择方向 //var firstTip = "请选择第一个点以确定正交剖面的定位点"; //var lastTip = "请选择第二个点以确定拉抻的深度"; //if (IsParallel) //{ // firstTip = "请选择第一个剖面范围水平的边界点"; // lastTip = "请选择第二个剖面范围水平的边界点"; //} //var firstrefer = uiapp.Selection // .PickObject(Autodesk.Revit.UI.Selection.ObjectType.PointOnElement, firstTip); //var lastrefer = uiapp.Selection // .PickObject(Autodesk.Revit.UI.Selection.ObjectType.PointOnElement, lastTip); //var first = firstrefer.GlobalPoint; //var last = firstrefer.GlobalPoint; //var elementByCurve = uiapp.Document.GetElement(firstrefer); //var firstProjectPoint = elementByCurve.GetCurve().Project(first).XYZPoint; //var lookProjectPoint = elementByCurve.GetCurve().Project(last).XYZPoint; #endregion var bb = element.get_BoundingBox(null); var minZ = bb.Min.Z; var maxZ = bb.Max.Z; ViewSection viewSection = null; BoundingBoxXYZ sectionBox; //transform.x:RightDirection,transform.y:UpDirection=Z轴,transform.z:ViewDirection (r x u=v) var t = Transform.Identity; Debug.WriteLine($"Length:{baseLength}"); Debug.WriteLine("拾取对象:"); Debug.WriteLine($"Min:{bb.Min}"); Debug.WriteLine($"Max:{bb.Max}"); //设置定位点 //t.Origin = line.Evaluate(0.5, true).Flatten(); t.Origin = placeProjectPoint.Flatten(); //t.Origin = line.GetEndPoint(0).Flatten(); Debug.WriteLine("定义剖面:"); Debug.WriteLine($"Transform.Origin:{t.Origin}"); t.BasisY = XYZ.BasisZ;//固定朝上UpDirection var viewName = $"{element.Category.Name}({element.Id})"; if (IsParallel) { //剖面视图中,裁剪框左下角的点 var min = new XYZ(-(baseLength) / 2, minZ - 10, 0); //剖面视图中,裁剪框右上角的点 var max = new XYZ((baseLength) / 2, maxZ + 10, depth); Debug.WriteLine($"Min:{min}"); Debug.WriteLine($"Max:{max}"); viewName = $"平行剖面-{viewName}"; //与生成的最终剖面视图的RightDirection反向(定义Transform) t.BasisX = XYZ.BasisZ.CrossProduct(lookDirection).Normalize(); //与生成的最终剖面视图的ViewDirection反向(定义Transform) t.BasisZ = lookDirection; Debug.WriteLine($"Transform.BasisX:{t.BasisX}"); Debug.WriteLine($"Transform.BasisZ:{t.BasisZ}"); sectionBox = new BoundingBoxXYZ { Transform = t, Min = min, Max = max }; } else { //var transform = line.ComputeDerivatives(0.5, true);//求导切向为BasisX viewName = $"正交剖面-{viewName}"; t.BasisX = XYZ.BasisZ.CrossProduct(locLine.Direction).Normalize(); t.BasisZ = locLine.Direction; var min = new XYZ(-10, minZ - 5, 0); var max = new XYZ(10, maxZ + 5, depth); Debug.WriteLine($"Transform.BasisX:{t.BasisX}"); Debug.WriteLine($"Transform.BasisZ:{t.BasisZ}"); try { sectionBox = new BoundingBoxXYZ { Transform = t, Min = min, Max = max }; } catch (Exception) { throw; } } doc.Invoke( ts => { if (sectionBox == null) { return; } //获取剖面图类型 var viewfamilyType = doc.OfClass() .Cast() .Where(t => t.ViewFamily == ViewFamily.Section) .FirstOrDefault(); viewSection = ViewSection.CreateSection(uidoc.Document, viewfamilyType.Id, sectionBox); viewSection.DisplayStyle = DisplayStyle.ShadingWithEdges; viewSection.DetailLevel = ViewDetailLevel.Fine; var isExistName = false; try { viewSection.Name = viewName; } catch (Autodesk.Revit.Exceptions.ArgumentException) { isExistName = true; } if (isExistName) { for (var i = 0; i < 100; i++) { try { viewSection.Name = $"{viewName} {i + 1}"; break; } catch (Autodesk.Revit.Exceptions.ArgumentException) { } } } ts.Commit(); if (viewSection != null) { viewSections.Add(viewSection); } Debug.WriteLine("生成后:"); Debug.WriteLine($"CropBox.Origin:{viewSection.CropBox.Transform.Origin}"); Debug.WriteLine($"CropBox.BasisX:{viewSection.CropBox.Transform.BasisX}"); Debug.WriteLine($"CropBox.BasisZ:{viewSection.CropBox.Transform.BasisZ}"); Debug.WriteLine($"CropBox.Min:{viewSection.CropBox.Min}"); Debug.WriteLine($"CropBox.Max:{viewSection.CropBox.Max}"); Debug.WriteLine($"RightDirection:{viewSection.RightDirection}"); Debug.WriteLine($"ViewDirection:{viewSection.ViewDirection}"); if (viewSection != null) { uidoc.ActiveView = viewSection; uidoc.Selection.SetElementIds([element.Id]); } }, "创建快速剖面"); }); } } }