commit 1588dc09d1a7eb1cce7e6fddd7f9c34e1fafb02a
Author: GG Z <903524121@qq.com>
Date: Mon Feb 23 11:05:30 2026 +0800
添加项目文件。
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1ff0c42
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9491a2f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,363 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Oo]ut/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
\ No newline at end of file
diff --git a/DimensionTools.AddInDeployer/AddInManager.cs b/DimensionTools.AddInDeployer/AddInManager.cs
new file mode 100644
index 0000000..03b23b5
--- /dev/null
+++ b/DimensionTools.AddInDeployer/AddInManager.cs
@@ -0,0 +1,72 @@
+#region
+
+using System;
+using System.IO;
+using Autodesk.RevitAddIns;
+
+#endregion
+
+namespace DimensionTools.AddInDeployer
+{
+ public class AddInManager
+ {
+ private readonly string vendorDescription = "深圳市地铁集团有限公司";
+ private readonly string vendorid = "SZMC";
+
+ internal AddInManager(string revitVersion, string addinname)
+ {
+ Manifest = new RevitAddInManifest();
+ ManifestPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
+ "Autodesk\\ApplicationPlugins\\DimensionTools.bundle\\Contents", revitVersion, addinname);
+ //ManifestPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Autodesk\\Revit\\Addins", revitVersion, addinname);
+ }
+
+ private RevitAddInManifest Manifest { get; }
+
+ private string ManifestPath { get; }
+
+
+ internal void CreateApplication(string name, string assemblyPath, string fullClassName)
+ {
+ RevitAddInApplication item =
+ new RevitAddInApplication(name, assemblyPath, Guid.NewGuid(), fullClassName, vendorid)
+ {
+ VendorDescription = vendorDescription
+ };
+ Manifest.AddInApplications.Add(item);
+ }
+
+ internal void CreateCommand(string assemblyPath, string fullClassName)
+ {
+ RevitAddInCommand item = new RevitAddInCommand(assemblyPath, Guid.NewGuid(), fullClassName, vendorid)
+ {
+ VendorDescription = vendorDescription
+ };
+ Manifest.AddInCommands.Add(item);
+ }
+
+ internal void Install()
+ {
+ DirectoryInfo directory = new FileInfo(ManifestPath).Directory;
+ if (directory == null)
+ {
+ return;
+ }
+
+ if (!directory.Exists)
+ {
+ Directory.CreateDirectory(directory.FullName);
+ }
+
+ Manifest.SaveAs(ManifestPath);
+ }
+
+ internal void Uninstall()
+ {
+ if (File.Exists(ManifestPath))
+ {
+ File.Delete(ManifestPath);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools.AddInDeployer/CustomAction.config b/DimensionTools.AddInDeployer/CustomAction.config
new file mode 100644
index 0000000..9696db3
--- /dev/null
+++ b/DimensionTools.AddInDeployer/CustomAction.config
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DimensionTools.AddInDeployer/CustomAction.cs b/DimensionTools.AddInDeployer/CustomAction.cs
new file mode 100644
index 0000000..a4cd118
--- /dev/null
+++ b/DimensionTools.AddInDeployer/CustomAction.cs
@@ -0,0 +1,63 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Microsoft.Deployment.WindowsInstaller;
+
+namespace DimensionTools.AddInDeployer
+{
+ public class CustomActions
+ {
+ public const string dllName = "DimensionTools.dll";
+ public const string addinName = "DimensionTools.addin";
+
+ [CustomAction]
+ public static ActionResult Uninstaller(Session session)
+ {
+ session.Log("Begin Uninstaller");
+ var commonAppDataFolder = session["CommonAppDataFolder"];
+ var addinFilePath = $"{commonAppDataFolder}\\Autodesk\\DimensionTools.bundle";
+ Directory.Delete(addinFilePath,true);
+ return ActionResult.Success;
+ }
+
+ [CustomAction]
+ public static ActionResult Installer(Session session)
+ {
+ session.Log("Begin Installer");
+ var manufacturer = session["Manufacturer"];
+ var productName = session["ProductName"];
+ var appdir = session["APPDIR"]; //װ·,ûѡ
+ var sourceDir = session["SourceDir"]; //װѹ·
+ var programFiles64Folder = session["ProgramFiles64Folder"]; //64λװ·C:\ProgramFiles
+ var commonAppDataFolder = session["CommonAppDataFolder"]; //C:\ProgramData
+ var addinFilePath = $"{commonAppDataFolder}\\Autodesk\\DimensionTools.bundle\\Contents";
+ //List revitProductsInstalled = RevitProductUtility.GetAllInstalledRevitProducts();
+ //foreach (var product in revitProductsInstalled)
+ //{
+ //}
+ List dlls = new List();
+ DirectoryInfo dir = Directory.CreateDirectory(appdir);
+ StringBuilder sb = new StringBuilder();
+ foreach (var fileInfo in dir.GetFiles("*", SearchOption.AllDirectories))
+ {
+ if (fileInfo.Name == dllName)
+ {
+ dlls.Add(fileInfo);
+ }
+ }
+
+ foreach (var dllPath in dlls)
+ {
+ var versionNum = dllPath.Directory.Name;
+ AddInManager manager = new AddInManager(versionNum, addinName);
+
+ manager.CreateApplication("ע", dllPath.FullName, "DimensionTools.UiRibbon");
+
+ manager.Uninstall();
+ manager.Install();
+ }
+
+ return ActionResult.Success;
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools.AddInDeployer/DimensionTools.AddInDeployer.csproj b/DimensionTools.AddInDeployer/DimensionTools.AddInDeployer.csproj
new file mode 100644
index 0000000..3b09b48
--- /dev/null
+++ b/DimensionTools.AddInDeployer/DimensionTools.AddInDeployer.csproj
@@ -0,0 +1,97 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {1E6F7706-97B3-4929-8FF9-79DF5485801B}
+ Library
+ Properties
+ DimensionTools.AddInDeployer
+ DimensionTools.AddInDeployer
+ v4.7.2
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ x64
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE
+ full
+ AnyCPU
+ 7.3
+ prompt
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ pdbonly
+ x64
+ 7.3
+ prompt
+
+
+ true
+ bin\Debug\
+ DEBUG;TRACE
+ full
+ AnyCPU
+ 7.3
+ prompt
+
+
+ bin\Release\
+ TRACE
+ true
+ pdbonly
+ AnyCPU
+ 7.3
+ prompt
+
+
+
+ C:\Program Files\Autodesk\Revit 2020\RevitAddInUtility.dll
+
+
+
+
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DimensionTools.AddInDeployer/Properties/AssemblyInfo.cs b/DimensionTools.AddInDeployer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..9150077
--- /dev/null
+++ b/DimensionTools.AddInDeployer/Properties/AssemblyInfo.cs
@@ -0,0 +1,34 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Szmedi.AddinDeployer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyCompany("Administrator")]
+[assembly: AssemblyProduct("Szmedi.AddinDeployer")]
+[assembly: AssemblyCopyright("Copyright © Administrator 2022")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("1e6f7706-97b3-4929-8ff9-79df5485801b")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DimensionTools.sln b/DimensionTools.sln
new file mode 100644
index 0000000..3f0fdbb
--- /dev/null
+++ b/DimensionTools.sln
@@ -0,0 +1,55 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 18
+VisualStudioVersion = 18.3.11512.155
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DimensionTools", "DimensionTools\DimensionTools.csproj", "{5FE4E018-C3DF-481E-A739-9B0B663EDE60}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug One|Any CPU = Debug One|Any CPU
+ Debug One|x64 = Debug One|x64
+ Debug One|x86 = Debug One|x86
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ DefaultBuild|Any CPU = DefaultBuild|Any CPU
+ DefaultBuild|x64 = DefaultBuild|x64
+ DefaultBuild|x86 = DefaultBuild|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Debug One|Any CPU.ActiveCfg = Debug One|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Debug One|Any CPU.Build.0 = Debug One|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Debug One|x64.ActiveCfg = Debug One|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Debug One|x64.Build.0 = Debug One|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Debug One|x86.ActiveCfg = Debug One|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Debug One|x86.Build.0 = Debug One|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Debug|Any CPU.Build.0 = Debug|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Debug|x64.ActiveCfg = Debug|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Debug|x64.Build.0 = Debug|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Debug|x86.ActiveCfg = Debug|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Debug|x86.Build.0 = Debug|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.DefaultBuild|Any CPU.ActiveCfg = Debug One|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.DefaultBuild|Any CPU.Build.0 = Debug One|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.DefaultBuild|x64.ActiveCfg = Debug One|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.DefaultBuild|x64.Build.0 = Debug One|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.DefaultBuild|x86.ActiveCfg = Debug One|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.DefaultBuild|x86.Build.0 = Debug One|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Release|Any CPU.ActiveCfg = Release|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Release|Any CPU.Build.0 = Release|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Release|x64.ActiveCfg = Release|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Release|x64.Build.0 = Release|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Release|x86.ActiveCfg = Release|x64
+ {5FE4E018-C3DF-481E-A739-9B0B663EDE60}.Release|x86.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {FEA09681-016B-4A46-AEDC-0C863FA1AA1B}
+ EndGlobalSection
+EndGlobal
diff --git a/DimensionTools/Civil/ExportPilesInfo.cs b/DimensionTools/Civil/ExportPilesInfo.cs
new file mode 100644
index 0000000..5ab2c25
--- /dev/null
+++ b/DimensionTools/Civil/ExportPilesInfo.cs
@@ -0,0 +1,39 @@
+using System;
+using System.IO;
+
+using Autodesk.Revit.Attributes;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+
+using EPPlus.Core.Extensions;
+
+namespace DimensionTools.Civil
+{
+ ///
+ /// Revit执行命令
+ ///
+ [Transaction(TransactionMode.Manual)]
+ [Regeneration(RegenerationOption.Manual)]
+ public class ExportPilesInfo : IExternalCommand
+ {
+ public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ //程序UI界面
+ UIApplication uiapp = commandData.Application;
+ //获取元素(选择) 显示元素 视图(活动视图)管理(对象)
+ UIDocument uidoc = uiapp.ActiveUIDocument;
+
+ string addInPath = typeof(ExportPilesInfo).Assembly.Location;
+ string dirAssembly = System.IO.Path.GetDirectoryName(addInPath);
+ PilesInfo pilesInfo = new PilesInfo(uidoc);
+ _ = new System.Windows.Interop.WindowInteropHelper(pilesInfo)
+ {
+ Owner = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle
+ };
+ pilesInfo.Show();
+
+ return Result.Succeeded;
+ //OfficeOpenXml.ExcelWorksheet worksheet = excelPackage.GenerateWorksheet(Assembly.GetExecutingAssembly(), nameof(FamilyInstance));
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools/Civil/PileModel.cs b/DimensionTools/Civil/PileModel.cs
new file mode 100644
index 0000000..59e10f8
--- /dev/null
+++ b/DimensionTools/Civil/PileModel.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Autodesk.Revit.DB;
+
+namespace DimensionTools.Civil
+{
+ public class PileModel
+ {
+
+ public string FamilyName { get; set; }
+ public string SymbolName { get; set; }
+ public string Code { get; set; }
+
+ public ElementId InstanceId { get; set; }
+
+ public double TopElev { get; set; }
+ public double BottomElev { get; set; }
+
+ public double WestEast { get; set; }
+ public double NorthSouth { get; set; }
+ }
+}
diff --git a/DimensionTools/Civil/PilesAnnotationCmd.cs b/DimensionTools/Civil/PilesAnnotationCmd.cs
new file mode 100644
index 0000000..d0819a9
--- /dev/null
+++ b/DimensionTools/Civil/PilesAnnotationCmd.cs
@@ -0,0 +1,317 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Revit.UI.Selection;
+
+namespace DimensionTools.Civil
+{
+ [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
+ [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
+ public class PilesAnnotationCmd : IExternalCommand
+ {
+ ///
+ /// 按路径排序的集合
+ ///
+ private readonly List orderedByPath = new List();
+
+ public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ UIApplication uiapp = commandData.Application;
+ UIDocument uidoc = uiapp.ActiveUIDocument;
+ Document doc = uidoc.Document;
+ if (doc.ActiveView.ViewType != ViewType.FloorPlan && doc.ActiveView.ViewType != ViewType.CeilingPlan && doc.ActiveView.ViewType != ViewType.EngineeringPlan)
+ {
+ message = "请选择平面视图";
+ return Result.Failed;
+ }
+ string addInPath = typeof(ExportPilesInfo).Assembly.Location;
+ string dirAssembly = System.IO.Path.GetDirectoryName(addInPath);
+ PilesDimSettings pilesDim = new PilesDimSettings(doc);
+ pilesDim.ShowDialog();
+
+ if (pilesDim.DialogResult != true) return Result.Cancelled;
+
+ var isManualSelected = pilesDim.SelectedRb.IsChecked;
+ var id = pilesDim.DimStyleCbb.SelectedValue as ElementId;
+ var ruleIndex = pilesDim.RuleCbb.SelectedIndex;
+ var prefix = pilesDim.CodeTb.Text;
+ var canParse = int.TryParse(pilesDim.StartCodeTb.Text, out int startCode);
+ if (!canParse)
+ {
+ TaskDialog.Show("错误", "起始编号有误");
+ return Result.Cancelled;
+ }
+
+ using (TransactionGroup tg = new TransactionGroup(doc, "标注桩"))
+ {
+ try
+ {
+ //桩集合
+ //沿路径编号起点
+ FamilyInstance firstElem;
+ //排序后集合
+ List elemsOrdered;
+ tg.Start();
+ if (isManualSelected == true)
+ {
+ IList refers = uidoc.Selection.PickObjects(ObjectType.Element, new PileFilter(), "请选择需要编码标注的围护桩");
+ var enumerable = from refer in refers
+ select doc.GetElement(refer) as FamilyInstance;
+ elemsOrdered = enumerable.OrderBy(x => ((LocationPoint)x.Location).Point.X)
+ .ThenBy(y => ((LocationPoint)y.Location).Point.Y)
+ .ToList();
+ }
+ else
+ {
+ List elems = new FilteredElementCollector(doc,
+ doc.ActiveView.Id)
+ .OfClass(typeof(FamilyInstance))
+ .Cast()
+ .Where(p => p.Name.Contains("桩") || p.Symbol.FamilyName.Contains("桩"))
+ .ToList();
+ switch (ruleIndex)
+ {
+ case 0:
+ //从左到右
+ elemsOrdered = elems.OrderBy(x => ((LocationPoint)x.Location).Point.X).ToList();
+ break;
+ case 1:
+ //从上到下
+ elemsOrdered = elems.OrderByDescending(y => ((LocationPoint)y.Location).Point.Y).ToList();
+ break;
+ default:
+ {
+ var first = uidoc.Selection.PickObject(ObjectType.Element, new PileFilter(), "请选择路径起点围护桩");
+ firstElem = doc.GetElement(first) as FamilyInstance;
+ elems = elems.Where(x => firstElem != null && x.Id.IntegerValue != firstElem.Id.IntegerValue && x.Symbol.Family.Id == firstElem.Symbol.Family.Id)
+ .ToList();
+ orderedByPath.Clear();
+ Order(elems, firstElem);
+ elemsOrdered = orderedByPath;
+ break;
+ }
+ }
+ //uidoc.Selection.SetElementIds(elems.Select(e => e.Id).ToList());
+ }
+
+ MarkPiles(doc, id, elemsOrdered, isManualSelected);
+ CodePile(doc, elemsOrdered, prefix, startCode);
+
+ if (tg.GetStatus() == TransactionStatus.Started)
+ {
+ tg.Assimilate();
+ }
+ }
+ catch (Autodesk.Revit.Exceptions.OperationCanceledException)
+ {
+ if (tg.GetStatus() == TransactionStatus.Started)
+ {
+ tg.RollBack();
+ }
+ }
+ catch (Exception)
+ {
+ if (tg.GetStatus() == TransactionStatus.Started)
+ {
+ tg.RollBack();
+ }
+ }
+ }
+
+ return Result.Succeeded;
+ }
+
+ ///
+ /// 桩编号
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static void CodePile(Document doc, List orderElem, string prefix, int startCode)
+ {
+ using (Transaction trans = new Transaction(doc, "围护桩编号"))
+ {
+ try
+ {
+ trans.Start();
+
+ for (int i = 0; i < orderElem.Count; i++)
+ {
+ //if (i + startCode <= 9)
+ //{
+ // code = startCode == 0 ? $"00{i + 1 + startCode}" : $"00{i + startCode}";
+ //}
+ //else if (i + startCode <= 99)
+ //{
+ // code = startCode == 0 ? $"0{i + 1 + startCode}" : $"0{i + startCode}";
+ //}
+ //else
+ //{
+ // code = startCode == 0 ? $"{i + 1 + startCode}" : $"{i + startCode}";
+ //}
+ int number = i + startCode;
+ var code = number > 1000 ? number.ToString() : number.ToString().PadLeft(4, '0');
+ if (prefix != string.Empty)
+ {
+ code = $"{prefix}-{code}";
+ }
+ //间隔四个标注一个
+
+ orderElem[i].get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS).Set(code);
+ }
+
+ trans.Commit();
+ }
+ catch (Autodesk.Revit.Exceptions.OperationCanceledException)
+ {
+ if (trans.GetStatus() == TransactionStatus.Started)
+ {
+ trans.RollBack();
+ }
+ }
+ catch (Exception)
+ {
+ if (trans.GetStatus() == TransactionStatus.Started)
+ {
+ trans.RollBack();
+ }
+ }
+ }
+ }
+ ///
+ /// 标注
+ ///
+ ///
+ /// 坐标标注类型Id
+ ///
+ /// 是否手动选择
+ private static void MarkPiles(Document doc, ElementId id, List elems, bool? isManualSelected)
+ {
+ using (Transaction trans = new Transaction(doc, "标注"))
+ {
+ trans.Start();
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < elems.Count; i++)
+ {
+ FamilyInstance fi = elems[i];
+ var pt = (fi.Location as LocationPoint)?.Point;
+ //var face = GeometryUtil.GetTopFaceByElement(fi);
+ //Reference refer = GeometryUtil.GetSpotDimensionReference(doc, pt) ?? fi.GetReferences(FamilyInstanceReferenceType.CenterFrontBack).FirstOrDefault();
+ Reference refer = fi.GetReferences(FamilyInstanceReferenceType.CenterFrontBack).FirstOrDefault();
+ if (refer != null)
+ refer = fi.GetReferences(FamilyInstanceReferenceType.CenterLeftRight).FirstOrDefault();
+ //Line l = Line.CreateUnbound(pt, XYZ.BasisZ);
+ //var t = fi.FindIntersects(l).OrderBy(p => p.Key.Z).LastOrDefault();
+ //if (t.Key == null)
+ //{
+ // sb.AppendLine($"{fi.Name}:{fi.Id}");
+ // continue;
+ //}
+
+ if (isManualSelected == true)
+ {
+ SpotDimension spotDimension = doc.Create.NewSpotCoordinate(doc.ActiveView, refer, pt, pt + new XYZ(0.1, 1, 0) * 5, pt + XYZ.BasisX * 5, pt, true);
+ //SpotDimension spotDimension = doc.Create.NewSpotCoordinate(doc.ActiveView, refer, t.Key, t.Key + new XYZ(0.1, 1, 0) * 5, t.Key + XYZ.BasisX * 5, t.Key, true);
+ spotDimension.ChangeTypeId(id);
+ }
+ else
+ {
+ //坐标标注
+ if (i % 10 == 0)
+ {
+ //SpotDimension spotDimension = doc.Create.NewSpotCoordinate(doc.ActiveView, refer, t.Key, t.Key + new XYZ(0.1, 1, 0) * 5, t.Key + XYZ.BasisX * 5, t.Key, true);
+ SpotDimension spotDimension = doc.Create.NewSpotCoordinate(doc.ActiveView, refer, pt, pt + new XYZ(0.1, 1, 0) * 5, pt + XYZ.BasisX * 5, pt, true);
+ spotDimension.ChangeTypeId(id);
+ }
+ }
+
+
+ //pt = face.Origin / 2 + face.Origin.Z * XYZ.BasisZ;
+ //var centerPoint = face.Origin / 2 + face.Origin.Z * XYZ.BasisZ;
+ //var pt = fi.GetTransform().OfPoint(centerPoint);
+ //标高标注
+ //SpotDimension spotDimension1 = doc.Create.NewSpotElevation(doc.ActiveView, face.Reference, p, p + new XYZ(0.2, 1, 0) * 5, p + XYZ.BasisX * 2, p, true);
+ }
+
+ if (sb.Length > 0)
+ {
+ TaskDialog.Show("无法创建坐标标注", sb.ToString());
+ }
+
+ trans.Commit();
+ }
+ }
+
+ ///
+ /// 排序
+ ///
+ /// 合集,不包含第一个元素
+ /// 第一个元素
+ private void Order(List elements, FamilyInstance firstElem)
+ {
+ while (true)
+ {
+ if (firstElem == null)
+ {
+ return;
+ }
+ orderedByPath.Add(firstElem);
+ if (elements.Count == 0)
+ {
+ return;
+ }
+ Debug.Assert(elements.Count >= 1, "条件不成立");
+ //var b = elements.Remove(firstElem);
+ double distance = 10.0;
+ FamilyInstance closest = null;
+
+ foreach (var elem in elements) //最后一次循环为0个
+ {
+ if (elements.Count == 1)
+ {
+ closest = elem;
+ }
+ if (elem.Location is LocationPoint lp && firstElem?.Location is LocationPoint lpf)
+ {
+ var tempDistance = (lp.Point - lp.Point.Z * XYZ.BasisZ).DistanceTo(lpf.Point - lpf.Point.Z * XYZ.BasisZ);
+ if (tempDistance < distance)
+ {
+ closest = elem;
+ distance = tempDistance;
+ }
+ }
+
+ }
+ elements.Remove(closest);
+ firstElem = closest;
+ }
+ }
+ }
+
+ ///
+ /// 桩过滤器
+ ///
+ public class PileFilter : ISelectionFilter
+ {
+ public bool AllowElement(Element elem)
+ {
+ if (elem is FamilyInstance fi)
+ {
+ return fi.Symbol.FamilyName.Contains("桩") || fi.Symbol.Name.Contains("桩");
+ }
+
+ return false;
+ }
+
+ public bool AllowReference(Reference reference, XYZ position)
+ {
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools/Civil/PilesDimSettings.xaml b/DimensionTools/Civil/PilesDimSettings.xaml
new file mode 100644
index 0000000..51f5842
--- /dev/null
+++ b/DimensionTools/Civil/PilesDimSettings.xaml
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DimensionTools/Civil/PilesDimSettings.xaml.cs b/DimensionTools/Civil/PilesDimSettings.xaml.cs
new file mode 100644
index 0000000..7033862
--- /dev/null
+++ b/DimensionTools/Civil/PilesDimSettings.xaml.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using Autodesk.Revit.DB;
+
+namespace DimensionTools.Civil
+{
+ ///
+ /// PilesDimSettings.xaml 的交互逻辑
+ ///
+ public partial class PilesDimSettings
+ {
+ public PilesDimSettings(Document doc)
+ {
+ var elementTypes = new FilteredElementCollector(doc).OfClass(typeof(SpotDimensionType)).Cast().Where(t => t.StyleType == DimensionStyleType.SpotCoordinate);
+ var types = new List();
+
+ InitializeComponent();
+ DimStyleCbb.ItemsSource = elementTypes;
+ }
+
+ private void ConfirmBtn_Click(object sender, RoutedEventArgs e)
+ {
+ DialogResult = true;
+ Close();
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools/Civil/PilesInfo.xaml b/DimensionTools/Civil/PilesInfo.xaml
new file mode 100644
index 0000000..5ab1640
--- /dev/null
+++ b/DimensionTools/Civil/PilesInfo.xaml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DimensionTools/Civil/PilesInfo.xaml.cs b/DimensionTools/Civil/PilesInfo.xaml.cs
new file mode 100644
index 0000000..90244b7
--- /dev/null
+++ b/DimensionTools/Civil/PilesInfo.xaml.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Forms;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+using Autodesk.Revit.DB;
+
+using Autodesk.Revit.UI;
+
+using EPPlus.Core.Extensions;
+
+namespace DimensionTools.Civil
+{
+ ///
+ /// PilesInfo.xaml 的交互逻辑
+ ///
+ public partial class PilesInfo : Window
+ {
+ public PilesInfo(UIDocument uidoc)
+ {
+ DataContext = this;
+ InitializeComponent();
+ this.uidoc = uidoc;
+ SetItemsSource(uidoc.Document);
+
+ }
+
+ private void SetItemsSource(Document doc)
+ {
+ Models.Clear();
+ var view3D = new FilteredElementCollector(doc).OfClass(typeof(View3D)).Cast().FirstOrDefault(v => !v.IsTemplate);
+ List instances = new FilteredElementCollector(doc)
+ .OfClass(typeof(FamilyInstance))
+ .Cast()
+ .Where(instance => instance.Name.Contains("桩") || instance.Symbol.FamilyName.Contains("桩"))
+ .OrderBy(x => x.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS).AsString())
+ .ToList();
+ foreach (FamilyInstance instance in instances)
+ {
+ var bound = instance.get_BoundingBox(view3D);
+ var point = (instance.Location as LocationPoint)?.Point;
+ Debug.Assert(point != null, nameof(point) + " != null");
+ Models.Add(new PileModel
+ {
+ FamilyName = instance.Symbol.FamilyName,
+ SymbolName = instance.Symbol.Name,
+ Code = instance.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS).AsString(),
+ InstanceId = instance.Id,
+ TopElev = Math.Round(bound.Max.Z * 304.8 / 1000, 3, MidpointRounding.AwayFromZero),
+ BottomElev = Math.Round(bound.Min.Z * 304.8 / 1000, 3, MidpointRounding.AwayFromZero),
+ WestEast = Math.Round(point.X * 304.8 / 1000, 3, MidpointRounding.AwayFromZero),
+ NorthSouth = Math.Round(point.Y * 304.8 / 1000, 3, MidpointRounding.AwayFromZero)
+ });
+ }
+ }
+
+ private readonly UIDocument uidoc;
+
+ public List Models { get; } = new List();
+
+ private void BtnExport_Click(object sender, RoutedEventArgs e)
+ {
+ this.Close();
+ FileSaveDialog fileSaveDialog = new FileSaveDialog("Excel文件(*.xlsx)|*.xlsx")
+ {
+ Title = "导出全部桩信息",
+ InitialFileName = "桩信息"
+ };
+ if (fileSaveDialog.Show() == ItemSelectionDialogResult.Confirmed)
+ {
+ var mp = fileSaveDialog.GetSelectedModelPath();
+ string filePath = ModelPathUtils.ConvertModelPathToUserVisiblePath(mp);
+ //string filePath = fileSaveDialog.FileName;
+ var excelPackage = Models.ToWorksheet("围护桩信息")
+ .WithConfiguration(configuration => configuration
+ .WithColumnConfiguration(x => x.AutoFit()))
+ .WithColumn(instance => Models.IndexOf(instance) + 1, "序号")
+ .WithColumn(instance => instance.Code, "桩编码")
+ .WithColumn(instance => instance.FamilyName, "族名称")
+ .WithColumn(instance => instance.SymbolName, "类型名称")
+ .WithColumn(instance => instance.WestEast, "东/西坐标值(米)")
+ .WithColumn(instance => instance.NorthSouth, "南/北坐标值(米)")
+ .WithColumn(instance => instance.BottomElev, "底标高(米)")
+ .WithColumn(instance => instance.TopElev, "顶标高(米)")
+ .WithColumn(instance => instance.InstanceId, "元素Id")
+ //.WithTitle("围护桩信息")
+ .ToExcelPackage();
+ FileInfo info = new FileInfo(filePath);
+ excelPackage.SaveAs(info);
+ var result = TaskDialog.Show("导出完成", "是否打开导出的文件?", TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No);
+ if (result == TaskDialogResult.Yes)
+ {
+ System.Diagnostics.Process.Start(filePath);
+ }
+ }
+ }
+
+ private void BtnShow_Click(object sender, RoutedEventArgs e)
+ {
+ if (ElementDataGrid.SelectedItem is PileModel model)
+ {
+ uidoc.ShowElements(model.InstanceId);
+ uidoc.Selection.SetElementIds(new List() { model.InstanceId });
+ }
+ }
+
+ private void BtnUpdate_Click(object sender, RoutedEventArgs e)
+ {
+ ElementDataGrid.ItemsSource = null;
+ SetItemsSource(uidoc.Document);
+ ElementDataGrid.ItemsSource = Models;
+ }
+
+ private void ElementDataGrid_OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
+ {
+ if (ElementDataGrid.SelectedItem is PileModel model)
+ {
+ uidoc.ShowElements(model.InstanceId);
+ uidoc.Selection.SetElementIds(new List() { model.InstanceId });
+ }
+ }
+ }
+}
diff --git a/DimensionTools/Civil/QuickSpotDimCmd.cs b/DimensionTools/Civil/QuickSpotDimCmd.cs
new file mode 100644
index 0000000..c2f39ac
--- /dev/null
+++ b/DimensionTools/Civil/QuickSpotDimCmd.cs
@@ -0,0 +1,311 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Revit.UI.Selection;
+using Sai.RvWrapper.Shared;
+
+namespace Sai.RvKits.RvDrawing.QuickDim
+{
+ [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
+ [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
+ public class QuickSpotDimCmd : ExternalCommand
+ {
+ ///
+ /// 按路径排序的集合
+ ///
+ private readonly List orderedByPath = new();
+
+ public override Result Execute()
+ {
+
+ if (Document.ActiveView.ViewType != Autodesk.Revit.DB.ViewType.FloorPlan && Document.ActiveView.ViewType != Autodesk.Revit.DB.ViewType.CeilingPlan && Document.ActiveView.ViewType != Autodesk.Revit.DB.ViewType.EngineeringPlan)
+ {
+ Document.InvokeGroup(tg => { });
+ ErrorMessage = "请选择平面视图";
+ return Result.Failed;
+ }
+
+ QuickSpotDimViewModel viewModel = new QuickSpotDimViewModel(Document);
+ QuickSpotDimWin quickSpotDim = new QuickSpotDimWin(viewModel);
+ quickSpotDim.ShowDialog();
+
+ if (quickSpotDim.DialogResult != true) return Result.Cancelled;
+ var isManualSelected = viewModel.IsManual;
+ var id = viewModel.SpotDimensionTypeId;
+ var ruleIndex = viewModel.RuleIndex;
+ var prefix = viewModel.Prefix;
+ var startCode = Convert.ToInt16(viewModel.StartNum);
+ var relativeText = viewModel.RelativeText;
+
+ using (TransactionGroup tg = new TransactionGroup(Document, $"标注{relativeText}"))
+ {
+ try
+ {
+ //桩集合
+ //沿路径编号起点
+ FamilyInstance firstElem;
+ //排序后集合
+ List elemsOrdered;
+ tg.Start();
+ if (isManualSelected == true)
+ {
+ IList refers = UIDocument.Selection.PickObjects(ObjectType.Element, new PileFilter(relativeText), $"请选择需要编号标注的{relativeText}");
+ var enumerable = from refer in refers
+ select Document.GetElement(refer) as FamilyInstance;
+ elemsOrdered = enumerable.ToList();
+ }
+ else
+ {
+ var elems = new FilteredElementCollector(Document, Document.ActiveView.Id).OfClass(typeof(FamilyInstance)).Cast().Where(p => p.Name.Contains(relativeText) || (p.Symbol.FamilyName.Contains(relativeText) && p.Symbol.Family.FamilyPlacementType == FamilyPlacementType.OneLevelBased)).ToList();
+ switch (ruleIndex)
+ {
+ case 0:
+ {
+ //从左到右
+ elemsOrdered = elems.OrderBy(x => x.GetLocXYZ().X).ThenBy(y => y.GetLocXYZ().Y).ToList();
+ break;
+ }
+
+ case 1:
+ {
+ //从上到下
+ elemsOrdered = elems.OrderByDescending(y => y.GetLocXYZ().Y).ThenBy(x => x.GetLocXYZ().X).ToList();
+ break;
+ }
+
+ default:
+ {
+ var first = UIDocument.Selection.PickObject(ObjectType.Element, new PileFilter(relativeText), $"请选择路径起点{relativeText}");
+ firstElem = Document.GetElement(first) as FamilyInstance;
+ elems = elems.Where(x => x.Id.IntegerValue != firstElem?.Id.IntegerValue).ToList();
+
+ Order(elems, firstElem);
+ elemsOrdered = orderedByPath;
+ break;
+ }
+ }
+ }
+
+ MarkingPiles(Document, id, elemsOrdered, isManualSelected);
+ CodePile(UIDocument, elemsOrdered, prefix, startCode);
+ if (tg.GetStatus() == TransactionStatus.Started)
+ {
+ tg.Assimilate();
+ }
+ }
+ catch (Autodesk.Revit.Exceptions.OperationCanceledException)
+ {
+ if (tg.GetStatus() == TransactionStatus.Started)
+ {
+ tg.RollBack();
+ }
+ }
+ catch (Exception)
+ {
+ if (tg.GetStatus() == TransactionStatus.Started)
+ {
+ tg.RollBack();
+ }
+ }
+ }
+
+ return Result.Succeeded;
+ }
+
+ ///
+ /// 桩编号
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void CodePile(UIDocument uidoc, List orderElem, string prefix, int startCode)
+ {
+ Document Document = uidoc.Document;
+
+ Document.Invoke(ts =>
+ {
+ try
+ {
+ for (int i = 0; i < orderElem.Count; i++)
+ {
+ string code;
+ if (i + startCode <= 9)
+ {
+ if (startCode == 0)
+ {
+ code = $"00{i + 1 + startCode}";
+ }
+ else
+ {
+ code = $"00{i + startCode}";
+ }
+ }
+ else if (i + startCode <= 99)
+ {
+ if (startCode == 0)
+ {
+ code = $"0{i + 1 + startCode}";
+ }
+ else
+ {
+ code = $"0{i + startCode}";
+ }
+ }
+ else
+ {
+ if (startCode == 0)
+ {
+ code = $"{i + 1 + startCode}";
+ }
+ else
+ {
+ code = $"{i + startCode}";
+ }
+ }
+
+ if (prefix != string.Empty)
+ {
+ code = $"{prefix}-{code}";
+ }
+ //间隔四个标注一个
+
+ orderElem[i].get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS).Set(code);
+ }
+ }
+ catch (Autodesk.Revit.Exceptions.OperationCanceledException)
+ {
+ }
+ catch (Exception)
+ {
+ // ignored
+ }
+ });
+ }
+
+ private static void MarkingPiles(Document Document, ElementId annotationTypeId, List elems, bool? isManualSelected)
+ {
+ Document.Invoke(ts =>
+ {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < elems.Count; i++)
+ {
+ FamilyInstance fi = elems[i];
+ var pt = (fi.Location as LocationPoint)?.Point;
+ //var face = GeometryUtil.GetTopFaceByElement(fi);
+ Reference refer = Document.GetSpotDimensionReference(pt) ?? fi.GetReferences(FamilyInstanceReferenceType.CenterFrontBack).FirstOrDefault();
+
+ Line l = Line.CreateUnbound(pt, XYZ.BasisZ);
+ var t = fi.FindIntersects(l).OrderBy(p => p.Key.Z).LastOrDefault();
+ if (t.Key == null)
+ {
+ sb.AppendLine($"{fi.Name}:{fi.Id}");
+ continue;
+ }
+
+ if (isManualSelected == true)
+ {
+ SpotDimension spotDimension = Document.Create.NewSpotCoordinate(Document.ActiveView, refer, t.Key, t.Key + new XYZ(0.1, 1, 0) * 5, t.Key + XYZ.BasisX * 5, t.Key, true);
+ spotDimension.ChangeTypeId(annotationTypeId);
+ }
+ else
+ {
+ //坐标标注
+ if (i % 5 == 0)
+ {
+ SpotDimension spotDimension = Document.Create.NewSpotCoordinate(Document.ActiveView, refer, t.Key, t.Key + new XYZ(0.1, 1, 0) * 5, t.Key + XYZ.BasisX * 5, t.Key, true);
+ spotDimension.ChangeTypeId(annotationTypeId);
+ }
+ }
+
+
+ //pt = face.Origin / 2 + face.Origin.Z * XYZ.BasisZ;
+ //var centerPoint = face.Origin / 2 + face.Origin.Z * XYZ.BasisZ;
+ //var pt = fi.GetTransform().OfPoint(centerPoint);
+ //标高标注
+ //SpotDimension spotDimension1 = Document.Create.NewSpotElevation(Document.ActiveView, face.Reference, p, p + new XYZ(0.2, 1, 0) * 5, p + XYZ.BasisX * 2, p, true);
+ }
+
+ if (sb.Length > 0)
+ {
+ TaskDialog.Show("无法创建坐标标注", sb.ToString());
+ }
+ }, "坐标标注");
+ }
+
+ ///
+ ///
+ /// 合集,不包含第一个元素
+ /// 第一个元素
+ private void Order(List elements, FamilyInstance firstElem)
+ {
+ while (true)
+ {
+ orderedByPath.Add(firstElem);
+
+ if (elements.Count == 0)
+ {
+ return;
+ }
+
+ //var b = elements.Remove(firstElem);
+ double distance = 100.0;
+ double tempDistance = 0;
+ FamilyInstance closest = null;
+ foreach (var elem in elements) //最后一次循环为0个
+ {
+ if (elem.Location is LocationPoint lp)
+ {
+ var locPoint = firstElem.GetLocXYZ();
+ if (locPoint != null) tempDistance = (lp.Point - lp.Point.Z * XYZ.BasisZ).DistanceTo(locPoint - locPoint.Z * XYZ.BasisZ);
+ }
+
+ if (tempDistance < distance)
+ {
+ closest = elem;
+ distance = tempDistance;
+ }
+
+ if (elements.Count == 1)
+ {
+ closest = elem;
+ }
+ }
+
+ elements.Remove(closest);
+ firstElem = closest;
+ }
+ }
+ }
+
+ ///
+ /// 桩过滤器
+ ///
+ public class PileFilter : ISelectionFilter
+ {
+ public PileFilter(string relativeText)
+ {
+ this.relativeText = relativeText;
+ }
+
+ private readonly string relativeText;
+
+ public bool AllowElement(Element elem)
+ {
+ if (elem is FamilyInstance fi)
+ {
+ return fi.Symbol.FamilyName.Contains(relativeText);
+ }
+
+ return false;
+ }
+
+ public bool AllowReference(Reference reference, XYZ position)
+ {
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools/Civil/QuickSpotDimViewModel.cs b/DimensionTools/Civil/QuickSpotDimViewModel.cs
new file mode 100644
index 0000000..57994a5
--- /dev/null
+++ b/DimensionTools/Civil/QuickSpotDimViewModel.cs
@@ -0,0 +1,73 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Windows;
+
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+
+namespace Sai.RvKits.RvDrawing.QuickDim
+{
+ public partial class QuickSpotDimViewModel : ObservableValidator
+ {
+ public QuickSpotDimViewModel(Document doc)
+ {
+ this.doc = doc;
+ IsManual = true;
+ }
+
+ private readonly Document doc;
+
+ [ObservableProperty]
+ [Required]
+ private bool? isManual;
+
+ [ObservableProperty]
+ [Required(AllowEmptyStrings = true)]
+ private string prefix;
+
+ [ObservableProperty]
+ [Required]
+ [MinLength(1)]
+ //族的类型名称包含的字符
+ private string relativeText;
+
+ [ObservableProperty]
+ //全部编号的规则,左右、上下,路径等
+ private int ruleIndex;
+
+ [ObservableProperty]
+ [Required]
+ private ElementId spotDimensionTypeId;
+
+ [ObservableProperty]
+ [Required]
+ [Range(1, 10000)]
+ private string startNum;
+
+ public IEnumerable SpotDimensionTypes => new FilteredElementCollector(doc).OfClass(typeof(SpotDimensionType)).Cast().Where(t => t.StyleType == DimensionStyleType.SpotCoordinate);
+
+
+ [RelayCommand]
+ private void Confirm(object obj)
+ {
+ if (!(obj is Window window))
+ {
+ return;
+ }
+
+ var canParse = int.TryParse(StartNum, out _);
+ if (SpotDimensionTypeId == null || RuleIndex == -1 || string.IsNullOrWhiteSpace(Prefix) || !canParse || string.IsNullOrEmpty(RelativeText) || string.IsNullOrWhiteSpace(RelativeText))
+ {
+ TaskDialog.Show("错误", "参数有误");
+ }
+ else
+ {
+ window.DialogResult = true;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools/Civil/QuickSpotDimWin.xaml b/DimensionTools/Civil/QuickSpotDimWin.xaml
new file mode 100644
index 0000000..43f3af4
--- /dev/null
+++ b/DimensionTools/Civil/QuickSpotDimWin.xaml
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DimensionTools/Civil/QuickSpotDimWin.xaml.cs b/DimensionTools/Civil/QuickSpotDimWin.xaml.cs
new file mode 100644
index 0000000..24dc8e9
--- /dev/null
+++ b/DimensionTools/Civil/QuickSpotDimWin.xaml.cs
@@ -0,0 +1,16 @@
+using System.Windows;
+
+namespace Sai.RvKits.RvDrawing.QuickDim
+{
+ ///
+ /// QuickSpotDimWin.xaml 的交互逻辑
+ ///
+ public partial class QuickSpotDimWin : Window
+ {
+ public QuickSpotDimWin(QuickSpotDimViewModel viewModel)
+ {
+ DataContext = viewModel;
+ InitializeComponent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools/Command/DimCoordinate.cs b/DimensionTools/Command/DimCoordinate.cs
new file mode 100644
index 0000000..c3774fb
--- /dev/null
+++ b/DimensionTools/Command/DimCoordinate.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Revit.UI.Selection;
+
+using DimensionTools.Util;
+
+namespace DimensionTools.Command
+{
+ [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
+ [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
+ public class DimCoordinate : IExternalCommand
+ {
+ public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ UIApplication uiapp = commandData.Application;
+ UIDocument uidoc = uiapp.ActiveUIDocument;
+ Document doc = uidoc.Document;
+
+ using (Transaction trans = new Transaction(doc, "ע"))
+ {
+ try
+ {
+ while (true)
+ {
+
+ if (doc.ActiveView is View3D)
+ {
+ trans.Start();
+ var reference = uidoc.Selection.PickObject(ObjectType.PointOnElement, new ReferenceFilter(doc), "ѡעĵ");
+ var point = reference.GlobalPoint;
+ var spot = doc.Create.NewSpotCoordinate(
+ doc.ActiveView,
+ reference,
+ point,
+ point + new XYZ(0.2, 1, 0) * 5,
+ point + XYZ.BasisX * 10, point, true);
+ trans.Commit();
+ }
+ else
+ {
+ var reference = uidoc.Selection.PickObject(ObjectType.PointOnElement, new ReferenceFilter(doc), "ѡעԪصIJգߡ桢ƽȣ");
+
+ ObjectSnapTypes objectSnapTypes = ObjectSnapTypes.Intersections
+ | ObjectSnapTypes.Endpoints
+ | ObjectSnapTypes.Centers
+ | ObjectSnapTypes.Midpoints
+ | ObjectSnapTypes.Points
+ | ObjectSnapTypes.Nearest
+ | ObjectSnapTypes.Perpendicular
+ | ObjectSnapTypes.Quadrants
+ | ObjectSnapTypes.Tangents;
+
+ pickPoint: XYZ point = uidoc.Selection.PickPoint(objectSnapTypes, "ѡѡϵĵ(δעȷλãͼΧ)");
+ point += (reference.GlobalPoint.Z - point.Z) * XYZ.BasisZ;
+ try
+ {
+ trans.Start();
+ doc.Create.NewSpotCoordinate(
+ doc.ActiveView,
+ reference,
+ point,
+ point + new XYZ(0.2, 1, 0) * 5,
+ point + XYZ.BasisX * 10, point, true);
+ trans.Commit();
+ }
+ catch (Exception ex)
+ {
+ var msg = ex.Message.Contains("Error") ? "ע" : ex.Message;
+ if (msg.Contains("עûλ"))
+ {
+ TaskDialog.Show("ʾ", "ѡοϵĵ");
+ }
+
+ if (trans.GetStatus() == TransactionStatus.Started)
+ {
+ trans.RollBack();
+ }
+ goto pickPoint;
+ }
+ }
+
+
+
+ }
+ }
+ catch (Autodesk.Revit.Exceptions.OperationCanceledException)
+ {
+ return Result.Succeeded;
+ }
+ }
+ }
+
+ private void CreateSpotCoordinate(XYZ pt, Element ele)
+ {
+ var doc = ele.Document;
+ Line l = Line.CreateUnbound(pt, XYZ.BasisZ);
+ Line l1 = Line.CreateUnbound(pt, -XYZ.BasisZ);
+ var t = ele.FindIntersects(l).OrderBy(p => p.Key.Z).LastOrDefault();
+ var t1 = ele.FindIntersects(l1).OrderBy(p => p.Key.Z).LastOrDefault();
+ if (t.Key == null && t1.Key == null)
+ {
+ return;
+ }
+ if (t.Key != null)
+ {
+ doc.Create.NewSpotCoordinate(doc.ActiveView, t.Value.Reference, t.Key, t.Key + new XYZ(0.1, 1, 0) * 5, t.Key + XYZ.BasisX * 5, t.Key, true);
+ }
+ else if (t1.Key != null)
+ {
+ doc.Create.NewSpotCoordinate(doc.ActiveView, t1.Value.Reference, t1.Key, t1.Key + new XYZ(0.1, 1, 0) * 5, t1.Key + XYZ.BasisX * 5, t1.Key, true);
+ }
+ }
+ }
+ public class ReferenceFilter : ISelectionFilter
+ {
+ private readonly Document _document;
+
+ public ReferenceFilter(Document document)
+ {
+ _document = document;
+ }
+ public bool AllowElement(Element elem)
+ {
+ return !(elem is Dimension || elem.Category == Category.GetCategory(_document, BuiltInCategory.OST_Views) || elem is IndependentTag);
+ }
+
+ public bool AllowReference(Reference reference, XYZ position)
+ {
+ var elem = _document.GetElement(reference);
+
+ var referenceCondition =
+ reference.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_NONE
+ || reference.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_SURFACE
+ || reference.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_LINEAR;
+
+ var geo = elem.GetGeometryObjectFromReference(reference);
+ //if (_point != null)
+ //{
+ // var pointCondition = (position - _point).Normalize().CrossProduct(XYZ.BasisZ).IsZeroLength();
+ // //var pointCondition = ((position - _point).X == 0 | (position - _point).Y == 0) && (position - _point).Z != 0;
+ // //var pointCondition =true;
+ // return referenceCondition && pointCondition;
+ //}
+
+ return referenceCondition && geo != null && !(geo is Point);
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools/Command/DimFacePoint.cs b/DimensionTools/Command/DimFacePoint.cs
new file mode 100644
index 0000000..f49d2e3
--- /dev/null
+++ b/DimensionTools/Command/DimFacePoint.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Collections.Generic;
+
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Revit.UI.Selection;
+
+using DimensionTools.Util;
+
+namespace DimensionTools.Command
+{
+ [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
+ [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
+ public class DimFacePoint : IExternalCommand
+ {
+ private DimUpdater updater;
+
+ public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ UIApplication uiapp = commandData.Application;
+ UIDocument uidoc = uiapp.ActiveUIDocument;
+ Autodesk.Revit.ApplicationServices.Application app = uiapp.Application;
+ Document doc = uidoc.Document;
+ DocumentSet docset = uiapp.Application.Documents;
+
+ using (Transaction trans = new Transaction(doc, "点面标注"))
+ {
+ try
+ {
+ var face = uidoc.Selection.PickObject(ObjectType.Face, new VerticalFaceFilter(doc), "请拾取面");
+
+ XYZ sp1 = null;
+ pickPoint: var sp2 = uidoc.Selection.PickPoint("请拾取点");
+ Line line = null;
+ var instance = doc.GetElement(face);
+ var pf = instance.GetGeometryObjectFromReference(face) as PlanarFace;
+ trans.Start();
+ if (!(pf.XVector.X == 0 && pf.XVector.Y == 0))
+ {
+ var direction = pf.XVector - pf.XVector.Z * XYZ.BasisZ;
+ Line l1 = Line.CreateUnbound(pf.Origin, direction);
+ var result = l1.Project(sp2);
+ if (result != null)
+ {
+ sp1 = result.XYZPoint;
+ }
+ }
+ else
+ {
+ var direction = pf.YVector - pf.YVector.Z * XYZ.BasisZ;
+ Line l2 = Line.CreateUnbound(pf.Origin, pf.YVector);
+ var result1 = l2.Project(sp2);
+ if (result1 != null)
+ {
+ sp1 = result1.XYZPoint;
+ }
+ }
+
+ var point1 = sp1 - sp1.Z * XYZ.BasisZ;
+ var point2 = sp2 - sp2.Z * XYZ.BasisZ;
+ if (point1.DistanceTo(point2) < 0.8 / 304.8)
+ {
+ TaskDialog.Show("提示", "标注距离过小");
+ trans.RollBack();
+ goto pickPoint;
+ }
+ line = Line.CreateBound(point1, point2);
+
+
+ DetailLine detailLine = doc.Create.NewDetailCurve(doc.ActiveView, line) as DetailLine;
+ //var refer = detailLine.GeometryCurve.GetEndPointReference(0);
+ var refer1 = detailLine.GeometryCurve.GetEndPointReference(1);
+ ReferenceArray array = new ReferenceArray();
+ array.Append(face);
+ array.Append(refer1);
+ var dim = doc.Create.NewDimension(doc.ActiveView, line, array);
+ //doc.ActiveView.HideElements(new List() { detailLine.Id });
+ trans.Commit();
+
+ updater = new DimUpdater(uiapp.ActiveAddInId);
+ if (UpdaterRegistry.IsUpdaterRegistered(updater.GetUpdaterId()))
+ {
+ UpdaterRegistry.UnregisterUpdater(updater.GetUpdaterId());
+ }
+
+ UpdaterRegistry.RegisterUpdater(updater);
+ updater.CheckDimId = dim.Id;
+ updater.DetailLineId = detailLine.Id;
+ ICollection ids = new List
+ {
+ dim.Id
+ };
+ UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), doc, ids, Element.GetChangeTypeElementDeletion());
+ //UpdaterRegistry.RemoveDocumentTriggers(updater.GetUpdaterId(), doc);
+ doc.DocumentClosing += Doc_DocumentClosing;
+ }
+ catch (Autodesk.Revit.Exceptions.OperationCanceledException ex)
+ {
+ if (trans.GetStatus() == TransactionStatus.Started)
+ {
+ trans.RollBack();
+ }
+
+ return Result.Cancelled;
+ }
+ catch (Exception ex)
+ {
+ message = ex.Message;
+ if (trans.GetStatus() == TransactionStatus.Started)
+ {
+ trans.RollBack();
+ }
+
+ return Result.Failed;
+ }
+ }
+
+ return Result.Succeeded;
+ }
+
+ ///
+ /// 关闭文档的时候,移除动态模型更新
+ ///
+ ///
+ ///
+ private void Doc_DocumentClosing(object sender, Autodesk.Revit.DB.Events.DocumentClosingEventArgs e)
+ {
+ if (updater != null)
+ {
+ UpdaterRegistry.UnregisterUpdater(updater.GetUpdaterId());
+ updater = null;
+ }
+ }
+
+ ///
+ /// 垂直面过滤器
+ ///
+ public class VerticalFaceFilter : ISelectionFilter
+ {
+ private readonly Document doc;
+
+ public VerticalFaceFilter(Document doc)
+ {
+ this.doc = doc;
+ }
+
+ public bool AllowElement(Element elem)
+ {
+ return true;
+ }
+
+ public bool AllowReference(Reference reference, XYZ position)
+ {
+ var pf = doc.GetElement(reference).GetGeometryObjectFromReference(reference) as PlanarFace;
+ if (pf != null )
+ {
+ return Math.Abs(pf.FaceNormal.DotProduct(XYZ.BasisZ)) < 0.00001;
+ }
+ return false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools/Command/DimTwoPoint.cs b/DimensionTools/Command/DimTwoPoint.cs
new file mode 100644
index 0000000..7285727
--- /dev/null
+++ b/DimensionTools/Command/DimTwoPoint.cs
@@ -0,0 +1,134 @@
+using System;
+using System.Collections.Generic;
+
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Revit.UI.Selection;
+
+using DimensionTools.Util;
+
+namespace DimensionTools.Command
+{
+ [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
+ [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
+ public class DimTwoPoint : IExternalCommand
+ {
+ private DimUpdater updater;
+
+ public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ UIApplication uiapp = commandData.Application;
+ UIDocument uidoc = uiapp.ActiveUIDocument;
+ Autodesk.Revit.ApplicationServices.Application app = uiapp.Application;
+ Document doc = uidoc.Document;
+ DocumentSet docset = uiapp.Application.Documents;
+
+
+ using (Transaction trans = new Transaction(doc, "两点标注"))
+ {
+ try
+ {
+ pickPoint: var sp1 = uidoc.Selection.PickPoint("请拾取点1");
+ var sp2 = uidoc.Selection.PickPoint("请拾取点2");
+ Line line = null;
+ if (sp1.DistanceTo(sp2) < 0.8 / 304.8)
+ {
+ TaskDialog.Show("警告", "选择点距离过近");
+ goto pickPoint;
+ }
+ trans.Start();
+
+ line = Line.CreateBound(sp1, sp2);
+ DetailLine detailLine = doc.Create.NewDetailCurve(doc.ActiveView, line) as DetailLine;
+ var refer = detailLine.GeometryCurve.GetEndPointReference(0);
+ var refer1 = detailLine.GeometryCurve.GetEndPointReference(1);
+ ReferenceArray array = new ReferenceArray();
+ array.Append(refer);
+ array.Append(refer1);
+ var dim = doc.Create.NewDimension(doc.ActiveView, line, array);
+ //doc.ActiveView.HideElements(new List() { detailLine.Id });
+ trans.Commit();
+
+ updater = new DimUpdater(uiapp.ActiveAddInId);
+ if (UpdaterRegistry.IsUpdaterRegistered(updater.GetUpdaterId()))
+ {
+ UpdaterRegistry.UnregisterUpdater(updater.GetUpdaterId());
+ }
+
+ UpdaterRegistry.RegisterUpdater(updater);
+ updater.CheckDimId = dim.Id;
+ updater.DetailLineId = detailLine.Id;
+ ICollection ids = new List();
+ ids.Add(dim.Id);
+ UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), doc, ids, Element.GetChangeTypeElementDeletion());
+ //UpdaterRegistry.RemoveDocumentTriggers(updater.GetUpdaterId(), doc);
+ doc.DocumentClosing += Doc_DocumentClosing;
+ }
+ catch (Autodesk.Revit.Exceptions.OperationCanceledException ex)
+ {
+ if (trans.GetStatus() == TransactionStatus.Started)
+ {
+ trans.RollBack();
+ }
+
+ return Result.Cancelled;
+ }
+ catch (Exception ex)
+ {
+ message = ex.Message;
+ if (trans.GetStatus() == TransactionStatus.Started)
+ {
+ trans.RollBack();
+ }
+
+ return Result.Failed;
+ }
+ }
+
+ return Result.Succeeded;
+ }
+
+ ///
+ /// 关闭文档的时候,移除动态模型更新
+ ///
+ ///
+ ///
+ private void Doc_DocumentClosing(object sender, Autodesk.Revit.DB.Events.DocumentClosingEventArgs e)
+ {
+ if (updater != null)
+ {
+ UpdaterRegistry.UnregisterUpdater(updater.GetUpdaterId());
+ updater = null;
+ }
+ }
+
+ ///
+ /// 垂直面过滤器
+ ///
+ public class VerticalFaceFilter : ISelectionFilter
+ {
+ private readonly Document doc;
+
+ public VerticalFaceFilter(Document doc)
+ {
+ this.doc = doc;
+ }
+
+ public bool AllowElement(Element elem)
+ {
+ return true;
+ }
+
+ public bool AllowReference(Reference reference, XYZ position)
+ {
+ var pf = doc.GetElement(reference).GetGeometryObjectFromReference(reference) as PlanarFace;
+ if (pf != null)
+ {
+ return Math.Abs(pf.FaceNormal.DotProduct(XYZ.BasisZ)) < 0.00001;
+ }
+
+ return false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools/DimensionTools.addin b/DimensionTools/DimensionTools.addin
new file mode 100644
index 0000000..717fb63
--- /dev/null
+++ b/DimensionTools/DimensionTools.addin
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/DimensionTools/DimensionTools.csproj b/DimensionTools/DimensionTools.csproj
new file mode 100644
index 0000000..ff53bdc
--- /dev/null
+++ b/DimensionTools/DimensionTools.csproj
@@ -0,0 +1,238 @@
+
+
+
+ Debug;Debug One;Release
+
+
+
+ net462;net47;net472
+ win
+
+
+
+ 2018
+ true
+
+
+
+
+
+
+ 2020
+ true
+
+
+ 2021
+ true
+
+
+
+
+ net472
+
+
+
+
+ x64
+ x64
+ None
+
+
+ {351668CC-8477-4fbf-BFE3-5F1006E4DB1F}
+
+
+ false
+ false
+
+
+ REVIT$(RevitVersion);WINFORMS
+ $(DefineConstants)
+
+
+ false
+
+
+ false
+ ..\bin\$(Configuration)\$(RevitVersion)
+
+
+
+
+ $(DefineConstants);USE_FORGETYPEID
+ $(DefineConstants)
+
+
+
+ $(DefineConstants);DEBUG
+ full
+ ..\bin\Debug\$(RevitVersion)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+ Never
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+ Never
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+
+
+
+
+
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+
+
+
+ DimensionTools
+ DimensionTools
+
+
+
+
+
+
+
+ en
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DimensionTools/PackageContents.xml b/DimensionTools/PackageContents.xml
new file mode 100644
index 0000000..beee48c
--- /dev/null
+++ b/DimensionTools/PackageContents.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DimensionTools/Properties/Resources.Designer.cs b/DimensionTools/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..e58b030
--- /dev/null
+++ b/DimensionTools/Properties/Resources.Designer.cs
@@ -0,0 +1,113 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace DimensionTools.Properties {
+ using System;
+
+
+ ///
+ /// 一个强类型的资源类,用于查找本地化的字符串等。
+ ///
+ // 此类是由 StronglyTypedResourceBuilder
+ // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+ // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+ // (以 /str 作为命令选项),或重新生成 VS 项目。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// 返回此类使用的缓存的 ResourceManager 实例。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DimensionTools.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// 重写当前线程的 CurrentUICulture 属性,对
+ /// 使用此强类型资源类的所有资源查找执行重写。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// 查找 System.Drawing.Bitmap 类型的本地化资源。
+ ///
+ internal static System.Drawing.Bitmap Coordinates {
+ get {
+ object obj = ResourceManager.GetObject("Coordinates", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// 查找 System.Drawing.Bitmap 类型的本地化资源。
+ ///
+ internal static System.Drawing.Bitmap Distance {
+ get {
+ object obj = ResourceManager.GetObject("Distance", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// 查找 System.Drawing.Bitmap 类型的本地化资源。
+ ///
+ internal static System.Drawing.Bitmap FacePoint {
+ get {
+ object obj = ResourceManager.GetObject("FacePoint", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// 查找 System.Drawing.Bitmap 类型的本地化资源。
+ ///
+ internal static System.Drawing.Bitmap Piles {
+ get {
+ object obj = ResourceManager.GetObject("Piles", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// 查找 System.Drawing.Bitmap 类型的本地化资源。
+ ///
+ internal static System.Drawing.Bitmap Xlsx {
+ get {
+ object obj = ResourceManager.GetObject("Xlsx", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+ }
+}
diff --git a/DimensionTools/Properties/Resources.resx b/DimensionTools/Properties/Resources.resx
new file mode 100644
index 0000000..1bc3f83
--- /dev/null
+++ b/DimensionTools/Properties/Resources.resx
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ ..\Resources\Coordinates.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\Distance.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\FacePoint.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\Piles.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\resources\xlsx.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
\ No newline at end of file
diff --git a/DimensionTools/Properties/launchSettings.json b/DimensionTools/Properties/launchSettings.json
new file mode 100644
index 0000000..dc64186
--- /dev/null
+++ b/DimensionTools/Properties/launchSettings.json
@@ -0,0 +1,58 @@
+{
+ "profiles": {
+ "Revit 2022": {
+ "commandName": "Executable",
+ "executablePath": "%ProgramW6432%\\Autodesk\\Revit 2022\\Revit.exe",
+ "commandLineArgs": "",
+ "use64Bit": true
+ },
+ "Revit 2021": {
+ "commandName": "Executable",
+ "executablePath": "%ProgramW6432%\\Autodesk\\Revit 2021\\Revit.exe",
+ "commandLineArgs": "",
+ "use64Bit": true
+ },
+ "Revit 2020": {
+ "commandName": "Executable",
+ "executablePath": "%ProgramW6432%\\Autodesk\\Revit 2020\\Revit.exe",
+ "commandLineArgs": "",
+ "use64Bit": true
+ },
+ "Revit 2019": {
+ "commandName": "Executable",
+ "executablePath": "%ProgramW6432%\\Autodesk\\Revit 2019\\Revit.exe",
+ "commandLineArgs": "",
+ "use64Bit": true
+ },
+ "Revit 2018": {
+ "commandName": "Executable",
+ "executablePath": "%ProgramW6432%\\Autodesk\\Revit 2018\\Revit.exe",
+ "commandLineArgs": "",
+ "use64Bit": true
+ },
+ "Revit 2017": {
+ "commandName": "Executable",
+ "executablePath": "%ProgramW6432%\\Autodesk\\Revit 2017\\Revit.exe",
+ "commandLineArgs": "",
+ "use64Bit": true
+ },
+ "Revit 2016": {
+ "commandName": "Executable",
+ "executablePath": "%ProgramW6432%\\Autodesk\\Revit 2016\\Revit.exe",
+ "commandLineArgs": "",
+ "use64Bit": true
+ },
+ "Revit 2015": {
+ "commandName": "Executable",
+ "executablePath": "%ProgramW6432%\\Autodesk\\Revit 2015\\Revit.exe",
+ "commandLineArgs": "",
+ "use64Bit": true
+ },
+ "Revit 2014": {
+ "commandName": "Executable",
+ "executablePath": "%ProgramW6432%\\Autodesk\\Revit 2014\\Revit.exe",
+ "commandLineArgs": "",
+ "use64Bit": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools/Resources/Coordinates.png b/DimensionTools/Resources/Coordinates.png
new file mode 100644
index 0000000..19a1db2
Binary files /dev/null and b/DimensionTools/Resources/Coordinates.png differ
diff --git a/DimensionTools/Resources/Distance.png b/DimensionTools/Resources/Distance.png
new file mode 100644
index 0000000..6d20a27
Binary files /dev/null and b/DimensionTools/Resources/Distance.png differ
diff --git a/DimensionTools/Resources/FacePoint.png b/DimensionTools/Resources/FacePoint.png
new file mode 100644
index 0000000..82003b8
Binary files /dev/null and b/DimensionTools/Resources/FacePoint.png differ
diff --git a/DimensionTools/Resources/Piles.png b/DimensionTools/Resources/Piles.png
new file mode 100644
index 0000000..1c15d7c
Binary files /dev/null and b/DimensionTools/Resources/Piles.png differ
diff --git a/DimensionTools/Resources/Xlsx.png b/DimensionTools/Resources/Xlsx.png
new file mode 100644
index 0000000..7ec5830
Binary files /dev/null and b/DimensionTools/Resources/Xlsx.png differ
diff --git a/DimensionTools/UiRibbon.cs b/DimensionTools/UiRibbon.cs
new file mode 100644
index 0000000..db888f5
--- /dev/null
+++ b/DimensionTools/UiRibbon.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Interop;
+using System.Windows.Media.Imaging;
+
+using System.Windows;
+
+using Autodesk.Revit.UI;
+using System.Runtime.InteropServices;
+using DimensionTools.Command;
+using Autodesk.Revit.DB;
+using System.Reflection;
+using DimensionTools.Civil;
+
+namespace DimensionTools
+{
+ public class UiRibbon : IExternalApplication
+ {
+ private static readonly string AddInPath = typeof(UiRibbon).Assembly.Location;
+ public Result OnShutdown(UIControlledApplication application)
+ {
+ return Result.Succeeded;
+ }
+
+ public Result OnStartup(UIControlledApplication application)
+ {
+
+ try
+ {
+ var panel = application.CreateRibbonPanel("标注工具");
+ PushButtonData pbd = new PushButtonData("坐标标注", "坐标标注", AddInPath, typeof(DimCoordinate).FullName)
+ {
+ LargeImage = ConvertToBitmapSource(Properties.Resources.Coordinates),
+ Image = ConvertToBitmapSource(Properties.Resources.Coordinates),
+ ToolTip = "选择要标注坐标的元素及元素上的点进行坐标定位标注。"
+ };
+ PushButtonData pbd1 = new PushButtonData("点面标注", "点面标注", AddInPath, typeof(DimFacePoint).FullName)
+ {
+ LargeImage = ConvertToBitmapSource(Properties.Resources.FacePoint),
+ Image = ConvertToBitmapSource(Properties.Resources.FacePoint),
+ AvailabilityClassName = typeof(EnableCmdInViewPlan).FullName,
+ ToolTip = "选择要标注元素的平面和任意点进行标注。"
+ };
+ PushButtonData pbd2 = new PushButtonData("两点标注", "两点标注", AddInPath, typeof(DimTwoPoint).FullName)
+ {
+ LargeImage = ConvertToBitmapSource(Properties.Resources.Distance),
+ Image = ConvertToBitmapSource(Properties.Resources.Distance),
+ AvailabilityClassName = typeof(EnableCmdInViewPlan).FullName,
+ ToolTip = "点选选要标注的两个点,进行两点距离标注。"
+ };
+ PushButtonData pbd3 = new PushButtonData("桩标注", "桩标注", AddInPath, typeof(PilesAnnotationCmd).FullName)
+ {
+ LargeImage = ConvertToBitmapSource(Properties.Resources.Piles),
+ Image = ConvertToBitmapSource(Properties.Resources.Piles),
+ AvailabilityClassName = typeof(EnableCmdInViewPlan).FullName,
+ ToolTip = "对围护桩进行批量标注和编号。"
+ };
+ PushButtonData pbd4 = new PushButtonData("桩信息导出", "桩信息导出", AddInPath, typeof(ExportPilesInfo).FullName)
+ {
+ LargeImage = ConvertToBitmapSource(Properties.Resources.Xlsx),
+ Image = ConvertToBitmapSource(Properties.Resources.Xlsx),
+ ToolTip = "围护桩信息导出为xlsx文件。"
+ };
+ panel.AddItem(pbd);
+ panel.AddItem(pbd1);
+ panel.AddItem(pbd2);
+ panel.AddItem(pbd3);
+ panel.AddItem(pbd4);
+ }
+ catch (Exception ex)
+ {
+ TaskDialog.Show("错误", "标注工具加载失败");
+ return Result.Failed;
+ }
+ return Result.Succeeded;
+ }
+ public static BitmapSource ConvertToBitmapSource(Bitmap bitmap)
+ {
+ IntPtr hBitmap = bitmap.GetHbitmap();
+
+ try
+ {
+ var bs = Imaging.CreateBitmapSourceFromHBitmap(
+ hBitmap,
+ //Properties.Resources.logoITC_Revit.GetHbitmap(),
+ IntPtr.Zero,
+ Int32Rect.Empty,
+ BitmapSizeOptions.FromEmptyOptions());
+
+ return bs;
+ }
+ finally
+ {
+ DeleteObject(hBitmap);
+ }
+ }
+ [DllImport("gdi32.dll")]
+ private static extern bool DeleteObject(IntPtr hObject);
+ }
+ internal class EnableCmdInViewPlan : IExternalCommandAvailability
+ {
+ public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories)
+ {
+ if (null == applicationData.ActiveUIDocument) return false;
+ Autodesk.Revit.DB.View view = applicationData.ActiveUIDocument.Document.ActiveView;
+ return (view.ViewType == ViewType.FloorPlan || view.ViewType == ViewType.EngineeringPlan || view.ViewType == ViewType.CeilingPlan) && !applicationData.ActiveUIDocument.Document.IsFamilyDocument;
+ }
+ }
+}
diff --git a/DimensionTools/Util/Checked2VisibilityConverter.cs b/DimensionTools/Util/Checked2VisibilityConverter.cs
new file mode 100644
index 0000000..1dae3f3
--- /dev/null
+++ b/DimensionTools/Util/Checked2VisibilityConverter.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace DimensionTools.Util
+{
+ public class Checked2VisibilityConverter : IValueConverter
+ {
+ ///
+ /// 绑定的后台属性值,经过此转换器转换成前端的值
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var isChecked = value as bool?;
+ if (isChecked == null || isChecked == false)
+ {
+ return Visibility.Collapsed;
+ }
+
+ return Visibility.Visible;
+ }
+
+ ///
+ /// 前端的值,经过此转换器转为后台属性值
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools/Util/DimUpdater.cs b/DimensionTools/Util/DimUpdater.cs
new file mode 100644
index 0000000..bb82a61
--- /dev/null
+++ b/DimensionTools/Util/DimUpdater.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using Autodesk.Revit.DB;
+
+namespace DimensionTools.Util
+{
+ public class DimUpdater : IUpdater
+ {
+ private AddInId addinID { get; }
+ public ElementId CheckDimId { get; set; }
+ public ElementId DetailLineId { get; set; }
+ private UpdaterId updaterId => new UpdaterId(addinID, new Guid("2DC963D6-2440-4D15-8266-AE0A024BD9A5"));
+
+ public DimUpdater(AddInId addinID)
+ {
+ this.addinID = addinID;
+ }
+
+ public void Execute(UpdaterData data)
+ {
+ Document rvtDoc = data.GetDocument();
+ ICollection idsDeleted = data.GetDeletedElementIds();
+ //ICollection idsModified = data.GetModifiedElementIds();
+ foreach (ElementId id in idsDeleted)
+ {
+ if (CheckDimId.IntegerValue == id.IntegerValue)
+ {
+ try
+ {
+ rvtDoc.Delete(DetailLineId);
+ }
+ catch (Exception)
+ {
+ break;
+ }
+ }
+ }
+ //执行更新的操作
+ //TaskDialog.Show("提示", "触发更新");
+ }
+
+ public string GetAdditionalInformation()
+ {
+ return "更新的附加说明";
+ }
+
+ public ChangePriority GetChangePriority()
+ {
+ return ChangePriority.Views;
+ }
+
+ public UpdaterId GetUpdaterId()
+ {
+ return updaterId;
+ }
+
+ public string GetUpdaterName()
+ {
+ return "调整尺寸标注";
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools/Util/GeometryUtil.cs b/DimensionTools/Util/GeometryUtil.cs
new file mode 100644
index 0000000..0b7aaf7
--- /dev/null
+++ b/DimensionTools/Util/GeometryUtil.cs
@@ -0,0 +1,541 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+
+namespace DimensionTools.Util
+{
+ internal static class GeometryUtil
+ {
+ public static Dictionary FindIntersects(this Element elementToDim, Line line)
+ {
+ var faces = GetElementFaces(elementToDim);
+ var intersects = new Dictionary();
+
+ foreach (var f in faces)
+ {
+ //face = FindCeilingAndFloorFace(openingElement as Wall);
+ if (f is PlanarFace pf && pf.FaceNormal.IsAlmostEqualTo(XYZ.BasisZ, 0.0001))
+ {
+ //var xyz = GetIN(line.Origin, line.Direction, pf.Origin, pf.FaceNormal);
+ //if (xyz != null)
+ //{
+
+ //}
+ var intersect = pf.Intersect(line, out IntersectionResultArray result);
+ if (intersect == SetComparisonResult.Overlap)
+ {
+ var x = result.get_Item(0);
+ XYZ intersection = x.XYZPoint;
+ intersects.Add(intersection, pf);
+ }
+ }
+ }
+
+ return intersects;
+ }
+ ///
+ ///
+ ///
+ /// 直线上的一点
+ /// 直线方向
+ /// 平面上一点
+ /// 平面上方向
+ ///
+ private static XYZ GetIN(XYZ p, XYZ d, XYZ p1, XYZ d1)
+ {
+
+ if (d.X * d1.X + d.Y * d1.Y + d.Z * d1.Z == 0)
+ {
+ //方向向量与平面平行,没有交点
+ return null;
+ }
+ var m = ((p1.X - p.X) * d1.X +
+ (p1.Y - p.Y) * d1.Y +
+ (p1.Z - p.Z) * d1.Z) /
+ (d1.X * d.X + d1.Y * d.Y + d1.Z * d.Z);
+ return new XYZ(p.X + d.X * m, p.Y + d.Y * m, p.Z + d.Z * m);
+ }
+ ///
+ /// 射线法获取族
+ ///
+ ///
+ ///
+ ///
+ [Obsolete]
+ public static Element GetElement(Document doc, XYZ p)
+ {
+ Reference reference = null;
+ if (doc.ActiveView is ViewPlan view)
+ {
+ //可能存在贯穿标高的构件,需修改射线贯穿距离
+
+ #region 视图范围
+
+ var range = view.GetViewRange();
+ var bottomLevel = doc.GetElement(range.GetLevelId(PlanViewPlane.BottomClipPlane)) as Level;
+ var b = range.GetOffset(PlanViewPlane.BottomClipPlane);
+ var topLevel = doc.GetElement(range.GetLevelId(PlanViewPlane.TopClipPlane)) as Level;
+ var t = range.GetOffset(PlanViewPlane.TopClipPlane);
+ var bot = bottomLevel.Elevation + b;
+ var tt = topLevel.Elevation + t;
+ var p1 = new XYZ(p.X, p.Y, bot);
+ var p2 = new XYZ(p.X, p.Y, tt);
+
+ #endregion 视图范围
+
+ //var p1 = new XYZ(p.X, p.Y, -100000 / 304.8);
+ //var p2 = new XYZ(p.X, p.Y, 100000 / 304.8);
+ View3D v3d = new FilteredElementCollector(doc).OfClass(typeof(View3D)).Cast().FirstOrDefault(v => v.IsTemplate == false);
+ //Line l = Line.CreateUnbound(p1, p2);
+ //Plane plane = Plane.CreateByOriginAndBasis(p1, XYZ.BasisX, XYZ.BasisZ);
+ //SketchPlane sketch = SketchPlane.Create(doc, plane);
+ //ModelCurve curve = doc.Create.NewModelCurve(l, sketch);
+ //Id = curve.Id;
+ //Face face = null;
+ //射线法找到相交的元素
+ ReferenceIntersector intersector = new ReferenceIntersector(v3d);
+ var refer = intersector.FindNearest(p1, XYZ.BasisZ)?.GetReference();
+ var refer1 = intersector.FindNearest(p2, -XYZ.BasisZ)?.GetReference();
+
+ if (refer != null && refer1 != null)
+ {
+ if (refer.GlobalPoint.Z > refer1.GlobalPoint.Z)
+ {
+ reference = refer;
+ }
+ else
+ {
+ reference = refer1;
+ }
+ }
+ else if (refer != null)
+ {
+ reference = refer;
+ }
+ else
+ {
+ reference = refer1;
+ }
+
+ if (reference == null)
+ {
+ TaskDialog.Show("提示", "所选点的得不到参考,可能参考不在当前视图可见范围内或请选择族实例上的点,无法创建");
+ }
+ }
+
+ return doc.GetElement(reference);
+ //Line l2 = Line.CreateUnbound(p, XYZ.BasisZ);
+ }
+
+ public static List GetElementFaces(this Element elem)
+ {
+ List faces = new List();
+ GeometryElement geometry = elem.get_Geometry(SetOptions());
+ if (geometry == null)
+ {
+ //TaskDialog.Show("提示","元素不包含几何实体,无法标注");
+ return faces;
+ }
+ foreach (GeometryObject geomObj in geometry)
+ {
+ GeometryInstance geomInstance = geomObj as GeometryInstance;
+
+ if (geomInstance != null)
+ {
+ bool usesSymbolGeometry = elem is FamilyInstance && !(elem as FamilyInstance).HasModifiedGeometry();
+ GeometryElement instanceGeometry = usesSymbolGeometry
+ ? geomInstance.GetSymbolGeometry()
+ : geomInstance.GetInstanceGeometry();
+
+ foreach (GeometryObject instObj in instanceGeometry)
+ {
+ Solid instSolid = instObj as Solid;
+ if (instSolid == null || instSolid.Faces.Size == 0 || instSolid.Edges.Size == 0)
+ {
+ continue;
+ }
+
+ foreach (Face face in instSolid.Faces)
+ {
+ faces.Add(face);
+ }
+ }
+ }
+
+ Solid solid = geomObj as Solid;
+ if (solid != null)
+ {
+ if (solid.Faces.Size == 0 || solid.Edges.Size == 0)
+ {
+ continue;
+ }
+
+ foreach (Face face in solid.Faces)
+ {
+ faces.Add(face);
+ }
+ }
+ }
+
+ return faces;
+ }
+
+ public static List GetAllReferences(Element element)
+ {
+ //实例族的GeometryElement集合中具有Solid等几何对象的原因是由于族实例对象碰撞后,软件自动会使用geometryInstance用来指定其位置(即使碰撞后,移开),用Solid作为其几何体
+ //GeometryInstance Transform是族实例在全局坐标系的变换
+ List faces = new List();
+ List edges = new List();
+ var references = new List();
+ Options geomOptions = new Options
+ {
+ ComputeReferences = true,
+
+ DetailLevel = ViewDetailLevel.Medium,
+
+ IncludeNonVisibleObjects = true
+ };
+ var geoElem = element.get_Geometry(geomOptions);
+ foreach (GeometryObject obj in geoElem)
+ {
+ if (obj is GeometryInstance)
+ {
+ if ((obj as GeometryInstance).GetSymbolGeometry().Any())
+ {
+ foreach (GeometryObject item in (obj as GeometryInstance).GetSymbolGeometry())
+ {
+ if (item is Solid solid)
+ {
+ if (solid.Edges.Size > 0)
+ {
+ edges.AddRange(from Edge edge in solid.Edges
+ select edge.Reference);
+ }
+
+ if (solid.Faces.Size > 0)
+ {
+ faces.AddRange(from Face face in solid.Faces
+ select face.Reference);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (obj is Solid solid)
+ {
+ if (solid.Edges.Size > 0)
+ {
+ edges.AddRange(from Edge edge in solid.Edges
+ select edge.Reference);
+ }
+
+ if (solid.Faces.Size > 0)
+ {
+ faces.AddRange(from Face face in solid.Faces
+ select face.Reference);
+ }
+ }
+ }
+ }
+
+ if (element is FamilyInstance familyInstance)
+ {
+ try
+ {
+ var r1 = familyInstance.GetReferences(FamilyInstanceReferenceType.CenterFrontBack);
+ var r2 = familyInstance.GetReferences(FamilyInstanceReferenceType.CenterLeftRight);
+ var r3 = familyInstance.GetReferences(FamilyInstanceReferenceType.CenterElevation);
+ var e1 = familyInstance.GetReferences(FamilyInstanceReferenceType.StrongReference);
+ if (r1 != null)
+ {
+ references.AddRange(r1);
+ references.AddRange(r2);
+ references.AddRange(r3);
+ references.AddRange(e1);
+ }
+ }
+ catch (Exception)
+ {
+ }
+ }
+
+ return references;
+ }
+
+ public static Options SetOptions()
+ {
+ Options option = new Options
+ {
+ ComputeReferences = true,
+ DetailLevel = ViewDetailLevel.Fine
+ };
+ return option;
+ }
+
+ public static PlanarFace GetTopFaceByElement(Element elem)
+ {
+ Options opt = new Options
+ {
+ ComputeReferences = true,
+ DetailLevel = ViewDetailLevel.Fine
+ };
+ GeometryElement ge = elem.get_Geometry(opt);
+ PlanarFace pf = null;
+ foreach (GeometryObject obj in ge)
+ {
+ if (obj is GeometryInstance)
+ {
+ GeometryElement symobolInstance = (obj as GeometryInstance).SymbolGeometry;
+ foreach (var temppf in from GeometryObject geom in symobolInstance
+ let solid = geom as Solid
+ where solid.Faces.Size != 0
+ from Face face in solid.Faces
+ let temppf = face as PlanarFace
+ where temppf != null
+ where temppf.FaceNormal.IsAlmostEqualTo(XYZ.BasisZ)
+ select temppf)
+ {
+ pf = temppf;
+ break;
+ }
+ }
+ else
+ {
+ Solid solid = obj as Solid;
+ if (solid.Faces.Size != 0)
+ {
+ foreach (var temppf in from Face face in solid.Faces
+ let temppf = face as PlanarFace
+ where temppf != null
+ where temppf.FaceNormal.IsAlmostEqualTo(XYZ.BasisZ)
+ select temppf)
+ {
+ pf = temppf;
+ break;
+ }
+ }
+ }
+ }
+
+ return pf;
+ }
+
+ public static Reference GetSpecialFamilyReference(Document doc, FamilyInstance instance, SpecialReferenceType ReferenceType)
+ {
+ Reference indexReference = null;
+
+ int index = (int)ReferenceType;
+
+ Options geomOptions = new Options
+ {
+ ComputeReferences = true,
+
+ DetailLevel = ViewDetailLevel.Medium,
+
+ IncludeNonVisibleObjects = true
+ };
+
+ GeometryElement geoElement = instance.get_Geometry(geomOptions);
+
+ foreach (GeometryObject obj in geoElement)
+
+ {
+ if (obj is GeometryInstance)
+
+ {
+ GeometryInstance geoInstance = obj as GeometryInstance;
+
+ string sampleStableRef = null;
+
+ if (geoInstance != null)
+
+ {
+ GeometryElement geoSymbol = geoInstance.GetSymbolGeometry();
+
+ if (geoSymbol != null)
+
+ {
+ foreach (GeometryObject geomObj in geoSymbol)
+
+ {
+ if (geomObj is Solid)
+
+ {
+ Solid solid = geomObj as Solid;
+
+ if (solid.Faces.Size > 0)
+
+ {
+ Face face = solid.Faces.get_Item(0);
+
+ sampleStableRef = face.Reference.ConvertToStableRepresentation(doc);
+
+ break;
+ }
+ }
+ }
+ }
+
+ if (sampleStableRef != null)
+
+ {
+ string[] refTokens = sampleStableRef.Split(':');
+
+ string customStableRef = refTokens[0] + ":" + refTokens[1] + ":" + refTokens[2] + ":" + refTokens[3] + ":" + index;
+
+ indexReference = Reference.ParseFromStableRepresentation(doc, customStableRef);
+ }
+
+ break;
+ }
+ }
+ }
+
+ return indexReference;
+ }
+
+ ///
+ /// 射线法获取参照
+ ///
+ ///
+ ///
+ ///
+ public static Reference GetSpotDimensionReference(Document doc, XYZ p)
+ {
+ Reference reference = null;
+ if (doc.ActiveView is ViewPlan view)
+ {
+ //可能存在贯穿标高的构件,需修改射线贯穿距离
+
+ #region 视图范围
+
+ var range = view.GetViewRange();
+ var bottomLevel = doc.GetElement(range.GetLevelId(PlanViewPlane.BottomClipPlane)) as Level;
+ var b = range.GetOffset(PlanViewPlane.BottomClipPlane);
+ var topLevel = doc.GetElement(range.GetLevelId(PlanViewPlane.TopClipPlane)) as Level;
+ var t = range.GetOffset(PlanViewPlane.TopClipPlane);
+ var bot = bottomLevel.Elevation + b;
+ var tt = topLevel.Elevation + t;
+ var p1 = new XYZ(p.X, p.Y, bot);
+ var p2 = new XYZ(p.X, p.Y, tt);
+
+ #endregion 视图范围
+
+ //var p1 = new XYZ(p.X, p.Y, -100000 / 304.8);
+ //var p2 = new XYZ(p.X, p.Y, 100000 / 304.8);
+ View3D v3d = new FilteredElementCollector(doc).OfClass(typeof(View3D)).Cast().FirstOrDefault(v => v.IsTemplate == false);
+ //Line l = Line.CreateUnbound(p1, p2);
+ //Plane plane = Plane.CreateByOriginAndBasis(p1, XYZ.BasisX, XYZ.BasisZ);
+ //SketchPlane sketch = SketchPlane.Create(doc, plane);
+ //ModelCurve curve = doc.Create.NewModelCurve(l, sketch);
+ //Id = curve.Id;
+ //Face face = null;
+ //射线法找到相交的元素
+ ReferenceIntersector intersector = new ReferenceIntersector(v3d);
+ var refer = intersector.FindNearest(p1, XYZ.BasisZ)?.GetReference();
+ var refer1 = intersector.FindNearest(p2, -XYZ.BasisZ)?.GetReference();
+
+ if (refer != null && refer1 != null)
+ {
+ reference = refer.GlobalPoint.Z > refer1.GlobalPoint.Z ? refer : refer1;
+ }
+ }
+
+ return reference;
+ //Line l2 = Line.CreateUnbound(p, XYZ.BasisZ);
+ }
+
+ ///
+ /// 获取元素边缘线和面
+ ///
+ ///
+ ///
+ ///
+ public static void GetGeometryObj(Element element, out List faces, List edges)
+ {
+ //实例族的GeometryElement集合中具有Solid等几何对象的原因是由于族实例对象碰撞后,软件自动会使用geometryInstance用来指定其位置(即使碰撞后,移开),用Solid作为其几何体
+ //GeometryInstance Transform是族实例在全局坐标系的变换
+ faces = new List();
+ edges = new List();
+ var references = new List();
+ Options geomOptions = new Options
+ {
+ ComputeReferences = true,
+
+ DetailLevel = ViewDetailLevel.Medium,
+
+ IncludeNonVisibleObjects = true
+ };
+ var geoElem = element.get_Geometry(geomOptions);
+ foreach (GeometryObject obj in geoElem)
+ {
+ if (obj is GeometryInstance)
+ {
+ if ((obj as GeometryInstance).GetSymbolGeometry().Count() > 0)
+ {
+ foreach (GeometryObject item in (obj as GeometryInstance).GetSymbolGeometry())
+ {
+ if (item is Solid solid)
+ {
+ if (solid.Edges.Size > 0)
+ {
+ edges.AddRange(from Edge edge in solid.Edges
+ select edge);
+ }
+
+ if (solid.Faces.Size > 0)
+ {
+ faces.AddRange(from Face face in solid.Faces
+ select face);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (obj is Solid solid)
+ {
+ if (solid.Edges.Size > 0)
+ {
+ edges.AddRange(from Edge edge in solid.Edges
+ select edge);
+ }
+
+ if (solid.Faces.Size > 0)
+ {
+ faces.AddRange(from Face face in solid.Faces
+ select face);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public enum SpecialReferenceType
+ {
+ Left = 0,
+
+ CenterLR = 1,
+
+ Right = 2,
+
+ Front = 3,
+
+ CenterFB = 4,
+
+ Back = 5,
+
+ Bottom = 6,
+
+ CenterElevation = 7,
+
+ Top = 8
+ }
+}
\ No newline at end of file
diff --git a/DimensionTools/Util/VistaFolderBrowserDialog.cs b/DimensionTools/Util/VistaFolderBrowserDialog.cs
new file mode 100644
index 0000000..a41fa35
--- /dev/null
+++ b/DimensionTools/Util/VistaFolderBrowserDialog.cs
@@ -0,0 +1,342 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows;
+using System.Windows.Interop;
+using Microsoft.Win32;
+
+namespace Sai.RegularUtils.IO
+{
+ public sealed class VistaFolderBrowserDialog
+ {
+ public bool AllowNonStoragePlaces { get; set; }
+
+ public bool Multiselect { get; set; }
+ public string SelectedPath { get; set; }
+
+ public string SelectedElementName { get; private set; }
+
+ public string[] SeletcedPaths { get; private set; }
+
+ public string[] SelectedElementNames { get; private set; }
+
+ public bool ShowDialog()
+ {
+ return ShowDialog(IntPtr.Zero);
+ }
+
+ public bool ShowDialog(Window owner)
+ {
+ return ShowDialog(owner == null ? IntPtr.Zero : new WindowInteropHelper(owner).Handle);
+ }
+
+ public bool ShowDialog(IWin32Window owner)
+ {
+ return ShowDialog(owner == null ? IntPtr.Zero : owner.Handle);
+ }
+
+ public bool ShowDialog(IntPtr owner)
+ {
+ if (Environment.OSVersion.Version.Major < 6)
+ {
+ throw new InvalidOperationException("对话框需要至少在Visia系统以上才能使用");
+ }
+
+ IFileOpenDialog dialog = CreateNativeDialog();
+ try
+ {
+ SetInitialFolder(dialog);
+ SetOptions(dialog);
+
+ if (dialog.Show(owner) != 0)
+ {
+ return false;
+ }
+
+ SetDialogResults(dialog);
+
+ return true;
+ }
+ finally
+ {
+ Marshal.ReleaseComObject(dialog);
+ }
+ }
+
+ private IFileOpenDialog CreateNativeDialog()
+ {
+ return (IFileOpenDialog)new FileOpenDialog();
+ }
+
+ private Fos GetDialogOptions()
+ {
+ Fos options = Fos.Pickfolders;
+ if (Multiselect)
+ {
+ options |= Fos.Allowmultiselect;
+ }
+
+ if (!AllowNonStoragePlaces)
+ {
+ options |= Fos.Forcefilesystem;
+ }
+
+ return options;
+ }
+
+ private void GetPathAndElementName(IShellItem item, out string path, out string elementName)
+ {
+ item.GetDisplayName(Sigdn.Parentrelativeforaddressbar, out elementName);
+ try
+ {
+ item.GetDisplayName(Sigdn.Filesyspath, out path);
+ }
+ catch (ArgumentException ex) when (ex.HResult == -2147024809)
+ {
+ path = null;
+ }
+ }
+
+ private void SetDialogResults(IFileOpenDialog dialog)
+ {
+ IShellItem item;
+ if (!Multiselect)
+ {
+ dialog.GetResult(out item);
+ string path, value;
+ GetPathAndElementName(item, out path, out value);
+ SelectedPath = path;
+ SeletcedPaths = new[] { path };
+ SelectedElementName = value;
+ SelectedElementNames = new[] { value };
+ }
+ else
+ {
+ IShellItemArray items;
+ dialog.GetResults(out items);
+
+ uint count;
+ items.GetCount(out count);
+
+ SeletcedPaths = new string[count];
+ SelectedElementNames = new string[count];
+
+ for (uint i = 0; i < count; ++i)
+ {
+ items.GetItemAt(i, out item);
+ string path, value;
+ GetPathAndElementName(item, out path, out value);
+ SeletcedPaths[i] = path;
+ SelectedElementNames[i] = value;
+ }
+
+ SelectedPath = null;
+ SelectedElementName = null;
+ }
+ }
+
+ private void SetInitialFolder(IFileOpenDialog dialog)
+ {
+ IShellItem item;
+ if (!string.IsNullOrEmpty(SelectedPath))
+ {
+ IntPtr idl;
+ uint atts = 0;
+ if (NativeMethods.SHILCreateFromPath(SelectedPath, out idl, ref atts) == 0
+ && NativeMethods.SHCreateShellItem(IntPtr.Zero, IntPtr.Zero, idl, out item) == 0)
+ {
+ dialog.SetFolder(item);
+ }
+ }
+ }
+
+ private void SetOptions(IFileOpenDialog dialog)
+ {
+ dialog.SetOptions(GetDialogOptions());
+ }
+
+ [ComImport]
+ [Guid("DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7")]
+ private class FileOpenDialog
+ {
+ }
+
+ private class NativeMethods
+ {
+ [DllImport("user32.dll")]
+ public static extern IntPtr GetActiveWindow();
+
+ [DllImport("shell32.dll")]
+ public static extern int SHCreateShellItem(IntPtr pidlParent, IntPtr psfParent, IntPtr pidl,
+ out IShellItem ppsi);
+
+ [DllImport("shell32.dll")]
+ public static extern int SHILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)] string pszPath, out IntPtr ppIdl,
+ ref uint rgflnOut);
+ }
+
+ [Flags]
+ private enum Fos
+ {
+ Allnonstorageitems = 0x80,
+
+ Allowmultiselect = 0x200,
+
+ Createprompt = 0x2000,
+
+ Defaultnominimode = 0x20000000,
+
+ Dontaddtorecent = 0x2000000,
+
+ Filemustexist = 0x1000,
+
+ Forcefilesystem = 0x40,
+
+ Forceshowhidden = 0x10000000,
+
+ Hidemruplaces = 0x20000,
+
+ Hidepinnedplaces = 0x40000,
+
+ Nochangedir = 8,
+
+ Nodereferencelinks = 0x100000,
+
+ Noreadonlyreturn = 0x8000,
+
+ Notestfilecreate = 0x10000,
+
+ Novalidate = 0x100,
+
+ Overwriteprompt = 2,
+
+ Pathmustexist = 0x800,
+
+ Pickfolders = 0x20,
+
+ Shareaware = 0x4000,
+
+ Strictfiletypes = 4
+ }
+
+ [ComImport]
+ [Guid("d57c7288-d4ad-4768-be02-9d969532d960")]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ [CoClass(typeof(FileOpenDialog))]
+ private interface IFileOpenDialog
+ {
+ [PreserveSig]
+ int Show([In] IntPtr parent);
+
+ void SetFileTypes([In] uint cFileTypes, [In] [MarshalAs(UnmanagedType.Struct)] ref IntPtr rgFilterSpec);
+
+ void SetFileTypeIndex([In] uint iFileType);
+
+ void GetFileTypeIndex(out uint piFileType);
+
+ void Advise([In] [MarshalAs(UnmanagedType.Interface)] IntPtr pfde, out uint pdwCookie);
+
+ void Unadvise([In] uint dwCookie);
+
+ void SetOptions([In] Fos fos);
+
+ void GetOptions(out Fos pfos);
+
+ void SetDefaultFolder([In] [MarshalAs(UnmanagedType.Interface)] IShellItem psi);
+
+ void SetFolder([In] [MarshalAs(UnmanagedType.Interface)] IShellItem psi);
+
+ void GetFolder([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);
+
+ void GetCurrentSelection([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);
+
+ void SetFileName([In] [MarshalAs(UnmanagedType.LPWStr)] string pszName);
+
+ void GetFileName([MarshalAs(UnmanagedType.LPWStr)] out string pszName);
+
+ void SetTitle([In] [MarshalAs(UnmanagedType.LPWStr)] string pszTitle);
+
+ void SetOkButtonLabel([In] [MarshalAs(UnmanagedType.LPWStr)] string pszText);
+
+ void SetFileNameLabel([In] [MarshalAs(UnmanagedType.LPWStr)] string pszLabel);
+
+ void GetResult([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);
+
+ void AddPlace([In] [MarshalAs(UnmanagedType.Interface)] IShellItem psi, FileDialogCustomPlace fdcp);
+
+ void SetDefaultExtension([In] [MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension);
+
+ void Close([MarshalAs(UnmanagedType.Error)] int hr);
+
+ void SetClientGuid([In] ref Guid guid);
+
+ void ClearClientData();
+
+ void SetFilter([MarshalAs(UnmanagedType.Interface)] IntPtr pFilter);
+
+ void GetResults([MarshalAs(UnmanagedType.Interface)] out IShellItemArray ppenum);
+
+ void GetSelectedItems([MarshalAs(UnmanagedType.Interface)] out IShellItemArray ppsai);
+ }
+
+ [ComImport]
+ [Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE")]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ private interface IShellItem
+ {
+ void BindToHandler([In] [MarshalAs(UnmanagedType.Interface)] IntPtr pbc, [In] ref Guid bhid, [In] ref Guid riid,
+ out IntPtr ppv);
+
+ void GetParent([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);
+
+ void GetDisplayName([In] Sigdn sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName);
+
+ void GetAttributes([In] uint sfgaoMask, out uint psfgaoAttribs);
+
+ void Compare([In] [MarshalAs(UnmanagedType.Interface)] IShellItem psi, [In] uint hint, out int piOrder);
+ }
+
+ [ComImport]
+ [Guid("B63EA76D-1F85-456F-A19C-48159EFA858B")]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ private interface IShellItemArray
+ {
+ void BindToHandler([In] [MarshalAs(UnmanagedType.Interface)] IntPtr pbc, [In] ref Guid rbhid,
+ [In] ref Guid riid, out IntPtr ppvOut);
+
+ void GetPropertyStore([In] int flags, [In] ref Guid riid, out IntPtr ppv);
+
+ void GetPropertyDescriptionList([In] [MarshalAs(UnmanagedType.Struct)] ref IntPtr keyType, [In] ref Guid riid,
+ out IntPtr ppv);
+
+ void GetAttributes([In] [MarshalAs(UnmanagedType.I4)] IntPtr dwAttribFlags, [In] uint sfgaoMask,
+ out uint psfgaoAttribs);
+
+ void GetCount(out uint pdwNumItems);
+
+ void GetItemAt([In] uint dwIndex, [MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);
+
+ void EnumItems([MarshalAs(UnmanagedType.Interface)] out IntPtr ppenumShellItems);
+ }
+
+ private enum Sigdn : uint
+ {
+ Desktopabsoluteediting = 0x8004c000,
+
+ Desktopabsoluteparsing = 0x80028000,
+
+ Filesyspath = 0x80058000,
+
+ Normaldisplay = 0,
+
+ Parentrelative = 0x80080001,
+
+ Parentrelativeediting = 0x80031001,
+
+ Parentrelativeforaddressbar = 0x8007c001,
+
+ Parentrelativeparsing = 0x80018001,
+
+ Url = 0x80068000
+ }
+ }
+}
\ No newline at end of file
diff --git a/DimensionToolsSetup/DimensionTools-cache/cacheIndex.txt b/DimensionToolsSetup/DimensionTools-cache/cacheIndex.txt
new file mode 100644
index 0000000..39f0303
Binary files /dev/null and b/DimensionToolsSetup/DimensionTools-cache/cacheIndex.txt differ
diff --git a/DimensionToolsSetup/DimensionTools-cache/part2/DimensionTools1.cab b/DimensionToolsSetup/DimensionTools-cache/part2/DimensionTools1.cab
new file mode 100644
index 0000000..15389b8
Binary files /dev/null and b/DimensionToolsSetup/DimensionTools-cache/part2/DimensionTools1.cab differ
diff --git a/DimensionToolsSetup/DimensionTools-cache/part2/output-info.ini b/DimensionToolsSetup/DimensionTools-cache/part2/output-info.ini
new file mode 100644
index 0000000..63d43c5
Binary files /dev/null and b/DimensionToolsSetup/DimensionTools-cache/part2/output-info.ini differ
diff --git a/DimensionToolsSetup/DimensionTools.aip b/DimensionToolsSetup/DimensionTools.aip
new file mode 100644
index 0000000..4e56916
--- /dev/null
+++ b/DimensionToolsSetup/DimensionTools.aip
@@ -0,0 +1,522 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DimensionToolsSetup/DimensionToolsSetup.aiproj b/DimensionToolsSetup/DimensionToolsSetup.aiproj
new file mode 100644
index 0000000..a42e39b
--- /dev/null
+++ b/DimensionToolsSetup/DimensionToolsSetup.aiproj
@@ -0,0 +1,37 @@
+
+
+ All
+ 2.0
+ c076d0df-c55c-461a-b6c9-8d0ac16175fd
+ msi
+ .
+ Sai.RvKitSetup.aip
+
+
+ .
+ True
+ Sai.RvKitSetup
+ DimensionToolsSetup
+ Sai.RvKitSetup
+
+
+
+
+
+
+ Content
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DimensionToolsSetup/Ico/Revit2020x.ico b/DimensionToolsSetup/Ico/Revit2020x.ico
new file mode 100644
index 0000000..b48fbe8
Binary files /dev/null and b/DimensionToolsSetup/Ico/Revit2020x.ico differ
diff --git a/DimensionToolsSetup/Ico/Revit2021x.ico b/DimensionToolsSetup/Ico/Revit2021x.ico
new file mode 100644
index 0000000..23d1ccd
Binary files /dev/null and b/DimensionToolsSetup/Ico/Revit2021x.ico differ
diff --git a/DimensionToolsSetup/Ico/SZMC.png b/DimensionToolsSetup/Ico/SZMC.png
new file mode 100644
index 0000000..d1939d3
Binary files /dev/null and b/DimensionToolsSetup/Ico/SZMC.png differ
diff --git a/DimensionToolsSetup/Ico/logo.ico b/DimensionToolsSetup/Ico/logo.ico
new file mode 100644
index 0000000..f799edc
Binary files /dev/null and b/DimensionToolsSetup/Ico/logo.ico differ
diff --git a/DimensionToolsSetup/Ico/logo.png b/DimensionToolsSetup/Ico/logo.png
new file mode 100644
index 0000000..7de1d08
Binary files /dev/null and b/DimensionToolsSetup/Ico/logo.png differ