功能更新
This commit is contained in:
@@ -8,11 +8,12 @@
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ui:ThemeResources RequestedTheme="Dark" />
|
||||
<ui:ThemeResources RequestedTheme="Light" />
|
||||
<ui:XamlControlsResources />
|
||||
<!--<ResourceDictionary Source="pack://application:,,,/iNKORE.UI.WPF.Modern;component/themes/schemes/dark.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/iNKORE.UI.WPF.Modern;component/themes/themeresources.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/iNKORE.UI.WPF.Modern;component/themes/controlsresources.xaml" />-->
|
||||
|
||||
<!--<ResourceDictionary Source="pack://application:,,,/iNKORE.UI.WPF.Modern;component/themes/themeresources.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/iNKORE.UI.WPF.Modern;component/themes/controlsresources.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/iNKORE.UI.WPF.Modern;component/themes/schemes/dark.xaml" />-->
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<UseWPF>true</UseWPF>
|
||||
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
|
||||
<ApplicationIcon>authentication.ico</ApplicationIcon>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="authentication.ico" />
|
||||
|
||||
@@ -28,131 +28,198 @@
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<GroupBox
|
||||
Margin="5"
|
||||
BorderThickness="0"
|
||||
FontSize="16"
|
||||
Foreground="DeepSkyBlue"
|
||||
Header="公私密钥"
|
||||
Style="{x:Null}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox
|
||||
x:Name="PrivateKeyTextBox"
|
||||
ui:ControlHelper.Header="RSA私钥:"
|
||||
ui:ControlHelper.PlaceholderText="请输入RSA私钥,私钥需要保存在自己电脑,避免外泄"
|
||||
TextWrapping="WrapWithOverflow"
|
||||
ToolTip="私钥需要保存在自己电脑,避免外泄" />
|
||||
<TextBox
|
||||
x:Name="PublicKeyTextBox"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
ui:ControlHelper.Header="RSA公钥:"
|
||||
ui:ControlHelper.PlaceholderText="请输入RSA公钥,公钥用在需要验证密钥的客户端代码、蓝图里"
|
||||
TextWrapping="WrapWithOverflow"
|
||||
ToolTip="公钥用在需要验证密钥的客户端代码、蓝图里" />
|
||||
<Button
|
||||
x:Name="ToggleButton"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Click="Button_ToggleTheme_Click"
|
||||
Content="明暗切换" />
|
||||
<Button
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="5"
|
||||
HorizontalAlignment="Right"
|
||||
Click="ImportPrivateKeyClick"
|
||||
Content="导入文件私钥" />
|
||||
<UniformGrid
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
Rows="1">
|
||||
<Button Click="GenerateKeyClick" Content="计算公私密钥" />
|
||||
<Button Click="SaveKeysClick" Content="保存公私密钥" />
|
||||
</UniformGrid>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
<Rectangle
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Height="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Top"
|
||||
Fill="Gray" />
|
||||
<GroupBox
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="5"
|
||||
BorderThickness="0"
|
||||
FontSize="16"
|
||||
Foreground="DeepSkyBlue"
|
||||
Header="获取授权"
|
||||
Style="{x:Null}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox
|
||||
x:Name="MachineCodeTextBox"
|
||||
ui:ControlHelper.Header="机器码:"
|
||||
ui:ControlHelper.PlaceholderText="请输入硬件机器码,由CPU、主板、C盘所在磁盘构成"
|
||||
ToolTip="硬件机器码由CPU、主板、C盘所在磁盘构成" />
|
||||
<TextBox
|
||||
x:Name="LicenseTextBox"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
ui:ControlHelper.Header="授权激活码:"
|
||||
ui:ControlHelper.PlaceholderText="授权激活码"
|
||||
IsReadOnly="True" />
|
||||
<DatePicker
|
||||
x:Name="ExpiryDatePicker"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
ui:ControlHelper.Header="授权到期日期:" />
|
||||
<UniformGrid
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Rows="1">
|
||||
<Button
|
||||
|
||||
<TabControl ui:TabControlHelper.IsAddTabButtonVisible="False">
|
||||
<TabItem
|
||||
ui:TabItemHelper.IsClosable="False"
|
||||
Header="长期授权算号器"
|
||||
IsSelected="True">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<GroupBox
|
||||
Margin="5"
|
||||
BorderThickness="0"
|
||||
FontSize="16"
|
||||
Foreground="DeepSkyBlue"
|
||||
Header="公私密钥"
|
||||
Style="{x:Null}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox
|
||||
x:Name="PrivateKeyTextBox"
|
||||
ui:ControlHelper.Header="RSA私钥:"
|
||||
ui:ControlHelper.PlaceholderText="请输入RSA私钥,私钥需要保存在自己电脑,避免外泄"
|
||||
TextWrapping="WrapWithOverflow"
|
||||
ToolTip="私钥需要保存在自己电脑,避免外泄" />
|
||||
<TextBox
|
||||
x:Name="PublicKeyTextBox"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
ui:ControlHelper.Header="RSA公钥:"
|
||||
ui:ControlHelper.PlaceholderText="请输入RSA公钥,公钥用在需要验证密钥的客户端代码、蓝图里"
|
||||
TextWrapping="WrapWithOverflow"
|
||||
ToolTip="公钥用在需要验证密钥的客户端代码、蓝图里" />
|
||||
|
||||
<Button
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="5"
|
||||
HorizontalAlignment="Right"
|
||||
Click="ImportPrivateKeyClick">
|
||||
<ui:IconAndText Content="导入文件私钥" Icon="{x:Static ui:SegoeFluentIcons.Import}" />
|
||||
</Button>
|
||||
<UniformGrid
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
Rows="1">
|
||||
<Button Click="GenerateKeyClick">
|
||||
<ui:IconAndText Content="计算公私密钥" Icon="{x:Static ui:SegoeFluentIcons.Calculator}" />
|
||||
</Button>
|
||||
<Button Click="SaveKeysClick">
|
||||
<ui:IconAndText Content="保存公私密钥" Icon="{x:Static ui:SegoeFluentIcons.Save}" />
|
||||
</Button>
|
||||
</UniformGrid>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
<Rectangle
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Height="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Click="LicenseClick"
|
||||
Content="获取激活码" />
|
||||
<Button
|
||||
VerticalAlignment="Top"
|
||||
Fill="Gray" />
|
||||
<GroupBox
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="5"
|
||||
BorderThickness="0"
|
||||
FontSize="16"
|
||||
Foreground="DeepSkyBlue"
|
||||
Header="获取授权"
|
||||
Style="{x:Null}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox
|
||||
x:Name="MachineCodeTextBox"
|
||||
ui:ControlHelper.Header="机器码:"
|
||||
ui:ControlHelper.PlaceholderText="请输入硬件机器码,由CPU、主板、C盘所在磁盘构成"
|
||||
ToolTip="硬件机器码由CPU、主板、C盘所在磁盘构成" />
|
||||
<TextBox
|
||||
x:Name="LicenseTextBox"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
ui:ControlHelper.Header="授权激活码:"
|
||||
ui:ControlHelper.PlaceholderText="授权激活码"
|
||||
IsReadOnly="True" />
|
||||
<DatePicker
|
||||
x:Name="ExpiryDatePicker"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
ui:ControlHelper.Header="授权到期日期:" />
|
||||
<UniformGrid
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Bottom"
|
||||
Rows="1">
|
||||
<Button HorizontalAlignment="Stretch" Click="LicenseClick">
|
||||
<ui:IconAndText Content="获取激活码" Icon="{x:Static ui:SegoeFluentIcons.Calculator}" />
|
||||
</Button>
|
||||
<Button HorizontalAlignment="Stretch" Click="SaveLicenseClick">
|
||||
<ui:IconAndText Content="保存激活码" Icon="{x:Static ui:SegoeFluentIcons.SaveLocal}" />
|
||||
</Button>
|
||||
</UniformGrid>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
<Rectangle
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Height="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Click="SaveLicenseClick"
|
||||
Content="保存激活码" />
|
||||
</UniformGrid>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
<Rectangle
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Height="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Top"
|
||||
Fill="Gray" />
|
||||
VerticalAlignment="Top"
|
||||
Fill="Gray" />
|
||||
|
||||
|
||||
</Grid>
|
||||
</TabItem>
|
||||
<TabItem ui:TabItemHelper.IsClosable="False" Header="应急动态码计算">
|
||||
<Grid Margin="5">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<UniformGrid Rows="1">
|
||||
<ComboBox
|
||||
x:Name="DynamicDurationComboBox"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
ui:ControlHelper.Header="授权时长:">
|
||||
<ComboBoxItem
|
||||
Content="1天"
|
||||
IsSelected="True"
|
||||
Tag="1D" />
|
||||
<ComboBoxItem Content="7天" Tag="7D" />
|
||||
<ComboBoxItem Content="30天" Tag="30D" />
|
||||
</ComboBox>
|
||||
<TextBox
|
||||
x:Name="SaltTextBox"
|
||||
ui:ControlHelper.Header="应急盐值(Emergency Salt):"
|
||||
ui:ControlHelper.PlaceholderText="盐值,需要与UE中设置的一致" />
|
||||
</UniformGrid>
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox
|
||||
x:Name="DynamicLicenseTextBox"
|
||||
ui:ControlHelper.Header="动态授权激活码:"
|
||||
ui:ControlHelper.PlaceholderText="动态授权激活码"
|
||||
IsReadOnly="True" />
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Click="DynamicLicenseClick">
|
||||
<ui:IconAndText Content="计算动态激活码" Icon="{x:Static ui:SegoeFluentIcons.Calculator}" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
<TextBox
|
||||
x:Name="Message"
|
||||
Grid.Row="2"
|
||||
ui:ControlHelper.Header="消息:"
|
||||
Foreground="LightCoral" />
|
||||
|
||||
<ui:ToggleSwitch
|
||||
x:Name="ToggleButton"
|
||||
MinWidth="80"
|
||||
Margin="5,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
ui:OffContent="浅色"
|
||||
ui:OnContent="深色"
|
||||
Toggled="ToggleTheme_Click" />
|
||||
</Grid>
|
||||
|
||||
</Window>
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
using iNKORE.UI.WPF.Modern;
|
||||
|
||||
@@ -174,7 +175,7 @@ namespace KeyGen
|
||||
Message.Text = ($"导入文件私钥完成");
|
||||
}
|
||||
}
|
||||
private void Button_ToggleTheme_Click(object sender, RoutedEventArgs e)
|
||||
private void ToggleTheme_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (ThemeManager.Current.ApplicationTheme == ApplicationTheme.Dark)
|
||||
{
|
||||
@@ -185,5 +186,61 @@ namespace KeyGen
|
||||
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 生成通用的 6 位应急码
|
||||
/// </summary>
|
||||
/// <param name="durationTag">"1D", "7D", 或 "30D"</param>
|
||||
public static string GenerateGlobalOTP(string durationTag, string salt)
|
||||
{
|
||||
string secret = salt + durationTag;
|
||||
|
||||
// 计算天数步长
|
||||
long unixTime = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
|
||||
long step = unixTime / 86400;
|
||||
|
||||
byte[] secretBytes = Encoding.UTF8.GetBytes(secret);
|
||||
// 字符表必须严格一致
|
||||
string charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
// 步长转 8 字节大端
|
||||
byte[] stepBytes = BitConverter.GetBytes(step);
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(stepBytes);
|
||||
byte[] msg = new byte[8];
|
||||
Array.Copy(stepBytes, 0, msg, 8 - stepBytes.Length, stepBytes.Length);
|
||||
|
||||
using (var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(secret)))
|
||||
{
|
||||
byte[] hash = hmac.ComputeHash(msg);
|
||||
int offset = hash[hash.Length - 1] & 0xf;
|
||||
uint binary = (uint)(((hash[offset] & 0x7f) << 24) | ((hash[offset + 1] & 0xff) << 16) | ((hash[offset + 2] & 0xff) << 8) | (hash[offset + 3] & 0xff));
|
||||
|
||||
string code = "";
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
code += charset[(int)(binary % (uint)charset.Length)];
|
||||
binary /= (uint)charset.Length;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
private void DynamicLicenseClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DynamicDurationComboBox.SelectedItem is not ComboBoxItem selectedItem)
|
||||
{
|
||||
Message.Text = ("请选择授权时长");
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrEmpty(SaltTextBox.Text))
|
||||
{
|
||||
Message.Text = ("请设置Salt值");
|
||||
return;
|
||||
}
|
||||
string durationTag = selectedItem.Tag.ToString();
|
||||
string salt = SaltTextBox.Text.Trim();
|
||||
string globalOTP = GenerateGlobalOTP(durationTag, salt);
|
||||
DynamicLicenseTextBox.Text = globalOTP;
|
||||
Clipboard.SetText(globalOTP);
|
||||
Message.Text = "动态应急码已复制!";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,12 @@
|
||||
Margin="5"
|
||||
Click="CleanLinesButton_Click"
|
||||
Content="清理连线" />
|
||||
<Button
|
||||
x:Name="ConvertToPointsButton"
|
||||
Margin="5"
|
||||
Click="ConvertToPointsButton_Click"
|
||||
Content="多段线转点"
|
||||
ToolTip="将列表中所有的多段线圆弧符号转换为几何中心点" />
|
||||
<!--<Button
|
||||
x:Name="CloseButton"
|
||||
Margin="5"
|
||||
|
||||
@@ -14,18 +14,29 @@ using Autodesk.AutoCAD.Windows;
|
||||
|
||||
using Application = Autodesk.AutoCAD.ApplicationServices.Application;
|
||||
|
||||
|
||||
namespace Szmedi.CADkits
|
||||
{
|
||||
// 定义视图模型,对应列表中的一行
|
||||
public class EntityReviewItem
|
||||
{
|
||||
public ObjectId EntityId { get; set; }
|
||||
public string Handle { get; set; }
|
||||
public string Position { get; set; }
|
||||
// 支持属性通知可使用 INotifyPropertyChanged,这里为了简化直接使用属性
|
||||
public string Status { get; set; }
|
||||
}
|
||||
|
||||
public partial class ReviewAndMatchWindow : UserControl
|
||||
{
|
||||
public ObservableCollection<BlockReviewItem> ReviewItems { get; set; }
|
||||
public ObservableCollection<EntityReviewItem> ReviewItems { get; set; }
|
||||
private readonly string _checkLineLayer;
|
||||
private bool _isListeningToSelection = true;
|
||||
private readonly PaletteSet _parentPalette;
|
||||
private readonly Dictionary<ObjectId, TextWithPosition> _textDataMap;
|
||||
|
||||
// 构造函数参数改为 TerrainEntityInfo
|
||||
public ReviewAndMatchWindow(
|
||||
List<BlockRefWithPosition> allBlocks,
|
||||
List<TerrainEntityInfo> allEntities,
|
||||
Dictionary<ObjectId, ObjectId> autoPairs,
|
||||
List<TextWithPosition> allTexts,
|
||||
string checkLineLayer,
|
||||
@@ -36,67 +47,51 @@ namespace Szmedi.CADkits
|
||||
_parentPalette = parentPalette;
|
||||
_textDataMap = allTexts.ToDictionary(t => t.ObjectId, t => t);
|
||||
|
||||
ReviewItems = new ObservableCollection<BlockReviewItem>();
|
||||
ReviewItems = new ObservableCollection<EntityReviewItem>();
|
||||
ReviewListView.ItemsSource = ReviewItems;
|
||||
|
||||
PopulateList(allBlocks, autoPairs);
|
||||
PopulateList(allEntities, autoPairs);
|
||||
}
|
||||
private void PopulateList(List<BlockRefWithPosition> allBlocks, Dictionary<ObjectId, ObjectId> autoPairs)
|
||||
|
||||
private void PopulateList(List<TerrainEntityInfo> allEntities, Dictionary<ObjectId, ObjectId> autoPairs)
|
||||
{
|
||||
foreach (var blockData in allBlocks)
|
||||
foreach (var entData in allEntities)
|
||||
{
|
||||
var item = new BlockReviewItem
|
||||
var item = new EntityReviewItem
|
||||
{
|
||||
BlockId = blockData.ObjectId,
|
||||
Handle = blockData.ObjectId.Handle.Value.ToString(),
|
||||
Position = $"{blockData.Position.X:F2}, {blockData.Position.Y:F2}"
|
||||
EntityId = entData.ObjectId,
|
||||
Handle = entData.Handle,
|
||||
Position = $"{entData.Position.X:F2}, {entData.Position.Y:F2}"
|
||||
};
|
||||
|
||||
if (autoPairs.TryGetValue(blockData.ObjectId, out ObjectId textId))
|
||||
if (autoPairs.TryGetValue(entData.ObjectId, out ObjectId textId))
|
||||
{
|
||||
// 自动匹配成功
|
||||
item.Status = _textDataMap[textId].TextContent;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 未匹配
|
||||
item.Status = "--- 未匹配 ---";
|
||||
}
|
||||
ReviewItems.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
//private void LocateButton_Click(object sender, RoutedEventArgs e)
|
||||
//{
|
||||
// if (UnmatchedBlocksListView.SelectedItem is UnmatchedBlockItem selected)
|
||||
// {
|
||||
// ZoomToEntity(selected.BlockId);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// MessageBox.Show("请先在列表中选择一个块。", "提示");
|
||||
// }
|
||||
//}
|
||||
private void MatchButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!(ReviewListView.SelectedItem is BlockReviewItem selected))
|
||||
if (!(ReviewListView.SelectedItem is EntityReviewItem selected))
|
||||
{
|
||||
MessageBox.Show("请先在列表中选择一个要匹配的块。", "提示");
|
||||
MessageBox.Show("请先在列表中选择一个要匹配的实体。", "提示");
|
||||
return;
|
||||
}
|
||||
|
||||
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
|
||||
Editor ed = doc.Editor;
|
||||
if (_parentPalette.Dock == DockSides.None)
|
||||
{
|
||||
// 通过控制父面板来隐藏
|
||||
_parentPalette.Visible = false;
|
||||
}
|
||||
if (_parentPalette.Dock == DockSides.None) _parentPalette.Visible = false;
|
||||
MatchButton.IsEnabled = false;
|
||||
|
||||
try
|
||||
{
|
||||
PromptEntityOptions peo = new PromptEntityOptions("\n请点选此块对应的标高文字: ");
|
||||
PromptEntityOptions peo = new PromptEntityOptions("\n请点选此实体对应的标高文字: ");
|
||||
peo.SetRejectMessage("\n选择的不是文字对象。");
|
||||
peo.AddAllowedClass(typeof(DBText), true);
|
||||
peo.AddAllowedClass(typeof(MText), true);
|
||||
@@ -105,7 +100,7 @@ namespace Szmedi.CADkits
|
||||
|
||||
if (per.Status == PromptStatus.OK)
|
||||
{
|
||||
UpdateBlockWithSelectedText(selected, per.ObjectId);
|
||||
UpdateEntityWithSelectedText(selected, per.ObjectId);
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
@@ -114,17 +109,12 @@ namespace Szmedi.CADkits
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_parentPalette.Dock == DockSides.None)
|
||||
{
|
||||
// 操作结束后,重新显示父面板
|
||||
_parentPalette.Visible = true;
|
||||
}
|
||||
if (_parentPalette.Dock == DockSides.None) _parentPalette.Visible = true;
|
||||
MatchButton.IsEnabled = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateBlockWithSelectedText(BlockReviewItem itemToUpdate, ObjectId textId)
|
||||
private void UpdateEntityWithSelectedText(EntityReviewItem itemToUpdate, ObjectId textId)
|
||||
{
|
||||
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
|
||||
Database db = doc.Database;
|
||||
@@ -132,13 +122,11 @@ namespace Szmedi.CADkits
|
||||
{
|
||||
using (Transaction tr = db.TransactionManager.StartTransaction())
|
||||
{
|
||||
// 1. 获取文字内容和中心点
|
||||
Entity textEnt = (Entity)tr.GetObject(textId, OpenMode.ForRead);
|
||||
string textContent = "";
|
||||
if (textEnt is MText mtext) textContent = mtext.Contents;
|
||||
else if (textEnt is DBText dbtext) textContent = dbtext.TextString;
|
||||
|
||||
// 验证文字内容
|
||||
if (!double.TryParse(textContent, NumberStyles.Float, CultureInfo.InvariantCulture, out double elevationZ))
|
||||
{
|
||||
MessageBox.Show($"文字内容 '{textContent}' 不是有效的数字。", "匹配失败");
|
||||
@@ -146,40 +134,62 @@ namespace Szmedi.CADkits
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 更新块
|
||||
BlockReference blockRef = (BlockReference)tr.GetObject(itemToUpdate.BlockId, OpenMode.ForWrite);
|
||||
blockRef.Position = new Point3d(blockRef.Position.X, blockRef.Position.Y, elevationZ);
|
||||
// --- 更新逻辑:区分 BlockReference 和 DBPoint ---
|
||||
Entity targetEnt = (Entity)tr.GetObject(itemToUpdate.EntityId, OpenMode.ForWrite);
|
||||
Point3d currentPos;
|
||||
|
||||
// 3. 创建校对线
|
||||
if (targetEnt is BlockReference blockRef)
|
||||
{
|
||||
blockRef.Position = new Point3d(blockRef.Position.X, blockRef.Position.Y, elevationZ);
|
||||
currentPos = blockRef.Position;
|
||||
}
|
||||
else if (targetEnt is DBPoint dbPoint)
|
||||
{
|
||||
dbPoint.Position = new Point3d(dbPoint.Position.X, dbPoint.Position.Y, elevationZ);
|
||||
currentPos = dbPoint.Position;
|
||||
}
|
||||
else if (targetEnt is Polyline polyline)
|
||||
{
|
||||
//// 修改多段线的整体标高
|
||||
//polyline.Elevation = elevationZ;
|
||||
//currentPos = polyline.GetPoint3dAt(0);
|
||||
polyline.Elevation = elevationZ;
|
||||
|
||||
// 重新计算中心点用于校对线绘制
|
||||
Extents3d ext = polyline.GeometricExtents;
|
||||
currentPos = ext.MinPoint + (ext.MaxPoint - ext.MinPoint) * 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("未知的实体类型,无法更新。");
|
||||
tr.Abort();
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建连线
|
||||
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
|
||||
Extents3d textExtents = textEnt.GeometricExtents;
|
||||
Point3d textCenter = textExtents.MinPoint + (textExtents.MaxPoint - textExtents.MinPoint) * 0.5;
|
||||
|
||||
Line checkLine = new Line(blockRef.Position, textCenter);
|
||||
Line checkLine = new Line(currentPos, textCenter);
|
||||
checkLine.Layer = _checkLineLayer;
|
||||
checkLine.ColorIndex = 256; // ByLayer
|
||||
checkLine.ColorIndex = 256;
|
||||
btr.AppendEntity(checkLine);
|
||||
tr.AddNewlyCreatedDBObject(checkLine, true);
|
||||
|
||||
// 更新UI
|
||||
itemToUpdate.Status = $"手动: {elevationZ}";
|
||||
// 强制刷新列表显示 (如果需要)
|
||||
ReviewListView.Items.Refresh();
|
||||
|
||||
tr.Commit();
|
||||
//Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog($"块 {itemToUpdate.Handle} 已手动更新为 {elevationZ}。");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//private void CloseButton_Click(object sender, RoutedEventArgs e)
|
||||
//{
|
||||
// _parentPalette.Visible = false;
|
||||
//}
|
||||
|
||||
// 辅助方法:缩放到实体
|
||||
private void ZoomToEntity(ObjectId entId)
|
||||
{
|
||||
if (!entId.IsValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!entId.IsValid) return;
|
||||
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
|
||||
if (doc == null) return;
|
||||
Editor ed = doc.Editor;
|
||||
@@ -191,11 +201,17 @@ namespace Szmedi.CADkits
|
||||
Entity ent = tr.GetObject(entId, OpenMode.ForRead) as Entity;
|
||||
if (ent != null)
|
||||
{
|
||||
// 创建一个基于实体包围盒的视图
|
||||
Extents3d extents = ent.GeometricExtents;
|
||||
// 如果是点,包围盒可能很小,稍微扩大一点显示范围
|
||||
if (ent is DBPoint)
|
||||
{
|
||||
extents = new Extents3d(extents.MinPoint - new Vector3d(1, 1, 0), extents.MaxPoint + new Vector3d(1, 1, 0));
|
||||
}
|
||||
|
||||
Matrix3d ucs = ed.CurrentUserCoordinateSystem;
|
||||
double viewSize = Math.Max(extents.MaxPoint.X - extents.MinPoint.X, extents.MaxPoint.Y - extents.MinPoint.Y) * 5.0;
|
||||
// 扩大一点包围盒,使其不至于占满全屏
|
||||
double viewSize = Math.Max(extents.MaxPoint.X - extents.MinPoint.X, extents.MaxPoint.Y - extents.MinPoint.Y) * 10.0;
|
||||
if (viewSize < 1.0) viewSize = 20.0; // 最小视野
|
||||
|
||||
extents.TransformBy(ucs.Inverse());
|
||||
ViewTableRecord view = new ViewTableRecord
|
||||
{
|
||||
@@ -214,16 +230,15 @@ namespace Szmedi.CADkits
|
||||
|
||||
private void ListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (ReviewListView.SelectedItem is BlockReviewItem selected)
|
||||
if (ReviewListView.SelectedItem is EntityReviewItem selected)
|
||||
{
|
||||
ZoomToEntity(selected.BlockId);
|
||||
ZoomToEntity(selected.EntityId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void SelectAndScrollToItem(ObjectId blockId)
|
||||
private void SelectAndScrollToItem(ObjectId entId)
|
||||
{
|
||||
var itemToSelect = ReviewItems.FirstOrDefault(item => item.BlockId == blockId);
|
||||
var itemToSelect = ReviewItems.FirstOrDefault(item => item.EntityId == entId);
|
||||
if (itemToSelect != null)
|
||||
{
|
||||
ReviewListView.SelectedItem = itemToSelect;
|
||||
@@ -231,8 +246,6 @@ namespace Szmedi.CADkits
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void CleanLinesButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MessageBoxResult result = MessageBox.Show(
|
||||
@@ -243,7 +256,6 @@ namespace Szmedi.CADkits
|
||||
|
||||
if (result == MessageBoxResult.Yes)
|
||||
{
|
||||
// 调用主类中的公共静态方法来执行清理
|
||||
TerrainTools.CleanAllCheckLines();
|
||||
}
|
||||
}
|
||||
@@ -253,34 +265,25 @@ namespace Szmedi.CADkits
|
||||
Document doc = Application.DocumentManager.MdiActiveDocument;
|
||||
Editor ed = doc.Editor;
|
||||
ObjectId targetId = ObjectId.Null;
|
||||
_isListeningToSelection = false; // 暂时关闭自动监听,避免冲突
|
||||
_isListeningToSelection = false;
|
||||
LocateInListButton.IsEnabled = false;
|
||||
|
||||
try
|
||||
{
|
||||
// 1. 检查是否已经有选中的对象
|
||||
PromptSelectionResult psr = ed.GetSelection();
|
||||
if (psr.Status == PromptStatus.OK && psr.Value.Count > 0)
|
||||
{
|
||||
// 如果有,直接使用第一个
|
||||
targetId = psr.Value.GetObjectIds()[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_parentPalette.Dock == DockSides.None)
|
||||
{
|
||||
// 2. 如果没有选中,则提示用户去选择
|
||||
_parentPalette.Visible = false; // 隐藏面板方便用户选择
|
||||
}
|
||||
else
|
||||
{
|
||||
LocateInListButton.IsEnabled = false;
|
||||
}
|
||||
if (_parentPalette.Dock == DockSides.None) _parentPalette.Visible = false;
|
||||
|
||||
|
||||
PromptEntityOptions peo = new PromptEntityOptions("\n请在图中选择一个地形点块进行定位: ");
|
||||
peo.SetRejectMessage("\n选择的不是块参照。");
|
||||
// 允许选择块或点
|
||||
PromptEntityOptions peo = new PromptEntityOptions("\n请在图中选择一个地形点(块或点)进行定位: ");
|
||||
peo.SetRejectMessage("\n选择的不是块参照或点。");
|
||||
peo.AddAllowedClass(typeof(BlockReference), true);
|
||||
peo.AddAllowedClass(typeof(DBPoint), true);
|
||||
|
||||
PromptEntityResult per = ed.GetEntity(peo);
|
||||
if (per.Status == PromptStatus.OK)
|
||||
@@ -289,7 +292,6 @@ namespace Szmedi.CADkits
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 如果成功获取到ID,则在列表中定位
|
||||
if (!targetId.IsNull)
|
||||
{
|
||||
SelectAndScrollToItem(targetId);
|
||||
@@ -297,17 +299,84 @@ namespace Szmedi.CADkits
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 4. 无论如何都恢复UI状态
|
||||
_isListeningToSelection = true; // 重新开启监听
|
||||
if (_parentPalette.Dock == DockSides.None)
|
||||
{
|
||||
// 操作结束后,重新显示父面板
|
||||
_parentPalette.Visible = true;
|
||||
}
|
||||
_isListeningToSelection = true;
|
||||
if (_parentPalette.Dock == DockSides.None) _parentPalette.Visible = true;
|
||||
LocateInListButton.IsEnabled = true;
|
||||
|
||||
this.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private void ConvertToPointsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Document doc = Application.DocumentManager.MdiActiveDocument;
|
||||
if (doc == null) return;
|
||||
Database db = doc.Database;
|
||||
Editor ed = doc.Editor;
|
||||
|
||||
int convertCount = 0;
|
||||
|
||||
using (DocumentLock docLock = doc.LockDocument())
|
||||
{
|
||||
using (Transaction tr = db.TransactionManager.StartTransaction())
|
||||
{
|
||||
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
|
||||
|
||||
// 遍历列表中所有的项
|
||||
foreach (var item in ReviewItems)
|
||||
{
|
||||
// 获取实体对象,判断是否为多段线
|
||||
if (item.EntityId.IsErased) continue;
|
||||
|
||||
Entity ent = tr.GetObject(item.EntityId, OpenMode.ForRead) as Entity;
|
||||
if (ent is Polyline pl)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 1. 计算几何中心
|
||||
Extents3d ext = pl.GeometricExtents;
|
||||
Point3d center = ext.MinPoint + (ext.MaxPoint - ext.MinPoint) * 0.5;
|
||||
|
||||
// 2. 创建新点 (继承图层和当前的高程)
|
||||
DBPoint newPoint = new DBPoint(center);
|
||||
newPoint.Layer = pl.Layer;
|
||||
newPoint.Color = pl.Color;
|
||||
|
||||
btr.AppendEntity(newPoint);
|
||||
tr.AddNewlyCreatedDBObject(newPoint, true);
|
||||
|
||||
// 3. 更新列表中的数据源 (核心步骤)
|
||||
item.EntityId = newPoint.ObjectId;
|
||||
item.Handle = newPoint.ObjectId.Handle.Value.ToString();
|
||||
// 坐标显示也更新一下
|
||||
item.Position = $"{center.X:F2}, {center.Y:F2}";
|
||||
|
||||
// 4. 删除原多段线
|
||||
pl.UpgradeOpen();
|
||||
pl.Erase();
|
||||
|
||||
convertCount++;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
ed.WriteMessage($"\n转换句柄为 {item.Handle} 的对象时失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
if (convertCount > 0)
|
||||
{
|
||||
// 强制刷新 UI 列表显示
|
||||
ReviewListView.Items.Refresh();
|
||||
MessageBox.Show($"成功将 {convertCount} 个多段线符号转换为中心点。", "转换完成");
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("列表中没有检测到可转换的多段线实体。", "提示");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ public class TerrainTools
|
||||
{
|
||||
private static PaletteSet ps;
|
||||
public const string CheckLineLayer = "校对线";
|
||||
|
||||
[CommandMethod("MoveTerrainElevation")]
|
||||
public void MoveTerrainElevation()
|
||||
{
|
||||
@@ -33,29 +34,97 @@ public class TerrainTools
|
||||
{
|
||||
// --- Phase 1: User Input ---
|
||||
#region User Input Section
|
||||
string targetBlockName; string blockLayerName; string textLayerName; double maxDistance = 5.0;
|
||||
using (Transaction tr = db.TransactionManager.StartTransaction()) { PromptEntityOptions peoBlock = new PromptEntityOptions("\n请选择一个样例地形点块 (用于确定块名和图层): "); peoBlock.SetRejectMessage("\n选择的不是块参照。"); peoBlock.AddAllowedClass(typeof(BlockReference), true); PromptEntityResult perBlock = ed.GetEntity(peoBlock); if (perBlock.Status != PromptStatus.OK) { ed.WriteMessage("\n操作已取消。"); return; } BlockReference sampleBlockRef = (BlockReference)tr.GetObject(perBlock.ObjectId, OpenMode.ForRead); targetBlockName = sampleBlockRef.IsDynamicBlock ? ((BlockTableRecord)tr.GetObject(sampleBlockRef.DynamicBlockTableRecord, OpenMode.ForRead)).Name : sampleBlockRef.Name; blockLayerName = sampleBlockRef.Layer; ed.WriteMessage($"\n已选择样例块: '{targetBlockName}', 所在图层: '{blockLayerName}'"); tr.Commit(); }
|
||||
using (Transaction tr = db.TransactionManager.StartTransaction()) { PromptEntityOptions peoText = new PromptEntityOptions("\n请选择一个样例标高文字 (用于确定图层): "); peoText.SetRejectMessage("\n选择的不是 MText 或 DBText。"); peoText.AddAllowedClass(typeof(MText), true); peoText.AddAllowedClass(typeof(DBText), true); PromptEntityResult perText = ed.GetEntity(peoText); if (perText.Status != PromptStatus.OK) { ed.WriteMessage("\n操作已取消。"); return; } Entity sampleTextEnt = (Entity)tr.GetObject(perText.ObjectId, OpenMode.ForRead); textLayerName = sampleTextEnt.Layer; ed.WriteMessage($"\n已选择样例文字,所在图层: '{textLayerName}'"); tr.Commit(); }
|
||||
PromptDoubleOptions pdo = new PromptDoubleOptions($"\n请输入查找标高文字的最大距离(图形单位) <{maxDistance}>: "); pdo.AllowNegative = false; pdo.AllowZero = false; pdo.AllowNone = true; pdo.DefaultValue = maxDistance; PromptDoubleResult pdr = ed.GetDouble(pdo); if (pdr.Status != PromptStatus.OK && pdr.Status != PromptStatus.None) { ed.WriteMessage("\n操作已取消。"); return; }
|
||||
if (pdr.Status == PromptStatus.OK) maxDistance = pdr.Value; ed.WriteMessage($"\n最大匹配距离设置为: {maxDistance}");
|
||||
|
||||
string targetBlockName = null; // 仅当选中块时使用
|
||||
string terrainLayerName;
|
||||
|
||||
// 定义处理模式: 0-块, 1-点, 2-多段线
|
||||
int processingMode = 0;
|
||||
string textLayerName;
|
||||
double maxDistance = 5.0;
|
||||
|
||||
// 1. 选择样例地形点(块 或 点)
|
||||
using (Transaction tr = db.TransactionManager.StartTransaction())
|
||||
{
|
||||
PromptEntityOptions peoEnt = new PromptEntityOptions("\n请选择一个样例地形点 (块/点/多段线(起终点重合)): ");
|
||||
peoEnt.SetRejectMessage("\n选择的对象无效。");
|
||||
peoEnt.AddAllowedClass(typeof(BlockReference), true);
|
||||
peoEnt.AddAllowedClass(typeof(DBPoint), true);
|
||||
peoEnt.AddAllowedClass(typeof(Polyline), true);
|
||||
|
||||
PromptEntityResult perEnt = ed.GetEntity(peoEnt);
|
||||
if (perEnt.Status != PromptStatus.OK) { ed.WriteMessage("\n操作已取消。"); return; }
|
||||
|
||||
Entity sampleEnt = (Entity)tr.GetObject(perEnt.ObjectId, OpenMode.ForRead);
|
||||
terrainLayerName = sampleEnt.Layer;
|
||||
|
||||
if (sampleEnt is BlockReference sampleBlock)
|
||||
{
|
||||
processingMode = 0;
|
||||
targetBlockName = sampleBlock.IsDynamicBlock ? ((BlockTableRecord)tr.GetObject(sampleBlock.DynamicBlockTableRecord, OpenMode.ForRead)).Name : sampleBlock.Name;
|
||||
ed.WriteMessage($"\n已选择模式: [处理块]。块名: '{targetBlockName}', 图层: '{terrainLayerName}'");
|
||||
}
|
||||
else if (sampleEnt is DBPoint)
|
||||
{
|
||||
processingMode = 1;
|
||||
ed.WriteMessage($"\n已选择模式: [处理点实体]。所在图层: '{terrainLayerName}'");
|
||||
}
|
||||
else if (sampleEnt is Polyline)
|
||||
{
|
||||
processingMode = 2;
|
||||
ed.WriteMessage("\n模式: [多段线]");
|
||||
}
|
||||
tr.Commit();
|
||||
}
|
||||
|
||||
// 2. 选择样例文字
|
||||
using (Transaction tr = db.TransactionManager.StartTransaction())
|
||||
{
|
||||
PromptEntityOptions peoText = new PromptEntityOptions("\n请选择一个样例标高文字 (用于确定图层): ");
|
||||
peoText.SetRejectMessage("\n选择的不是 MText 或 DBText。");
|
||||
peoText.AddAllowedClass(typeof(MText), true);
|
||||
peoText.AddAllowedClass(typeof(DBText), true);
|
||||
PromptEntityResult perText = ed.GetEntity(peoText);
|
||||
if (perText.Status != PromptStatus.OK) { ed.WriteMessage("\n操作已取消。"); return; }
|
||||
Entity sampleTextEnt = (Entity)tr.GetObject(perText.ObjectId, OpenMode.ForRead);
|
||||
textLayerName = sampleTextEnt.Layer;
|
||||
ed.WriteMessage($"\n已选择样例文字,所在图层: '{textLayerName}'");
|
||||
tr.Commit();
|
||||
}
|
||||
|
||||
// 3. 输入距离
|
||||
PromptDoubleOptions pdo = new PromptDoubleOptions($"\n请输入查找标高文字的最大距离(图形单位) <{maxDistance}>: ");
|
||||
pdo.AllowNegative = false; pdo.AllowZero = false; pdo.AllowNone = true; pdo.DefaultValue = maxDistance;
|
||||
PromptDoubleResult pdr = ed.GetDouble(pdo);
|
||||
if (pdr.Status != PromptStatus.OK && pdr.Status != PromptStatus.None) { ed.WriteMessage("\n操作已取消。"); return; }
|
||||
if (pdr.Status == PromptStatus.OK) maxDistance = pdr.Value;
|
||||
|
||||
#endregion
|
||||
|
||||
// --- Phase 2: Automatic Matching ---
|
||||
List<BlockRefWithPosition> terrainBlocks;
|
||||
List<TextWithPosition> elevationTexts;
|
||||
Dictionary<ObjectId, ObjectId> validPairs;
|
||||
List<TerrainEntityInfo> terrainEntities = new List<TerrainEntityInfo>();
|
||||
int updatedCount = 0;
|
||||
|
||||
using (Transaction tr = db.TransactionManager.StartTransaction())
|
||||
{
|
||||
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
|
||||
terrainBlocks = CollectBlocks(tr, btr, targetBlockName, blockLayerName);
|
||||
if (terrainBlocks.Count == 0) { ed.WriteMessage($"\n错误: 在图层 '{blockLayerName}' 上未找到名为 '{targetBlockName}' 的块。"); return; }
|
||||
elevationTexts = CollectFilteredTexts(tr, btr, textLayerName);
|
||||
|
||||
// 根据模式采集
|
||||
if (processingMode == 0)
|
||||
terrainEntities = CollectBlocks(tr, btr, targetBlockName, terrainLayerName);
|
||||
else if (processingMode == 1)
|
||||
terrainEntities = CollectPoints(tr, btr, terrainLayerName);
|
||||
else if (processingMode == 2)
|
||||
terrainEntities = CollectPolylines(tr, btr, terrainLayerName);
|
||||
var elevationTexts = CollectFilteredTexts(tr, btr, textLayerName);
|
||||
|
||||
if (elevationTexts.Count == 0) { ed.WriteMessage($"\n警告: 在图层 '{textLayerName}' 上未找到任何有效的标高文字。"); tr.Commit(); return; }
|
||||
|
||||
ed.WriteMessage($"\n正在使用贪婪匹配算法分析 {terrainBlocks.Count} 个块...");
|
||||
validPairs = GetScoredValidPairs(terrainBlocks, elevationTexts, maxDistance);
|
||||
ed.WriteMessage($"\n正在使用贪婪匹配算法分析 {terrainEntities.Count} 个地形点...");
|
||||
|
||||
// 核心匹配算法不需要修改,因为它只依赖 ObjectId 和 Position,这在 TerrainEntityInfo 中都有
|
||||
var validPairs = GetScoredValidPairs(terrainEntities, elevationTexts, maxDistance);
|
||||
|
||||
ed.WriteMessage($"\n分析完成。找到 {validPairs.Count} 个最优匹配对。");
|
||||
|
||||
if (validPairs.Count > 0)
|
||||
@@ -63,17 +132,46 @@ public class TerrainTools
|
||||
CreateLayerIfNotExists(db, tr, CheckLineLayer, 8);
|
||||
ProgressMeter pm = new ProgressMeter();
|
||||
pm.SetLimit(validPairs.Count);
|
||||
pm.Start("正在更新已自动匹配的块...");
|
||||
pm.Start("正在更新已自动匹配的实体...");
|
||||
|
||||
var textDataMap = elevationTexts.ToDictionary(t => t.ObjectId, t => t);
|
||||
|
||||
foreach (var pair in validPairs)
|
||||
{
|
||||
if (double.TryParse(textDataMap[pair.Value].TextContent, out double elevationZ))
|
||||
{
|
||||
BlockReference blockRef = (BlockReference)tr.GetObject(pair.Key, OpenMode.ForWrite);
|
||||
blockRef.Position = new Point3d(blockRef.Position.X, blockRef.Position.Y, elevationZ);
|
||||
Line line = new Line(blockRef.Position, textDataMap[pair.Value].Position);
|
||||
line.Layer = CheckLineLayer;
|
||||
line.ColorIndex = 256;
|
||||
// 更新位置逻辑:需要判断是块还是点
|
||||
Entity ent = (Entity)tr.GetObject(pair.Key, OpenMode.ForWrite);
|
||||
Point3d currentPos;
|
||||
|
||||
if (ent is BlockReference blk)
|
||||
{
|
||||
blk.Position = new Point3d(blk.Position.X, blk.Position.Y, elevationZ);
|
||||
currentPos = blk.Position;
|
||||
}
|
||||
else if (ent is DBPoint pt)
|
||||
{
|
||||
pt.Position = new Point3d(pt.Position.X, pt.Position.Y, elevationZ);
|
||||
currentPos = pt.Position;
|
||||
}
|
||||
else if (ent is Polyline pl)
|
||||
{
|
||||
// 对于 2D 多段线,修改 Elevation 属性
|
||||
pl.Elevation = elevationZ;
|
||||
Extents3d ext = pl.GeometricExtents;
|
||||
currentPos = ext.MinPoint + (ext.MaxPoint - ext.MinPoint) * 0.5;
|
||||
//currentPos = pl.GetPoint3dAt(0); // 取第一个点作为连线起点
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Line line = new Line(currentPos, textDataMap[pair.Value].Position)
|
||||
{
|
||||
Layer = CheckLineLayer,
|
||||
ColorIndex = 256
|
||||
};
|
||||
btr.AppendEntity(line);
|
||||
tr.AddNewlyCreatedDBObject(line, true);
|
||||
updatedCount++;
|
||||
@@ -82,124 +180,183 @@ public class TerrainTools
|
||||
pm.Stop();
|
||||
}
|
||||
tr.Commit();
|
||||
ed.WriteMessage($"\n\n--- 自动处理报告 ---\n成功自动更新 {updatedCount} 个实体。\n{terrainEntities.Count - updatedCount} 个实体需要审核。");
|
||||
|
||||
if (terrainEntities.Count > 0)
|
||||
{
|
||||
if (ps == null) { ps = new PaletteSet("审核并校对高程点", new Guid("C4E61D33-3162-4889-A263-6A1D2C52D26C")); }
|
||||
if (ps.Count > 0) { ps.Remove(0); }
|
||||
|
||||
// UI 控件初始化
|
||||
var reviewControl = new ReviewAndMatchWindow(terrainEntities, validPairs, elevationTexts, CheckLineLayer, ps);
|
||||
ElementHost host = new ElementHost { Dock = DockStyle.Fill, Child = reviewControl };
|
||||
ps.Add("ReviewAndMatch", host);
|
||||
ps.Visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Phase 3: Reporting and Launching Review Palette ---
|
||||
ed.WriteMessage($"\n\n--- 自动处理报告 ---\n成功自动更新 {updatedCount} 个块。\n{terrainBlocks.Count - updatedCount} 个块需要审核。");
|
||||
|
||||
if (terrainBlocks.Count > 0)
|
||||
{
|
||||
if (ps == null) { ps = new PaletteSet("审核并校对高程点", new Guid("C4E61D33-3162-4889-A263-6A1D2C52D26C")); }
|
||||
if (ps.Count > 0) { ps.Remove(0); }
|
||||
|
||||
var reviewControl = new ReviewAndMatchWindow(terrainBlocks, validPairs, elevationTexts, CheckLineLayer, ps);
|
||||
ElementHost host = new ElementHost { Dock = DockStyle.Fill, Child = reviewControl };
|
||||
ps.Add("ReviewAndMatch", host);
|
||||
ps.Visible = true;
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex) { ed.WriteMessage($"\n发生严重错误: {ex.Message}\n{ex.StackTrace}"); }
|
||||
}
|
||||
private Dictionary<ObjectId, ObjectId> GetScoredValidPairs(List<BlockRefWithPosition> blocks, List<TextWithPosition> texts, double maxDist)
|
||||
|
||||
// 匹配算法逻辑保持不变,只需签名中的 List 类型改为 TerrainEntityInfo
|
||||
private Dictionary<ObjectId, ObjectId> GetScoredValidPairs(List<TerrainEntityInfo> entities, List<TextWithPosition> texts, double maxDist)
|
||||
{
|
||||
// 1. 预先计算每个文字的竞争情况
|
||||
var textCompetition = new Dictionary<ObjectId, double>();
|
||||
// ... (原逻辑不变,ent.Position 属性是一样的) ...
|
||||
foreach (var text in texts)
|
||||
{
|
||||
var distancesToBlocks = blocks
|
||||
var distancesToEnts = entities
|
||||
.Select(b => new Point2d(b.Position.X, b.Position.Y).GetDistanceTo(new Point2d(text.Position.X, text.Position.Y)))
|
||||
.OrderBy(d => d)
|
||||
.ToList();
|
||||
|
||||
if (distancesToBlocks.Count >= 2)
|
||||
if (distancesToEnts.Count >= 2)
|
||||
{
|
||||
double d1 = distancesToBlocks[0]; // 最近距离
|
||||
double d2 = distancesToBlocks[1]; // 次近距离
|
||||
// 竞争度比率:d1/d2越小,说明越没有争议。范围 [0, 1]
|
||||
double d1 = distancesToEnts[0];
|
||||
double d2 = distancesToEnts[1];
|
||||
textCompetition[text.ObjectId] = (d2 > 0.001) ? (d1 / d2) : 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
textCompetition[text.ObjectId] = 0.0; // 只有一个块,没有竞争
|
||||
textCompetition[text.ObjectId] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 计算所有可能配对的综合得分
|
||||
var allPossiblePairs = new List<Tuple<ObjectId, ObjectId, double>>(); // BlockId, TextId, Score
|
||||
foreach (var block in blocks)
|
||||
var allPossiblePairs = new List<Tuple<ObjectId, ObjectId, double>>();
|
||||
foreach (var ent in entities)
|
||||
{
|
||||
foreach (var text in texts)
|
||||
{
|
||||
double dist = new Point2d(block.Position.X, block.Position.Y)
|
||||
double dist = new Point2d(ent.Position.X, ent.Position.Y)
|
||||
.GetDistanceTo(new Point2d(text.Position.X, text.Position.Y));
|
||||
|
||||
if (dist <= maxDist)
|
||||
{
|
||||
// 距离分:距离越小,分数越高。用 1/dist 标准化
|
||||
double distanceScore = 1.0 / (dist + 0.001); // 加一个小数防止除以0
|
||||
|
||||
// 唯一性分:竞争度越小(比率越小),分数越高
|
||||
double uniquenessScore = 1.0 - textCompetition[text.ObjectId]; // 范围 [0, 1]
|
||||
|
||||
// **综合得分 = 70% 距离分 + 30% 唯一性分**
|
||||
double finalScore = 0.7 * distanceScore + 0.3 * uniquenessScore * distanceScore; // 让唯一性也受距离影响
|
||||
|
||||
allPossiblePairs.Add(new Tuple<ObjectId, ObjectId, double>(block.ObjectId, text.ObjectId, finalScore));
|
||||
double distanceScore = 1.0 / (dist + 0.001);
|
||||
double uniquenessScore = 1.0 - textCompetition[text.ObjectId];
|
||||
double finalScore = 0.7 * distanceScore + 0.3 * uniquenessScore * distanceScore;
|
||||
allPossiblePairs.Add(new Tuple<ObjectId, ObjectId, double>(ent.ObjectId, text.ObjectId, finalScore));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 按综合得分从高到低排序
|
||||
var sortedPairs = allPossiblePairs.OrderByDescending(p => p.Item3).ToList();
|
||||
|
||||
// 4. 贪婪匹配最高分的
|
||||
var validPairs = new Dictionary<ObjectId, ObjectId>();
|
||||
var matchedBlocks = new HashSet<ObjectId>();
|
||||
var matchedEnts = new HashSet<ObjectId>();
|
||||
var matchedTexts = new HashSet<ObjectId>();
|
||||
|
||||
foreach (var pair in sortedPairs)
|
||||
{
|
||||
ObjectId blockId = pair.Item1;
|
||||
ObjectId textId = pair.Item2;
|
||||
|
||||
if (!matchedBlocks.Contains(blockId) && !matchedTexts.Contains(textId))
|
||||
if (!matchedEnts.Contains(pair.Item1) && !matchedTexts.Contains(pair.Item2))
|
||||
{
|
||||
validPairs.Add(blockId, textId);
|
||||
matchedBlocks.Add(blockId);
|
||||
matchedTexts.Add(textId);
|
||||
validPairs.Add(pair.Item1, pair.Item2);
|
||||
matchedEnts.Add(pair.Item1);
|
||||
matchedTexts.Add(pair.Item2);
|
||||
}
|
||||
}
|
||||
return validPairs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 采集多段线方法 ---
|
||||
/// </summary>
|
||||
/// <param name="tr"></param>
|
||||
/// <param name="btr"></param>
|
||||
/// <param name="layerName"></param>
|
||||
/// <returns></returns>
|
||||
private List<TerrainEntityInfo> CollectPolylines(Transaction tr, BlockTableRecord btr, string layerName)
|
||||
{
|
||||
var list = new List<TerrainEntityInfo>();
|
||||
foreach (ObjectId id in btr)
|
||||
{
|
||||
if (id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(Polyline))))
|
||||
{
|
||||
var pl = (Polyline)tr.GetObject(id, OpenMode.ForRead);
|
||||
if (pl.Layer.Equals(layerName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
try
|
||||
{
|
||||
// 【核心修改】:对于圆弧/圆形多段线,取其几何中心作为参考点
|
||||
// 这样即使多段线是由两个半圆组成的,中心点也会准确落在圆心
|
||||
Extents3d ext = pl.GeometricExtents;
|
||||
Point3d center = ext.MinPoint + (ext.MaxPoint - ext.MinPoint) * 0.5;
|
||||
|
||||
// 将计算出的“圆心”存入 TerrainEntityInfo
|
||||
list.Add(new TerrainEntityInfo(id, center));
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 如果某些特殊情况无法获取包围盒,则退而求其次取第一个点
|
||||
list.Add(new TerrainEntityInfo(id, pl.GetPoint3dAt(0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
/// 采集点
|
||||
/// </summary>
|
||||
/// <param name="tr"></param>
|
||||
/// <param name="btr"></param>
|
||||
/// <param name="layerName"></param>
|
||||
/// <returns></returns>
|
||||
private List<TerrainEntityInfo> CollectPoints(Transaction tr, BlockTableRecord btr, string layerName)
|
||||
{
|
||||
var list = new List<TerrainEntityInfo>();
|
||||
foreach (ObjectId id in btr)
|
||||
{
|
||||
if (id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(DBPoint))))
|
||||
{
|
||||
var pt = (DBPoint)tr.GetObject(id, OpenMode.ForRead);
|
||||
if (pt.Layer.Equals(layerName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
list.Add(new TerrainEntityInfo(id, pt.Position));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// 修改:采集块实体 (返回类型变更为 TerrainEntityInfo)
|
||||
private List<TerrainEntityInfo> CollectBlocks(Transaction tr, BlockTableRecord btr, string targetBlockName, string blockLayerName)
|
||||
{
|
||||
var list = new List<TerrainEntityInfo>();
|
||||
foreach (ObjectId id in btr)
|
||||
if (id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(BlockReference))))
|
||||
{
|
||||
var br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
|
||||
string name = br.IsDynamicBlock ? ((BlockTableRecord)tr.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead)).Name : br.Name;
|
||||
if (br.Layer.Equals(blockLayerName, StringComparison.OrdinalIgnoreCase) && name.Equals(targetBlockName, StringComparison.OrdinalIgnoreCase))
|
||||
list.Add(new TerrainEntityInfo(id, br.Position));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<TextWithPosition> CollectFilteredTexts(Transaction tr, BlockTableRecord btr, string textLayerName) { var list = new List<TextWithPosition>(); Regex rgx = new Regex(@"[\u4e00-\u9fa5]"); foreach (ObjectId id in btr) { if (id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(DBText))) || id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(MText)))) { var ent = (Entity)tr.GetObject(id, OpenMode.ForRead); if (ent.Layer.Equals(textLayerName, StringComparison.OrdinalIgnoreCase)) { string txt = (ent is MText mt) ? mt.Contents : ((DBText)ent).TextString; if (!string.IsNullOrWhiteSpace(txt) && !rgx.IsMatch(txt) && txt.Contains(".") && double.TryParse(txt, out _)) { try { Extents3d ext = ent.GeometricExtents; Point3d center = ext.MinPoint + (ext.MaxPoint - ext.MinPoint) * 0.5; list.Add(new TextWithPosition(id, center, txt)); } catch { } } } } } return list; }
|
||||
private void CreateLayerIfNotExists(Database db, Transaction tr, string layerName, short colorIndex) { LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); if (!lt.Has(layerName)) { lt.UpgradeOpen(); var ltr = new LayerTableRecord { Name = layerName, Color = Color.FromColorIndex(ColorMethod.ByAci, colorIndex) }; lt.Add(ltr); tr.AddNewlyCreatedDBObject(ltr, true); } }
|
||||
|
||||
// 清理功能保持不变
|
||||
public static void CleanAllCheckLines()
|
||||
{
|
||||
// ... (与原代码一致,此处略) ...
|
||||
// 请确保保留原 CleanAllCheckLines 实现
|
||||
Document doc = Application.DocumentManager.MdiActiveDocument;
|
||||
if (doc == null) return;
|
||||
Database db = doc.Database;
|
||||
Editor ed = doc.Editor;
|
||||
int cleanedCount = 0;
|
||||
|
||||
using (doc.LockDocument())
|
||||
using (Transaction tr = db.TransactionManager.StartTransaction())
|
||||
{
|
||||
try
|
||||
{
|
||||
LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
|
||||
if (!lt.Has(CheckLineLayer))
|
||||
{
|
||||
ed.WriteMessage($"\n图层 '{CheckLineLayer}' 不存在,无需清理。");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lt.Has(CheckLineLayer)) return;
|
||||
LayerTableRecord layer = (LayerTableRecord)tr.GetObject(lt[CheckLineLayer], OpenMode.ForRead);
|
||||
if (layer.IsLocked)
|
||||
{
|
||||
layer.UpgradeOpen();
|
||||
layer.IsLocked = false;
|
||||
}
|
||||
|
||||
if (layer.IsLocked) { layer.UpgradeOpen(); layer.IsLocked = false; }
|
||||
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead);
|
||||
|
||||
foreach (ObjectId id in btr)
|
||||
{
|
||||
if (id.ObjectClass.DxfName.Equals("LINE", StringComparison.OrdinalIgnoreCase))
|
||||
@@ -207,72 +364,13 @@ public class TerrainTools
|
||||
Line line = tr.GetObject(id, OpenMode.ForRead) as Line;
|
||||
if (line != null && line.Layer.Equals(CheckLineLayer, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
line.UpgradeOpen();
|
||||
line.Erase();
|
||||
cleanedCount++;
|
||||
line.UpgradeOpen(); line.Erase(); cleanedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
tr.Commit();
|
||||
ed.WriteMessage($"\n已清理 {cleanedCount} 条校对线。");
|
||||
ed.Regen();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
ed.WriteMessage($"\n清理时发生错误: {ex.Message}");
|
||||
tr.Abort();
|
||||
tr.Commit(); ed.WriteMessage($"\n已清理 {cleanedCount} 条校对线。"); ed.Regen();
|
||||
}
|
||||
catch { tr.Abort(); }
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Implements a greedy algorithm to find the best one-to-one block/text pairings.
|
||||
/// </summary>
|
||||
private Dictionary<ObjectId, ObjectId> GetGreedyValidPairs(List<BlockRefWithPosition> blocks, List<TextWithPosition> texts, double maxDist)
|
||||
{
|
||||
// 1. Create a list of all possible pairs within the max distance
|
||||
var allPossiblePairs = new List<Tuple<ObjectId, ObjectId, double>>();
|
||||
foreach (var block in blocks)
|
||||
{
|
||||
foreach (var text in texts)
|
||||
{
|
||||
double dist = new Point2d(block.Position.X, block.Position.Y)
|
||||
.GetDistanceTo(new Point2d(text.Position.X, text.Position.Y));
|
||||
if (dist <= maxDist)
|
||||
{
|
||||
allPossiblePairs.Add(new Tuple<ObjectId, ObjectId, double>(block.ObjectId, text.ObjectId, dist));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Sort all pairs by distance, ascending
|
||||
var sortedPairs = allPossiblePairs.OrderBy(p => p.Item3).ToList();
|
||||
|
||||
// 3. Iterate and match, ensuring one-to-one mapping
|
||||
var validPairs = new Dictionary<ObjectId, ObjectId>();
|
||||
var matchedBlocks = new HashSet<ObjectId>();
|
||||
var matchedTexts = new HashSet<ObjectId>();
|
||||
|
||||
foreach (var pair in sortedPairs)
|
||||
{
|
||||
ObjectId blockId = pair.Item1;
|
||||
ObjectId textId = pair.Item2;
|
||||
|
||||
// If neither the block nor the text has been matched yet, it's a valid pair
|
||||
if (!matchedBlocks.Contains(blockId) && !matchedTexts.Contains(textId))
|
||||
{
|
||||
validPairs.Add(blockId, textId);
|
||||
matchedBlocks.Add(blockId);
|
||||
matchedTexts.Add(textId);
|
||||
}
|
||||
}
|
||||
|
||||
return validPairs;
|
||||
}
|
||||
|
||||
|
||||
#region Other Helper Methods (Unchanged)
|
||||
private List<BlockRefWithPosition> CollectBlocks(Transaction tr, BlockTableRecord btr, string targetBlockName, string blockLayerName) { var list = new List<BlockRefWithPosition>(); foreach (ObjectId id in btr) if (id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(BlockReference)))) { var br = (BlockReference)tr.GetObject(id, OpenMode.ForRead); string name = br.IsDynamicBlock ? ((BlockTableRecord)tr.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead)).Name : br.Name; if (br.Layer.Equals(blockLayerName, StringComparison.OrdinalIgnoreCase) && name.Equals(targetBlockName, StringComparison.OrdinalIgnoreCase)) list.Add(new BlockRefWithPosition(id, br.Position)); } return list; }
|
||||
private List<TextWithPosition> CollectFilteredTexts(Transaction tr, BlockTableRecord btr, string textLayerName) { var list = new List<TextWithPosition>(); Regex rgx = new Regex(@"[\u4e00-\u9fa5]"); foreach (ObjectId id in btr) { if (id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(DBText))) || id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(MText)))) { var ent = (Entity)tr.GetObject(id, OpenMode.ForRead); if (ent.Layer.Equals(textLayerName, StringComparison.OrdinalIgnoreCase)) { string txt = (ent is MText mt) ? mt.Contents : ((DBText)ent).TextString; if (!string.IsNullOrWhiteSpace(txt) && !rgx.IsMatch(txt) && txt.Contains(".") && double.TryParse(txt, out _)) { try { Extents3d ext = ent.GeometricExtents; Point3d center = ext.MinPoint + (ext.MaxPoint - ext.MinPoint) * 0.5; list.Add(new TextWithPosition(id, center, txt)); } catch { } } } } } return list; }
|
||||
private void CreateLayerIfNotExists(Database db, Transaction tr, string layerName, short colorIndex) { LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); if (!lt.Has(layerName)) { lt.UpgradeOpen(); var ltr = new LayerTableRecord { Name = layerName, Color = Color.FromColorIndex(ColorMethod.ByAci, colorIndex) }; lt.Add(ltr); tr.AddNewlyCreatedDBObject(ltr, true); } }
|
||||
#endregion
|
||||
}
|
||||
@@ -20,3 +20,18 @@ public readonly struct TextWithPosition
|
||||
TextContent = content;
|
||||
}
|
||||
}
|
||||
|
||||
// 用于通用存储 地形点(块或点实体)的信息
|
||||
public readonly struct TerrainEntityInfo
|
||||
{
|
||||
public ObjectId ObjectId { get; }
|
||||
public Point3d Position { get; }
|
||||
public string Handle { get; }
|
||||
|
||||
public TerrainEntityInfo(ObjectId id, Point3d pos)
|
||||
{
|
||||
ObjectId = id;
|
||||
Position = pos;
|
||||
Handle = id.Handle.Value.ToString();
|
||||
}
|
||||
}
|
||||
8
Szmedi.RvKits.crproj
Normal file
8
Szmedi.RvKits.crproj
Normal file
@@ -0,0 +1,8 @@
|
||||
<project outputDir="I:\04 程序开发\Revit Dev\Szmedi.RvKit\bin\Release" baseDir="I:\04 程序开发\Revit Dev\Szmedi.RvKit\bin\Release" xmlns="http://confuser.codeplex.com">
|
||||
<rule pattern="true" />
|
||||
<rule pattern="member-type('type')" inherit="false">
|
||||
<protection id="rename" action="remove" />
|
||||
</rule>
|
||||
<module path="bin\Release\2018\Szmedi.RvKits.dll" />
|
||||
<module path="bin\Release\2020\Szmedi.RvKits.dll" />
|
||||
</project>
|
||||
@@ -55,7 +55,7 @@
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ErrorMessage, Converter={StaticResource NullOrEmptyToBooleanConverter}}" Value="True">
|
||||
<Setter Property="Background" Value="Red" />
|
||||
<Setter Property="Background" Value="IndianRed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
@@ -63,7 +63,8 @@ namespace Szmedi.RvKits.MEPTools
|
||||
AppDomain.CurrentDomain.AssemblyResolve += ResolveHelper.ResolveAssembly;
|
||||
try
|
||||
{
|
||||
Items = package.ToList<FacilityItem>(1, configuration => configuration.SkipCastingErrors());
|
||||
var resultList = package.ToList<FacilityItem>(1, configuration => configuration.SkipCastingErrors());
|
||||
Items = resultList.Where(f => !string.IsNullOrEmpty(f.Name)).ToList();
|
||||
}
|
||||
catch (EPPlus.Core.Extensions.Exceptions.ExcelValidationException ex)
|
||||
{
|
||||
@@ -207,7 +208,10 @@ namespace Szmedi.RvKits.MEPTools
|
||||
foreach (var item in Items)
|
||||
{
|
||||
double minRatio = 30;
|
||||
|
||||
if(string.IsNullOrEmpty(item.Name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach (var family in Families)
|
||||
{
|
||||
var famName = family.Name;
|
||||
|
||||
Binary file not shown.
@@ -16,7 +16,7 @@
|
||||
<AssemblyName>Szmedi.RvKits</AssemblyName>
|
||||
<RootNamespace>$(AssemblyName)</RootNamespace>
|
||||
<Company>Szmedi</Company>
|
||||
<AssemblyVersion>2.2.3.83</AssemblyVersion>
|
||||
<AssemblyVersion>2.2.3.84</AssemblyVersion>
|
||||
<ProductVersion>$(AssemblyVersion)</ProductVersion>
|
||||
<FileVersion>$(AssemblyVersion)</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
; 定义应用程序的名称
|
||||
#define MyAppName "SzmediTools"
|
||||
; 定义应用程序的版本号
|
||||
#define MyAppVersion "2.2.3.83"
|
||||
#define MyAppVersion "2.2.3.84"
|
||||
; 定义应用程序的发布者
|
||||
#define MyAppPublisher "SZMEDI"
|
||||
; 定义应用程序的网址
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
xmlns:editor="clr-namespace:RoslynPad.Editor;assembly=RoslynPad.Editor.Windows"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes">
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<!--<ResourceDictionary Source="pack://application:,,,/Szmedi.RvKits;component/Controls/MaterialWindow.xaml" />-->
|
||||
|
||||
<!--<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/Internal/MaterialDesignTheme.BaseThemeColors.xaml" />-->
|
||||
<!--<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Dark.xaml" />-->
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
|
||||
using Autodesk.Revit.DB;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RevitAddins
|
||||
{
|
||||
internal class ElementModel
|
||||
{
|
||||
private readonly Element element;
|
||||
private readonly EngineeringType engineeringType;
|
||||
|
||||
public string Category => element.GetParameters("深圳构件标识").FirstOrDefault()?.AsString() ?? "无";
|
||||
public int Count => Parameters.Count;
|
||||
|
||||
public Dictionary<string, List<Parameter>> Groups
|
||||
{
|
||||
get
|
||||
{
|
||||
var groups = new Dictionary<string, List<Parameter>>();
|
||||
foreach (Parameter parameter in Parameters)
|
||||
{
|
||||
string groupName = string.Empty;
|
||||
var parameterName = parameter.Definition.Name;
|
||||
|
||||
switch (engineeringType)
|
||||
{
|
||||
case EngineeringType.Architecture:
|
||||
//对Revit中的所有模型元素按照“深圳构件标识”属性的值进行分组,分组后每个组中的元素都具有相同的“深圳构件标识”属性值。每个组都创建一张Sheet表格,SheetName为“深圳构件标识”属性的值
|
||||
//Revit第一行是深圳构件标识的属性值
|
||||
//第二行是根据参数的名称,比如属性包含名称、编号、编码,则为身份信息,包含基点坐标则为定位信息,其余为技术信息
|
||||
//第三行是Revit中的元素的“深圳构件标识”属性值对应的参数的名称
|
||||
{
|
||||
if (parameterName is "名称" or "编号" or "编码")
|
||||
{
|
||||
groupName = "身份信息";
|
||||
}
|
||||
else if (parameterName.Contains("基点坐标") || parameterName is "所在楼层" or "建筑单体名称")
|
||||
{
|
||||
groupName = "定位信息";
|
||||
}
|
||||
else if (parameterName.Contains("生产") || parameterName.Contains("产品") || parameterName.Contains("出厂"))
|
||||
{
|
||||
groupName = "生产信息";
|
||||
}
|
||||
else
|
||||
{
|
||||
groupName = "技术信息";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case EngineeringType.Municipal:
|
||||
{
|
||||
//第二行是根据参数的名称,比如属性包含模型元素名称、编号、分类编码,则为身份信息,包含桩号范围、桥面高度、相对位置、梁底高程则为定位信息,包含长度、宽度、高度则为构造尺寸,其余为设计信息
|
||||
if (parameterName is "模型元素名称" or "编号" or "分类编码")
|
||||
{
|
||||
groupName = "身份信息";
|
||||
}
|
||||
else if (parameterName is "桩号范围" or "桥面高度" or "相对位置" or "梁底高程")
|
||||
{
|
||||
groupName = "定位信息";
|
||||
}
|
||||
else if (parameterName is "长度" or "宽度" or "高度")
|
||||
{
|
||||
groupName = "构造尺寸";
|
||||
}
|
||||
else
|
||||
{
|
||||
groupName = "设计信息";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!groups.ContainsKey(groupName))
|
||||
{
|
||||
groups[groupName] = new List<Parameter>();
|
||||
}
|
||||
groups[groupName].Add(parameter);
|
||||
}
|
||||
|
||||
//对分组后的参数进行排序,排序按照名称、编号、分类编码、模型元素名称
|
||||
//var sortedParameters = new Dictionary<string, List<Parameter>>();
|
||||
//var paramOrder = new List<string>
|
||||
//{
|
||||
// "名称",
|
||||
// "编号",
|
||||
// "分类编码",
|
||||
// "模型元素名称",
|
||||
// "建筑单体名称",
|
||||
// "所在楼层",
|
||||
// "基点坐标X",
|
||||
// "基点坐标Y",
|
||||
// "基点坐标Z",
|
||||
// "主要材料导热系数",
|
||||
// "主要材料密度",
|
||||
// "K 值",
|
||||
// "耐火极限",
|
||||
// "墙厚",
|
||||
//};
|
||||
|
||||
foreach (var group in groups)
|
||||
{
|
||||
group.Value.Sort((x, y) => string.Compare(x.Definition.Name, y.Definition.Name, StringComparison.Ordinal));
|
||||
}
|
||||
//对分组进行排序,顺序是身份信息、定位信息、构造尺寸、设计信息、技术信息、生产信息
|
||||
var sortedGroups = new Dictionary<string, List<Parameter>>();
|
||||
var groupOrder = new List<string>
|
||||
{
|
||||
"身份信息",
|
||||
"定位信息",
|
||||
"构造尺寸",
|
||||
"设计信息",
|
||||
"技术信息",
|
||||
"生产信息"
|
||||
};
|
||||
foreach (var groupName in groupOrder)
|
||||
{
|
||||
if (groups.ContainsKey(groupName))
|
||||
{
|
||||
sortedGroups[groupName] = groups[groupName];
|
||||
}
|
||||
}
|
||||
//将排序后的分组添加到字典中
|
||||
foreach (var group in groups)
|
||||
{
|
||||
if (!sortedGroups.ContainsKey(group.Key))
|
||||
{
|
||||
sortedGroups[group.Key] = group.Value;
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
}
|
||||
|
||||
private List<Parameter> Parameters
|
||||
{
|
||||
get
|
||||
{
|
||||
var parameters = new List<Parameter>();
|
||||
foreach (Parameter parameter in element.Parameters)
|
||||
{
|
||||
if (parameter.HasValue && parameter.Definition.ParameterGroup == BuiltInParameterGroup.PG_ADSK_MODEL_PROPERTIES && !string.IsNullOrEmpty(parameter.AsString()))
|
||||
{
|
||||
parameters.Add(parameter);
|
||||
}
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
public ElementModel(Element element, EngineeringType engineeringType)
|
||||
{
|
||||
this.element = element;
|
||||
this.engineeringType = engineeringType;
|
||||
}
|
||||
}
|
||||
enum EngineeringType
|
||||
{
|
||||
Architecture,
|
||||
Municipal
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
using System;
|
||||
using Autodesk.Windows;
|
||||
using ricaun.Revit.ExtensibleShortcuts.Services;
|
||||
|
||||
namespace ricaun.Revit.ExtensibleShortcuts
|
||||
{
|
||||
/// <summary>
|
||||
/// 为菜单按钮设置快捷键的扩展类
|
||||
/// </summary>
|
||||
/// <para>
|
||||
/// private void SetShortcuts(Autodesk.Revit.UI.RibbonItem ribbonItem, params string[] shortcuts)
|
||||
/// {
|
||||
/// App.app.ControlledApplication.ApplicationInitialized += (object s, ApplicationInitializedEventArgs e)=>
|
||||
/// {
|
||||
/// KeyboardShortcutExtension.SetShortcutUnique(Autodesk.Windows.RibbonItem(需要转换), shortcuts);
|
||||
/// };
|
||||
///}
|
||||
/// </para>
|
||||
public static class KeyboardShortcutExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 设置快捷键
|
||||
/// </summary>
|
||||
/// <param name="ribbonItem"></param>
|
||||
/// <param name="shortcuts"></param>
|
||||
/// <returns></returns>
|
||||
public static bool SetShortcut(this RibbonItem ribbonItem, params string[] shortcuts)
|
||||
{
|
||||
KeyboardShortcutService keyboardShortcutService = new KeyboardShortcutService();
|
||||
keyboardShortcutService.RemoveRibbonItemShortcut(ribbonItem.Id);
|
||||
return keyboardShortcutService.SetRibbonItemShortcut(ribbonItem.Id, string.Join("#", shortcuts));
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置唯一快捷键
|
||||
/// </summary>
|
||||
/// <param name="ribbonItem"></param>
|
||||
/// <param name="shortcuts"></param>
|
||||
/// <returns></returns>
|
||||
public static bool SetShortcutUnique(this RibbonItem ribbonItem, params string[] shortcuts)
|
||||
{
|
||||
KeyboardShortcutService keyboardShortcutService = new KeyboardShortcutService();
|
||||
string text = shortcuts[0];
|
||||
return !keyboardShortcutService.HasRibbonItemShortcut(ribbonItem.Id) && !keyboardShortcutService.HasCommandShortcut(text) && keyboardShortcutService.SetRibbonItemShortcut(ribbonItem.Id, string.Join("#", shortcuts));
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否具有快捷键
|
||||
/// </summary>
|
||||
/// <param name="ribbonItem"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasShortcut(this RibbonItem ribbonItem)
|
||||
{
|
||||
return new KeyboardShortcutService().HasRibbonItemShortcut(ribbonItem.Id);
|
||||
}
|
||||
/// <summary>
|
||||
/// 移除快捷键
|
||||
/// </summary>
|
||||
/// <param name="ribbonItem"></param>
|
||||
/// <returns></returns>
|
||||
public static bool RemoveShortcut(this RibbonItem ribbonItem)
|
||||
{
|
||||
return new KeyboardShortcutService().RemoveRibbonItemShortcut(ribbonItem.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
using Autodesk.Revit.UI;
|
||||
|
||||
using Szmedi.RvKits.Mvvm.Attributes;
|
||||
|
||||
using UIFramework;
|
||||
|
||||
using UIFrameworkServices;
|
||||
|
||||
namespace ricaun.Revit.ExtensibleShortcuts.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// 通过命令id设置快捷键
|
||||
/// </summary>
|
||||
public class KeyboardShortcutService
|
||||
{
|
||||
/// <summary>
|
||||
/// 设置菜单快捷键
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="shortcutsRep"></param>
|
||||
/// <returns></returns>
|
||||
public bool SetRibbonItemShortcut(string id, string shortcutsRep)
|
||||
{
|
||||
Dictionary<string, UIFrameworkServices.ShortcutItem> dictionary = this.LoadShortcuts();
|
||||
if (this.Commands.TryGetValue(id, out UIFrameworkServices.ShortcutItem shortcutItem))
|
||||
{
|
||||
shortcutItem.ShortcutsRep = shortcutsRep;
|
||||
shortcutItem.Shortcuts.Clear();
|
||||
//多个快捷键中间以#分割
|
||||
foreach (string text in shortcutsRep.Split('#'))
|
||||
{
|
||||
shortcutItem.Shortcuts.Add(text);
|
||||
}
|
||||
dictionary.Add(id, shortcutItem);
|
||||
List<UIFrameworkServices.ShortcutItem> list = dictionary.Select((KeyValuePair<string, UIFrameworkServices.ShortcutItem> e) => e.Value).ToList<UIFrameworkServices.ShortcutItem>();
|
||||
this.SaveShortcuts(list);
|
||||
this.ArmCommands();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 通过外部命令类设置快捷键
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="shortcutsRep"></param>
|
||||
/// <returns></returns>
|
||||
public bool SetRibbonItemShortcut<T>() where T : IExternalCommand
|
||||
{
|
||||
var attribute = typeof(T).GetCustomAttribute<ShortcutRepAttribute>();
|
||||
if (attribute == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Dictionary<string, UIFrameworkServices.ShortcutItem> dictionary = this.LoadShortcuts();
|
||||
foreach (var item in Commands)
|
||||
{
|
||||
if (item.Key.EndsWith(nameof(T)))
|
||||
{
|
||||
ShortcutItem shortcutItem = item.Value;
|
||||
shortcutItem.ShortcutsRep = attribute.Shortcuts;
|
||||
shortcutItem.Shortcuts.Clear();
|
||||
//多个快捷键中间以#分割
|
||||
foreach (string text in attribute.Shortcuts.Split('#'))
|
||||
{
|
||||
shortcutItem.Shortcuts.Add(text);
|
||||
}
|
||||
dictionary.Add(item.Key, shortcutItem);
|
||||
List<UIFrameworkServices.ShortcutItem> list = dictionary.Select((KeyValuePair<string, UIFrameworkServices.ShortcutItem> e) => e.Value).ToList<UIFrameworkServices.ShortcutItem>();
|
||||
this.SaveShortcuts(list);
|
||||
this.ArmCommands();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 移除菜单快捷键
|
||||
/// </summary>
|
||||
/// <param name="id">命令id</param>
|
||||
/// <returns></returns>
|
||||
public bool RemoveRibbonItemShortcut(string id)
|
||||
{
|
||||
Dictionary<string, UIFrameworkServices.ShortcutItem> dictionary = this.LoadShortcuts();
|
||||
UIFrameworkServices.ShortcutItem shortcutItem;
|
||||
if (dictionary.TryGetValue(id, out shortcutItem))
|
||||
{
|
||||
dictionary.Remove(id);
|
||||
List<UIFrameworkServices.ShortcutItem> list = dictionary.Select((KeyValuePair<string, UIFrameworkServices.ShortcutItem> e) => e.Value).ToList<UIFrameworkServices.ShortcutItem>();
|
||||
this.SaveShortcuts(list);
|
||||
this.ArmCommands();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否具有菜单快捷键
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public bool HasRibbonItemShortcut(string id)
|
||||
{
|
||||
return this.LoadShortcuts().TryGetValue(id, out var _);
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取快捷键的映射(最多五个按键)
|
||||
/// </summary>
|
||||
/// <param name="id">CommandId</param>
|
||||
/// <returns>快捷键</returns>
|
||||
public string GetRibbonItemShortcutsRep(string id)
|
||||
{
|
||||
if (this.LoadShortcuts().TryGetValue(id, out var shortcutItem))
|
||||
{
|
||||
return shortcutItem.ShortcutsRep;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取全部命令快捷键CommandId-ObservableCollect<string>()
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Dictionary<string, IEnumerable<string>> GetCommandShortcuts()
|
||||
{
|
||||
return (from e in this.Commands
|
||||
select e.Value into e
|
||||
group e by e.CommandId).ToDictionary((IGrouping<string, UIFrameworkServices.ShortcutItem> i) => i.Key, (IGrouping<string, UIFrameworkServices.ShortcutItem> j) => j.SelectMany((UIFrameworkServices.ShortcutItem i) => i.Shortcuts));
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取自定义快捷键被关联到的命令CommandId
|
||||
/// </summary>
|
||||
/// <param name="shortcut">自定义的快捷键</param>
|
||||
/// <returns>CommandId</returns>
|
||||
public string GetCommandShortcut(string shortcut)
|
||||
{
|
||||
return this.Commands.FirstOrDefault((KeyValuePair<string, UIFrameworkServices.ShortcutItem> e) => e.Value.Shortcuts.Contains(shortcut)).Key;
|
||||
}
|
||||
/// <summary>
|
||||
/// 自定义的快捷键是否已经被关联到某个命令上
|
||||
/// </summary>
|
||||
/// <param name="shortcut">自定义的快捷键</param>
|
||||
/// <returns></returns>
|
||||
public bool HasCommandShortcut(string shortcut)
|
||||
{
|
||||
return this.GetCommandShortcuts().Any((KeyValuePair<string, IEnumerable<string>> e) => e.Value.Contains(shortcut));
|
||||
}
|
||||
/// <summary>
|
||||
/// 加载命令
|
||||
/// </summary>
|
||||
public void LoadCommands()
|
||||
{
|
||||
ShortcutsHelper.LoadCommands();
|
||||
}
|
||||
/// <summary>
|
||||
/// 应用快捷键更改
|
||||
/// </summary>
|
||||
public void ApplyShortcutChanges()
|
||||
{
|
||||
UIFrameworkServices.KeyboardShortcutService.applyShortcutChanges(this.LoadShortcuts());
|
||||
}
|
||||
/// <summary>
|
||||
/// 应用更改
|
||||
/// </summary>
|
||||
private void ArmCommands()
|
||||
{
|
||||
ShortcutsHelper.ArmCommands();
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取已经加载的ShortcutItems
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private Dictionary<string, UIFrameworkServices.ShortcutItem> LoadShortcuts()
|
||||
{
|
||||
return ShortcutsHelper.LoadShortcuts();
|
||||
}
|
||||
/// <summary>
|
||||
/// 保存ShortcutItems
|
||||
/// </summary>
|
||||
/// <param name="shortcutList"></param>
|
||||
private void SaveShortcuts(ICollection<UIFrameworkServices.ShortcutItem> shortcutList)
|
||||
{
|
||||
ShortcutsHelper.SaveShortcuts(shortcutList);
|
||||
}
|
||||
/// <summary>
|
||||
/// 所有快捷命令条目字典
|
||||
/// </summary>
|
||||
private Dictionary<string, UIFrameworkServices.ShortcutItem> Commands
|
||||
{
|
||||
get
|
||||
{
|
||||
return ShortcutsHelper.Commands;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取所有ShortcutItems
|
||||
/// </summary>
|
||||
/// <returns>ShortcutItems</returns>
|
||||
public IEnumerable<UIFrameworkServices.ShortcutItem> GetShortcutItems()
|
||||
{
|
||||
return from e in this.LoadShortcuts()
|
||||
select new UIFrameworkServices.ShortcutItem(e.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
using System.Linq;
|
||||
|
||||
using Autodesk.Revit.Attributes;
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.DB.Mechanical;
|
||||
using Autodesk.Revit.DB.Plumbing;
|
||||
using Autodesk.Revit.UI;
|
||||
using Autodesk.Revit.UI.Selection;
|
||||
|
||||
namespace Szmedi.Test
|
||||
{
|
||||
/// <summary>
|
||||
/// Revit执行命令
|
||||
/// </summary>
|
||||
[Transaction(TransactionMode.Manual)]
|
||||
[Regeneration(RegenerationOption.Manual)]
|
||||
public class MappingSystemCmd : IExternalCommand
|
||||
{
|
||||
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
|
||||
{
|
||||
//程序UI界面
|
||||
UIApplication uiapp = commandData.Application;
|
||||
//获取元素(选择) 显示元素 视图(活动视图)管理(对象)
|
||||
UIDocument uidoc = uiapp.ActiveUIDocument;
|
||||
//程序
|
||||
Autodesk.Revit.ApplicationServices.Application app = uiapp.Application;
|
||||
//获取位置和场地 视图(多个视图)管理 获取元素(Revit 项目里的全部元素)
|
||||
Document doc = uidoc.Document;
|
||||
//获取所有打开文档
|
||||
DocumentSet docset = uiapp.Application.Documents;
|
||||
//当前视图
|
||||
View view = doc.ActiveView;
|
||||
var systems=new FilteredElementCollector(doc)
|
||||
.OfClass(typeof(MEPSystem))
|
||||
.WhereElementIsNotElementType().Cast<MEPSystem>().ToList();
|
||||
using (Transaction tx = new Transaction(doc, "Mapping System Names"))
|
||||
{
|
||||
tx.Start();
|
||||
foreach (var sys in systems)
|
||||
{
|
||||
var typeId = sys.GetTypeId();
|
||||
var type = doc.GetElement(typeId) as MEPSystemType;
|
||||
if (sys is MechanicalSystem mechanicalSystem)
|
||||
{
|
||||
var elementSet = mechanicalSystem.DuctNetwork;
|
||||
foreach (Element elem in elementSet)
|
||||
{
|
||||
elem.LookupParameter("三级系统名称")?.Set(type.Name);
|
||||
}
|
||||
}
|
||||
if (sys is PipingSystem pipingSystem)
|
||||
{
|
||||
var elementSet = pipingSystem.PipingNetwork;
|
||||
foreach (Element elem in elementSet)
|
||||
{
|
||||
elem.LookupParameter("三级系统名称")?.Set(type.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
tx.Commit();
|
||||
}
|
||||
|
||||
return Result.Succeeded;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,34 +29,6 @@ namespace Szmedi.Test
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
//UiApplication.Application.DocumentOpening+= (s, e) =>
|
||||
//{
|
||||
// MessageBox.Show("DocumentOpening");
|
||||
//};
|
||||
//UiApplication.Application.FamilyLoadingIntoDocument += (s, e) =>
|
||||
//{
|
||||
// MessageBox.Show("FamilyLoadingIntoDocument");
|
||||
//};
|
||||
//UiApplication.Application.FamilyLoadedIntoDocument += (s, e) =>
|
||||
//{
|
||||
// MessageBox.Show("FamilyLoadedIntoDocument");
|
||||
//};
|
||||
//var ptr = ComponentManager.ApplicationWindow;
|
||||
|
||||
var win = GetWindowFromHwnd(Process.GetCurrentProcess().MainWindowHandle);
|
||||
win?.Drop += (s, e) =>
|
||||
{
|
||||
MessageBox.Show("Drop");
|
||||
};
|
||||
//UIApplication.DoDragDrop(, new DropHandler());
|
||||
|
||||
return;
|
||||
|
||||
#if false
|
||||
var refer = UiDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
|
||||
var wall = Document.GetElement(refer);
|
||||
//var point = UiDocument.Selection.PickPoint(Autodesk.Revit.UI.Selection.ObjectSnapTypes.Nearest);
|
||||
#endif
|
||||
Array builtInCategories = Enum.GetValues(typeof(BuiltInCategory));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var encoding = Encoding.GetEncoding(936);
|
||||
@@ -91,318 +63,6 @@ namespace Szmedi.Test
|
||||
|
||||
//LogAssists.WriteTxtFile("内建类别", sb.ToString());
|
||||
}
|
||||
/// <summary>
|
||||
/// 通过窗口句柄安全地获取WPF窗口对象
|
||||
/// </summary>
|
||||
/// <param name="hwnd">窗口句柄</param>
|
||||
/// <returns>对应的WPF窗口对象,如果找不到则返回null</returns>
|
||||
public static Window GetWindowFromHwnd(IntPtr hwnd)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 从句柄获取HwndSource
|
||||
var hwndSource = HwndSource.FromHwnd(hwnd);
|
||||
if (hwndSource == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 检查RootVisual是否为Window类型
|
||||
if (hwndSource.RootVisual is DependencyObject rootVisual)
|
||||
{
|
||||
// 通过可视化树向上查找Window
|
||||
DependencyObject current = rootVisual;
|
||||
while (current != null)
|
||||
{
|
||||
if (current is Window window)
|
||||
{
|
||||
return window;
|
||||
}
|
||||
current = VisualTreeHelper.GetParent(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 可以在此记录异常或进行其他处理
|
||||
Console.WriteLine($"获取窗口失败: {ex.Message}");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
private static void MoveElement(Element item, XYZ vector)
|
||||
{
|
||||
if (item.Pinned || !item.IsValidObject || item == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var doc = item.Document;
|
||||
var levels = doc.OfType<Level>().OrderBy(l => l.Elevation).ToList();
|
||||
if (item is FamilyInstance instance)
|
||||
{
|
||||
var baseElev = instance.get_BoundingBox(null).Min.Z + vector.Z;
|
||||
var topElev = instance.get_BoundingBox(null).Max.Z + vector.Z;
|
||||
var baseLevel = GetClosetLevel(levels, baseElev);
|
||||
var topLevel = GetClosetLevel(levels, topElev);
|
||||
|
||||
switch (instance.Symbol.Family.FamilyPlacementType)
|
||||
{
|
||||
//柱
|
||||
case FamilyPlacementType.TwoLevelsBased:
|
||||
{
|
||||
instance.Location.Move(vector);
|
||||
|
||||
instance.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM).Set(baseLevel.Id);
|
||||
instance.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM).Set(baseElev - baseLevel.Elevation);
|
||||
|
||||
instance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM).Set(topLevel.Id);
|
||||
instance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM).Set(topElev - topLevel.Elevation);
|
||||
}
|
||||
break;
|
||||
case FamilyPlacementType.ViewBased:
|
||||
break;
|
||||
case FamilyPlacementType.WorkPlaneBased:
|
||||
{
|
||||
//instance.Location.Move(vector);
|
||||
var param = instance.get_Parameter(BuiltInParameter.INSTANCE_ELEVATION_PARAM);
|
||||
if (param != null && !param.IsReadOnly)
|
||||
{
|
||||
ElementTransformUtils.MoveElement(doc, instance.Id, XYZ.BasisZ * vector.Z);
|
||||
|
||||
//var value = param.AsDouble() + vector.Z;
|
||||
//param.Set(value);
|
||||
}
|
||||
|
||||
doc.Regenerate();
|
||||
|
||||
if (instance.Host == null)
|
||||
{
|
||||
ElementTransformUtils.MoveElement(doc, instance.Id, vector.Flatten());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FamilyPlacementType.OneLevelBased:
|
||||
{
|
||||
ElementTransformUtils.MoveElement(doc, instance.Id, vector);
|
||||
}
|
||||
break;
|
||||
case FamilyPlacementType.OneLevelBasedHosted:
|
||||
{
|
||||
var ins = doc.Create
|
||||
.NewFamilyInstance(
|
||||
instance.GetLocXYZ(),
|
||||
instance.Symbol,
|
||||
instance.Host,
|
||||
baseLevel,
|
||||
StructuralType.NonStructural);
|
||||
ins.get_Parameter(BuiltInParameter.INSTANCE_SILL_HEIGHT_PARAM)
|
||||
.Set(baseElev - baseLevel.Elevation);
|
||||
doc.Delete(instance.Id);
|
||||
}
|
||||
break;
|
||||
case FamilyPlacementType.CurveBased:
|
||||
{
|
||||
instance.Location.Move(vector);
|
||||
//var loc = instance.GetLocCurve().CreateTransformed(Transform.CreateTranslation(vector)) as Line;
|
||||
//doc.Create.NewFamilyInstance(instance.HostFace, loc, instance.Symbol);
|
||||
//doc.Delete(instance.Id);
|
||||
}
|
||||
break;
|
||||
case FamilyPlacementType.CurveBasedDetail:
|
||||
break;
|
||||
//梁
|
||||
case FamilyPlacementType.CurveDrivenStructural:
|
||||
{
|
||||
//instance.Location.Move(vector);
|
||||
var loc = instance.GetLocCurve().CreateTransformed(Autodesk.Revit.DB.Transform.CreateTranslation(vector));
|
||||
//var newLoc =
|
||||
doc.Create.NewFamilyInstance(loc, instance.Symbol, baseLevel, StructuralType.Beam);
|
||||
doc.Delete(instance.Id);
|
||||
|
||||
//ElementTransformUtils.MoveElement(doc, instance.Id, vector.Flatten());
|
||||
}
|
||||
break;
|
||||
case FamilyPlacementType.Adaptive:
|
||||
break;
|
||||
case FamilyPlacementType.Invalid:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (item is Wall wall)
|
||||
{
|
||||
var flat = vector.Flatten();
|
||||
ElementTransformUtils.MoveElement(doc, wall.Id, flat);
|
||||
doc.Regenerate();
|
||||
SetWallHeight(vector, levels, wall);
|
||||
var elemIds = wall.FindInserts(true, true, true, true);
|
||||
foreach (var id in elemIds)
|
||||
{
|
||||
var elem = doc.GetElement(id);
|
||||
if (elem is Wall nestWall)
|
||||
{
|
||||
SetWallHeight(vector, levels, nestWall);
|
||||
}
|
||||
else
|
||||
{
|
||||
MoveElement(elem, vector);
|
||||
}
|
||||
}
|
||||
//墙饰条
|
||||
var sweeps = doc.OfType<WallSweep>().Where(s => s.GetHostIds().Contains(wall.Id));
|
||||
foreach (var sweep in sweeps)
|
||||
{
|
||||
//ElementTransformUtils.MoveElement(doc, sweep.Id, flat);
|
||||
var boundingBox = sweep.get_BoundingBox(null);
|
||||
var offset = boundingBox.Min.Z + vector.Z;
|
||||
|
||||
var baseLevel = levels.First(l => Math.Abs(l.Elevation - offset) == levels.Min(l => Math.Abs(l.Elevation - offset)));
|
||||
sweep.get_Parameter(BuiltInParameter.WALL_SWEEP_LEVEL_PARAM).Set(baseLevel.Id);
|
||||
sweep.get_Parameter(BuiltInParameter.WALL_SWEEP_OFFSET_PARAM).Set(offset - baseLevel.Elevation);
|
||||
}
|
||||
//依附在墙上的实例
|
||||
var instances = doc.OfType<FamilyInstance>().Where(s =>
|
||||
{
|
||||
|
||||
var stackedWallIds = wall.GetStackedWallMemberIds();
|
||||
if (stackedWallIds.Count > 0)
|
||||
{
|
||||
return stackedWallIds.Any(id => s.Host?.Id == id);
|
||||
}
|
||||
return s.Host?.Id == wall.Id;
|
||||
}).ToList();
|
||||
foreach (var ins in instances)
|
||||
{
|
||||
//ins.Location.Move(vector);
|
||||
ElementTransformUtils.MoveElement(doc, ins.Id, vector.Z * XYZ.BasisZ);
|
||||
}
|
||||
|
||||
//ElementTransformUtils.CopyElements(v1, [wall.Id], v2, Transform.Identity, new CopyPasteOptions());
|
||||
//var b = wall.Location.Move(vector);
|
||||
|
||||
//var loc = wall.GetLocCurve();
|
||||
//var c = loc.CreateTransformed(Transform.CreateTranslation(vector));
|
||||
//(wall.Location as LocationCurve).Curve = c; //可以移动,但是偏移量属性没更新
|
||||
}
|
||||
else if (item is Room room)
|
||||
{
|
||||
}
|
||||
else if (item is Stairs stairs)
|
||||
{
|
||||
var flat = vector.Flatten();
|
||||
ElementTransformUtils.MoveElement(doc, item.Id, flat);
|
||||
}
|
||||
else if (item is ModelCurve curve)//房间分割
|
||||
{
|
||||
|
||||
}
|
||||
else if (item is Railing railing)
|
||||
{
|
||||
if (railing.HasHost)
|
||||
{
|
||||
|
||||
}
|
||||
else//连带主体移动
|
||||
{
|
||||
ElementTransformUtils.MoveElement(doc, item.Id, vector);
|
||||
}
|
||||
}
|
||||
//坡道
|
||||
else if (item.Category.ToBuiltInCategory() == BuiltInCategory.OST_Ramps)
|
||||
{
|
||||
var flat = vector.Flatten();
|
||||
ElementTransformUtils.MoveElement(doc, item.Id, flat);
|
||||
}
|
||||
else if (item is TopographySurface surface)
|
||||
{
|
||||
}
|
||||
else if (item is SlabEdge or Fascia or Gutter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//else if (item is CeilingAndFloor ceilingAndFloor)
|
||||
//{
|
||||
// ElementTransformUtils.MoveElement(doc, ceilingAndFloor.Id, vector);
|
||||
//}
|
||||
else if (item is Opening opening)
|
||||
{
|
||||
if (opening.Host is Wall)
|
||||
{
|
||||
ElementTransformUtils.MoveElement(doc, opening.Id, vector.Z * XYZ.BasisZ);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ElementTransformUtils.MoveElement(doc, item.Id, vector);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置墙高度
|
||||
/// </summary>
|
||||
/// <param name="vector"></param>
|
||||
/// <param name="levels"></param>
|
||||
/// <param name="wall"></param>
|
||||
private static void SetWallHeight(XYZ vector, List<Level> levels, Wall wall)
|
||||
{
|
||||
var boundingBox = wall.get_BoundingBox(null);
|
||||
//底部实际高度
|
||||
var bottomElev = boundingBox.Min.Z + vector.Z;
|
||||
var topElev = boundingBox.Max.Z + vector.Z;
|
||||
//查找距离底部偏移最近的Level
|
||||
var baseLevel = GetClosetLevel(levels, bottomElev);
|
||||
wall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).Set(baseLevel.Id);
|
||||
wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(bottomElev - baseLevel.Elevation);
|
||||
//是否有顶部约束
|
||||
var topContraint = wall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).AsElementId();
|
||||
if (topContraint != ElementId.InvalidElementId)
|
||||
{
|
||||
var topLevel = GetClosetLevel(levels, topElev);
|
||||
|
||||
wall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).Set(topLevel.Id);
|
||||
wall.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(topElev - topLevel.Elevation);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取距离最近的标高
|
||||
/// </summary>
|
||||
/// <param name="levels"></param>
|
||||
/// <param name="elev">高度</param>
|
||||
/// <returns></returns>
|
||||
private static Level GetClosetLevel(List<Level> levels, double elev)
|
||||
{
|
||||
return levels.First(l => Math.Abs(l.Elevation - elev) == levels.Min(l => Math.Abs(l.Elevation - elev)));
|
||||
}
|
||||
|
||||
private void Application_DocumentChanged(object sender, Autodesk.Revit.DB.Events.DocumentChangedEventArgs e)
|
||||
{
|
||||
UiApplication.Application.DocumentChanged -= Application_DocumentChanged;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
var doc = e.GetDocument();
|
||||
sb.AppendLine("删除的元素ID");
|
||||
e.GetDeletedElementIds().ToList().ForEach(id => sb.AppendLine(id.IntegerValue.ToString()));
|
||||
//Debug.WriteLine(e.GetDeletedElementIds().Count);
|
||||
sb.AppendLine("修改的元素");
|
||||
e.GetModifiedElementIds().Select(Document.GetElement).Where(e => e != null && e.Category != null && e.Category.CategoryType == CategoryType.Model && e.get_BoundingBox(null) != null).ToList().ForEach(e =>
|
||||
{
|
||||
sb.AppendLine(e?.Category.Name + "---------" + e?.Name);
|
||||
});
|
||||
File.WriteAllText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "修改的元素.txt"), sb.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public class DropHandler : IControllableDropHandler
|
||||
{
|
||||
public bool CanExecute(UIDocument document, object data, ElementId dropViewId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Execute(UIDocument document, object data)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Szmedi.RvKits.Mvvm.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// 多个快捷键使用#分割
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
class ShortcutRepAttribute : Attribute
|
||||
{
|
||||
public ShortcutRepAttribute(string shortcuts)
|
||||
{
|
||||
Shortcuts = shortcuts;
|
||||
}
|
||||
|
||||
public string Shortcuts { get; }
|
||||
}
|
||||
}
|
||||
@@ -12,255 +12,14 @@ using EPPlus.Core.Extensions;
|
||||
using Nice3point.Revit.Toolkit.External;
|
||||
using Nice3point.Revit.Toolkit.Utils;
|
||||
|
||||
using OfficeOpenXml;
|
||||
|
||||
using RevitAddins;
|
||||
|
||||
using Szmedi.RvKits.Mvvm.Attributes;
|
||||
|
||||
namespace Szmedi.Test
|
||||
{
|
||||
[Transaction(TransactionMode.Manual)]
|
||||
[Regeneration(RegenerationOption.Manual)]
|
||||
[ShortcutRep("TEST")]
|
||||
public class TestCmd : ExternalCommand
|
||||
{
|
||||
//一个判断两条模型线是否平行的方法
|
||||
/// <summary>
|
||||
/// 扩展包围盒的大小
|
||||
/// </summary>
|
||||
/// <param name="boundingBox"></param>
|
||||
/// <param name="distance"></param>
|
||||
/// <returns></returns>
|
||||
public static BoundingBoxXYZ Extend(BoundingBoxXYZ boundingBox, double distance = 2.0)
|
||||
{
|
||||
var transform = boundingBox.Transform;
|
||||
var max = boundingBox.Max + (distance * (transform.BasisX + transform.BasisY + transform.BasisZ));
|
||||
var min = boundingBox.Min - (distance * (transform.BasisX + transform.BasisY + transform.BasisZ));
|
||||
return new BoundingBoxXYZ { Max = max, Min = min, Transform = transform };
|
||||
}
|
||||
|
||||
// 合法化 Sheet 名称
|
||||
private string MakeValidSheetName(string name)
|
||||
{
|
||||
var invalid = new[] { '\\', '/', '*', '[', ']', ':', '?' };
|
||||
foreach (var ch in invalid)
|
||||
{
|
||||
name = name.Replace(ch, '_');
|
||||
}
|
||||
|
||||
return name.Length > 31 ? name.Substring(0, 31) : name;
|
||||
}
|
||||
|
||||
private void NewMethod(IEnumerable<IGrouping<string, ElementModel>> groupedModels)
|
||||
{
|
||||
using (var pkg = new ExcelPackage())
|
||||
{
|
||||
//深圳构件标识
|
||||
foreach (var g in groupedModels)
|
||||
{
|
||||
var sheetName = MakeValidSheetName(g.Key);
|
||||
|
||||
var ws = pkg.Workbook.Worksheets.Add(sheetName);
|
||||
//第一行
|
||||
ws.Cells[1, 1].Value = g.Key;
|
||||
var columns = g.Sum(m => m.Count);
|
||||
//合并单元格
|
||||
ws.Cells[1, 1, 1, columns].Merge = true;
|
||||
ws.Cells[1, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
|
||||
ws.Cells[1, 1].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center;
|
||||
ws.Cells[1, 1].Style.Font.Size = 20;
|
||||
ws.Cells[1, 1].Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.FromArgb(255, 255, 0));
|
||||
ws.Cells[1, 1].Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin);
|
||||
var currentColumns = 1;
|
||||
var models = g.ToList();
|
||||
foreach (var m in models)
|
||||
{
|
||||
var subColumns = m.Count;
|
||||
//第二行
|
||||
ws.Cells[2, currentColumns, 2, subColumns].Merge = true;
|
||||
|
||||
//合并单元格
|
||||
ws.Cells[2, currentColumns].Value = models.FirstOrDefault().Groups.Keys;
|
||||
|
||||
currentColumns += 1 + subColumns;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsParallel(Line line1, Line line2)
|
||||
{
|
||||
return line1.Direction.IsAlmostEqualTo(line2.Direction) ||
|
||||
line1.Direction.IsAlmostEqualTo(-line2.Direction);
|
||||
}
|
||||
//private bool IsConnectToSystem(FamilyInstance ins)
|
||||
//{
|
||||
// bool hasConnectToSystem = false;
|
||||
// if (ins.Category.CategoryType != CategoryType.FacilityNumber)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
// if (ins.get_BoundingBox(null) != null &&
|
||||
// ins.MEPModel?.ConnectorManager != null)
|
||||
// {
|
||||
// var cons = ins.GetConnectors(false);
|
||||
|
||||
// foreach (Connector con in cons)
|
||||
// {
|
||||
// if (con.Domain != Domain.DomainElectrical && con.Domain != Domain.DomainUndefined)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// if (con.IsConnected)
|
||||
// {
|
||||
// hasConnectToSystem = true;
|
||||
// }
|
||||
// }
|
||||
// catch (Exception)
|
||||
// {
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return hasConnectToSystem;
|
||||
|
||||
//}
|
||||
|
||||
public List<Family> GetUsedFamilies(Document doc)
|
||||
{
|
||||
// 获取所有实例元素(这里不需要由ToElements()转化全部对象,节省内存,仅遍历)
|
||||
var instances = doc.OfClass<FamilyInstance>();
|
||||
|
||||
// 3. 收集所有被使用的“类型ID” (使用HashSet自动去重)
|
||||
HashSet<ElementId> usedTypeIds = new HashSet<ElementId>();
|
||||
|
||||
foreach (Element elem in instances)
|
||||
{
|
||||
ElementId typeId = elem.GetTypeId();
|
||||
if (typeId != ElementId.InvalidElementId)
|
||||
{
|
||||
usedTypeIds.Add(typeId);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 从类型反向获取族 (使用HashSet再次去重族ID,防止多个类型属于同一个族)
|
||||
HashSet<ElementId> usedFamilyIds = new HashSet<ElementId>();
|
||||
List<Family> resultFamilies = new List<Family>();
|
||||
|
||||
foreach (ElementId typeId in usedTypeIds)
|
||||
{
|
||||
// 获取类型元素 (FamilySymbol)
|
||||
Element typeElem = doc.GetElement(typeId);
|
||||
FamilySymbol symbol = typeElem as FamilySymbol;
|
||||
|
||||
if (symbol != null)
|
||||
{
|
||||
Family family = symbol.Family;
|
||||
|
||||
// 确保族存在且未被添加过
|
||||
if (family != null && !usedFamilyIds.Contains(family.Id))
|
||||
{
|
||||
usedFamilyIds.Add(family.Id);
|
||||
resultFamilies.Add(family);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resultFamilies;
|
||||
}
|
||||
public static void ToExcel(string excelPath, List<TestExcel> infos)
|
||||
{
|
||||
FileInfo fi = new(excelPath);
|
||||
ExcelPackage package = infos.ToWorksheet("构件数量变动对比表")
|
||||
.WithConfiguration(cfg => cfg.WithColumnConfiguration(c => c.AutoFit()))
|
||||
.ToExcelPackage();
|
||||
|
||||
package.SaveAs(fi);
|
||||
}
|
||||
public override void Execute()
|
||||
{
|
||||
//var parameter = Document.FamilyManager.GetParameters().FirstOrDefault(p => p.Definition.Name == "额定电流");
|
||||
//Document.Invoke(
|
||||
// ts =>
|
||||
// {
|
||||
// Document.FamilyManager.ReplaceParameter(parameter, "测试", BuiltInParameterGroup.PG_TEXT, true);
|
||||
// });
|
||||
var docs = Application.Documents;
|
||||
if (docs.Size != 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var doc1 = docs.OfType<Document>().First();
|
||||
var doc2 = docs.OfType<Document>().Last();
|
||||
var elements1 = doc1.OfCollector().WhereElementIsNotElementType().Where(e => e.Category?.CategoryType == CategoryType.Model && e.get_BoundingBox(null) != null);
|
||||
var elements2 = doc2.OfCollector().WhereElementIsNotElementType().Where(e => e.Category?.CategoryType == CategoryType.Model && e.get_BoundingBox(null) != null);
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
foreach (var e1 in elements1)
|
||||
{
|
||||
foreach (var e2 in elements2)
|
||||
{
|
||||
if (e1.Id.IntegerValue == e2.Id.IntegerValue)
|
||||
{
|
||||
stringBuilder.Append($"重复图元:{e1.Id};");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageBox.Show(stringBuilder.ToString());
|
||||
return;
|
||||
var doc = Document;
|
||||
if (doc.IsFamilyDocument)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var familyCollector = new FilteredElementCollector(doc)
|
||||
.OfClass(typeof(Family))
|
||||
.Cast<Family>()
|
||||
.ToList();
|
||||
MessageBox.Show(familyCollector.Count().ToString());
|
||||
|
||||
var fams = GetUsedFamilies(doc)
|
||||
.Cast<Family>()
|
||||
.Where(
|
||||
fam => fam.FamilyCategory.AllowsBoundParameters &&
|
||||
fam.IsEditable &&
|
||||
fam.FamilyCategory.CategoryType == CategoryType.Model &&
|
||||
!Enum.GetName(typeof(BuiltInCategory), fam.FamilyCategoryId.IntegerValue)!.Contains(
|
||||
"Fitting") &&
|
||||
fam.FamilyCategoryId.IntegerValue != -2008013).ToList();//风道末端
|
||||
MessageBox.Show(fams.Count().ToString());
|
||||
return;
|
||||
|
||||
var elements = new FilteredElementCollector(Document).WhereElementIsNotElementType()
|
||||
.ToElements()
|
||||
.ToList();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var elementIds = new List<ElementId>();
|
||||
foreach (var item in elements)
|
||||
{
|
||||
var level = Document.GetElement(item.GetLevelId())?.Name;
|
||||
var param = item.get_Parameter(BuiltInParameter.DOOR_NUMBER)?.AsString();
|
||||
if (param != null && level != null && param.Contains("B2") && level.Contains("站厅"))
|
||||
{
|
||||
sb.AppendLine($"{item.Id}");
|
||||
elementIds.Add(item.Id);
|
||||
|
||||
}
|
||||
if (param != null && level != null && param.Contains("B1") && level.Contains("站台"))
|
||||
{
|
||||
sb.AppendLine($"{item.Id}");
|
||||
elementIds.Add(item.Id);
|
||||
|
||||
}
|
||||
}
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
UiDocument.Selection.SetElementIds(elementIds);
|
||||
}
|
||||
return;
|
||||
var walls = new FilteredElementCollector(Document).WhereElementIsNotElementType()
|
||||
.OfClass(typeof(Wall))
|
||||
.ToElements()
|
||||
@@ -310,372 +69,6 @@ namespace Szmedi.Test
|
||||
}
|
||||
}
|
||||
}
|
||||
//var elements = UiDocument.Selection
|
||||
// .GetElementIds()
|
||||
// .Select(Document.GetElement)
|
||||
// .Cast<FamilyInstance>()
|
||||
// .Where(e => e.get_Parameter(BuiltInParameter.INSTANCE_ELEVATION_PARAM).AsDouble() < 10e-5)
|
||||
// .Select(e => e.Id).ToList();
|
||||
//UiDocument.Selection.SetElementIds(elements);
|
||||
|
||||
return;
|
||||
//Document.Invoke(ts =>
|
||||
//{
|
||||
// elements.ForEach(e=>e.Host)
|
||||
//})
|
||||
//Material.Create(Document, "测试材质");
|
||||
|
||||
//var reference = UiDocument.Selection.PickObject(ObjectType.Element);
|
||||
//var ins = Document.GetElement(reference) as FamilyInstance;
|
||||
//var bo = IsConnectToSystem(ins);
|
||||
|
||||
//MessageBox.Show(bo.ToString());
|
||||
|
||||
//return;
|
||||
#if false
|
||||
var manager = Document.FamilyManager;
|
||||
|
||||
var names = manager.Types.OfType<FamilyType>().Select(t => t.Name);
|
||||
bool b = names.Contains(" ");
|
||||
MessageBox.Show(manager.Types.Size.ToString());
|
||||
return;
|
||||
|
||||
var e = UiDocument.Selection.PickElementsByRectangle().Cast<MEPCurve>().FirstOrDefault();
|
||||
//var b1 = e.Diameter == null;
|
||||
//var b2 = e.Height == null;
|
||||
//MessageBox.Show(.ToString());
|
||||
return;
|
||||
var refer1 = UiDocument.Selection.PickObject(ObjectType.Element, new GenericFilter<ModelCurve>(), "选择模型线");
|
||||
var elem = Document.GetElement(refer1) as ModelCurve;
|
||||
var col = new FilteredElementCollector(Document, Document.ActiveView.Id).WhereElementIsNotElementType()
|
||||
.Where(e => e is ModelCurve mc && mc.LineStyle.Id == elem.LineStyle.Id).Select(e => e.Id).ToList();
|
||||
UiDocument.Selection.SetElementIds(col);
|
||||
//var refer2 = UiDocument.Selection.PickObject(ObjectType.Element, new GenericFilter<ModelCurve>(), "选择模型线");
|
||||
//var elem2 = Document.GetElement(refer2) as ModelCurve;
|
||||
//if (IsParallel(elem.GeometryCurve as Line, elem2.GeometryCurve as Line))
|
||||
//{
|
||||
// MessageBox.Show("平行");
|
||||
//}
|
||||
|
||||
//var groups = Document.OfParentModelCollector().WhereElementIsNotElementType()
|
||||
// .GroupBy(e => e.GetParameters("深圳构件标识").FirstOrDefault().AsString());
|
||||
//StringBuilder sb = new StringBuilder();
|
||||
//foreach (var element in groups)
|
||||
//{
|
||||
// sb.AppendLine(element.Key);
|
||||
//}
|
||||
//MessageBox.Show(sb.ToString());
|
||||
|
||||
//var reference = UiDocument.Selection.PickObject(ObjectType.PointOnElement, new GenericFilter<ImportInstance>(), "请选择CAD文字");
|
||||
//var instance = doc.GetElement(reference) as ImportInstance;
|
||||
//var ids = UiDocument.Selection.GetElementIds();
|
||||
|
||||
|
||||
//Document.Modify(
|
||||
// settings => settings.Transaction).Commit((doc, _) =>
|
||||
// {
|
||||
//var familyName = "族名称";
|
||||
//using (Transaction ts = new Transaction(doc, "更新族类型名称"))
|
||||
//{
|
||||
// ts.Start();
|
||||
// //获取某个族
|
||||
// var element = new FilteredElementCollector(doc).OfClass(typeof(Family)).Where(e => e.Name == familyName).Cast<Family>().FirstOrDefault();
|
||||
// if (element == null)
|
||||
// {
|
||||
// TaskDialog.Show("提示", "没有找到指定的族");
|
||||
// ts.RollBack();
|
||||
// return;
|
||||
// }
|
||||
// var ids = element.GetFamilySymbolIds();
|
||||
// foreach (var id in ids)
|
||||
// {
|
||||
// //获取族类型
|
||||
// var symbol = doc.GetElement(id) as FamilySymbol;
|
||||
// //宽度
|
||||
// var w = Convert.ToDouble(symbol.GetParameters("宽度").FirstOrDefault().AsValueString());
|
||||
// //高度
|
||||
// var h = Convert.ToDouble(symbol.GetParameters("高度").FirstOrDefault().AsValueString());
|
||||
// if (ids != null)
|
||||
|
||||
// {
|
||||
// //前缀
|
||||
// var prefix = string.Empty;
|
||||
// //后缀
|
||||
// var suffix = string.Empty;
|
||||
|
||||
// string width = string.Empty;
|
||||
// string height = string.Empty;
|
||||
|
||||
// if (w / 1000 < 1)
|
||||
// {
|
||||
// width = $"0{w}mm";
|
||||
// }
|
||||
// if (h / 1000 < 1)
|
||||
// {
|
||||
// height = $"0{h}mm";
|
||||
// }
|
||||
// //如果width和height最后一个数字是5,则把5改成a
|
||||
// if (width.Last() == '5')
|
||||
// {
|
||||
// width = width.Remove(width.Length - 1) + "a";
|
||||
// }
|
||||
// if (height.Last() == '5')
|
||||
// {
|
||||
// height = height.Remove(height.Length - 1) + "a";
|
||||
// }
|
||||
// var newName = $"{prefix}{width} x {height}{suffix}";
|
||||
// symbol.Name = newName;
|
||||
// }
|
||||
// }
|
||||
// ts.Commit();
|
||||
//}
|
||||
// });
|
||||
|
||||
|
||||
//var ids = Document.ActiveView
|
||||
// .OfCollector()
|
||||
// .Where(e => e.get_Parameter(BuiltInParameter.DOOR_NUMBER)?.AsString() == "J4921321-11332-(005)DK0001").Select(e => e.Id).ToList();
|
||||
//MessageBox.Show(ids.Count.ToString());
|
||||
//UiDocument.Selection.SetElementIds(ids);
|
||||
//var elemIds = GetElementIds();
|
||||
//var ids = UiDocument.Selection.GetElementIds();
|
||||
//var start = new XYZ(-61995.832703373, 4243.667605320, 5999.999999997);
|
||||
//var end = new XYZ(0.000000000, 0.000000000, 5999.999999997);
|
||||
//var translate = (end - start) / 304.8;
|
||||
//using (Transaction ts = new Transaction(doc, "移动"))
|
||||
//{
|
||||
// ts.Start();
|
||||
// ElementTransformUtils.MoveElements(doc, ids, translate);
|
||||
// ts.Commit();
|
||||
//}
|
||||
|
||||
//var id = UiDocument.Selection.GetElementIds().FirstOrDefault();
|
||||
//var ids = doc.GetElement(id) as FamilyInstance;
|
||||
//var n = ids.GetSubComponentIds().Count;
|
||||
//MessageBox.Show(n.ToString());
|
||||
//var ids = UiDocument.Selection.GetElementIds();
|
||||
//var translate = XYZ.BasisZ * 20;
|
||||
//using (Transaction ts = new Transaction(doc, "移动"))
|
||||
//{
|
||||
// ts.Start();
|
||||
// ElementTransformUtils.CopyElements(doc, ids, translate);
|
||||
// ElementTransformUtils.MoveElements(doc, ids, translate);
|
||||
// ts.Commit();
|
||||
//}
|
||||
#endif
|
||||
#if false
|
||||
var symbols = new FilteredElementCollector(Document).OfClass(typeof(Wall)).ToElementIds();
|
||||
foreach (var item in symbols)
|
||||
{
|
||||
var elem = Document.GetElement(item);
|
||||
var cat = elem.Category.Name;
|
||||
var cate = Category.GetCategory(Document, elem.Category.Id);
|
||||
var cate1 = Category.GetCategory(Document, (BuiltInCategory)elem.Category.Id.IntegerValue);
|
||||
}
|
||||
var dict = new FilteredElementCollector(Document).OfClass(typeof(ElementType))
|
||||
.OfType<ElementType>()
|
||||
.Where(
|
||||
t => t.CanBeRenamed && t.Category is { CategoryType: CategoryType.Model or CategoryType.Annotation })
|
||||
.GroupBy(t => t.Category.Id)
|
||||
.Where(g => !string.IsNullOrEmpty(g.FirstOrDefault().Category?.Name))
|
||||
.ToDictionary(g => g.FirstOrDefault().Category.Name, g => g.ToList());
|
||||
//UiDocument.Selection.SetElementIds(symbols);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (var kv in dict)
|
||||
{
|
||||
foreach (var item in kv.Value)
|
||||
{
|
||||
if (item is WallType t)
|
||||
{
|
||||
sb.AppendLine($"{kv.Key}-{t.Kind}-{item.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
MessageBox.Show(sb.ToString());
|
||||
#endif
|
||||
//foreach (BuiltInCategory id in Enum.GetValues(typeof(BuiltInCategory)))
|
||||
//{
|
||||
// var names = Enum.GetName(typeof(BuiltInCategory), id);
|
||||
//}
|
||||
|
||||
//using (Transaction ts = new Transaction(doc, "修改类型名称"))
|
||||
//{
|
||||
// ts.Start();
|
||||
// try
|
||||
// {
|
||||
// foreach (var id in symbols)
|
||||
// {
|
||||
// if (id.Name == "标准")
|
||||
// {
|
||||
// if (id is FamilySymbol ids)
|
||||
// {
|
||||
// id.Name = ids.FamilyName;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// catch (Exception)
|
||||
// {
|
||||
|
||||
// throw;
|
||||
// }
|
||||
|
||||
// ts.Commit();
|
||||
//}
|
||||
//UiDocument.Selection.SetElementIds([new ElementId(2222596)]);
|
||||
|
||||
//var dims = doc.QueryElementsByType<Dimension>().WhereElementIsNotElementType().ToElementIds();
|
||||
|
||||
//UiDocument.Selection.SetElementIds(dims);
|
||||
//var refer = UiDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
|
||||
//var ids = doc.GetElement(refer);
|
||||
//foreach (Parameter param in ids.Parameters)
|
||||
//{
|
||||
|
||||
//}
|
||||
|
||||
#region MyRegion
|
||||
|
||||
////var service = new ricaun.Revit.ExtensibleShortcuts.Services.KeyboardShortcutService();
|
||||
////service.SetRibbonItemShortcut("CustomCtrl_%CustomCtrl_%SZMEDI工具%机电工具%MoveConnectCmd", "MC");
|
||||
//var dict = ShortcutsHelper.Commands;
|
||||
//StringBuilder sb = new StringBuilder();
|
||||
//sb.AppendLine("Name,CommandName,CommandId,CommandPaths,CommandScope,Shortcuts,ShortcutType,ShortcutsRep,");
|
||||
//foreach (var id in dict)
|
||||
//{
|
||||
// string text = id.Value.CommandName;
|
||||
// string commandName = string.Join("", text.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries));
|
||||
// sb.AppendLine(
|
||||
// $"{id.Key},{commandName},{id.Value.CommandId},{id.Value.CommandPaths},{id.Value.CommandScope},{id.Value.Shortcuts},{id.Value.ShortcutType},{id.Value.ShortcutsRep},");
|
||||
// //if (ShortcutsHelper.Commands.TryGetValue("CustomCtrl_%CustomCtrl_%SZMEDI工具%机电工具%MoveConnectCmd", out var shortcutItem))
|
||||
// //{
|
||||
// // //为命令指定快捷键QQQQ
|
||||
// // shortcutItem.Shortcuts.Add("MC");
|
||||
// // break;
|
||||
// // //为命令删除快捷键QQQQ
|
||||
// // //shortcutItem.Shortcuts.Remove("QQQQ");
|
||||
// // //为命令清空快捷键
|
||||
// // //shortcutItem.Shortcuts.Clear();
|
||||
// //}
|
||||
//}
|
||||
//LogUtil.WriteTxtFile("快捷键", sb.ToString());
|
||||
|
||||
////KeyboardShortcutService.applyShortcutChanges(dict);
|
||||
|
||||
#endregion
|
||||
|
||||
//var window = new MainWindow() { DataContext = new MainWindowViewModel(UiDocument) };
|
||||
//window.Show();
|
||||
//var refer = UiDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
|
||||
//var ids = doc.GetElement(refer);
|
||||
//var boundingbox = ids.get_BoundingBox(null);
|
||||
//using var ts = new Transaction(doc, "Test");
|
||||
//ts.Start();
|
||||
//if (doc.ActiveView is View3D view3D)
|
||||
//{
|
||||
// view3D.SetSectionBox(Extend(boundingbox));
|
||||
//}
|
||||
//ts.Commit();
|
||||
//var ids = UiDocument.Selection.GetElementIds();
|
||||
|
||||
//using (var ts = new Transaction(doc, "Test"))
|
||||
//{
|
||||
// ts.Start();
|
||||
// foreach (var id in ids)
|
||||
// {
|
||||
// var ids = doc.GetElement(id) as FamilyInstance;
|
||||
// //ElementTransformUtils.RotateElement(doc, id, Line.CreateUnbound((ids.Location as LocationPoint).Point, XYZ.BasisZ), /*65.43 / 180 * */Math.PI);
|
||||
// ElementTransformUtils.MoveElement(doc, id, ids.HandOrientation * 1200 / 304.8);
|
||||
// doc.Regenerate();
|
||||
// //ElementTransformUtils.RotateElement(doc, id, Line.CreateUnbound((ids.Location as LocationPoint).Point, XYZ.BasisZ), /*65.43 / 180 * */Math.PI);
|
||||
// }
|
||||
// ts.Commit();
|
||||
//}
|
||||
|
||||
#region Updater
|
||||
|
||||
//ChangeTypeUpdater _updater = new(UiApplication, new Guid("{A3441B77-7558-41EF-A3BF-4690C99F67C0}"));
|
||||
//UpdaterRegistry.RegisterUpdater(_updater, true);
|
||||
//UpdaterRegistry.AddTrigger(_updater.GetUpdaterId(), new ElementClassFilter(typeof(FamilyInstance)), Element.GetChangeTypeAny());
|
||||
|
||||
#endregion
|
||||
|
||||
//var ids = UiDocument.Selection.GetElementIds().Select(id=>doc.GetElement(id)).OfType<ModelCurve>().Select(mc=>mc.GeometryCurve).ToList();
|
||||
|
||||
//SetComparisonResult comparisonR = ids[0].Intersect(ids[1], out var intersectionResult);
|
||||
//System.Windows.MessageBox.Show($"{comparisonR}");
|
||||
//try
|
||||
//{
|
||||
// var cl = CurveLoop.Create(ids);
|
||||
//}
|
||||
//catch (Exception)
|
||||
//{
|
||||
// throw;
|
||||
//}
|
||||
//Application.DocumentChanged -= Application_DocumentChanged;
|
||||
//Application.DocumentChanged += Application_DocumentChanged;
|
||||
|
||||
#region MyRegion
|
||||
|
||||
var refer = UiDocument.Selection.PickObject(ObjectType.Element);
|
||||
var ids = (Document.GetElement(refer) as FamilyInstance).Symbol;
|
||||
Document.Modify(set => set.Transaction)
|
||||
.Commit((d, _) =>
|
||||
{
|
||||
if (!ids.IsActive)
|
||||
{
|
||||
ids.Activate();
|
||||
}
|
||||
|
||||
var level = new FilteredElementCollector(d).OfClass(typeof(Level))
|
||||
.OfType<Level>()
|
||||
.FirstOrDefault(l => l.Elevation > 0);
|
||||
d.Create
|
||||
.NewFamilyInstance(
|
||||
new XYZ(0, 0, 0),
|
||||
ids,
|
||||
level,
|
||||
Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
//XYZ p1 = new XYZ();
|
||||
//XYZ p2 = XYZ.BasisX;
|
||||
//XYZ p3 = XYZ.BasisY;
|
||||
//XYZ p4 = XYZ.BasisZ;
|
||||
//var list = new List<XYZ>() { p1, p2, p3 };
|
||||
//HermiteSpline curve = HermiteSpline.Create(list, false);
|
||||
//using (Transaction ts = new Transaction(doc, "test"))
|
||||
//{
|
||||
// ts.Start();
|
||||
// SketchPlane sketch = SketchPlane.Create(doc, Plane.CreateByNormalAndOrigin(p4, p1));
|
||||
// var mc = doc.Create.NewModelCurve(curve, sketch);
|
||||
// ts.Commit();
|
||||
//}
|
||||
//Autodesk.Revit.DB.Reference e = UiDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
|
||||
}
|
||||
|
||||
private static void MoveRoomSeparator(Document doc, ICollection<ElementId> ids, double dis)
|
||||
{
|
||||
var distance = dis / 304.8;
|
||||
foreach (var id in ids)
|
||||
{
|
||||
var element = doc.GetElement(id);
|
||||
if (element is ModelCurve modelCurve)
|
||||
{
|
||||
var start = modelCurve.GeometryCurve.GetEndPoint(0);
|
||||
var end = modelCurve.GeometryCurve.GetEndPoint(1);
|
||||
var sketch = SketchPlane.Create(doc,
|
||||
Plane.CreateByNormalAndOrigin(XYZ.BasisZ, start + (XYZ.BasisZ * distance)));
|
||||
var line = Line.CreateBound(start + (XYZ.BasisZ * distance), end + (XYZ.BasisZ * distance));
|
||||
var array = new CurveArray();
|
||||
array.Append(line);
|
||||
doc.Create.NewRoomBoundaryLines(sketch, array, doc.ActiveView);
|
||||
}
|
||||
}
|
||||
|
||||
doc.Delete(ids);
|
||||
}
|
||||
|
||||
|
||||
@@ -732,98 +125,5 @@ namespace Szmedi.Test
|
||||
}
|
||||
}
|
||||
}
|
||||
public class SelectionFilter : ISelectionFilter
|
||||
{
|
||||
public bool AllowElement(Element elem)
|
||||
{
|
||||
return elem is Wall;
|
||||
}
|
||||
|
||||
public bool AllowReference(Reference reference, XYZ position)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class ChangeTypeUpdater : IUpdater
|
||||
{
|
||||
private UpdaterId _uid;
|
||||
|
||||
public ChangeTypeUpdater(UIApplication uiapp, Guid guid)
|
||||
{
|
||||
_uid = new UpdaterId(uiapp.ActiveAddInId,
|
||||
guid);
|
||||
}
|
||||
|
||||
public void Execute(UpdaterData data)
|
||||
{
|
||||
Func<ICollection<ElementId>, string> toString = ids =>
|
||||
ids.Aggregate(string.Empty, (ss, id) => ss + "," + id).TrimStart(',');
|
||||
StringBuilder sb = new();
|
||||
sb.AppendLine("added:" + toString(data.GetAddedElementIds()));
|
||||
sb.AppendLine("modified:" + toString(data.GetModifiedElementIds()));
|
||||
sb.AppendLine("deleted:" + toString(data.GetDeletedElementIds()));
|
||||
TaskDialog.Show("Changes", sb.ToString());
|
||||
}
|
||||
|
||||
public string GetAdditionalInformation()
|
||||
{
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
public ChangePriority GetChangePriority()
|
||||
{
|
||||
return ChangePriority.FreeStandingComponents;
|
||||
}
|
||||
|
||||
public UpdaterId GetUpdaterId()
|
||||
{
|
||||
return _uid;
|
||||
}
|
||||
|
||||
public string GetUpdaterName()
|
||||
{
|
||||
return "ChangeTypeUpdater";
|
||||
}
|
||||
}
|
||||
|
||||
private void Application_DocumentChanged(object sender, Autodesk.Revit.DB.Events.DocumentChangedEventArgs e)
|
||||
{
|
||||
var a = sender as Autodesk.Revit.ApplicationServices.Application;
|
||||
var doc = e.GetDocument();
|
||||
ElementClassFilter filter = new(typeof(FamilyInstance));
|
||||
var modifyIds = e.GetModifiedElementIds(filter);
|
||||
var addIds = e.GetAddedElementIds(filter);
|
||||
var deleteIds = e.GetDeletedElementIds();
|
||||
StringBuilder sb = new();
|
||||
if (modifyIds.Count > 0)
|
||||
{
|
||||
sb.AppendLine("修改");
|
||||
foreach (var id in modifyIds)
|
||||
{
|
||||
sb.AppendLine($"{id}-{doc.GetElement(id).Name}");
|
||||
}
|
||||
}
|
||||
|
||||
if (addIds.Count > 0)
|
||||
{
|
||||
sb.AppendLine("添加");
|
||||
foreach (var id in addIds)
|
||||
{
|
||||
sb.AppendLine($"{id}-{doc.GetElement(id).Name}");
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteIds.Count > 0)
|
||||
{
|
||||
sb.AppendLine("删除");
|
||||
foreach (var id in deleteIds)
|
||||
{
|
||||
sb.AppendLine($"{id}-{doc.GetElement(id).Name}");
|
||||
}
|
||||
}
|
||||
|
||||
MessageBox.Show(sb.ToString(), "文档修改");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using EPPlus.Core.Extensions.Attributes;
|
||||
|
||||
namespace Szmedi.Test
|
||||
{
|
||||
public class TestExcel
|
||||
{
|
||||
[ExcelTableColumn("变更前")]
|
||||
public Test Old { get; set; }
|
||||
[ExcelTableColumn("变更后")]
|
||||
public Test New { get; set; }
|
||||
}
|
||||
public class Test
|
||||
{
|
||||
public Test(string iD, string name, string description)
|
||||
{
|
||||
ID = iD;
|
||||
Name = name;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
[ExcelTableColumn("ID")]
|
||||
public string ID { get; set; }
|
||||
[ExcelTableColumn("名称")]
|
||||
public string Name { get; set; }
|
||||
[ExcelTableColumn("描述")]
|
||||
public string Description { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user