2025-07-11 09:20:23 +08:00
|
|
|
|
using System.ComponentModel.DataAnnotations;
|
|
|
|
|
|
using System.Windows;
|
|
|
|
|
|
using Autodesk.Revit.DB;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
using Autodesk.Revit.UI.Selection;
|
|
|
|
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
|
|
|
|
using CommunityToolkit.Mvvm.Input;
|
|
|
|
|
|
using Nice3point.Revit.Toolkit.External.Handlers;
|
2026-02-21 16:31:24 +08:00
|
|
|
|
using ShrlAlgoToolkit.RevitAddins.Common.Assists;
|
|
|
|
|
|
|
2025-04-24 20:56:44 +08:00
|
|
|
|
|
|
|
|
|
|
namespace ShrlAlgoToolkit.RevitAddins.RvCommon
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
public partial class ModelByCurveCreatorViewModel : ObservableValidator
|
|
|
|
|
|
{
|
|
|
|
|
|
[ObservableProperty]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial CenterCurveType CenterCurveType { get; set; }
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial List<FamilySymbol> FamilyTypes { get; set; }
|
|
|
|
|
|
|
2024-09-22 11:05:41 +08:00
|
|
|
|
private readonly ActionEventHandler handler;
|
|
|
|
|
|
|
|
|
|
|
|
[Required(ErrorMessage = "不可为空")]
|
2026-02-21 16:31:24 +08:00
|
|
|
|
[Common.Attributes.IsNumeric]
|
2024-09-22 11:05:41 +08:00
|
|
|
|
[ObservableProperty]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial double InstanceOffsetX { get; set; } = 0;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
[Required(ErrorMessage = "不可为空")]
|
2026-02-21 16:31:24 +08:00
|
|
|
|
[Common.Attributes.IsNumeric]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial double InstanceOffsetY { get; set; } = 0;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
2026-02-24 11:34:18 +08:00
|
|
|
|
[NotifyCanExecuteChangedFor(nameof(CreateTrackCommand))]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial bool IsRunning { get; set; }
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial bool IsTwoSides { get; set; } = false;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial List<Material> Materials { get; set; }
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
[Required(ErrorMessage = "不可为空")]
|
2026-02-21 16:31:24 +08:00
|
|
|
|
[Common.Attributes.IsNumeric]
|
2024-09-22 11:05:41 +08:00
|
|
|
|
[ObservableProperty]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial double OffsetX { get; set; } = 0;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
[Required(ErrorMessage = "不可为空")]
|
2026-02-21 16:31:24 +08:00
|
|
|
|
[Common.Attributes.IsNumeric]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial double OffsetY { get; set; } = 0;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
[Required(ErrorMessage = "不可为空")]
|
2026-02-21 16:31:24 +08:00
|
|
|
|
[Common.Attributes.IsNumeric]
|
|
|
|
|
|
[Common.Attributes.Minimum(0.5)]
|
2024-09-22 11:05:41 +08:00
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
[NotifyDataErrorInfo]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial double Precision { get; set; } = 1.0;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
//private List<ElementId> previewIds = [];
|
|
|
|
|
|
[ObservableProperty]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial List<FamilySymbol> ProfileFamilyTypes { get; set; }
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
2026-02-24 11:34:18 +08:00
|
|
|
|
[NotifyCanExecuteChangedFor(nameof(CreateTrackCommand))]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial FamilySymbol SelectedFamilyType { get; set; }
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial Material SelectedMaterial { get; set; }
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
2026-02-24 11:34:18 +08:00
|
|
|
|
[NotifyCanExecuteChangedFor(nameof(CreateTrackCommand))]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial FamilySymbol SelectedProfileFamilyType { get; set; }
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
[Required(ErrorMessage = "不可为空")]
|
2026-02-21 16:31:24 +08:00
|
|
|
|
[Common.Attributes.IsNumeric]
|
|
|
|
|
|
[Common.Attributes.Minimum(100)]
|
2024-09-22 11:05:41 +08:00
|
|
|
|
[NotifyDataErrorInfo]
|
|
|
|
|
|
[ObservableProperty]
|
2025-10-04 08:52:23 +08:00
|
|
|
|
public partial double Spacing { get; set; } = 100;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
public ModelByCurveCreatorViewModel(Document doc)
|
|
|
|
|
|
{
|
|
|
|
|
|
handler = new();
|
2025-10-04 08:52:23 +08:00
|
|
|
|
ProfileFamilyTypes = [.. doc.OfClass<FamilySymbol>()
|
2024-09-22 11:05:41 +08:00
|
|
|
|
.OfCategory(BuiltInCategory.OST_ProfileFamilies)
|
|
|
|
|
|
.Cast<FamilySymbol>()
|
|
|
|
|
|
.OrderBy(n => n.FamilyName)];
|
2025-10-04 08:52:23 +08:00
|
|
|
|
FamilyTypes = [.. doc.OfClass<FamilySymbol>()
|
2024-09-22 11:05:41 +08:00
|
|
|
|
.OfType<FamilySymbol>()
|
|
|
|
|
|
.Where(
|
|
|
|
|
|
s =>
|
|
|
|
|
|
s.Category.Parent == null
|
|
|
|
|
|
&& s.Family.IsEditable
|
|
|
|
|
|
&& s.Family.IsUserCreated
|
|
|
|
|
|
&& s.Family.FamilyPlacementType == FamilyPlacementType.OneLevelBased
|
|
|
|
|
|
)
|
|
|
|
|
|
.OrderBy(n => n.FamilyName)];
|
2025-10-04 08:52:23 +08:00
|
|
|
|
Materials = doc.OfClass<Material>().OrderBy(n => n.Name).OfType<Material>().ToList();
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private void ClearFmailyTypeSelection()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (SelectedFamilyType != null)
|
|
|
|
|
|
SelectedFamilyType = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private void ClearMaterialSelection()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (SelectedMaterial != null)
|
|
|
|
|
|
SelectedMaterial = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private void ClearProfilesSelection()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (SelectedProfileFamilyType != null)
|
|
|
|
|
|
SelectedProfileFamilyType = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand(CanExecute = nameof(CanCreate))]
|
|
|
|
|
|
private void CreateTrack()
|
|
|
|
|
|
{
|
|
|
|
|
|
handler.Raise(uiapp =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var UiDocument = uiapp.ActiveUIDocument;
|
|
|
|
|
|
var doc = UiDocument.Document;
|
|
|
|
|
|
List<Curve> curves = null;
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
IsRunning = true;
|
|
|
|
|
|
switch (CenterCurveType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case CenterCurveType.ModelCurve:
|
|
|
|
|
|
{
|
|
|
|
|
|
var refers = UiDocument.Selection.PickObjects(
|
|
|
|
|
|
ObjectType.Element,
|
|
|
|
|
|
new GenericFilter<ModelCurve>(),
|
|
|
|
|
|
"请选择模型线并完成选择"
|
|
|
|
|
|
);
|
|
|
|
|
|
curves = refers.Select(r => doc.GetElement(r)).OfType<ModelCurve>().Select(mc => mc.GeometryCurve).ToList();
|
2025-07-11 09:20:23 +08:00
|
|
|
|
var loops = SpatialAssist.GroupContinuousCurves(curves);
|
2024-09-22 11:05:41 +08:00
|
|
|
|
if (loops.Count != 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("未选择路径或所选线条不止一条路径", "错误");
|
|
|
|
|
|
IsRunning = false;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
curves = loops.FirstOrDefault();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case CenterCurveType.MassCurve:
|
|
|
|
|
|
{
|
|
|
|
|
|
var refer = UiDocument.Selection.PickObject(
|
|
|
|
|
|
ObjectType.Element,
|
|
|
|
|
|
new FuncFilter(e => e is FamilyInstance importInstance && importInstance.Category.ToBuiltInCategory() == BuiltInCategory.OST_Mass),
|
|
|
|
|
|
"请选择仅包含一条连续曲线的体量族"
|
|
|
|
|
|
);
|
|
|
|
|
|
var instance = doc.GetElement(refer) as FamilyInstance;
|
|
|
|
|
|
var geo = instance.GetGeometryObjects().FirstOrDefault();
|
|
|
|
|
|
if (geo is GeometryInstance geometryInstance)
|
|
|
|
|
|
{
|
|
|
|
|
|
curves = geometryInstance.GetInstanceGeometry().Where(g => g is Curve).Cast<Curve>().ToList();
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case CenterCurveType.DWGCurve:
|
|
|
|
|
|
{
|
|
|
|
|
|
var refer = UiDocument.Selection.PickObject(
|
|
|
|
|
|
ObjectType.Element,
|
|
|
|
|
|
new FuncFilter(e => e is ImportInstance importInstance && importInstance.Category.Name.EndsWith(".dwg")),
|
|
|
|
|
|
"请选择dwg实例"
|
|
|
|
|
|
);
|
|
|
|
|
|
var importInstance = doc.GetElement(refer) as ImportInstance;
|
|
|
|
|
|
//curves = importInstance.GetCurves();
|
|
|
|
|
|
var geo = importInstance.GetGeometryObjects().FirstOrDefault();
|
|
|
|
|
|
if (geo is GeometryInstance geometryInstance)
|
|
|
|
|
|
{
|
|
|
|
|
|
var polyLine = geometryInstance.GetInstanceGeometry().FirstOrDefault() as PolyLine;
|
|
|
|
|
|
curves = [polyLine.ConverToHermiteSpline()];
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
|
|
|
|
|
|
{
|
|
|
|
|
|
IsRunning = false;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((curves != null) && (curves.Count > 1))
|
|
|
|
|
|
{
|
|
|
|
|
|
var loop = CurveLoop.Create(curves);
|
|
|
|
|
|
if (!loop.IsOpen())
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("选择的模型线是闭合的,无法使用", "提示");
|
|
|
|
|
|
IsRunning = false;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
var cs = loop.GetEnumerator();
|
|
|
|
|
|
curves = [];
|
|
|
|
|
|
while (cs.MoveNext())
|
|
|
|
|
|
{
|
|
|
|
|
|
curves.Add(cs.Current);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Autodesk.Revit.Exceptions.ArgumentException)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("所选模型线不连续或包含螺旋线", "错误");
|
|
|
|
|
|
IsRunning = false;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
List<XYZ> points = [];
|
|
|
|
|
|
var imperial = Precision * 1000 / 304.8;
|
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < curves.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var curve = curves[i];
|
|
|
|
|
|
var divide = (int)Math.Floor(curve.Length / imperial);
|
|
|
|
|
|
//长度小于最小细分间距
|
|
|
|
|
|
//始终都会添加起始点
|
|
|
|
|
|
if (divide == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
points.Add(curve.Evaluate(0, true));
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
for (double j = 0; j < divide; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var x = j / divide;
|
|
|
|
|
|
points.Add(curve.Evaluate(x, true));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
points.Add(curves.Last().GetEndPoint(1));
|
|
|
|
|
|
|
|
|
|
|
|
var planePoints = points.Select(p => p.Flatten()).ToList();
|
|
|
|
|
|
|
|
|
|
|
|
var spline3D = HermiteSpline.Create(points, false);
|
|
|
|
|
|
|
|
|
|
|
|
doc.InvokeGroup(
|
|
|
|
|
|
_ =>
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
if (SelectedFamilyType != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
doc.Invoke(
|
|
|
|
|
|
_ =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var horizonSpline = HermiteSpline.Create(planePoints, false);
|
|
|
|
|
|
|
|
|
|
|
|
if (!SelectedFamilyType.IsActive)
|
|
|
|
|
|
{
|
|
|
|
|
|
SelectedFamilyType.Activate();
|
|
|
|
|
|
}
|
|
|
|
|
|
var level = new FilteredElementCollector(doc)
|
|
|
|
|
|
.OfClass(typeof(Level))
|
|
|
|
|
|
.Cast<Level>()
|
|
|
|
|
|
.FirstOrDefault(l => Math.Abs(l.Elevation) < 0.00001);
|
|
|
|
|
|
|
|
|
|
|
|
List<Autodesk.Revit.Creation.FamilyInstanceCreationData> dataList = [];
|
|
|
|
|
|
var spacing = Spacing / 304.8;
|
|
|
|
|
|
var x = InstanceOffsetX / 304.8;
|
|
|
|
|
|
var y = InstanceOffsetY / 304.8;
|
|
|
|
|
|
var n = Math.Floor(horizonSpline.Length / spacing);
|
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < n; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
//XYZ pointSplie = spline3D.Evaluate(spacing * i, false);
|
|
|
|
|
|
var pointxoy = horizonSpline.Evaluate(spacing * i, false);
|
|
|
|
|
|
var unboundLine = Line.CreateUnbound(pointxoy, XYZ.BasisZ);
|
|
|
|
|
|
|
|
|
|
|
|
var point = unboundLine.IntersectionPoint(spline3D);
|
|
|
|
|
|
|
|
|
|
|
|
var transform = spline3D.ComputeDerivatives(spacing * i, false);
|
|
|
|
|
|
//族的参考方向
|
|
|
|
|
|
var referVector = transform.BasisX.CrossProduct(XYZ.BasisZ);
|
|
|
|
|
|
if (IsTwoSides)
|
|
|
|
|
|
{
|
|
|
|
|
|
var locLeft = point.Add(-referVector.Normalize() * x) + y * XYZ.BasisZ;
|
|
|
|
|
|
Autodesk.Revit.Creation.FamilyInstanceCreationData data1 =
|
|
|
|
|
|
new(
|
|
|
|
|
|
locLeft,
|
|
|
|
|
|
SelectedFamilyType,
|
|
|
|
|
|
referVector,
|
|
|
|
|
|
level,
|
|
|
|
|
|
Autodesk.Revit.DB.Structure.StructuralType.Footing
|
|
|
|
|
|
);
|
|
|
|
|
|
dataList.Add(data1);
|
|
|
|
|
|
}
|
|
|
|
|
|
var loc = point.Add(referVector.Normalize() * x) + y * XYZ.BasisZ;
|
|
|
|
|
|
Autodesk.Revit.Creation.FamilyInstanceCreationData data =
|
|
|
|
|
|
new(
|
|
|
|
|
|
loc,
|
|
|
|
|
|
SelectedFamilyType,
|
|
|
|
|
|
referVector,
|
|
|
|
|
|
level,
|
|
|
|
|
|
Autodesk.Revit.DB.Structure.StructuralType.Footing
|
|
|
|
|
|
);
|
|
|
|
|
|
dataList.Add(data);
|
|
|
|
|
|
}
|
|
|
|
|
|
doc.Create.NewFamilyInstances2(dataList);
|
|
|
|
|
|
},
|
|
|
|
|
|
"创建轨枕"
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
ex.StackTrace.ToLog();
|
|
|
|
|
|
//曲线之间的过度可能不平滑,平面点在三维点交点point==null
|
|
|
|
|
|
MessageBox.Show(ex.Message, "实例布置失败", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
|
|
|
|
IsRunning = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Document familyDocument = null;
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
if (SelectedProfileFamilyType == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
IsRunning = false;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var point = spline3D.GetEndPoint(0);
|
|
|
|
|
|
//非刚性变换,会改变原几何,此变换在曲线计算导数时,为非刚性变换,各个basis的模不等于1
|
|
|
|
|
|
var transform = spline3D.ComputeDerivatives(0, false);
|
|
|
|
|
|
|
|
|
|
|
|
familyDocument = doc.EditFamily(SelectedProfileFamilyType.Family);
|
|
|
|
|
|
|
|
|
|
|
|
var tangent = transform.BasisX.Normalize();
|
|
|
|
|
|
var rightBasis = tangent.CrossProduct(XYZ.BasisZ).Normalize();
|
|
|
|
|
|
var topBasis = rightBasis.CrossProduct(tangent).Normalize();
|
|
|
|
|
|
if (!XYZ.IsWithinLengthLimits(point))
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("点不在Revit模型空间内,内部原点坐标与模型线相距太远", "错误");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//var d0 = transform.BasisX.CrossProduct(XYZ.BasisZ).DotProduct(transform.BasisX);
|
|
|
|
|
|
//var translate = Transform.CreateTranslation(transform.Origin);
|
|
|
|
|
|
//var rotate = Transform.CreateRotationAtPoint(
|
|
|
|
|
|
// -rightBasis,
|
|
|
|
|
|
// XYZ.BasisZ.AngleTo(transform.BasisX),
|
|
|
|
|
|
// XYZ.Zero);
|
|
|
|
|
|
//double det = transform.Determinant;
|
|
|
|
|
|
//Transform profileTransform = rotate.Multiply(translate);
|
|
|
|
|
|
//构造放样截面的变换
|
|
|
|
|
|
var profileTransform = Transform.Identity;
|
|
|
|
|
|
profileTransform.Origin = point;
|
|
|
|
|
|
profileTransform.BasisX = rightBasis;
|
|
|
|
|
|
profileTransform.BasisY = topBasis;
|
|
|
|
|
|
profileTransform.BasisZ = tangent;
|
|
|
|
|
|
|
|
|
|
|
|
//偏移变换
|
|
|
|
|
|
var offsetTransform = Transform.CreateTranslation(new XYZ(OffsetX, OffsetY, 0) / 304.8);
|
|
|
|
|
|
|
|
|
|
|
|
//修改类型以适应选择的族类型,保证几何与族类型一致
|
|
|
|
|
|
familyDocument.Invoke(_ =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var fm = familyDocument.FamilyManager;
|
|
|
|
|
|
foreach (FamilyType type in fm.Types)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (type.Name == SelectedProfileFamilyType.Name)
|
|
|
|
|
|
{
|
|
|
|
|
|
fm.CurrentType = type;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
//获取截面
|
|
|
|
|
|
var profiles = familyDocument
|
|
|
|
|
|
.OfClass<CurveElement>()
|
|
|
|
|
|
.OfType<CurveElement>()
|
|
|
|
|
|
.Select(c => c.GeometryCurve)
|
|
|
|
|
|
.ToList();
|
|
|
|
|
|
#if DEBUG
|
|
|
|
|
|
//famdoc.Invoke(_ =>
|
|
|
|
|
|
//{
|
|
|
|
|
|
//var plane = Plane.CreateByOriginAndBasis(point, rightBasis, topBasis);
|
|
|
|
|
|
// SketchPlane sketch = SketchPlane.Create(
|
|
|
|
|
|
// famdoc,
|
|
|
|
|
|
// plane)
|
|
|
|
|
|
// );
|
|
|
|
|
|
// var mc = famdoc.Create.NewModelCurve(spline3D, sketch);
|
|
|
|
|
|
//});
|
|
|
|
|
|
#endif
|
|
|
|
|
|
//famdoc.Invoke(
|
|
|
|
|
|
// _ =>
|
|
|
|
|
|
// {
|
|
|
|
|
|
// SketchPlane sketch = SketchPlane.Create(famdoc, Plane.CreateByNormalAndOrigin(XYZ.BasisZ, XYZ.Zero));
|
|
|
|
|
|
|
|
|
|
|
|
// foreach (var item in profiles)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// var mc = famdoc.Create.NewModelCurve(item, sketch);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// });
|
|
|
|
|
|
doc.Invoke(
|
|
|
|
|
|
_ =>
|
|
|
|
|
|
{
|
|
|
|
|
|
//if (!SelectedProfileFamilyType.IsActive)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// SelectedProfileFamilyType.Activate();
|
|
|
|
|
|
//}
|
|
|
|
|
|
//if (loop.IsOpen())
|
|
|
|
|
|
//{
|
|
|
|
|
|
// return;
|
|
|
|
|
|
//}
|
|
|
|
|
|
//familyDocument.FamilyCreate.NewSweep
|
|
|
|
|
|
Solid solidAnother = null;
|
|
|
|
|
|
var options = new SolidOptions(
|
|
|
|
|
|
SelectedMaterial == null ? ElementId.InvalidElementId : SelectedMaterial.Id,
|
|
|
|
|
|
ElementId.InvalidElementId
|
|
|
|
|
|
);
|
|
|
|
|
|
//获取截面的曲线集合
|
2025-07-11 09:20:23 +08:00
|
|
|
|
var list = SpatialAssist.GroupContinuousCurves(profiles);
|
2024-09-22 11:05:41 +08:00
|
|
|
|
//生成截面线串
|
|
|
|
|
|
var loops = list.Select(cs => CurveLoop.Create(cs)).ToList();
|
|
|
|
|
|
//两侧放在前面,先复制
|
|
|
|
|
|
if (IsTwoSides)
|
|
|
|
|
|
{
|
|
|
|
|
|
var loopsAnother = new List<CurveLoop>();
|
|
|
|
|
|
var offsetTransformAnother = Transform.CreateTranslation(new XYZ(-OffsetX, OffsetY, 0) / 304.8);
|
|
|
|
|
|
//var offsetTransformAnother = Transform.CreateReflection(Plane.CreateByNormalAndOrigin(XYZ.BasisX, XYZ.Zero));
|
|
|
|
|
|
foreach (var item in loops)
|
|
|
|
|
|
{
|
|
|
|
|
|
loopsAnother.Add(CurveLoop.CreateViaCopy(item));
|
|
|
|
|
|
}
|
|
|
|
|
|
foreach (var item in loopsAnother)
|
|
|
|
|
|
{
|
|
|
|
|
|
item.Transform(offsetTransformAnother);
|
|
|
|
|
|
item.Transform(profileTransform);
|
|
|
|
|
|
}
|
|
|
|
|
|
solidAnother = GeometryCreationUtilities.CreateFixedReferenceSweptGeometry(
|
|
|
|
|
|
CurveLoop.Create([spline3D]),
|
|
|
|
|
|
0,
|
|
|
|
|
|
0,
|
|
|
|
|
|
loopsAnother,
|
|
|
|
|
|
XYZ.BasisZ,
|
|
|
|
|
|
options
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
foreach (var item in loops)
|
|
|
|
|
|
{
|
|
|
|
|
|
item.Transform(offsetTransform);
|
|
|
|
|
|
item.Transform(profileTransform);
|
|
|
|
|
|
}
|
|
|
|
|
|
//foreach (var item in loops)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// foreach (var curve in item)
|
|
|
|
|
|
// {
|
2025-12-28 11:47:54 +08:00
|
|
|
|
// previewIds.Add(DebugExtensions.CreateTransientElements(doc, curve));
|
2024-09-22 11:05:41 +08:00
|
|
|
|
// }
|
|
|
|
|
|
//}
|
|
|
|
|
|
//var solid = GeometryCreationUtilities.CreateSweptGeometry(
|
|
|
|
|
|
// CurveLoop.Create([spline3D]),
|
|
|
|
|
|
// 0,
|
|
|
|
|
|
// 0,
|
|
|
|
|
|
// loops,
|
|
|
|
|
|
// options);
|
|
|
|
|
|
var solid = GeometryCreationUtilities.CreateFixedReferenceSweptGeometry(
|
|
|
|
|
|
CurveLoop.Create([spline3D]),
|
|
|
|
|
|
0,
|
|
|
|
|
|
0,
|
|
|
|
|
|
loops,
|
|
|
|
|
|
XYZ.BasisZ,
|
|
|
|
|
|
options
|
|
|
|
|
|
);
|
|
|
|
|
|
var geos = new List<GeometryObject>() { solid };
|
|
|
|
|
|
if (IsTwoSides && solidAnother != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
geos.Add(solidAnother);
|
|
|
|
|
|
}
|
|
|
|
|
|
var shape = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel));
|
|
|
|
|
|
shape.SetShape(geos);
|
|
|
|
|
|
},
|
|
|
|
|
|
"曲线布置"
|
|
|
|
|
|
);
|
|
|
|
|
|
IsRunning = false;
|
|
|
|
|
|
familyDocument.Close(false);
|
|
|
|
|
|
//spline3D.CreateOffset();
|
|
|
|
|
|
//SketchPlane sketch = SketchPlane.Create(Document, Plane.CreateByNormalAndOrigin(p4, p1));
|
|
|
|
|
|
//var mc = Document.Create.NewModelCurve(spline3D, sketch);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
familyDocument?.Close(false);
|
|
|
|
|
|
ex.StackTrace.ToLog();
|
|
|
|
|
|
MessageBox.Show(ex.Message, "轮廓放样失败", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
|
|
|
|
IsRunning = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
"基于曲线创建模型"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
partial void OnCenterCurveTypeChanged(CenterCurveType value)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (value)
|
|
|
|
|
|
{
|
|
|
|
|
|
case CenterCurveType.ModelCurve:
|
|
|
|
|
|
Precision = 1;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case CenterCurveType.MassCurve:
|
|
|
|
|
|
Precision = 1;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case CenterCurveType.DWGCurve:
|
|
|
|
|
|
Precision = 2;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private bool CanCreate => !IsRunning && !HasErrors && (SelectedProfileFamilyType != null || SelectedFamilyType != null);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//public double Precision
|
|
|
|
|
|
//{
|
|
|
|
|
|
// get { return precision; }
|
|
|
|
|
|
// set { SetProperty(ref precision, value, true); }
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
//public double Spacing
|
|
|
|
|
|
//{
|
|
|
|
|
|
// get { return spacing; }
|
|
|
|
|
|
// set { SetProperty(ref spacing, value, true); }
|
|
|
|
|
|
//}
|
|
|
|
|
|
}
|
|
|
|
|
|
public enum CenterCurveType
|
|
|
|
|
|
{
|
|
|
|
|
|
ModelCurve,
|
|
|
|
|
|
MassCurve,
|
|
|
|
|
|
DWGCurve,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|