添加项目文件。
This commit is contained in:
117
Sai.RvKits/RvCommon/AlignModelElement.cs
Normal file
117
Sai.RvKits/RvCommon/AlignModelElement.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using Autodesk.Revit.DB;
|
||||
|
||||
|
||||
namespace Sai.RvKits.RvCommon;
|
||||
|
||||
internal class AlignModelElement
|
||||
{
|
||||
|
||||
private readonly View ownerView;
|
||||
|
||||
public AlignModelElement(Element e)
|
||||
{
|
||||
Parent = e;
|
||||
var doc = e.Document;
|
||||
|
||||
ownerView = doc.GetElement(e.OwnerViewId) != null ? doc.GetElement(e.OwnerViewId) as View : doc.ActiveView;
|
||||
|
||||
//var viewPlane = Plane.CreateByNormalAndOrigin(ownerView is View3D ? XYZ.BasisZ : ownerView!.ViewDirection, ownerView.Origin);
|
||||
|
||||
var elementBBox = e.get_BoundingBox(ownerView);
|
||||
|
||||
var max = elementBBox.Max;
|
||||
var min = elementBBox.Min;
|
||||
//var globalMax = elementBBox.Max;
|
||||
//var globalMin = elementBBox.Min;
|
||||
|
||||
//var distanceProjected = ProjectedDistance(viewPlane, globalMax, globalMin);
|
||||
|
||||
//XYZ alternateMax = new(globalMax.X, globalMin.Y, globalMax.Z);
|
||||
//XYZ alternateMin = new(globalMin.X, globalMax.Y, globalMin.Z);
|
||||
//var alternateDistanceProjected = ProjectedDistance(viewPlane, alternateMax, alternateMin);
|
||||
|
||||
//if (alternateDistanceProjected > distanceProjected)
|
||||
//{
|
||||
// globalMax = alternateMax;
|
||||
// globalMin = alternateMin;
|
||||
//}
|
||||
|
||||
//var ownerViewTransform = ownerView.CropBox.Transform;
|
||||
//var max = ownerViewTransform.Inverse.OfPoint(globalMax); //Max in the coordinate space of the view
|
||||
//var min = ownerViewTransform.Inverse.OfPoint(globalMin); //Min in the coordinate space of the view
|
||||
|
||||
UpLeft = new XYZ(Math.Min(min.X, max.X), Math.Max(max.Y, min.Y), 0);
|
||||
UpRight = new XYZ(Math.Max(min.X, max.X), Math.Max(max.Y, min.Y), 0);
|
||||
DownLeft = new XYZ(Math.Min(min.X, max.X), Math.Min(max.Y, min.Y), 0);
|
||||
DownRight = new XYZ(Math.Max(min.X, max.X), Math.Min(max.Y, min.Y), 0);
|
||||
Center = (UpRight + DownLeft) / 2;
|
||||
Bottom = min.Z;
|
||||
Top = max.Z;
|
||||
Middle = (max.Z + min.Z) / 2;
|
||||
//if (ownerView is View3D)
|
||||
//{
|
||||
// Bottom = min.Z;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// Bottom = Math.Min(max.Z, min.Z);
|
||||
//}
|
||||
}
|
||||
|
||||
//private static double ProjectedDistance(Plane plane, XYZ pointA, XYZ pointB)
|
||||
//{
|
||||
// //To be tested
|
||||
// var uva = plane.ProjectOf(pointA);
|
||||
// var uvb = plane.ProjectOf(pointB);
|
||||
// return uva.DistanceTo(uvb);
|
||||
//}
|
||||
|
||||
public void MoveTo(XYZ point, AlignType alignType)
|
||||
{
|
||||
if (!Parent.Pinned)
|
||||
{
|
||||
var displacementVector = alignType switch
|
||||
{
|
||||
AlignType.Left => point - UpLeft,
|
||||
AlignType.Right => point - UpRight,
|
||||
AlignType.Up => point - UpRight,
|
||||
AlignType.Down => point - DownRight,
|
||||
AlignType.HorizontallyCenter => point - Center,
|
||||
AlignType.VerticallyCenter => point - Center,
|
||||
AlignType.Bottom => XYZ.BasisZ * (point.Z - Bottom),
|
||||
AlignType.Top => XYZ.BasisZ * (point.Z - Top),
|
||||
AlignType.Middle => XYZ.BasisZ * (point.Z - Middle),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(alignType), alignType, null)
|
||||
};
|
||||
|
||||
//位置不一样,移动
|
||||
if (!displacementVector.IsZeroLength())
|
||||
{
|
||||
//var translate = ownerView.CropBox.Transform.OfVector(displacementVector);
|
||||
//Parent.Location.Move(translate);
|
||||
ElementTransformUtils.MoveElement(Parent.Document, Parent.Id, displacementVector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public double Bottom { get; }
|
||||
/// <summary>
|
||||
/// 水平面的中心
|
||||
/// </summary>
|
||||
public XYZ Center { get; }
|
||||
|
||||
public XYZ DownLeft { get; }
|
||||
|
||||
public XYZ DownRight { get; }
|
||||
/// <summary>
|
||||
/// 垂向的中心
|
||||
/// </summary>
|
||||
public double Middle { get; }
|
||||
|
||||
public Element Parent { get; }
|
||||
public double Top { get; }
|
||||
|
||||
public XYZ UpLeft { get; }
|
||||
|
||||
public XYZ UpRight { get; }
|
||||
}
|
||||
32
Sai.RvKits/RvCommon/AlignType.cs
Normal file
32
Sai.RvKits/RvCommon/AlignType.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Sai.RvKits.RvCommon;
|
||||
|
||||
public enum AlignType
|
||||
{
|
||||
[Description("左对齐")]
|
||||
Left,
|
||||
[Description("右对齐")]
|
||||
Right,
|
||||
[Description("上对齐")]
|
||||
Up,
|
||||
[Description("下对齐")]
|
||||
Down,
|
||||
/// <summary>
|
||||
/// Y轴中心对齐,水平位置居中
|
||||
/// </summary>
|
||||
[Description("水平居中")]
|
||||
HorizontallyCenter,
|
||||
/// <summary>
|
||||
/// X轴中心对齐,垂直居中对齐
|
||||
/// </summary>
|
||||
[Description("垂直居中")]
|
||||
VerticallyCenter,
|
||||
|
||||
[Description("底对齐")]
|
||||
Bottom,
|
||||
[Description("中对齐")]
|
||||
Middle,
|
||||
[Description("顶对齐")]
|
||||
Top,
|
||||
}
|
||||
49
Sai.RvKits/RvCommon/AutoSaveCmd.cs
Normal file
49
Sai.RvKits/RvCommon/AutoSaveCmd.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Autodesk.Revit.Attributes;
|
||||
using Autodesk.Revit.UI;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External;
|
||||
using Nice3point.Revit.Toolkit.External.Handlers;
|
||||
|
||||
namespace Sai.RvKits.RvCommon;
|
||||
|
||||
[Transaction(TransactionMode.Manual)]
|
||||
[Regeneration(RegenerationOption.Manual)]
|
||||
public class AutoSaveCmd : ExternalCommand
|
||||
{
|
||||
private readonly System.Timers.Timer timer = Variables.Timer;
|
||||
public override void Execute()
|
||||
{
|
||||
if (string.IsNullOrEmpty(Document.PathName))
|
||||
{
|
||||
ErrorMessage = "当前文件尚未保存,请先保存文件";
|
||||
Result = Result.Failed;
|
||||
return;
|
||||
}
|
||||
AutoSaveViewModel viewModel = new();
|
||||
AutoSaveView view = new()
|
||||
{
|
||||
DataContext = viewModel
|
||||
};
|
||||
view.ShowDialog();
|
||||
if (view.DialogResult == true)
|
||||
{
|
||||
if (Properties.Settings.Default.AutoSave)
|
||||
{
|
||||
if (Properties.Settings.Default.AutoSaveIntervalTime >= 1)
|
||||
{
|
||||
timer.Interval = Properties.Settings.Default.AutoSaveIntervalTime * 60 * 1000;
|
||||
}
|
||||
Properties.Settings.Default.Save();
|
||||
//timer.Enabled = Properties.Settings.Default.AutoSave;
|
||||
timer.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
timer.Stop();
|
||||
}
|
||||
}
|
||||
Result = Result.Succeeded;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
37
Sai.RvKits/RvCommon/AutoSaveView.xaml
Normal file
37
Sai.RvKits/RvCommon/AutoSaveView.xaml
Normal file
@@ -0,0 +1,37 @@
|
||||
<ex:FluentWindowEx
|
||||
x:Class="Sai.RvKits.RvCommon.AutoSaveView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:ex="https://github.com/sherlockforrest/Wpf.Ui.Extend"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:rvCommon="clr-namespace:Sai.RvKits.RvCommon"
|
||||
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
||||
Title="自动保存"
|
||||
Width="300"
|
||||
d:DataContext="{d:DesignInstance Type=rvCommon:AutoSaveViewModel}"
|
||||
mc:Ignorable="d">
|
||||
<b:Interaction.Triggers>
|
||||
<b:EventTrigger EventName="Closing">
|
||||
<b:InvokeCommandAction Command="{Binding ClosingCommand}" />
|
||||
</b:EventTrigger>
|
||||
</b:Interaction.Triggers>
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/Sai.RvKits;component/WPFUI.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<ex:AutoGrid Margin="5" VerticalAlignment="Center">
|
||||
<CheckBox x:Name="CbAutoSave" IsChecked="{Binding IsActiveAutoSave, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<TextBlock VerticalAlignment="Center" Text="自动保存时间间隔(分钟):" />
|
||||
<TextBox
|
||||
x:Name="TbIntervalMinutes"
|
||||
Width="80"
|
||||
InputMethod.IsInputMethodEnabled="False"
|
||||
IsEnabled="{Binding IsChecked, ElementName=CbAutoSave}"
|
||||
Text="{Binding IntervalTime, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</ex:AutoGrid>
|
||||
</ex:FluentWindowEx>
|
||||
16
Sai.RvKits/RvCommon/AutoSaveView.xaml.cs
Normal file
16
Sai.RvKits/RvCommon/AutoSaveView.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
using Wpf.Ui.Extend.Controls;
|
||||
|
||||
namespace Sai.RvKits.RvCommon;
|
||||
|
||||
/// <summary>
|
||||
/// AutoSaveView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class AutoSaveView : FluentWindowEx
|
||||
{
|
||||
public AutoSaveView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
33
Sai.RvKits/RvCommon/AutoSaveViewModel.cs
Normal file
33
Sai.RvKits/RvCommon/AutoSaveViewModel.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace Sai.RvKits.RvCommon;
|
||||
|
||||
public partial class AutoSaveViewModel : ObservableValidator
|
||||
{
|
||||
public AutoSaveViewModel()
|
||||
{
|
||||
IsActiveAutoSave = Properties.Settings.Default.IsActiveAutoSave;
|
||||
IntervalTime = Properties.Settings.Default.AutoSaveIntervalTime;
|
||||
}
|
||||
[ObservableProperty]
|
||||
private bool isActiveAutoSave;
|
||||
|
||||
[Required(ErrorMessage = "不可为空")]
|
||||
[DefaultValue(15)]
|
||||
[NotifyDataErrorInfo]
|
||||
[Range(5, 30, ErrorMessage = "输入值应在5~30分钟之间")]
|
||||
[ObservableProperty]
|
||||
private int intervalTime;
|
||||
|
||||
|
||||
[RelayCommand]
|
||||
private void Closing()
|
||||
{
|
||||
Properties.Settings.Default.IsActiveAutoSave = IsActiveAutoSave;
|
||||
Properties.Settings.Default.AutoSaveIntervalTime = IntervalTime;
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
}
|
||||
28
Sai.RvKits/RvCommon/CustomLeader.cs
Normal file
28
Sai.RvKits/RvCommon/CustomLeader.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Autodesk.Revit.DB;
|
||||
|
||||
namespace Sai.RvKits.RvCommon
|
||||
{
|
||||
internal class CustomLeader
|
||||
{
|
||||
public CustomLeader(Leader leader)
|
||||
{
|
||||
End = leader.End;
|
||||
Elbow = leader.Elbow;
|
||||
}
|
||||
|
||||
public CustomLeader()
|
||||
{
|
||||
End = new XYZ(0, 0, 0);
|
||||
Elbow = new XYZ(0, 0, 0);
|
||||
}
|
||||
|
||||
public CustomLeader(XYZ end, XYZ elbow)
|
||||
{
|
||||
End = end;
|
||||
Elbow = elbow;
|
||||
}
|
||||
|
||||
public XYZ End { get; set; }
|
||||
public XYZ Elbow { get; set; }
|
||||
}
|
||||
}
|
||||
96
Sai.RvKits/RvCommon/DetailSelectFiltersView.xaml
Normal file
96
Sai.RvKits/RvCommon/DetailSelectFiltersView.xaml
Normal file
@@ -0,0 +1,96 @@
|
||||
<ex:FluentWindowEx
|
||||
x:Class="Sai.RvKits.RvCommon.DetailSelectFiltersView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:ex="https://github.com/sherlockforrest/Wpf.Ui.Extend"
|
||||
xmlns:local="clr-namespace:Sai.RvKits.RvCommon"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mvvm="clr-namespace:Sai.Toolkit.Mvvm"
|
||||
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
||||
Title="构件明细"
|
||||
Width="800"
|
||||
Height="450"
|
||||
d:DataContext="{d:DesignInstance Type=local:DetailSelectFiltersViewModel}"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/Sai.RvKits;component/WPFUI.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<!--<mvvm:BindingProxy x:Key="DocumentProxy" Data="{Binding Document}" />-->
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<ex:AutoGrid
|
||||
ChildMargin="5"
|
||||
Columns="*"
|
||||
Rows="*,Auto">
|
||||
<DataGrid
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
ColumnWidth="Auto"
|
||||
IsReadOnly="True"
|
||||
ItemsSource="{Binding FilteredList}"
|
||||
ToolTip="双击行可快速定位">
|
||||
<b:Interaction.Triggers>
|
||||
<b:EventTrigger EventName="MouseDoubleClick">
|
||||
<b:InvokeCommandAction Command="{Binding ShowElementCommand}" CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}, Mode=FindAncestor}}" />
|
||||
</b:EventTrigger>
|
||||
</b:Interaction.Triggers>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Binding="{Binding Id}" Header="元素ID" />
|
||||
<DataGridTextColumn Binding="{Binding CategoryName}" Header="类别名称" />
|
||||
<DataGridTextColumn
|
||||
Width="Auto"
|
||||
Binding="{Binding Name}"
|
||||
Header="名称" />
|
||||
<!--<DataGridTextColumn Binding="{Binding ReferenceLevel?.Name}" Header="参照标高" />-->
|
||||
<DataGridTextColumn Binding="{Binding LevelName}" Header="标高" />
|
||||
<DataGridTextColumn Binding="{Binding ReferenceLevel}" Header="参照标高" />
|
||||
<DataGridTextColumn Binding="{Binding HostName}" Header="主体" />
|
||||
<DataGridTextColumn Binding="{Binding Offset}" Header="偏移" />
|
||||
<!--<DataGridTextColumn Binding="{Binding Path=LevelId, Converter={StaticResource IdToNameConverter}, ConverterParameter={StaticResource DocumentProxy}}" Header="标高" />-->
|
||||
<!--<DataGridTextColumn Header="标高">
|
||||
<DataGridTextColumn.Binding>
|
||||
<MultiBinding Converter="{StaticResource IdToNameConverter}">
|
||||
<Binding Path="DataContext" RelativeSource="{RelativeSource Mode=Self}" />
|
||||
<Binding Path="LevelId" />
|
||||
</MultiBinding>
|
||||
</DataGridTextColumn.Binding>
|
||||
</DataGridTextColumn>-->
|
||||
<DataGridTextColumn Binding="{Binding MEPSystemName}" Header="系统类型" />
|
||||
<DataGridTextColumn Binding="{Binding RoomName}" Header="所属房间" />
|
||||
<DataGridTextColumn Binding="{Binding Phase}" Header="创建阶段" />
|
||||
<DataGridTextColumn Binding="{Binding Number}" Header="标记" />
|
||||
<DataGridTextColumn Binding="{Binding Comment}" Header="注释" />
|
||||
<!--<DataGridTextColumn Binding="{Binding ErrorMessage}" Header="错误信息" />-->
|
||||
<!--<DataGridTemplateColumn Header="操作">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
-->
|
||||
<!-- 按钮参数绑定到当前行的绑定的Item -->
|
||||
<!--
|
||||
<Button
|
||||
Command="{Binding DataContext.ShowElementCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="定位构件" />
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>-->
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
<ex:StackPanelEx Grid.Row="1" Orientation="Horizontal">
|
||||
<CheckBox
|
||||
Margin="5"
|
||||
Content="剖切"
|
||||
IsChecked="{Binding IsCutting, UpdateSourceTrigger=PropertyChanged}"
|
||||
ToolTip="仅三维视图可用" />
|
||||
<ui:TextBox
|
||||
Margin="5"
|
||||
ex:StackPanelEx.Fill="Fill"
|
||||
PlaceholderText="请输入检索属性条目"
|
||||
Text="{Binding SearchProp, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</ex:StackPanelEx>
|
||||
</ex:AutoGrid>
|
||||
</ex:FluentWindowEx>
|
||||
29
Sai.RvKits/RvCommon/DetailSelectFiltersView.xaml.cs
Normal file
29
Sai.RvKits/RvCommon/DetailSelectFiltersView.xaml.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
using Wpf.Ui.Extend.Controls;
|
||||
|
||||
namespace Sai.RvKits.RvCommon
|
||||
{
|
||||
/// <summary>
|
||||
/// DetailSelectFiltersView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class DetailSelectFiltersView : FluentWindowEx
|
||||
{
|
||||
public DetailSelectFiltersView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
162
Sai.RvKits/RvCommon/DetailSelectFiltersViewModel.cs
Normal file
162
Sai.RvKits/RvCommon/DetailSelectFiltersViewModel.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.UI;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External.Handlers;
|
||||
|
||||
namespace Sai.RvKits.RvCommon
|
||||
{
|
||||
public partial class DetailSelectFiltersViewModel : ObservableObject
|
||||
{
|
||||
private readonly ActionEventHandler handler;
|
||||
|
||||
[ObservableProperty]
|
||||
ICollectionView filteredList;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool isCutting;
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<SelectionElement> items;
|
||||
[ObservableProperty]
|
||||
private string searchProp;
|
||||
private readonly UIApplication uiapp;
|
||||
|
||||
public DetailSelectFiltersViewModel(UIApplication uiapp, ActionEventHandler handler)
|
||||
{
|
||||
var elemIds = uiapp.ActiveUIDocument.Selection.GetElementIds();
|
||||
Items = [];
|
||||
this.uiapp = uiapp;
|
||||
this.handler = handler;
|
||||
var doc = uiapp.ActiveUIDocument.Document;
|
||||
foreach (var elementId in elemIds)
|
||||
{
|
||||
//var elem = doc.GetElement(elementId);
|
||||
//var param = elem.GetParameters("ID-100-编号").FirstOrDefault();
|
||||
//if (param != null && param.AsString() == string.Empty)
|
||||
//{
|
||||
// Items.Add(doc.GetElement(elementId));
|
||||
//}
|
||||
var element = doc.GetElement(elementId);
|
||||
if (element.IsValidObject)
|
||||
{
|
||||
Items.Add(new SelectionElement(element));
|
||||
}
|
||||
}
|
||||
FilteredList = CollectionViewSource.GetDefaultView(Items);
|
||||
|
||||
}
|
||||
|
||||
partial void OnSearchPropChanged(string value)
|
||||
{
|
||||
FilteredList.Filter = o =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(SearchProp))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
var item = o as SelectionElement;
|
||||
return (item?.Name != null && item.Name.Contains(SearchProp))
|
||||
|| (item?.Number != null && item.Number.Contains(SearchProp))
|
||||
|| (item?.Comment != null && item.Comment.Contains(SearchProp));
|
||||
};
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void ShowElement(object obj)
|
||||
{
|
||||
if (obj is not SelectionElement selection) return;
|
||||
var model = selection.Element;
|
||||
var uidoc = uiapp.ActiveUIDocument;
|
||||
if (model.IsValidObject)
|
||||
{
|
||||
ZoomElement(model, uidoc);
|
||||
}
|
||||
else
|
||||
{
|
||||
Items.Remove(selection);
|
||||
}
|
||||
}
|
||||
private void ZoomElement(Element model, UIDocument uidoc)
|
||||
{
|
||||
var views = uidoc.Document.OfClass<View>().OfType<View>().Where(v => !v.IsTemplate);
|
||||
View targetView = null;
|
||||
if (model.IsVisible(uidoc.ActiveView))
|
||||
{
|
||||
targetView = uidoc.ActiveView;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var v in views)
|
||||
{
|
||||
if (model.IsVisible(v))
|
||||
{
|
||||
targetView = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetView == null)
|
||||
{
|
||||
MessageBox.Show("未找到可见的视图", "错误");
|
||||
return;
|
||||
}
|
||||
uidoc.ActiveView = targetView;
|
||||
|
||||
handler.Raise(
|
||||
_ =>
|
||||
{
|
||||
uidoc.Document
|
||||
.Invoke(
|
||||
_ =>
|
||||
{
|
||||
if (targetView is View3D view3D && IsCutting)
|
||||
{
|
||||
view3D.SectionBoxElement(model.Id);
|
||||
}
|
||||
}, "剖切元素");
|
||||
});
|
||||
targetView.ZoomElement(uidoc, model.Id);
|
||||
uidoc.Selection.SetElementIds([model.Id]);
|
||||
}
|
||||
}
|
||||
|
||||
public class SelectionElement(Element element)
|
||||
{
|
||||
public string CategoryName => element.Category?.Name;
|
||||
|
||||
public string Comment => element.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS)?.AsString();
|
||||
public Element Element => element;
|
||||
public string HostName => element is FamilyInstance { Host: not null } instance ? instance.Host.Name : null;
|
||||
public ElementId Id => element.Id;
|
||||
public string LevelName => element.LevelId != ElementId.InvalidElementId ? (doc.GetElement(element.LevelId)?.Name) : null;
|
||||
|
||||
public string MEPSystemName => element is MEPCurve mep ? doc.GetElement(mep.MEPSystem.GetTypeId()).Name : null;
|
||||
public string Name => element.Name;
|
||||
public string Number => element.get_Parameter(BuiltInParameter.DOOR_NUMBER)?.AsString();
|
||||
|
||||
public string Offset =>
|
||||
element is FamilyInstance instance
|
||||
? (instance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM)?.AsValueString())
|
||||
: null;
|
||||
|
||||
public string Phase => element.CreatedPhaseId == ElementId.InvalidElementId ? null : doc.GetElement(element.CreatedPhaseId).Name;
|
||||
|
||||
public string ReferenceLevel =>
|
||||
element is MEPCurve mep
|
||||
? mep.ReferenceLevel.Name
|
||||
: (element.get_Parameter(BuiltInParameter.FAMILY_LEVEL_PARAM)?.AsValueString());
|
||||
|
||||
public string RoomName => element is FamilyInstance instance && instance.Room != null ? instance.Room.Name : null;
|
||||
|
||||
private readonly Document doc = element.Document;
|
||||
|
||||
}
|
||||
}
|
||||
19
Sai.RvKits/RvCommon/InstanceCreatorCmd.cs
Normal file
19
Sai.RvKits/RvCommon/InstanceCreatorCmd.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using Autodesk.Revit.Attributes;
|
||||
using Autodesk.Revit.DB;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External;
|
||||
|
||||
namespace Sai.RvKits.RvCommon;
|
||||
|
||||
/// <summary>
|
||||
/// Revit执行命令
|
||||
/// </summary>
|
||||
[Transaction(TransactionMode.Manual)]
|
||||
[Regeneration(RegenerationOption.Manual)]
|
||||
public class InstanceCreatorCmd : ExternalCommand
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
WinDialogHelper.ShowModeless<InstanceCreatorView>(new InstanceCreatorViewModel(UiDocument));
|
||||
}
|
||||
}
|
||||
61
Sai.RvKits/RvCommon/InstanceCreatorView.xaml
Normal file
61
Sai.RvKits/RvCommon/InstanceCreatorView.xaml
Normal file
@@ -0,0 +1,61 @@
|
||||
<ex:FluentWindowEx
|
||||
x:Class="Sai.RvKits.RvCommon.InstanceCreatorView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:ex="https://github.com/sherlockforrest/Wpf.Ui.Extend"
|
||||
xmlns:local="clr-namespace:Sai.RvKits.RvCommon"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
||||
Title="族实例布置"
|
||||
Width="220"
|
||||
Height="340"
|
||||
MinHeight="300"
|
||||
d:DataContext="{d:DesignInstance local:InstanceCreatorViewModel}"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/Sai.RvKits;component/WPFUI.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<ex:StackPanelEx Margin="5" Spacing="5">
|
||||
<ex:ComboBoxEx
|
||||
DisplayMemberPath="Name"
|
||||
ItemsSource="{Binding Families}"
|
||||
PlaceholderText="选择族"
|
||||
SelectedItem="{Binding SelectedFamily, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<ex:ComboBoxEx
|
||||
DisplayMemberPath="Name"
|
||||
IsSynchronizedWithCurrentItem="True"
|
||||
ItemsSource="{Binding FamilySymbols, Mode=OneWay}"
|
||||
PlaceholderText="选择族类型"
|
||||
SelectedItem="{Binding SelectedFamilySymbol, UpdateSourceTrigger=PropertyChanged}"
|
||||
ShowFilterBox="False" />
|
||||
<Image
|
||||
Grid.Row="2"
|
||||
Width="128"
|
||||
Height="128"
|
||||
Source="{Binding Image}" />
|
||||
<ex:TextBoxEx
|
||||
Grid.Row="3"
|
||||
Prefix="偏移量:"
|
||||
Suffix="mm"
|
||||
Text="{Binding Offset}">
|
||||
<!--<TextBox.Text>
|
||||
<Binding Path="Offset" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<rules:DoubleValidationRule xmlns:rules="clr-namespace:Sai.RvKits.ValidationRules" ValidatesOnTargetUpdated="True" />
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</TextBox.Text>-->
|
||||
</ex:TextBoxEx>
|
||||
<Button
|
||||
Grid.Row="4"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding PlaceInstancesCommand}"
|
||||
Content="布置"
|
||||
ToolTip="选择dwg块并布置族实例" />
|
||||
</ex:StackPanelEx>
|
||||
</ex:FluentWindowEx>
|
||||
16
Sai.RvKits/RvCommon/InstanceCreatorView.xaml.cs
Normal file
16
Sai.RvKits/RvCommon/InstanceCreatorView.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows;
|
||||
|
||||
using Wpf.Ui.Controls;
|
||||
|
||||
namespace Sai.RvKits.RvCommon;
|
||||
|
||||
/// <summary>
|
||||
/// InstanceCreatorView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class InstanceCreatorView
|
||||
{
|
||||
public InstanceCreatorView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
326
Sai.RvKits/RvCommon/InstanceCreatorViewModel.cs
Normal file
326
Sai.RvKits/RvCommon/InstanceCreatorViewModel.cs
Normal file
@@ -0,0 +1,326 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.DB.Structure;
|
||||
using Autodesk.Revit.UI;
|
||||
using Autodesk.Revit.UI.Selection;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External.Handlers;
|
||||
// ReSharper disable ConditionIsAlwaysTrueOrFalse
|
||||
|
||||
namespace Sai.RvKits.RvCommon;
|
||||
|
||||
public partial class InstanceCreatorViewModel : ObservableObject
|
||||
{
|
||||
public InstanceCreatorViewModel(UIDocument uiDocument)
|
||||
{
|
||||
this.uiDocument = uiDocument;
|
||||
document = uiDocument.Document;
|
||||
uiDocument.Application.Application.FamilyLoadedIntoDocument += Application_FamilyLoadedIntoDocument;
|
||||
GetAvailableFamilies();
|
||||
}
|
||||
|
||||
private readonly UIDocument uiDocument;
|
||||
~InstanceCreatorViewModel()
|
||||
{
|
||||
uiDocument.Application.Application.FamilyLoadedIntoDocument -= Application_FamilyLoadedIntoDocument;
|
||||
}
|
||||
private void GetAvailableFamilies()
|
||||
{
|
||||
#if REVIT2018 || REVIT2020
|
||||
//过滤掉栏杆族
|
||||
var collector = document
|
||||
.OfClass<Family>()
|
||||
.Cast<Family>()
|
||||
.Where(
|
||||
f =>
|
||||
f.IsEditable
|
||||
&& !f.IsInPlace
|
||||
&& f.GetFamilySymbolIds().Any()
|
||||
&& f.FamilyCategory.Id.IntegerValue is not (-2000127 or -2009013 or -2005301 or -2009060)
|
||||
&& f.FamilyPlacementType
|
||||
is FamilyPlacementType.OneLevelBased
|
||||
or FamilyPlacementType.TwoLevelsBased
|
||||
or FamilyPlacementType.WorkPlaneBased
|
||||
or FamilyPlacementType.OneLevelBasedHosted
|
||||
)
|
||||
.OrderBy(f => f.Name)
|
||||
.ToList();
|
||||
#elif REVIT2025
|
||||
//过滤掉栏杆族
|
||||
var collector = document
|
||||
.OfClass<Family>()
|
||||
.Cast<Family>()
|
||||
.Where(
|
||||
f =>
|
||||
f.IsEditable
|
||||
&& !f.IsInPlace
|
||||
&& f.GetFamilySymbolIds().Any()
|
||||
&& f.FamilyCategory.Id.Value is not (-2000127 or -2009013 or -2005301 or -2009060)
|
||||
&& f.FamilyPlacementType
|
||||
is FamilyPlacementType.OneLevelBased
|
||||
or FamilyPlacementType.TwoLevelsBased
|
||||
or FamilyPlacementType.WorkPlaneBased
|
||||
or FamilyPlacementType.OneLevelBasedHosted
|
||||
)
|
||||
.OrderBy(f => f.Name)
|
||||
.ToList();
|
||||
#endif
|
||||
Families = collector;
|
||||
}
|
||||
|
||||
private void Application_FamilyLoadedIntoDocument(object sender, Autodesk.Revit.DB.Events.FamilyLoadedIntoDocumentEventArgs e)
|
||||
{
|
||||
GetAvailableFamilies();
|
||||
}
|
||||
|
||||
private readonly ActionEventHandler handler = new();
|
||||
|
||||
[ObservableProperty]
|
||||
private BitmapSource image;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(PlaceInstancesCommand))]
|
||||
private bool canPlaceInstance = true;
|
||||
|
||||
private readonly Document document;
|
||||
|
||||
[ObservableProperty]
|
||||
private double offset;
|
||||
|
||||
[ObservableProperty]
|
||||
private Family selectedFamily;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(PlaceInstancesCommand))]
|
||||
private FamilySymbol selectedFamilySymbol;
|
||||
|
||||
[ObservableProperty]
|
||||
private List<Family> families;
|
||||
|
||||
[ObservableProperty]
|
||||
private List<FamilySymbol> familySymbols;
|
||||
|
||||
private bool CanPlace()
|
||||
{
|
||||
return SelectedFamilySymbol != null && CanPlaceInstance;
|
||||
}
|
||||
[RelayCommand(CanExecute = nameof(CanPlace))]
|
||||
private void PlaceInstances()
|
||||
{
|
||||
CanPlaceInstance = false;
|
||||
handler.Raise(_ =>
|
||||
{
|
||||
var family = SelectedFamily;
|
||||
var symbol = SelectedFamilySymbol;
|
||||
var d = Offset / 304.8;
|
||||
Reference reference;
|
||||
try
|
||||
{
|
||||
reference = uiDocument.Selection.PickObject(ObjectType.PointOnElement, new DwgBlockSelection(), "请选择dwg块");
|
||||
}
|
||||
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
|
||||
{
|
||||
CanPlaceInstance = true;
|
||||
return;
|
||||
}
|
||||
|
||||
//图层ID;
|
||||
//Document.HideDwgLayer(referenceFunc, out ElementId columnGraphicStyleId, out GeometryElement columnGeoElem);
|
||||
var dwg = document.GetElement(reference) as ImportInstance;
|
||||
var geoInstances = dwg.GetBlocksByRef(reference);
|
||||
var dwgTransform = dwg!.GetTotalTransform();
|
||||
if (geoInstances == null || !geoInstances.Any())
|
||||
{
|
||||
MessageBox.Show("选中块为子块或选中块的嵌套层级过深,请使用Tab来选择整体快", "识别失败", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
CanPlaceInstance = true;
|
||||
return;
|
||||
}
|
||||
|
||||
document.Invoke(
|
||||
_ =>
|
||||
{
|
||||
if (!symbol.IsActive)
|
||||
{
|
||||
symbol.Activate();
|
||||
}
|
||||
|
||||
switch (family.FamilyPlacementType)
|
||||
{
|
||||
case FamilyPlacementType.OneLevelBased:
|
||||
foreach (var ins in geoInstances)
|
||||
{
|
||||
var level = document.ActiveView.GenLevel;
|
||||
|
||||
GetPose(dwgTransform, ins, out var loc, out var rotation);
|
||||
var familyInstance = document.Create.NewFamilyInstance(loc, symbol, level, StructuralType.NonStructural);
|
||||
document.Regenerate();
|
||||
ElementTransformUtils.RotateElement(document, familyInstance.Id, Line.CreateUnbound(loc, XYZ.BasisZ), rotation);
|
||||
document.Regenerate();
|
||||
var translation = XYZ.BasisZ * d;
|
||||
ElementTransformUtils.MoveElement(document, familyInstance.Id, translation);
|
||||
}
|
||||
|
||||
break;
|
||||
case FamilyPlacementType.OneLevelBasedHosted:
|
||||
#if REVIT2018 || REVIT2020
|
||||
if (family.FamilyCategory.Id.IntegerValue is -2000023 or -2000014)
|
||||
#elif REVIT2025
|
||||
if (family.FamilyCategory.Id.Value is -2000023 or -2000014)
|
||||
#endif
|
||||
{
|
||||
var level = document.ActiveView.GenLevel;
|
||||
foreach (var ins in geoInstances)
|
||||
{
|
||||
GetPose(dwgTransform, ins, out var loc, out var rotation);
|
||||
var minPoint = loc - new XYZ(0.4, 0.4, -level.Elevation);
|
||||
var maxPoint = loc + new XYZ(0.4, 0.4, level.Elevation + 1);
|
||||
var outline = new Outline(minPoint, maxPoint);
|
||||
var intersectsFilter = new BoundingBoxIntersectsFilter(outline);
|
||||
var intersect = document.OfClass<Wall>().WherePasses(intersectsFilter).FirstElement() as Wall;
|
||||
var point = loc + (XYZ.BasisZ * level.Elevation);
|
||||
document.Create.NewFamilyInstance(point, symbol, intersect, level, StructuralType.NonStructural);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case FamilyPlacementType.TwoLevelsBased:
|
||||
foreach (var ins in geoInstances)
|
||||
{
|
||||
var level = document.ActiveView.GenLevel;
|
||||
GetPose(dwgTransform, ins, out var loc, out var rotation);
|
||||
var familyInstance = document.Create.NewFamilyInstance(loc, symbol, level, StructuralType.NonStructural);
|
||||
document.Regenerate();
|
||||
ElementTransformUtils.RotateElement(document, familyInstance.Id, Line.CreateUnbound(loc, XYZ.BasisZ), rotation);
|
||||
document.Regenerate();
|
||||
var translation = XYZ.BasisZ * d;
|
||||
ElementTransformUtils.MoveElement(document, familyInstance.Id, translation);
|
||||
}
|
||||
|
||||
break;
|
||||
case FamilyPlacementType.WorkPlaneBased:
|
||||
foreach (var ins in geoInstances)
|
||||
{
|
||||
GetPose(dwgTransform, ins, out var loc, out var rotation);
|
||||
var familyInstance = document.Create.NewFamilyInstance(
|
||||
loc,
|
||||
symbol,
|
||||
document.ActiveView.SketchPlane,
|
||||
StructuralType.NonStructural
|
||||
);
|
||||
document.Regenerate();
|
||||
ElementTransformUtils.RotateElement(document, familyInstance.Id, Line.CreateUnbound(loc, XYZ.BasisZ), rotation);
|
||||
document.Regenerate();
|
||||
var translation = XYZ.BasisZ * d;
|
||||
ElementTransformUtils.MoveElement(document, familyInstance.Id, translation);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
CanPlaceInstance = true;
|
||||
},
|
||||
"实例布置"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
//private static Dictionary<XYZ, string> WriteCode(UIApplication uiapp)
|
||||
//{
|
||||
// var application = uiapp.Application;
|
||||
// var uiDocument = uiapp.ActiveUIDocument;
|
||||
// var doc = uiDocument.Document;
|
||||
// Reference textRefer;
|
||||
// try
|
||||
// {
|
||||
// //图层ID;
|
||||
// textRefer = uiDocument.Selection.PickObject(
|
||||
// ObjectType.PointOnElement,
|
||||
// new FuncFilter(e => e is ImportInstance import && import.IsLinked && doc.GetElement(e.GetTypeId()) is CADLinkType),
|
||||
// "请选择“链接(非导入)”的Cad文字图层"
|
||||
// );
|
||||
// }
|
||||
// catch (Autodesk.Revit.Exceptions.OperationCanceledException)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
// var dwg = doc.GetElement(textRefer) as ImportInstance;
|
||||
// var textLayerName = dwg.GetLayerName(textRefer);
|
||||
// var path = dwg.GetDwgPath();
|
||||
// var dwgTransform = dwg.GetTotalTransform();
|
||||
|
||||
// using ACadSharp.IO.DwgReader reader = new(path);
|
||||
// var cadDocument = reader.Read();
|
||||
// return cadDocument.Entities
|
||||
// .OfType<ACadSharp.Entities.TextEntity>()
|
||||
// .Where(e => e.Layer.Name == textLayerName)
|
||||
// .ToDictionary(
|
||||
// v =>
|
||||
// {
|
||||
// var loc = dwgTransform.OfPoint(new XYZ(v.InsertPoint.X, v.InsertPoint.Y, v.InsertPoint.Z));
|
||||
// return new XYZ(loc.X, loc.Y, 0);
|
||||
// },
|
||||
// e => e.Value
|
||||
// );
|
||||
//}
|
||||
/// <summary>
|
||||
/// 获取更加准确的位置
|
||||
/// </summary>
|
||||
/// <param name="dwgTransform"></param>
|
||||
/// <param name="ins"></param>
|
||||
/// <param name="loc"></param>
|
||||
/// <param name="rotation"></param>
|
||||
private static void GetPose(Transform dwgTransform, GeometryInstance ins, out XYZ loc, out double rotation)
|
||||
{
|
||||
var blockLocation = ins.Transform.Origin;
|
||||
|
||||
if (ins.Transform.Origin.GetLength() is > 1000 or 0) //块原点距离实际几何重心过远时
|
||||
{
|
||||
//存在标注的情况时,以多段线最准确
|
||||
var b = ins.GetInstanceGeometry().Any(i => i is PolyLine);
|
||||
foreach (var geometryObject in ins.GetInstanceGeometry())
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
if (geometryObject is PolyLine pl)
|
||||
{
|
||||
blockLocation = (pl.GetOutline().MaximumPoint + pl.GetOutline().MinimumPoint) / 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (geometryObject is Line l)
|
||||
{
|
||||
blockLocation = l.Evaluate(0.5, true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (geometryObject is Arc arc)
|
||||
{
|
||||
blockLocation = arc.Center;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loc = dwgTransform.OfPoint(blockLocation);
|
||||
loc = new XYZ(loc.X, loc.Y, 0);
|
||||
rotation = Math.Abs(ins.Transform.BasisX.AngleOnPlaneTo(XYZ.BasisX, XYZ.BasisZ) - (2 * Math.PI));
|
||||
}
|
||||
|
||||
partial void OnSelectedFamilyChanged(Family value)
|
||||
{
|
||||
var doc = value.Document;
|
||||
FamilySymbols = value.GetFamilySymbolIds().Select(id => doc.GetElement(id)).OfType<FamilySymbol>().ToList();
|
||||
}
|
||||
|
||||
partial void OnSelectedFamilySymbolChanged(FamilySymbol value)
|
||||
{
|
||||
Image = value.GetPreviewImage(new System.Drawing.Size(128, 128)).ToBitmapSource();
|
||||
}
|
||||
}
|
||||
23
Sai.RvKits/RvCommon/ModelByCurveCreatorCmd.cs
Normal file
23
Sai.RvKits/RvCommon/ModelByCurveCreatorCmd.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
|
||||
using Autodesk.Revit.Attributes;
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.UI;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External;
|
||||
|
||||
|
||||
namespace Sai.RvKits.RvCommon
|
||||
{
|
||||
[Transaction(TransactionMode.Manual)]
|
||||
[Regeneration(RegenerationOption.Manual)]
|
||||
internal class ModelByCurveCreatorCmd : ExternalCommand
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
WinDialogHelper.ShowModeless<ModelByCurveCreatorView>(new ModelByCurveCreatorViewModel(Document));
|
||||
}
|
||||
}
|
||||
}
|
||||
146
Sai.RvKits/RvCommon/ModelByCurveCreatorView.xaml
Normal file
146
Sai.RvKits/RvCommon/ModelByCurveCreatorView.xaml
Normal file
@@ -0,0 +1,146 @@
|
||||
<ex:FluentWindowEx
|
||||
x:Class="Sai.RvKits.RvCommon.ModelByCurveCreatorView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:ex="https://github.com/sherlockforrest/Wpf.Ui.Extend"
|
||||
xmlns:local="clr-namespace:Sai.RvKits.RvCommon"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
||||
Title="曲线布置"
|
||||
Width="500"
|
||||
d:DataContext="{d:DesignInstance Type=local:ModelByCurveCreatorViewModel}"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary Source="pack://application:,,,/Sai.RvKits;component/WPFUI.xaml" />
|
||||
</Window.Resources>
|
||||
<ex:AutoGrid Columns="*" Rows="*,Auto,Auto">
|
||||
<ex:AutoGrid
|
||||
Grid.Row="0"
|
||||
ChildMargin="5"
|
||||
Columns="*,*"
|
||||
Rows="*">
|
||||
<GroupBox
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Stretch"
|
||||
Header="沿线放样">
|
||||
<ex:StackPanelEx Spacing="5">
|
||||
<ex:ComboBoxEx
|
||||
ItemTemplate="{StaticResource MultiDisplayMemberPath}"
|
||||
ItemsSource="{Binding ProfileFamilyTypes, Mode=OneWay}"
|
||||
PlaceholderText="请选择轮廓类型"
|
||||
SelectedItem="{Binding SelectedProfileFamilyType, UpdateSourceTrigger=PropertyChanged}"
|
||||
ToolTip="选择轮廓类型,未选择则不创建,
右键点击清除选择">
|
||||
<b:Interaction.Triggers>
|
||||
<b:EventTrigger EventName="MouseRightButtonUp">
|
||||
<b:InvokeCommandAction Command="{Binding ClearProfilesSelectionCommand}" />
|
||||
</b:EventTrigger>
|
||||
</b:Interaction.Triggers>
|
||||
</ex:ComboBoxEx>
|
||||
<ex:ComboBoxEx
|
||||
DisplayMemberPath="Name"
|
||||
ItemsSource="{Binding Materials, Mode=OneWay}"
|
||||
PlaceholderText="请选择放样的材质"
|
||||
SelectedItem="{Binding SelectedMaterial, UpdateSourceTrigger=PropertyChanged}"
|
||||
ToolTip="选择放样模型材质,未选择则为默认材质,
右键点击清除选择">
|
||||
<b:Interaction.Triggers>
|
||||
<b:EventTrigger EventName="MouseRightButtonUp">
|
||||
<b:InvokeCommandAction Command="{Binding ClearMaterialSelectionCommand}" />
|
||||
</b:EventTrigger>
|
||||
</b:Interaction.Triggers>
|
||||
</ex:ComboBoxEx>
|
||||
<ex:TextBoxEx
|
||||
InputMethod.IsInputMethodEnabled="False"
|
||||
Prefix="偏移距离X:"
|
||||
Suffix="mm"
|
||||
Text="{Binding OffsetX, StringFormat={}{0:N2}, UpdateSourceTrigger=PropertyChanged}"
|
||||
ToolTip="向右偏移设置为正值,
向左偏移为负值" />
|
||||
<ex:TextBoxEx
|
||||
InputMethod.IsInputMethodEnabled="False"
|
||||
Prefix="偏移距离Y:"
|
||||
Suffix="mm"
|
||||
Text="{Binding OffsetY, StringFormat={}{0:N2}, UpdateSourceTrigger=PropertyChanged}"
|
||||
ToolTip="向上偏移设置为正值,
向下偏移为负值" />
|
||||
</ex:StackPanelEx>
|
||||
</GroupBox>
|
||||
<GroupBox
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Stretch"
|
||||
Header="沿线布置">
|
||||
<ex:StackPanelEx Spacing="5">
|
||||
<ex:ComboBoxEx
|
||||
ItemTemplate="{StaticResource MultiDisplayMemberPath}"
|
||||
ItemsSource="{Binding FamilyTypes, Mode=OneWay}"
|
||||
PlaceholderText="请选择实例类型"
|
||||
SelectedItem="{Binding SelectedFamilyType, UpdateSourceTrigger=PropertyChanged}"
|
||||
ToolTip="选择需要布置的族实例,未选择则不创建,
右键点击清除选择">
|
||||
<b:Interaction.Triggers>
|
||||
<b:EventTrigger EventName="MouseRightButtonUp">
|
||||
<b:InvokeCommandAction Command="{Binding ClearFmailyTypeSelectionCommand}" />
|
||||
</b:EventTrigger>
|
||||
</b:Interaction.Triggers>
|
||||
</ex:ComboBoxEx>
|
||||
<ex:TextBoxEx
|
||||
InputMethod.IsInputMethodEnabled="False"
|
||||
Prefix="水平间距:"
|
||||
Suffix="mm"
|
||||
Text="{Binding Spacing, StringFormat={}{0:N2}, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<ex:TextBoxEx
|
||||
InputMethod.IsInputMethodEnabled="False"
|
||||
Prefix="偏移距离X:"
|
||||
Suffix="mm"
|
||||
Text="{Binding InstanceOffsetX, StringFormat={}{0:N2}, UpdateSourceTrigger=PropertyChanged}"
|
||||
ToolTip="向右偏移设置为正值,
向左偏移为负值" />
|
||||
<ex:TextBoxEx
|
||||
InputMethod.IsInputMethodEnabled="False"
|
||||
Prefix="偏移距离Y:"
|
||||
Suffix="mm"
|
||||
Text="{Binding InstanceOffsetY, StringFormat={}{0:N2}, UpdateSourceTrigger=PropertyChanged}"
|
||||
ToolTip="向上偏移设置为正值,
向下偏移为负值" />
|
||||
</ex:StackPanelEx>
|
||||
</GroupBox>
|
||||
</ex:AutoGrid>
|
||||
<GroupBox
|
||||
Grid.Row="1"
|
||||
Margin="5"
|
||||
Header="中心线类型">
|
||||
<UniformGrid VerticalAlignment="Center" Rows="1">
|
||||
<RadioButton
|
||||
Content="模型线"
|
||||
IsChecked="{Binding CenterCurveType, ConverterParameter={x:Static local:CenterCurveType.ModelCurve}, Converter={StaticResource ComparisonConverter}}"
|
||||
ToolTip="模型线的定位平面为绘制时的工作平面,
如在楼层楼层平面为该楼层高度" />
|
||||
<RadioButton
|
||||
Content="体量族"
|
||||
IsChecked="{Binding CenterCurveType, ConverterParameter={x:Static local:CenterCurveType.MassCurve}, Converter={StaticResource ComparisonConverter}}"
|
||||
ToolTip="体量族中仅包含有一条连续的三维曲线" />
|
||||
<RadioButton
|
||||
Content="dwg链接"
|
||||
IsChecked="{Binding CenterCurveType, ConverterParameter={x:Static local:CenterCurveType.DWGCurve}, Converter={StaticResource ComparisonConverter}}"
|
||||
ToolTip="dwg中仅有一条连续的三维曲线" />
|
||||
</UniformGrid>
|
||||
</GroupBox>
|
||||
<UniformGrid
|
||||
Grid.Row="2"
|
||||
Margin="5"
|
||||
Rows="1">
|
||||
<ex:TextBoxEx
|
||||
InputMethod.IsInputMethodEnabled="False"
|
||||
Prefix="最小细分长度:"
|
||||
Suffix="m"
|
||||
Text="{Binding Precision, UpdateSourceTrigger=PropertyChanged}"
|
||||
ToolTip="数值越小,越拟合原曲线,
建议模型线(由于单条曲线较长)取值小一些,dwg的曲线(由于单条曲线较短)取值大一些" />
|
||||
<CheckBox
|
||||
HorizontalAlignment="Center"
|
||||
Content="两侧布置"
|
||||
IsChecked="{Binding IsTwoSides}"
|
||||
ToolTip="在中心线两侧布置放样(会合并)和实例" />
|
||||
<Button
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding CreateTrackCommand}"
|
||||
Content="创建" />
|
||||
</UniformGrid>
|
||||
</ex:AutoGrid>
|
||||
</ex:FluentWindowEx>
|
||||
29
Sai.RvKits/RvCommon/ModelByCurveCreatorView.xaml.cs
Normal file
29
Sai.RvKits/RvCommon/ModelByCurveCreatorView.xaml.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
using Wpf.Ui.Controls;
|
||||
|
||||
namespace Sai.RvKits.RvCommon
|
||||
{
|
||||
/// <summary>
|
||||
/// ModelByCurveCreatorView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class ModelByCurveCreatorView
|
||||
{
|
||||
public ModelByCurveCreatorView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
551
Sai.RvKits/RvCommon/ModelByCurveCreatorViewModel.cs
Normal file
551
Sai.RvKits/RvCommon/ModelByCurveCreatorViewModel.cs
Normal file
@@ -0,0 +1,551 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.UI.Selection;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External.Handlers;
|
||||
|
||||
using Sai.RvKits.Converters;
|
||||
using Sai.Toolkit.Mvvm.Attributes;
|
||||
|
||||
namespace Sai.RvKits.RvCommon
|
||||
{
|
||||
public partial class ModelByCurveCreatorViewModel : ObservableValidator
|
||||
{
|
||||
[ObservableProperty]
|
||||
private CenterCurveType centerCurveType;
|
||||
|
||||
[ObservableProperty]
|
||||
private List<FamilySymbol> familyTypes;
|
||||
private readonly ActionEventHandler handler;
|
||||
|
||||
[Required(ErrorMessage = "不可为空")]
|
||||
[IsNumeric]
|
||||
[ObservableProperty]
|
||||
private double instanceOffsetX = 0;
|
||||
|
||||
[ObservableProperty]
|
||||
[Required(ErrorMessage = "不可为空")]
|
||||
[IsNumeric]
|
||||
private double instanceOffsetY = 0;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(CreateTrackCommand))]
|
||||
private bool isRunning;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool isTwoSides = false;
|
||||
|
||||
[ObservableProperty]
|
||||
private List<Material> materials;
|
||||
|
||||
[Required(ErrorMessage = "不可为空")]
|
||||
[IsNumeric]
|
||||
[ObservableProperty]
|
||||
private double offsetX = 0;
|
||||
|
||||
[ObservableProperty]
|
||||
[Required(ErrorMessage = "不可为空")]
|
||||
[IsNumeric]
|
||||
private double offsetY = 0;
|
||||
|
||||
[Required(ErrorMessage = "不可为空")]
|
||||
[IsNumeric]
|
||||
[Minimum(0.5)]
|
||||
[ObservableProperty]
|
||||
[NotifyDataErrorInfo]
|
||||
private double precision = 1.0;
|
||||
|
||||
//private List<ElementId> previewIds = [];
|
||||
[ObservableProperty]
|
||||
private List<FamilySymbol> profileFamilyTypes;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(CreateTrackCommand))]
|
||||
private FamilySymbol selectedFamilyType;
|
||||
|
||||
[ObservableProperty]
|
||||
private Material selectedMaterial;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(CreateTrackCommand))]
|
||||
private FamilySymbol selectedProfileFamilyType;
|
||||
|
||||
[Required(ErrorMessage = "不可为空")]
|
||||
[IsNumeric]
|
||||
[Minimum(100)]
|
||||
[NotifyDataErrorInfo]
|
||||
[ObservableProperty]
|
||||
private double spacing = 100;
|
||||
|
||||
public ModelByCurveCreatorViewModel(Document doc)
|
||||
{
|
||||
handler = new();
|
||||
profileFamilyTypes = [.. doc.OfClass<FamilySymbol>()
|
||||
.OfCategory(BuiltInCategory.OST_ProfileFamilies)
|
||||
.Cast<FamilySymbol>()
|
||||
.OrderBy(n => n.FamilyName)];
|
||||
familyTypes = [.. doc.OfClass<FamilySymbol>()
|
||||
.OfType<FamilySymbol>()
|
||||
.Where(
|
||||
s =>
|
||||
s.Category.Parent == null
|
||||
&& s.Family.IsEditable
|
||||
&& s.Family.IsUserCreated
|
||||
&& s.Family.FamilyPlacementType == FamilyPlacementType.OneLevelBased
|
||||
)
|
||||
.OrderBy(n => n.FamilyName)];
|
||||
materials = doc.OfClass<Material>().OrderBy(n => n.Name).OfType<Material>().ToList();
|
||||
}
|
||||
|
||||
[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();
|
||||
var loops = SpatialAssist.ToCurveLoops(curves);
|
||||
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
|
||||
);
|
||||
//获取截面的曲线集合
|
||||
var list = SpatialAssist.ToCurveLoops(profiles);
|
||||
//生成截面线串
|
||||
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)
|
||||
// {
|
||||
// previewIds.Add(DebugAssist.CreateTransientGeometries(doc, curve));
|
||||
// }
|
||||
//}
|
||||
//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,
|
||||
}
|
||||
}
|
||||
105
Sai.RvKits/RvCommon/ModifyModelParams.cs
Normal file
105
Sai.RvKits/RvCommon/ModifyModelParams.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
using ACadSharp.Entities;
|
||||
|
||||
using Autodesk.Revit.Attributes;
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.UI.Selection;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External;
|
||||
|
||||
|
||||
|
||||
namespace Sai.RvKits.RvCommon;
|
||||
|
||||
[Transaction(TransactionMode.Manual)]
|
||||
[Regeneration(RegenerationOption.Manual)]
|
||||
public class ModifyModelParams : ExternalCommand
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
var elems = UiDocument.SelectObjects<FamilyInstance>();
|
||||
if (elems == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var textRefer = UiDocument.Selection.PickObject(ObjectType.PointOnElement, "请选择管线标注文字");
|
||||
var dwg = Document.GetElement(textRefer) as ImportInstance;
|
||||
var textLayerName = dwg.GetLayerName(textRefer);
|
||||
var path = dwg.GetDwgPath();
|
||||
var dwgTransform = dwg!.GetTransform();
|
||||
Document.Invoke(_ =>
|
||||
{
|
||||
using ACadSharp.IO.DwgReader reader = new(path);
|
||||
var cadDocument = reader.Read();
|
||||
var textEntities = cadDocument.Entities.OfType<TextEntity>().Where(e => e.Layer.Name == textLayerName).ToList();
|
||||
double topOffset = default;
|
||||
double bottomOffset = default;
|
||||
foreach (var familyInstance in elems)
|
||||
{
|
||||
string str1 = default;
|
||||
string str2 = default;
|
||||
//XYZ p1 = default;
|
||||
//XYZ p2 = default;
|
||||
var loc = familyInstance.GetLocXYZ();
|
||||
var smallest = double.MaxValue;
|
||||
var secondSmallest = double.MaxValue;
|
||||
foreach (var entity in textEntities)
|
||||
{
|
||||
if (!double.TryParse(entity.Value, out var _))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var xyz = new XYZ(entity.InsertPoint.X, entity.InsertPoint.Y, entity.InsertPoint.Z) / 304.8;
|
||||
var ofPoint = dwgTransform.OfPoint(xyz);
|
||||
//同一平面
|
||||
var point = new XYZ(ofPoint.X, ofPoint.Y, loc.Z);
|
||||
var temp = point.DistanceTo(loc);
|
||||
if (temp < smallest)
|
||||
{
|
||||
str2 = str1;
|
||||
str1 = entity.Value;
|
||||
//p2 = p1;
|
||||
//p1 = point;
|
||||
secondSmallest = smallest;
|
||||
smallest = temp;
|
||||
}
|
||||
else if (temp < secondSmallest)
|
||||
{
|
||||
//p2 = point;
|
||||
str2 = entity.Value;
|
||||
secondSmallest = temp;
|
||||
}
|
||||
}
|
||||
var b1 = double.TryParse(str1, out var d1);
|
||||
var b2 = double.TryParse(str2, out var d2);
|
||||
if (b1 && b2)
|
||||
{
|
||||
if (d1 > d2)
|
||||
{
|
||||
topOffset = d1;
|
||||
bottomOffset = d2;
|
||||
}
|
||||
else
|
||||
{
|
||||
topOffset = d2;
|
||||
bottomOffset = d1;
|
||||
}
|
||||
}
|
||||
//Debug.WriteLine(topOffset * 1000 / 304.8);
|
||||
//Debug.WriteLine(bottomOffset * 1000 / 304.8);
|
||||
if ((topOffset - bottomOffset) * 1000 / 304.8 < Application.ShortCurveTolerance)
|
||||
{
|
||||
|
||||
Debug.WriteLine(familyInstance.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
familyInstance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM).Set(topOffset * 1000 / 304.8);
|
||||
familyInstance.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM).Set(bottomOffset * 1000 / 304.8);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
16
Sai.RvKits/RvCommon/PipesCreatorCmd.cs
Normal file
16
Sai.RvKits/RvCommon/PipesCreatorCmd.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Autodesk.Revit.DB;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External;
|
||||
using Sai.Toolkit.Core.Helpers;
|
||||
|
||||
namespace Sai.RvKits.RvCommon;
|
||||
|
||||
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
|
||||
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
|
||||
public class PipesCreatorCmd : ExternalCommand
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
WinDialogHelper.ShowModeless<PipesCreatorView>(new PipesCreatorViewModel(Document));
|
||||
}
|
||||
}
|
||||
43
Sai.RvKits/RvCommon/PipesCreatorView.xaml
Normal file
43
Sai.RvKits/RvCommon/PipesCreatorView.xaml
Normal file
@@ -0,0 +1,43 @@
|
||||
<ex:FluentWindowEx
|
||||
x:Class="Sai.RvKits.RvCommon.PipesCreatorView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:ex="https://github.com/sherlockforrest/Wpf.Ui.Extend"
|
||||
xmlns:local="clr-namespace:Sai.RvKits.RvCommon"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Title="管道翻模"
|
||||
Width="250"
|
||||
Height="180"
|
||||
MinWidth="250"
|
||||
MinHeight="180"
|
||||
d:DataContext="{d:DesignInstance Type=local:PipesCreatorViewModel}"
|
||||
SizeToContent="Height"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/Sai.RvKits;component/WPFUI.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<ex:AutoGrid ChildMargin="5" Columns="*">
|
||||
<ex:ComboBoxEx
|
||||
Grid.Row="0"
|
||||
DisplayMemberPath="Name"
|
||||
ItemsSource="{Binding PipeTypes}"
|
||||
PlaceholderText="管线类型"
|
||||
SelectedItem="{Binding SelectedPipeType}" />
|
||||
<ex:ComboBoxEx
|
||||
Grid.Row="1"
|
||||
DisplayMemberPath="Name"
|
||||
ItemsSource="{Binding PipingSystemTypes}"
|
||||
PlaceholderText="系统类型"
|
||||
SelectedItem="{Binding SelectedPipingSystemType}" />
|
||||
<Button
|
||||
Grid.Row="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding CreateCommand}"
|
||||
Content="创建" />
|
||||
</ex:AutoGrid>
|
||||
</ex:FluentWindowEx>
|
||||
17
Sai.RvKits/RvCommon/PipesCreatorView.xaml.cs
Normal file
17
Sai.RvKits/RvCommon/PipesCreatorView.xaml.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Windows;
|
||||
|
||||
using Wpf.Ui.Controls;
|
||||
|
||||
namespace Sai.RvKits.RvCommon
|
||||
{
|
||||
/// <summary>
|
||||
/// PipesCreatorView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class PipesCreatorView
|
||||
{
|
||||
public PipesCreatorView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
272
Sai.RvKits/RvCommon/PipesCreatorViewModel.cs
Normal file
272
Sai.RvKits/RvCommon/PipesCreatorViewModel.cs
Normal file
@@ -0,0 +1,272 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using ACadSharp.Entities;
|
||||
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.DB.Mechanical;
|
||||
using Autodesk.Revit.DB.Plumbing;
|
||||
using Autodesk.Revit.UI.Selection;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External.Handlers;
|
||||
|
||||
namespace Sai.RvKits.RvCommon;
|
||||
|
||||
public partial class PipesCreatorViewModel : ObservableObject
|
||||
{
|
||||
public PipesCreatorViewModel(Document document)
|
||||
{
|
||||
this.document = document;
|
||||
}
|
||||
|
||||
private readonly ActionEventHandler createHandler = new();
|
||||
private readonly Document document;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(CreateCommand))]
|
||||
private PipeType selectedPipeType;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(CreateCommand))]
|
||||
private PipingSystemType selectedPipingSystemType;
|
||||
|
||||
public IList<PipeType> PipeTypes => document.OfClass<PipeType>().Cast<PipeType>().ToList();
|
||||
public IList<PipingSystemType> PipingSystemTypes => document.OfClass<PipingSystemType>().Cast<PipingSystemType>().ToList();
|
||||
|
||||
private bool CanCreate()
|
||||
{
|
||||
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
|
||||
return SelectedPipeType != null && SelectedPipingSystemType != null;
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanCreate))]
|
||||
private void Create()
|
||||
{
|
||||
createHandler.Raise(uiapp =>
|
||||
{
|
||||
var application = uiapp.Application;
|
||||
var uiDocument = uiapp.ActiveUIDocument;
|
||||
var doc = uiDocument.Document;
|
||||
Reference reference;
|
||||
Reference textRefer;
|
||||
try
|
||||
{
|
||||
reference = uiDocument.Selection.PickObject(
|
||||
ObjectType.PointOnElement,
|
||||
new FuncFilter(e => e is ImportInstance import && import.IsLinked && doc.GetElement(e.GetTypeId()) is CADLinkType),
|
||||
"请选择dwg管线图层"
|
||||
);
|
||||
|
||||
//图层ID;
|
||||
textRefer = uiDocument.Selection.PickObject(ObjectType.PointOnElement, new FuncFilter(e => e is ImportInstance import && import.IsLinked && doc.GetElement(e.GetTypeId()) is CADLinkType), "请选择管线标注文字");
|
||||
}
|
||||
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var dwg = doc.GetElement(reference) as ImportInstance;
|
||||
var pipeLayerName = dwg.GetLayerName(reference);
|
||||
var textLayerName = dwg.GetLayerName(textRefer);
|
||||
//SketchPlane sketchPlane = SketchPlane.Create(Document, Plane.CreateByNormalAndOrigin(XYZ.BasisZ, XYZ.Zero));
|
||||
|
||||
doc.Invoke(_ =>
|
||||
{
|
||||
var curve = dwg!.GetGeometryObjectFromReference(reference);
|
||||
var text = dwg.GetGeometryObjectFromReference(textRefer);
|
||||
|
||||
doc.ActiveView.SetCategoryHidden(curve.GraphicsStyleId, false);
|
||||
doc.ActiveView.SetCategoryHidden(text.GraphicsStyleId, false);
|
||||
});
|
||||
var path = dwg.GetDwgPath();
|
||||
using ACadSharp.IO.DwgReader reader = new(path);
|
||||
var cadDocument = reader.Read();
|
||||
//var blocks = cadDocument.Entities.OfType<ACadSharp.Entities.Insert>().Where(e => e.Layer.Name == layerName).ToList();
|
||||
var textEntities = cadDocument.Entities.OfType<TextEntity>().Where(e => e.Layer.Name == textLayerName).ToList();
|
||||
var lwPolyLines = cadDocument.Entities.OfType<LwPolyline>().Where(e => e.Layer.Name == pipeLayerName).ToList();
|
||||
var dwgTransform = dwg!.GetTransform();
|
||||
StringBuilder sb = new();
|
||||
doc.InvokeGroup(_ =>
|
||||
{
|
||||
foreach (var lwPolyline in lwPolyLines)
|
||||
{
|
||||
//if (n % 500 == 0)
|
||||
//{
|
||||
// var result = TaskDialog.Show("提示", $"已创建{n},是否继续?", TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No);
|
||||
// if (result == TaskDialogResult.No)
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
var v = lwPolyline.Vertices;
|
||||
if (v.Count == 2)
|
||||
{
|
||||
var p1 = new XYZ(v[0].Location.X, v[0].Location.Y, 0) / 304.8;
|
||||
var p2 = new XYZ(v[1].Location.X, v[1].Location.Y, 0) / 304.8;
|
||||
if (p1.DistanceTo(p2) < application.ShortCurveTolerance)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var di = double.MaxValue;
|
||||
TextEntity text = null;
|
||||
var l = Autodesk.Revit.DB.Line.CreateBound(p1, p2);
|
||||
foreach (var entity in textEntities)
|
||||
{
|
||||
try
|
||||
{
|
||||
var transform = Transform.CreateRotation(XYZ.BasisZ, entity.Rotation);
|
||||
var rotationVector = transform.OfPoint(XYZ.BasisX);
|
||||
if (entity.Value.StartsWith("DN") || entity.Value.StartsWith("De"))
|
||||
{
|
||||
var crossProduct = l.Direction.CrossProduct(rotationVector);
|
||||
if (crossProduct.GetLength() < 0.05)
|
||||
{
|
||||
var xyz = new XYZ(entity.InsertPoint.X, entity.InsertPoint.Y, entity.InsertPoint.Z) / 304.8;
|
||||
var ofPoint = dwgTransform.OfPoint(xyz);
|
||||
//同一平面
|
||||
var point = new XYZ(ofPoint.X, ofPoint.Y, 0);
|
||||
var d = l.Distance(point);
|
||||
if (d < di)
|
||||
{
|
||||
di = d;
|
||||
text = entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
doc.Invoke(
|
||||
_ =>
|
||||
{
|
||||
//var pipeDiameter = Regex.Match(text.Value, @"(?<=DN)\d+");
|
||||
//if (pipeDiameter.Length > 0)
|
||||
//{
|
||||
// var diameter = Convert.ToDouble(pipeDiameter.Value) / 304.8;
|
||||
// pipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(diameter);
|
||||
//}
|
||||
|
||||
//var elevation = Regex.Match(text.Value, @"(?<=\+)(\d|\.)+");
|
||||
//if (elevation.Length > 0)
|
||||
//{
|
||||
// var h = Convert.ToDouble(elevation.Value) * 1000 / 304.8;
|
||||
// pipe.get_Parameter(BuiltInParameter.RBS_OFFSET_PARAM).Set(h);
|
||||
//}
|
||||
p1 = dwgTransform.OfPoint(p1);
|
||||
p2 = dwgTransform.OfPoint(p2);
|
||||
var newPipe = Pipe.Create(doc, SelectedPipingSystemType.Id, SelectedPipeType.Id, doc.ActiveView.GenLevel.Id, p1, p2);
|
||||
doc.Regenerate();
|
||||
|
||||
if (text != null)
|
||||
{
|
||||
var diameter = string.Empty;
|
||||
//string slope = string.Empty;
|
||||
//var splitStrings = text.Value.Split(' ');
|
||||
//foreach (var str in splitStrings)
|
||||
//{
|
||||
// var str1 = str.Trim();
|
||||
// if (str1.Contains("DN"))
|
||||
// {
|
||||
// diameter = str.TrimStart("DN".ToCharArray());
|
||||
// }
|
||||
// else if (str1.Contains("De"))
|
||||
// {
|
||||
// diameter = str.TrimStart("De".ToCharArray());
|
||||
// }
|
||||
|
||||
// if (str1.Contains("i="))
|
||||
// {
|
||||
// slope = str.TrimStart("i=".ToCharArray());
|
||||
// }
|
||||
//}
|
||||
|
||||
if (double.TryParse(diameter, out var d))
|
||||
{
|
||||
newPipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(d / 304.8);
|
||||
}
|
||||
|
||||
//if (double.TryParse(slope, out var s))
|
||||
//{
|
||||
// newPipe.get_Parameter(BuiltInParameter.RBS_PIPE_SLOPE).Set(s);
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine($"{newPipe.Id}");
|
||||
}
|
||||
|
||||
// ElementTransformUtils.MoveElement(Document, newPipe.Id, move);
|
||||
//n++;
|
||||
},
|
||||
"创建管线"
|
||||
);
|
||||
doc.Invoke(_ =>
|
||||
{
|
||||
var mepCurves = doc.OfClass<MEPCurve>()
|
||||
.Where(p => p is not InsulationLiningBase and not FlexPipe and not FlexDuct)
|
||||
.ToList();
|
||||
foreach (var mep in mepCurves)
|
||||
{
|
||||
foreach (var mep1 in mepCurves)
|
||||
{
|
||||
if (
|
||||
mep.Id != mep1.Id
|
||||
&& !mep.GetConnectors(true).IsEmpty
|
||||
&& !mep1.GetConnectors(true).IsEmpty
|
||||
&& mep.GetType() == mep1.GetType()
|
||||
)
|
||||
{
|
||||
var connectors = ConnectorAssist.GetNearestConnectors(mep, mep1);
|
||||
if (connectors.Count == 2 && connectors[0].Origin.IsAlmostEqualTo(connectors[1].Origin))
|
||||
{
|
||||
connectors[0].ConnectByFitting(connectors[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
var filePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\问题管线.txt";
|
||||
File.WriteAllText(filePath, sb.ToString());
|
||||
System.Diagnostics.Process.Start(filePath);
|
||||
}
|
||||
|
||||
//UiDocument.Selection.SetElementIds(ids);
|
||||
//using (Transaction name = new Transaction(Document, "tsname"))
|
||||
//{
|
||||
// name.Start();
|
||||
// for (int i = 0; i < 20; i++)
|
||||
// {
|
||||
// var block = blocks[i];
|
||||
// var loc = new XYZ(block.InsertPoint.X / 304.8, block.InsertPoint.Y / 304.8, 0);
|
||||
|
||||
// //var loc = dwg.GetTransform().Origin;
|
||||
|
||||
// if (!instance.Symbol.IsActive)
|
||||
// {
|
||||
// instance.Symbol.Activate();
|
||||
// }
|
||||
|
||||
// var fi = Document.Create.NewFamilyInstance(loc, instance.Symbol, view.GenLevel, StructuralType.NonStructural);
|
||||
// Document.Regenerate();
|
||||
// ElementTransformUtils.MoveElement(Document,fi.Id,move);
|
||||
// }
|
||||
// name.Commit();
|
||||
//}
|
||||
});
|
||||
}
|
||||
}
|
||||
51
Sai.RvKits/RvCommon/PureModelCmd.cs
Normal file
51
Sai.RvKits/RvCommon/PureModelCmd.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Autodesk.Revit.Attributes;
|
||||
using Autodesk.Revit.DB;
|
||||
|
||||
using eTransmitForRevitDB;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External;
|
||||
|
||||
namespace Sai.RvKits.RvCommon;
|
||||
|
||||
/// <summary>
|
||||
/// Revit执行命令
|
||||
/// </summary>
|
||||
[Transaction(TransactionMode.Manual)]
|
||||
[Regeneration(RegenerationOption.Manual)]
|
||||
public class PureModelCmd : ExternalCommand
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
if (string.IsNullOrEmpty(Document.PathName))
|
||||
{
|
||||
System.Windows.MessageBox.Show("请先保存文件");
|
||||
return;
|
||||
}
|
||||
|
||||
var options = new SaveAsOptions()
|
||||
{
|
||||
Compact = true,
|
||||
OverwriteExistingFile = true,
|
||||
MaximumBackups = 3
|
||||
};
|
||||
for (var i = 0; i < 5; i++)
|
||||
{
|
||||
Purge(Document);
|
||||
}
|
||||
Document.SaveAs(Document.PathName, options);
|
||||
System.Windows.MessageBox.Show("清理完成", "提示");
|
||||
}
|
||||
/// <summary>
|
||||
/// 使用eTransmitForRevitDB清理文档未使用项
|
||||
/// </summary>
|
||||
/// <param name="doc"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Purge(Document doc)
|
||||
{
|
||||
var eTransmitUpgradeOMatic = new eTransmitUpgradeOMatic(doc.Application);
|
||||
|
||||
var result = eTransmitUpgradeOMatic.purgeUnused(doc);
|
||||
|
||||
return result == UpgradeFailureType.UpgradeSucceeded;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user