Files
Shrlalgo.RvKits/ShrlAlgoToolkit.RevitAddins/RvView/QuickViewSectionViewModel.cs
2025-04-24 20:56:10 +08:00

283 lines
14 KiB
C#
Raw 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.Collections.ObjectModel;
using System.Diagnostics;
using System.Security.Cryptography;
using System.Windows;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Nice3point.Revit.Toolkit.External.Handlers;
namespace ShrlAlgo.RvKits.RvView
{
public partial class QuickViewSectionViewModel : ObservableObject
{
private readonly ActionEventHandler handler = new();
[ObservableProperty]
private bool isParallel = true;
private readonly List<ViewSection> viewSections = [];
[RelayCommand]
private void DeleteViewSection()
{
handler.Raise(
uiapp =>
{
var uidoc = uiapp.ActiveUIDocument;
var doc = uidoc.Document;
doc.Invoke(
ts =>
{
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.xRightDirectiontransform.yUpDirection=Z轴transform.zViewDirection (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<ViewFamilyType>()
.Cast<ViewFamilyType>()
.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]);
}
}, "创建快速剖面");
});
}
}
}