├── .gitignore
├── AdnRme.sln
├── AdnRme
├── AboutBox.Designer.cs
├── AboutBox.cs
├── AboutBox.resx
├── AdnRme.addin
├── AdnRme.csproj
├── App.cs
├── Bip.cs
├── CmdAbout.cs
├── CmdAssignFlowToTerminals.cs
├── CmdChangeSize.cs
├── CmdElectricalConnectors.cs
├── CmdElectricalHierarchy2.cs
├── CmdElectricalSystemBrowser.cs
├── CmdInspectElectricalForm.Designer.cs
├── CmdInspectElectricalForm.cs
├── CmdInspectElectricalForm.resx
├── CmdInspectElectricallForm2.cs
├── CmdInspectElectricallForm2.designer.cs
├── CmdInspectElectricallForm2.resx
├── CmdPopulateCfmPerSf.cs
├── CmdResetDemo.cs
├── CmdUnhostedElements.cs
├── Command.cs
├── Const.cs
├── FamilySelector.Designer.cs
├── FamilySelector.cs
├── FamilySelector.resx
├── PanelTreeNodeHelper.cs
├── ParameterName.cs
├── ParameterValue.cs
├── ProgressForm.Designer.cs
├── ProgressForm.cs
├── ProgressForm.resx
├── Properties
│ └── AssemblyInfo.cs
├── Util.cs
└── WaitCursor.cs
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 | [Dd]ebug/
11 | [Dd]ebugPublic/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | bld/
16 | [Bb]in/
17 | [Oo]bj/
18 |
19 | # MSTest test Results
20 | [Tt]est[Rr]esult*/
21 | [Bb]uild[Ll]og.*
22 |
23 | #NUNIT
24 | *.VisualState.xml
25 | TestResult.xml
26 |
27 | # Build Results of an ATL Project
28 | [Dd]ebugPS/
29 | [Rr]eleasePS/
30 | dlldata.c
31 |
32 | *_i.c
33 | *_p.c
34 | *_i.h
35 | *.ilk
36 | *.meta
37 | *.obj
38 | *.pch
39 | *.pdb
40 | *.pgc
41 | *.pgd
42 | *.rsp
43 | *.sbr
44 | *.tlb
45 | *.tli
46 | *.tlh
47 | *.tmp
48 | *.tmp_proj
49 | *.log
50 | *.vspscc
51 | *.vssscc
52 | .builds
53 | *.pidb
54 | *.svclog
55 | *.scc
56 |
57 | # Chutzpah Test files
58 | _Chutzpah*
59 |
60 | # Visual C++ cache files
61 | .vs/
62 | ipch/
63 | *.aps
64 | *.ncb
65 | *.opensdf
66 | *.sdf
67 | *.cachefile
68 |
69 | # Visual Studio profiler
70 | *.psess
71 | *.vsp
72 | *.vspx
73 |
74 | # TFS 2012 Local Workspace
75 | $tf/
76 |
77 | # Guidance Automation Toolkit
78 | *.gpState
79 |
80 | # ReSharper is a .NET coding add-in
81 | _ReSharper*/
82 | *.[Rr]e[Ss]harper
83 | *.DotSettings.user
84 |
85 | # JustCode is a .NET coding addin-in
86 | .JustCode
87 |
88 | # TeamCity is a build add-in
89 | _TeamCity*
90 |
91 | # DotCover is a Code Coverage Tool
92 | *.dotCover
93 |
94 | # NCrunch
95 | *.ncrunch*
96 | _NCrunch_*
97 | .*crunch*.local.xml
98 |
99 | # MightyMoose
100 | *.mm.*
101 | AutoTest.Net/
102 |
103 | # Web workbench (sass)
104 | .sass-cache/
105 |
106 | # Installshield output folder
107 | [Ee]xpress/
108 |
109 | # DocProject is a documentation generator add-in
110 | DocProject/buildhelp/
111 | DocProject/Help/*.HxT
112 | DocProject/Help/*.HxC
113 | DocProject/Help/*.hhc
114 | DocProject/Help/*.hhk
115 | DocProject/Help/*.hhp
116 | DocProject/Help/Html2
117 | DocProject/Help/html
118 |
119 | # Click-Once directory
120 | publish/
121 |
122 | # Publish Web Output
123 | *.[Pp]ublish.xml
124 | *.azurePubxml
125 |
126 | # NuGet Packages Directory
127 | packages/
128 | ## TODO: If the tool you use requires repositories.config uncomment the next line
129 | #!packages/repositories.config
130 |
131 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
132 | # This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented)
133 | !packages/build/
134 |
135 | # Windows Azure Build Output
136 | csx/
137 | *.build.csdef
138 |
139 | # Windows Store app package directory
140 | AppPackages/
141 |
142 | # Others
143 | sql/
144 | *.Cache
145 | ClientBin/
146 | [Ss]tyle[Cc]op.*
147 | ~$*
148 | *~
149 | *.dbmdl
150 | *.dbproj.schemaview
151 | *.pfx
152 | *.publishsettings
153 | node_modules/
154 |
155 | # RIA/Silverlight projects
156 | Generated_Code/
157 |
158 | # Backup & report files from converting an old project file to a newer
159 | # Visual Studio version. Backup files are not needed, because we have git ;-)
160 | _UpgradeReport_Files/
161 | Backup*/
162 | UpgradeLog*.XML
163 | UpgradeLog*.htm
164 |
165 | # SQL Server files
166 | *.mdf
167 | *.ldf
168 |
169 | # Business Intelligence projects
170 | *.rdl.data
171 | *.bim.layout
172 | *.bim_*.settings
173 |
174 | # Microsoft Fakes
175 | FakesAssemblies/
176 |
--------------------------------------------------------------------------------
/AdnRme.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual Studio 2010
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdnRme", "AdnRme\AdnRme.csproj", "{DBAF92E6-72D5-4C38-ADC7-754F11E27E3A}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Any CPU = Debug|Any CPU
9 | Release|Any CPU = Release|Any CPU
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {DBAF92E6-72D5-4C38-ADC7-754F11E27E3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 | {DBAF92E6-72D5-4C38-ADC7-754F11E27E3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 | {DBAF92E6-72D5-4C38-ADC7-754F11E27E3A}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 | {DBAF92E6-72D5-4C38-ADC7-754F11E27E3A}.Release|Any CPU.Build.0 = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/AdnRme/AboutBox.Designer.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeremytammik/AdnRme/d2764222508f2dce275815bf95b755ae94754415/AdnRme/AboutBox.Designer.cs
--------------------------------------------------------------------------------
/AdnRme/AboutBox.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | #region Namespaces
26 | using System;
27 | using System.Windows.Forms;
28 | using System.Reflection;
29 | #endregion // Namespaces
30 |
31 | namespace AdnRme
32 | {
33 | partial class AboutBox : Form
34 | {
35 | public AboutBox()
36 | {
37 | InitializeComponent();
38 |
39 | // Initialize the AboutBox to display the product
40 | // information from the assembly information.
41 | // Change assembly information settings for your
42 | // application through either Project > Properties
43 | // > Application > Assembly Information or
44 | // by editing AssemblyInfo.cs
45 |
46 | Text = "About " + AssemblyTitle;
47 | labelProductName.Text = AssemblyProduct;
48 | labelVersion.Text = "Version " + AssemblyVersion;
49 | labelCopyright.Text = AssemblyCopyright;
50 | labelCompanyName.Text = AssemblyCompany;
51 | textBoxDescription.Text = AssemblyDescription;
52 | }
53 |
54 | #region Assembly Attribute Accessors
55 |
56 | ///
57 | /// Short cut to get executing assembly
58 | ///
59 | Assembly ExecutingAssembly
60 | {
61 | get
62 | {
63 | return Assembly.GetExecutingAssembly();
64 | }
65 | }
66 |
67 | object GetFirstCustomAttribute( Type t )
68 | {
69 | Assembly a = ExecutingAssembly;
70 | object[] attributes
71 | = a.GetCustomAttributes( t, false );
72 | return ( 0 < attributes.Length )
73 | ? attributes[0]
74 | : null;
75 | }
76 |
77 | public string AssemblyTitle
78 | {
79 | get
80 | {
81 | // Get all Title attributes on this assembly
82 | //object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes( typeof( AssemblyTitleAttribute ), false );
83 | //object[] attributes = GetCustomAttributes( typeof( AssemblyTitleAttribute ) );
84 | object a = GetFirstCustomAttribute( typeof( AssemblyTitleAttribute ) );
85 | // If there is at least one Title attribute
86 | if( null != a )
87 | {
88 | // Select the first one
89 | AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute) a;
90 | // If it is not an empty string, return it
91 | if( titleAttribute.Title != "" )
92 | return titleAttribute.Title;
93 | }
94 | // If there was no Title attribute, or if the Title attribute was the empty string, return the .exe name
95 | return System.IO.Path.GetFileNameWithoutExtension( ExecutingAssembly.CodeBase );
96 | }
97 | }
98 |
99 | public string AssemblyVersion
100 | {
101 | get
102 | {
103 | return ExecutingAssembly.GetName().Version.ToString();
104 | }
105 | }
106 |
107 | public string AssemblyDescription
108 | {
109 | get
110 | {
111 | // Get all Description attributes on this assembly
112 | //object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes( typeof( AssemblyDescriptionAttribute ), false );
113 | //object[] attributes = GetCustomAttributes( typeof( AssemblyDescriptionAttribute ) );
114 | object a = GetFirstCustomAttribute( typeof( AssemblyDescriptionAttribute ) );
115 | // If there aren't any Description attributes, return an empty string
116 | //if( attributes.Length == 0 )
117 | // return "";
118 | // If there is a Description attribute, return its value
119 | //return ( (AssemblyDescriptionAttribute) attributes[0] ).Description;
120 | return (null == a)
121 | ? string.Empty
122 | : ( (AssemblyDescriptionAttribute) a ).Description;
123 | }
124 | }
125 |
126 | public string AssemblyProduct
127 | {
128 | get
129 | {
130 | // Get all Product attributes on this assembly
131 | //object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes( typeof( AssemblyProductAttribute ), false );
132 | //object[] attributes = GetCustomAttributes( typeof( AssemblyProductAttribute ) );
133 | object a = GetFirstCustomAttribute( typeof( AssemblyProductAttribute ) );
134 | // If there aren't any Product attributes, return an empty string
135 | //if( attributes.Length == 0 )
136 | // return "";
137 | // If there is a Product attribute, return its value
138 | //return ( (AssemblyProductAttribute) attributes[0] ).Product;
139 | return ( null == a )
140 | ? string.Empty
141 | : ( ( AssemblyProductAttribute ) a ).Product;
142 | }
143 | }
144 |
145 | public string AssemblyCopyright
146 | {
147 | get
148 | {
149 | // Get all Copyright attributes on this assembly
150 | //object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes( typeof( AssemblyCopyrightAttribute ), false );
151 | //object[] attributes = GetCustomAttributes( typeof( AssemblyCopyrightAttribute ) );
152 | object a = GetFirstCustomAttribute( typeof( AssemblyCopyrightAttribute ) );
153 | // If there aren't any Copyright attributes, return an empty string
154 | //if( attributes.Length == 0 )
155 | // return "";
156 | // If there is a Copyright attribute, return its value
157 | //return ( (AssemblyCopyrightAttribute) attributes[0] ).Copyright;
158 | return ( null == a )
159 | ? string.Empty
160 | : ( ( AssemblyCopyrightAttribute ) a ).Copyright;
161 | }
162 | }
163 |
164 | public string AssemblyCompany
165 | {
166 | get
167 | {
168 | // Get all Company attributes on this assembly
169 | //object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes( typeof( AssemblyCompanyAttribute ), false );
170 | //object[] attributes = GetCustomAttributes( typeof( AssemblyCompanyAttribute ) );
171 | object a = GetFirstCustomAttribute( typeof( AssemblyCompanyAttribute ) );
172 | // If there aren't any Company attributes, return an empty string
173 | //if( attributes.Length == 0 )
174 | // return "";
175 | // If there is a Company attribute, return its value
176 | //return ( (AssemblyCompanyAttribute) attributes[0] ).Company;
177 | return ( null == a )
178 | ? string.Empty
179 | : ( ( AssemblyCompanyAttribute ) a ).Company;
180 | }
181 | }
182 | #endregion
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/AdnRme/AboutBox.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 |
123 | iVBORw0KGgoAAAANSUhEUgAAAHgAAAEGCAIAAAAhWcaAAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
124 | YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAD2JJREFUeF7tnU2S
125 | 5CgShWN2dZSq5Vxjlm02i57zzHJOUmZZu5ij1DLP0btskCtcHvw6wnGBoCwrLDIDIcnj4/FwkPSPH9+/
126 | vj0efz32f6H3/zeff3t828r8y/zPlbflVhkI6BEHE+jcz8eP788f3+E1W3gVCEfggbH7Jwni+3sTX/j5
127 | iJc5al9lIKROHGygc6GBEEOsA1Uwvqr1NXwdRMdlYUmHgB4u6VBqo4toAVo5HmFptFL/sYhWJDrnJZa9
128 | E9DxRbQi0Y18tBmA5tqKkj4yxgoCzGKXiCdO99uQaLo/Tr98jzKQ4vDPpZWPfiWpOPXfimsMdGAInkPp
129 | zMjQD3RuL0pa2fowYifeykfT/eX6AEl9vHZfeNZ+/9REo+n+plJqP9BHD8nIvRX76GCgr2VNx//ECDPn
130 | 3oRoOKupWKbSH3UdOdZO5qOXj14+uq3DUfXRIB25tnIfv0H7AAi0ko9eGu0Y9lY+2vazK9dBuG7oOlqP
131 | wcaqn5OLKPbRDG9+q/wG53zFiHa8euzXsTDkHC3zxMU0Gvb3Ff8HBe7nQ5gnLkm0CXIs1vD3W44V8dSC
132 | jOGnYhqNIfZjTT/SyTlothvmiQsTDd+qL1v4R/TXSDe8gU2o+/YLYAqFK4uMckG/T48E60gcObLs7PDt
133 | 7/4YxutDWbkOCjJtTShhqNF4GsAdDbR/VujHUd+xjNNUY1oZ/DtWQv0+/Wr97wjHuj4BFC/UTycgrYgO
134 | cs0gjFUk2BmUBlrzCPfWmtNNlo9mEp3gguLsaIjDXQJSv0dKE01zMoAqbUP0aw+2Ldj8SqKDaoWNzldG
135 | KC/pW1lto6BXyGq0v8O2Gk3Rxq8a37T2A87e8ctrt19KtN9tHLAzIGLNgsP+/CjTWDOZZRxSNKEcC3RN
136 | neltmScu6aNjUaYSlusPanMgfqDbsUztZnZIzJFFLtEcVWxHFp42PWedNpQ9cavvUj6aUY/GfIq+RjPb
137 | qBjRrVFl1q+v0dwD88aBPncsH+3XY865tT769etrdPAY/PbdkGgFffRp6oHo4Ik31GgFD+vrYw8aTQON
138 | vC+i5dd4RInO9ZtLo8v8EgT65us65tJox8Breo9rNdo5ccp1E43298c0m/XFriWanrhzLmK5DsdH4y4Z
139 | Pr02v0H7mGt9NA20kkb7ga6nlVPDtURDzhr+BYjOaShrztDpZ+nOcvWX9elpj3StRmOgA+NkBias7F1w
140 | kMaoXNjGXk40xDoQDYaGnvTRvpdk7KtWr6/V6ETbbeI69EHGPfZAdPD0G+Y6FPjtM9cR5HoRLdxJxFpz
141 | Kx+dy5/UanGsfmesZH7V9DyzaDREWXnOkNkh3Uej/SjThcKXcx3VaL8N9v8Xf/0KEzeFYgGNdtAwvz5/
142 | Pp+/nh8/P56/Pp8/P835bO+f8PfEkga1jxzFwJUkl3j5YP/hDcm9yyNsoPcom1j/NrF2woefqoU1uJKx
143 | Z5ztcJF+5zEuCL+fHxvRwX8X0h3sAy/X5bfYUnmKBTpNNA36VbGmRx5MNSiocHoXh3TEotx/H+gcIbk3
144 | MM07Xvw+FegXGjR79/vH908GHbK39LYx+uPfJiv2YfqLUV9RR+J5L8qCifInT/uOWPPKJ8aKNn34iq95
145 | M+Z7mvfy2iCc/AmiYUMpru03DfE1XA/6E5UO7FJe90IHri3RJXkMEa7t/di3QD9NlP/zp431cK/5QFcQ
146 | Da2hPj12F6Lxej8nHfPS1nMafaiHoEaPyDIcc2uiRZS6lmiOQ20t/flA12n0EegKrms1OjhEcJqvKdNU
147 | 9/OBrtPojoiOZQ7gazCvTaE+ch3SPpr64krvcfjocxqNoUxko25AdL33cDU6oblBKpEhf0N6cWuMaBHY
148 | 89JRrdG7eohoNObKEVIndqCzEBrb12/K6wQahAKrwuR1UKOD9Z9QcxNoy8s2xqV5ZzMSMx/RMSG8N7mO
149 | E77Yr6f4L9uA5ZgP5BiJdBnnOl/EllPzCTV/YK7Z7IDOm0DcydwKvv96/vp6/rSvH9sr432wnmOOZtuv
150 | oSydx7DHQ1t6MCJ8ov1Ac4jGtlLaWxwU+0RD3L3XPb4QZd5rsB6nZgh0LD+3Hye92jkYaGCN4gm/xjbM
151 | ajTu5QTFdBMzH7jHizZM+LZLmOVwnShj5h5tFjSmfb5oFKkkDbRjn2mgi+o8QbSlMkgHj1Y+14mShm5L
152 | dKLfp0dYChf2nGl7V1ptUXmjy/b8Yz0AQ38rWYbo7xrNJLqYpu30sgOWtkRnO1kVrlNEJ7SYyVT2HKEA
153 | s7ZzxVL3XkSlbs91SqN9GM1fmtJX2mI45fOB7oFof83GOawu3CofaBXvkdLoFkTrt4l8oG9JdGtF9ptO
154 | PtC8sV+l99DW6EV0YJI7KB2Vatsp0eycxmmul0bbTJPI2C+dFcn4aHHX0SnRd/LRzuBFzY/nO8ObEV2T
155 | M6npGPKBvpmPdgK9iD7sh7jrkEoxFwHOIvpOGg3zAMtHa/hohVzdyZHh8tGc/Fy6TF46buY6ioRVsHA+
156 | 0LfMddQTWlpDPtCLaBGu84G+mY8uJVGqfH46bREtQ3R7j8xZ06Sdj5bilF/PsUpGhdxYDk87eycCaVEl
157 | exb0aq6189F8EqVKLqKVLlw81t6p+OWYXi+N5q4XrZyFWRpdtg56mDlDKeXl17M0emn065rvFiuV+CRK
158 | lVxEaxHdPtfMuc5l+ejlOoTuELJ8tNLdP5ZGL42+mevAhPTK3hVl40oLH5crORHXzedNkOtwhgPmV/b1
159 | sJX5DZqbniDXERx3qcwTUn89gY/2Aw2LkXW5noPoMNRKeTvgegKNBnKhJ6RXoC+iS31FuvwxZ+gvPFCc
160 | c5lAo5Fc334oOusJNLr/+3XcLR+9iJYVZae2N4127s6yNFrwCpdjHLiIbkv00mipWcHMiv/lOpqCjJUv
161 | jVafYVka3RTtAe57t3y0YIZvgpEhrusIzgBozbOsXMda1yG4rgPzdv7IUGsdk2o++pprwYP3y4RbC941
162 | e3fNteDB698U7+GYvzepuOvAU9YZE8JebK6DxppOstySaHqyTY2zm70zvgJUIrHuoL330NNoJ9CC+bmV
163 | 63hbXedIpRrUk+Y6TLjVWD40Gu/V7di7W2o0IGwCrcbyvsc589EzE308r8Ltr0OPKq/k8QKi+8h1WDeN
164 | vfbrgSz2aSH0uUCCT5iYlmi7WioI6fZkFvskHqf/GI/oPjT6jWjHD4DBN+vzBInWHBN25TqiRINDgBAj
165 | 1/oKW9mA7Fl0qNFBovfFxBvXpQobzOf4I5emzrqTdR0sopHrUqIhprEH3sA3V1pnKeOdzBnmNdrpDIvo
166 | gyjHYo2fFtVZqvLjEf0CsOCp9xhiP9b0o1JIi8oPptHAdUJzY88kjG2YdTK4r0reRyU6Fm4nlQHKS7FF
167 | oXCEO6bRfp9ZBPKxUmkUH+1oNMdIpMs4qo1OhlPzCboX0fs3yCT6tDm5p0ZDOGJPUabMLo1m3ePfZEE4
168 | itmF6xhUo19PS7ZPT80q5vLRb6v3YmwGze/Rm8efVEvKdDAy7CrX8Xh8hn5Mj/358fPTvD63101ksWT0
169 | 2ctIOsdIoOvItg9OG/LLdOI67DPCH4//PR6/twg6r6bH/r3Fen/dAneU4cj05WVkch1ZZHJr+PTWdZzj
170 | sX4rGaJ9GY2tl4zMrK/10bx7HOQDnalnrY/OrY/Oika2wMb4TvQ2Q2jnZN9f7ZzhVmZ/3eoMlvS37eYv
171 | CR+djZGTl0lk1mMfmRro/Tro/Dd5b8o8t3t67LHe9osRNG9GeB+8zhBDnJ2VSItGNvSWzEmIDvpozUBv
172 | 3/Su0RE2LdGgG8D1i+hBWLYN7plyHTrSQYmOLO1wp/vMgV3ui0sPoMpHi2t0en4km2mrd7vtaqj10bIa
173 | fWeiK3Md9YGmGr2Ijj7Vuz7QS6MPVUlcw1IfaE6X69jE1pm2Fkp9vUZvYxa70AtecV1A8D1+WtrpX16+
174 | ds5QhGhYveisF00HulHWuAXL++xl5R1oRAI9BdGVc4Yygd7WiNLV5rRafxdLo7O5DbcA9IRTEH25j16u
175 | g3V3g3rpWD5ayUfPdf9ouMeBM9HHvHKW0/ZjZV6eZ80Z8uYMq58JsOYMc3OGTOpz91efgOhKH13N8jX3
176 | +Nd34rW5jkGJhj5DMwFSm+sQuse0qkZjz9wus9Hz2jtje+waXP8nOASvgZFaoJp6iratmjOUu9eS6to7
177 | Gmi1LOB0Gu04+iIqawpPrdGa3mM6ooFKZcth97h8tI73WESrP3PWTyoJeeQenwuuqc4yc4bjjgxrLMSJ
178 | bSfVaB1dpnuZVKNPIFm5yZt/96/wkRv7HdduhurM5Dr8eYPSER1ndqK0zqLy+6wKHMe5GZZcrjm6bo/o
179 | e9t8tH92/nR9a2f9Fmga620VwB6j9lynch0wvnAyQWU0Je+phPdYKaqzVOVT0iHkKGqJhkDTFWKlcomb
180 | +4lAvD1Kc6Ir13UIee2URvuBTgtuIBf8/j05m+PCyRjRUL6S9wFcB2YnnC4EAxRMyCGh+KlTHhUju0LV
181 | Ua3S9rQff/+5jn1k5fXVHCORKOMHuuhuCMUaXbmaVEjHU64DCXKUGiNVSjTVZSrfMVT9b+sE1APko9/G
182 | VwyMsQW87lKzbxOTGqZGgxadVuphNJoJEZXmWFOIdYbMXZwrNkCuo4YjR9/T9u40rZwjvBvRQdwgvsEo
183 | Uz05hypzq8E0msNO0EcztL3WKaePbQqimdA1LTaFRp9rB7JbLaLXnOGfDZ/YXZ+7KOV9UqJb5+p8uZ9U
184 | oxfRWoqpuzjaZnqHyEeLj9kW0c2JDqb6mjrowfLRpb18ojyNtXhbie13RtchMmNS2ghm1GgMtGArybaM
185 | GYm2HmD7V0plTfl5fXTljElpa5iX6Bo8T2w7o0Zn9bSUVk75SYk+gWTlJpNqNIdB2TKL6OZj0X1kOGeu
186 | Q5ZWTm2LaC2iu1l7tz/XnkPHiGU6IXp/ijJ9FkVlL9/b5p346MBTlPF+/yPy6x9zX0QHMYSI90Zo6fF0
187 | 4qNTzwUHOky4LxnRSbWnAYhGdobm2mq0c/EBrvsTuj6Fcy14nujRubZEx9YLC63m51yVtbsOjvANynVq
188 | laXidYZcosflejyi99TBaD5kMI2mHmAsHzKS63AUPHafPI7Q65cZxkcHxlqP/POTpVxwfT0DE21OfiAH
189 | 0m+ugzMOBPXglLy8zCJ6rnx0mY9GihfR3NEgvXvNprnBJ91/Jv8evkevvq9I77ETjbbPk308/vt4mJiW
190 | /ozhPTrRaNbdDXqDtOh4OvHRmXsqXe4Z6r3N31AGkrd5WtJ5AAAAAElFTkSuQmCC
191 |
192 |
193 |
--------------------------------------------------------------------------------
/AdnRme/AdnRme.addin:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | AdnRme
5 | Y:\a\src\rvt\AdnRme\AdnRme\bin\Debug\AdnRme.dll
6 | 62e0c2bf-02f4-4a95-be8d-4de120048dbb
7 | AdnRme.App
8 | com.typepad.thebuildingcoder
9 | The Building Coder, http://thebuildingcoder.typepad.com
10 | NotVisibleInArchitecture
11 | NotVisibleInFamily
12 | NotVisibleInStructure
13 | NotVisibleWhenNoActiveDocument
14 |
15 |
16 |
--------------------------------------------------------------------------------
/AdnRme/AdnRme.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | None
6 |
7 |
8 |
9 | Debug
10 | AnyCPU
11 | 9.0.30729
12 | 2.0
13 | {DBAF92E6-72D5-4C38-ADC7-754F11E27E3A}
14 | Library
15 | Properties
16 | AdnRme
17 | v4.8
18 | 512
19 |
20 |
21 | 3.5
22 |
23 | publish\
24 | true
25 | Disk
26 | false
27 | Foreground
28 | 7
29 | Days
30 | false
31 | false
32 | true
33 | 0
34 | 1.0.0.%2a
35 | false
36 | false
37 | true
38 |
39 |
40 |
41 | true
42 | full
43 | false
44 | bin\Debug\
45 | DEBUG;TRACE
46 | prompt
47 | 4
48 | Program
49 | $(ProgramFiles)\Autodesk\Revit Architecture 2011\Program\Revit.exe
50 | AllRules.ruleset
51 | false
52 |
53 |
54 | pdbonly
55 | true
56 | bin\Release\
57 | TRACE
58 | prompt
59 | 4
60 | Program
61 | $(ProgramFiles)\Autodesk\Revit Architecture 2011\Program\Revit.exe
62 | AllRules.ruleset
63 | false
64 |
65 |
66 |
67 | C:\Program Files\Autodesk\Revit 2021\RevitAPI.dll
68 | False
69 |
70 |
71 | C:\Program Files\Autodesk\Revit 2021\RevitAPIUI.dll
72 | False
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | Form
82 |
83 |
84 | AboutBox.cs
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | Form
96 |
97 |
98 | CmdInspectElectricalForm.cs
99 |
100 |
101 | Form
102 |
103 |
104 | CmdInspectElectricallForm2.cs
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | Form
113 |
114 |
115 |
116 |
117 |
118 |
119 | Form
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | AboutBox.cs
132 |
133 |
134 | CmdInspectElectricalForm.cs
135 |
136 |
137 | CmdInspectElectricallForm2.cs
138 |
139 |
140 |
141 |
142 |
143 |
144 | False
145 | .NET Framework 3.5 SP1 Client Profile
146 | false
147 |
148 |
149 | False
150 | .NET Framework 3.5 SP1
151 | true
152 |
153 |
154 | False
155 | Windows Installer 3.1
156 | true
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 | copy "$(ProjectDir)AdnRme.addin" "$(AppData)\Autodesk\REVIT\Addins\2021"
165 |
166 |
--------------------------------------------------------------------------------
/AdnRme/App.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | #region Namespaces
26 | using System.Collections.Generic;
27 | using System.Diagnostics;
28 | using System.Reflection;
29 | using Autodesk.Revit.Attributes;
30 | using Autodesk.Revit.UI;
31 | using Autodesk.Revit.ApplicationServices;
32 | #endregion // Namespaces
33 |
34 | namespace AdnRme
35 | {
36 | ///
37 | /// This MEP sample demonstrates use of the generic and the MEP
38 | /// specific parts of the Revit API for tasks in Revit MEP.
39 | ///
40 | /// The following HVAC tasks are adressed using the generic API:
41 | ///
42 | /// - determine air terminals for each space.
43 | /// - assign flow to the air terminals depending on the space's calculated supply air flow.
44 | /// - change size of diffuser, i.e. type, based on flow.
45 | /// - populate the value of the 'CFM per SF' variable on all spaces.
46 | /// - enter two element id's and create a 3D sectioned box view of their extents.
47 | /// - determine unhosted elements (cf. SPR 134098).
48 | /// - reset demo to original state.
49 | ///
50 | /// CFM = cubic feet per second, SF = square feet.
51 | /// Revit internal units are feet and seconds, so we need to multiply by 60 to get CFM.
52 | ///
53 | /// The electrical conection hierarchy is determined and displayed in a tree view
54 | /// using both the generic Revit API, based on parameters, and the MEP specific API,
55 | /// based on connectors.
56 | ///
57 | /// For Revit 2009, we implemented an external application demonstrating how to create
58 | /// an own add-in menu. In Revit 2010, this was migrated to the ribbon and a custom panel.
59 | /// One can also use RvtSamples from the Revit SDK Samples directory to load
60 | /// this MEP sample, with the following additional entries in RvtSamples.txt:
61 | ///
62 | /// ADN Rme
63 | /// About...
64 | /// About ADN RME API Samples
65 | /// LargeImage:
66 | /// Image:
67 | /// C:\a\j\adn\train\revit\2011\src\rme\mep\bin\Debug\mep.dll
68 | /// mep.CmdAbout
69 | ///
70 | /// ADN Rme
71 | /// Electrical System Browser
72 | /// Inspect electrical systems in model and reproduce system browser info using parameter data only
73 | /// LargeImage:
74 | /// Image:
75 | /// C:\a\j\adn\train\revit\2011\src\rme\mep\bin\Debug\mep.dll
76 | /// mep.CmdElectricalSystemBrowser
77 | ///
78 | /// #ADN Rme
79 | /// #Electrical Hierarchy
80 | /// #Inspect electrical systems in model and display full connection hierarchy tree structure
81 | /// #LargeImage:
82 | /// #Image:
83 | /// #C:\a\j\adn\train\revit\2011\src\rme\mep\bin\Debug\mep.dll
84 | /// #mep.CmdElectricalHierarchy
85 | /// #
86 | /// #ADN Rme
87 | /// #Electrical Hierarchy 2
88 | /// #Inspect electrical systems in model and display full connection hierarchy tree structure
89 | /// #LargeImage:
90 | /// #Image:
91 | /// #C:\a\j\adn\train\revit\2011\src\rme\mep\bin\Debug\mep.dll
92 | /// #mep.CmdElectricalHierarchy2
93 | ///
94 | /// ADN Rme
95 | /// Electrical Hierarchy Tree
96 | /// Inspect electrical systems and connectors in model and display full hierarchy tree structure
97 | /// LargeImage:
98 | /// Image:
99 | /// C:\a\j\adn\train\revit\2011\src\rme\mep\bin\Debug\mep.dll
100 | /// mep.CmdElectricalConnectors
101 | ///
102 | /// ADN Rme
103 | /// HVAC Assign flow to terminals
104 | /// Assign flow to terminals
105 | /// LargeImage:
106 | /// Image:
107 | /// C:\a\j\adn\train\revit\2011\src\rme\mep\bin\Debug\mep.dll
108 | /// mep.CmdAssignFlowToTerminals
109 | ///
110 | /// ADN Rme
111 | /// HVAC Change size
112 | /// Change terminal sizes
113 | /// LargeImage:
114 | /// Image:
115 | /// C:\a\j\adn\train\revit\2011\src\rme\mep\bin\Debug\mep.dll
116 | /// mep.CmdChangeSize
117 | ///
118 | /// ADN Rme
119 | /// HVAC Populate CFM per SF on rooms
120 | /// Populate CFM per SF variable on rooms
121 | /// LargeImage:
122 | /// Image:
123 | /// C:\a\j\adn\train\revit\2011\src\rme\mep\bin\Debug\mep.dll
124 | /// mep.CmdPopulateCfmPerSf
125 | ///
126 | /// ADN Rme
127 | /// HVAC Reset demo
128 | /// Reset ADN RME API Demo
129 | /// LargeImage:
130 | /// Image:
131 | /// C:\a\j\adn\train\revit\2011\src\rme\mep\bin\Debug\mep.dll
132 | /// mep.CmdResetDemo
133 | ///
134 | /// ADN Rme
135 | /// Unhosted elements
136 | /// List unhosted elementes
137 | /// LargeImage:
138 | /// Image:
139 | /// C:\a\j\adn\train\revit\2011\src\rme\mep\bin\Debug\mep.dll
140 | /// mep.CmdUnhostedElements
141 | ///
142 | class App : IExternalApplication
143 | {
144 | ///
145 | /// Create a ribbon panel for the MEP sample application.
146 | /// We present a column of three buttons: Electrical, HVAC and About.
147 | /// The first two include subitems, the third does not.
148 | ///
149 | static void AddRibbonPanel(
150 | UIControlledApplication a )
151 | {
152 | const int nElectricalCommands = 3;
153 |
154 | const string m = "AdnRme.Cmd"; // namespace and command prefix
155 |
156 | string path = Assembly.GetExecutingAssembly().Location;
157 |
158 | string[] text = new string[] {
159 | "Electrical Connectors",
160 | "Electrical System Browser",
161 | //"Electrical Hierarchy",
162 | //"Electrical Hierarchy 2",
163 | "Unhosted elements",
164 | "Assign flow to terminals",
165 | "Change size",
166 | "Populate CFM per SF on spaces",
167 | "Reset demo",
168 | "About..."
169 | };
170 |
171 | string[] classNameStem = new string[] {
172 | "ElectricalConnectors",
173 | "ElectricalSystemBrowser",
174 | //"ElectricalHierarchy",
175 | //"ElectricalHierarchy2",
176 | "UnhostedElements",
177 | "AssignFlowToTerminals",
178 | "ChangeSize",
179 | "PopulateCfmPerSf",
180 | "ResetDemo",
181 | "About"
182 | };
183 |
184 | int n = classNameStem.Length;
185 |
186 | Debug.Assert( text.Length == n,
187 | "expected equal number of text and class name entries" );
188 |
189 | // Create three stacked buttons for the HVAC,
190 | // electrical and about commands, respectively:
191 |
192 | RibbonPanel panel = a.CreateRibbonPanel(
193 | "MEP Sample" );
194 |
195 | PulldownButtonData d1 = new PulldownButtonData(
196 | "Electrical", "Electrical" );
197 |
198 | d1.ToolTip = "Electrical Commands";
199 |
200 | PulldownButtonData d2 = new PulldownButtonData(
201 | "Hvac", "HVAC" );
202 |
203 | d2.ToolTip = "HVAC Commands";
204 |
205 | n = n - 1;
206 |
207 | PushButtonData d3 = new PushButtonData(
208 | classNameStem[n], text[n], path, m + classNameStem[n] );
209 |
210 | d3.ToolTip = "About the HVAC and Electrical MEP Sample.";
211 |
212 | IList ribbonItems = panel.AddStackedItems(
213 | d1, d2, d3 );
214 |
215 | // Add subitems to the HVAC and
216 | // electrical pulldown buttons:
217 |
218 | PulldownButton pulldown;
219 | PushButton pb;
220 | int i, j;
221 |
222 | for( i = 0; i < n; ++i )
223 | {
224 | j = i < nElectricalCommands ? 0 : 1;
225 | pulldown = ribbonItems[j] as PulldownButton;
226 |
227 | PushButtonData pbd = new PushButtonData(
228 | text[i], text[i], path, m + classNameStem[i] );
229 |
230 | pb = pulldown.AddPushButton( pbd );
231 |
232 | pb.ToolTip = text[i];
233 | }
234 | }
235 |
236 | public Result OnStartup( UIControlledApplication a )
237 | {
238 | // only create a new ribbon panel in Revit MEP:
239 |
240 | ProductType pt = a.ControlledApplication.Product;
241 |
242 | //if( ProductType.MEP == pt ) // 2012
243 |
244 | if( ProductType.MEP == pt
245 | || ProductType.Revit == pt ) // 2013
246 | {
247 | AddRibbonPanel( a );
248 | return Result.Succeeded;
249 | }
250 | return Result.Cancelled;
251 | }
252 |
253 | public Result OnShutdown( UIControlledApplication a )
254 | {
255 | return Result.Succeeded;
256 | }
257 | }
258 | }
259 |
260 | // C:\Program Files\Autodesk\Revit Architecture 2011\Program\Revit.exe
261 | // C:\a\j\adn\train\revit\2011\src\rme\test\hvac_project.rvt
262 |
263 | // C:\Program Files\Autodesk\Revit MEP 2011\Program\Revit.exe
264 | // C:\a\j\adn\train\revit\2011\src\rme\test\elec_project.rvt
265 |
--------------------------------------------------------------------------------
/AdnRme/Bip.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeremytammik/AdnRme/d2764222508f2dce275815bf95b755ae94754415/AdnRme/Bip.cs
--------------------------------------------------------------------------------
/AdnRme/CmdAbout.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | #region Namespaces
26 | using System;
27 | using Autodesk.Revit.Attributes;
28 | using Autodesk.Revit.DB;
29 | using Autodesk.Revit.UI;
30 | using DialogResult = System.Windows.Forms.DialogResult;
31 | #endregion // Namespaces
32 |
33 | namespace AdnRme
34 | {
35 | ///
36 | /// Command to display "About..." box.
37 | ///
38 | [Transaction( TransactionMode.ReadOnly )]
39 | public class CmdAbout : IExternalCommand
40 | {
41 | #region Execute Command
42 | ///
43 | /// Execute the command to display "About..." box.
44 | ///
45 | public Result Execute(
46 | ExternalCommandData commandData,
47 | ref String message,
48 | ElementSet elements )
49 | {
50 | try
51 | {
52 | AboutBox a = new AboutBox();
53 | DialogResult r = a.ShowDialog();
54 | return Result.Cancelled;
55 | }
56 | catch( Exception ex )
57 | {
58 | message = ex.Message;
59 | return Result.Failed;
60 | }
61 | }
62 | #endregion // Execute Command
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/AdnRme/CmdAssignFlowToTerminals.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | #region Namespaces
26 | using System;
27 | using System.Collections.Generic;
28 | using System.Diagnostics;
29 | using Autodesk.Revit.ApplicationServices;
30 | using Autodesk.Revit.Attributes;
31 | using Autodesk.Revit.DB;
32 | using Autodesk.Revit.DB.Mechanical;
33 | using Autodesk.Revit.UI;
34 | #endregion // Namespaces
35 |
36 | namespace AdnRme
37 | {
38 | [Transaction( TransactionMode.Manual )]
39 | class CmdAssignFlowToTerminals : IExternalCommand
40 | {
41 | #region Get Terminals Per Space
42 | ///
43 | /// Helper class for sorting the spaces by space number before listing them
44 | ///
45 | class NumericalComparer : IComparer
46 | {
47 | public int Compare( string x, string y )
48 | {
49 | return int.Parse( x ) - int.Parse( y );
50 | }
51 | }
52 |
53 | static Dictionary> GetTerminalsPerSpace(
54 | Document doc )
55 | {
56 | FilteredElementCollector terminals = Util.GetSupplyAirTerminals( doc );
57 |
58 | Dictionary> terminalsPerSpace
59 | = new Dictionary>();
60 |
61 | foreach( FamilyInstance terminal in terminals )
62 | {
63 | //string roomNr = terminal.Room.Number;
64 | string spaceNr = terminal.Space.Number; // changed Room to Space
65 | if( !terminalsPerSpace.ContainsKey( spaceNr ) )
66 | {
67 | terminalsPerSpace.Add( spaceNr, new List() );
68 | }
69 | terminalsPerSpace[spaceNr].Add( terminal );
70 | }
71 |
72 | List keys = new List( terminalsPerSpace.Keys );
73 | keys.Sort( new NumericalComparer() );
74 |
75 | string ids;
76 | List spaceTerminals;
77 | int n, nTerminals = 0;
78 |
79 | foreach( string key in keys )
80 | {
81 | spaceTerminals = terminalsPerSpace[key];
82 | n = spaceTerminals.Count;
83 | ids = Util.IdList( spaceTerminals );
84 |
85 | Debug.WriteLine( string.Format(
86 | "Space {0} contains {1} air terminal{2}{3} {4}",
87 | key, n, Util.PluralSuffix( n ), Util.DotOrColon( n ), ids ) );
88 |
89 | nTerminals += n;
90 | }
91 | n = terminalsPerSpace.Count;
92 |
93 | Debug.WriteLine( string.Format(
94 | "Processing a total of {0} space{1} containing {2} air terminal{3}.",
95 | n, Util.PluralSuffix( n ), nTerminals, Util.PluralSuffix( nTerminals ) ) );
96 |
97 | return terminalsPerSpace;
98 | }
99 | #endregion // Get Terminals Per Space
100 |
101 | #region AssignFlowToTerminals
102 |
103 | static double RoundFlowTo( double a )
104 | {
105 | a = a / Const.RoundTerminalFlowTo;
106 | a = Math.Round( a, 0, MidpointRounding.AwayFromZero );
107 | a = a * Const.RoundTerminalFlowTo;
108 | return a;
109 | }
110 |
111 | static void AssignFlowToTerminals( List terminals, double flow )
112 | {
113 | foreach( FamilyInstance terminal in terminals )
114 | {
115 | Parameter p = Util.GetTerminalFlowParameter( terminal );
116 | p.Set( flow );
117 | }
118 | }
119 |
120 | static void AssignFlowToTerminalsForSpace(
121 | List terminals,
122 | Space space )
123 | {
124 | Debug.Assert( null != terminals, "expected valid list of terminals" );
125 | int n = terminals.Count;
126 |
127 | double calculatedSupplyAirFlow = Util.GetSpaceParameterValue(
128 | space, Bip.CalculatedSupplyAirFlow, ParameterName.CalculatedSupplyAirFlow );
129 |
130 | double flowCfm = calculatedSupplyAirFlow * Const.SecondsPerMinute;
131 | double flowCfmPerOutlet = flowCfm / n;
132 | double flowCfmPerOutletRounded = RoundFlowTo( flowCfmPerOutlet );
133 | double flowPerOutlet = flowCfmPerOutletRounded / Const.SecondsPerMinute;
134 |
135 | string format = "Space {0} has calculated supply airflow {1} f^3/s = {2} CFM and {3} terminal{4}"
136 | + " --> flow {5} CFM per terminal, rounded to {6} = {7} f^3/s";
137 |
138 | Debug.WriteLine( string.Format( format,
139 | space.Number, Util.RealString( calculatedSupplyAirFlow ), Util.RealString( flowCfm ),
140 | n, Util.PluralSuffix( n ), Util.RealString( flowCfmPerOutlet ),
141 | Util.RealString( flowCfmPerOutletRounded ), Util.RealString( flowPerOutlet ) ) );
142 |
143 | AssignFlowToTerminals( terminals, flowPerOutlet );
144 | }
145 | #endregion // AssignFlowToTerminals
146 |
147 | #region Execute Command
148 | public Result Execute(
149 | ExternalCommandData commandData,
150 | ref String message,
151 | ElementSet elements )
152 | {
153 | try
154 | {
155 | WaitCursor waitCursor = new WaitCursor();
156 | UIApplication uiapp = commandData.Application;
157 | Document doc = uiapp.ActiveUIDocument.Document;
158 | //
159 | // 1. determine air terminals for each space.
160 | // determine the relationship between all air terminals and all spaces:
161 | // extract and group all air terminals per space
162 | // (key=space, val=set of air terminals)
163 | //
164 | Debug.WriteLine( "\nDetermining terminals per space..." );
165 | Dictionary> terminalsPerSpace = GetTerminalsPerSpace( doc );
166 | //
167 | // 2. assign flow to the air terminals depending on the space's calculated supply air flow.
168 | //
169 | //ElementFilterIterator it = doc.get_Elements( typeof( Room ) ); // 2008
170 | //ElementIterator it = doc.get_Elements( typeof( Space ) ); // 2009
171 | //List spaces = new List(); // 2009
172 | //doc.get_Elements( typeof( Space ), spaces ); // 2009
173 | //FilteredElementCollector collector = new FilteredElementCollector( doc );
174 | //collector.OfClass( typeof( Space ) );
175 | //IList spaces = collector.ToElements();
176 |
177 | using( Transaction tx = new Transaction( doc ) )
178 | {
179 | List spaces = Util.GetSpaces( doc );
180 | int n = spaces.Count;
181 |
182 | string s = "{0} of " + n.ToString() + " spaces processed...";
183 | string caption = "Assign Flow to Terminals";
184 | tx.Start( caption );
185 |
186 | using( ProgressForm pf = new ProgressForm( caption, s, n ) )
187 | {
188 | foreach( Space space in spaces )
189 | {
190 | if( terminalsPerSpace.ContainsKey( space.Number ) )
191 | {
192 | AssignFlowToTerminalsForSpace( terminalsPerSpace[space.Number], space );
193 | }
194 | pf.Increment();
195 | }
196 | }
197 | tx.Commit();
198 | Debug.WriteLine( "Completed." );
199 | return Result.Succeeded;
200 | }
201 | }
202 | catch( Exception ex )
203 | {
204 | message = ex.Message;
205 | return Result.Failed;
206 | }
207 | }
208 | #endregion // Execute Command
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/AdnRme/CmdChangeSize.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeremytammik/AdnRme/d2764222508f2dce275815bf95b755ae94754415/AdnRme/CmdChangeSize.cs
--------------------------------------------------------------------------------
/AdnRme/CmdElectricalConnectors.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | #region Namespaces
26 | using System;
27 | using System.Collections.Generic;
28 | using System.Diagnostics;
29 | using TreeNode = System.Windows.Forms.TreeNode;
30 | using Autodesk.Revit.ApplicationServices;
31 | using Autodesk.Revit.Attributes;
32 | using Autodesk.Revit.DB;
33 | using Autodesk.Revit.DB.Electrical;
34 | using Autodesk.Revit.UI;
35 | #endregion // Namespaces
36 |
37 | namespace AdnRme
38 | {
39 | [Transaction( TransactionMode.ReadOnly )]
40 | class CmdElectricalConnectors : IExternalCommand
41 | {
42 | #region Test code
43 | #if TEST_CODE
44 | ///
45 | /// Get the connected connector of one connector
46 | ///
47 | /// The connector to be analyzed
48 | /// The connected connector
49 | static Connector GetConnectedConnector( Connector connector )
50 | {
51 | Connector connectedConnector = null;
52 | ConnectorSet allRefs = connector.AllRefs;
53 | foreach( Connector c in allRefs )
54 | {
55 | // ignore non-EndConn connectors and connectors of the current element:
56 | if( ConnectorType.EndConn != c.ConnectorType
57 | || c.Owner.Id.Equals( connector.Owner.Id ) )
58 | {
59 | continue;
60 | }
61 | connectedConnector = c;
62 | break;
63 | }
64 | return connectedConnector;
65 | }
66 |
67 | static void PopulateChildren(
68 | MapParentToChildren mapParentToChildren,
69 | Element parent )
70 | {
71 | Connector c2 = null;
72 | ElementId id = parent.Id;
73 | FamilyInstance fi = parent as FamilyInstance;
74 | ElectricalSystem eq = parent as ElectricalSystem;
75 | Debug.Assert( null != fi || null != eq, "expected element to be family instance or electrical system" );
76 | ConnectorSet connectors = (null == eq)
77 | ? fi.MEPModel.ConnectorManager.Connectors
78 | : eq.ConnectorManager.Connectors;
79 | foreach( Connector c in connectors )
80 | {
81 | Debug.Assert( c.Owner.Id.Equals( id ), "expected connector owner to be this element" );
82 | //if( c.IsConnected ) // only valid for PhysicalConn
83 | //MEPSystem mepSystem = c.MEPSystem; // null for electrical connector
84 | //if( null == mepSystem ) // || !mepSystem.Id.IntegerValue.Equals( m_system.Id.IntegerValue )
85 | //{
86 | // continue;
87 | //}
88 | //c2 = GetConnectedConnector( c );
89 |
90 | ConnectorSet refs = c.AllRefs;
91 | Debug.Assert( 1 == refs.Size, "expected one single connected connector" );
92 | foreach( Connector tmp in refs )
93 | {
94 | c2 = tmp;
95 | }
96 | if( null != c2 )
97 | {
98 | Element e = c2.Owner;
99 | Debug.Assert( null != e, "expected valid connector owner" );
100 | Debug.Assert( e is FamilyInstance || e is ElectricalSystem, "expected electrical connector owner to be family instance or electrical equipment" );
101 | mapParentToChildren.Add( id, e );
102 | }
103 | }
104 | }
105 | #endif // TEST_CODE
106 | #endregion // Test code
107 |
108 | public Result Execute(
109 | ExternalCommandData commandData,
110 | ref String message,
111 | ElementSet elements )
112 | {
113 | UIApplication app = commandData.Application;
114 | Document doc = app.ActiveUIDocument.Document;
115 | //
116 | // retrieve electrical equipment:
117 | //
118 | List equipment = Util.GetElectricalEquipment( doc );
119 | int n = equipment.Count;
120 | Debug.WriteLine( string.Format(
121 | "Retrieved {0} electrical equipment instance{1}{2}",
122 | n, Util.PluralSuffix( n ), Util.DotOrColon( n ) ) );
123 | //
124 | // determine which equipment has parents;
125 | // the remaining ones are root nodes:
126 | //
127 | Dictionary equipmentParents
128 | = new Dictionary();
129 |
130 | foreach( FamilyInstance fi in equipment )
131 | {
132 | foreach( Connector c in fi.MEPModel.ConnectorManager.Connectors )
133 | {
134 | ConnectorSet refs = c.AllRefs;
135 | foreach( Connector c2 in refs )
136 | {
137 | Debug.Assert( null != c2.Owner,
138 | "expected valid connector owner" );
139 |
140 | Debug.Assert( c2.Owner is ElectricalSystem,
141 | "expected panel element to be electrical system" );
142 |
143 | ElectricalSystem eq = c2.Owner as ElectricalSystem;
144 | foreach( Element e2 in eq.Elements )
145 | {
146 | Debug.Assert( e2 is FamilyInstance,
147 | "expected electrical system element to be family instance" );
148 |
149 | if( !e2.Id.Equals( fi.Id ) )
150 | {
151 | if( equipment.Exists(
152 | delegate( Element e )
153 | { return e.Id.Equals( e2.Id ); } ) )
154 | {
155 | equipmentParents[e2.Id] = eq.Id;
156 | }
157 | }
158 | }
159 | }
160 | }
161 | }
162 |
163 | //n = equipment.RemoveAll( delegate( Element e ) { return subequipment.Exists( delegate( Element e2 ) { return e2.Id.Equals( e.Id ); } ); } );
164 |
165 | //
166 | // populate parent to children mapping:
167 | //
168 | ElementId nullId = ElementId.InvalidElementId;
169 | MapParentToChildren mapParentToChildren = new MapParentToChildren();
170 |
171 | foreach( FamilyInstance fi in equipment )
172 | {
173 | //ElementId parentId = equipmentParents.ContainsKey( fi.Id ) ? equipmentParents[fi.Id] : nullId;
174 | //mapParentToChildren.Add( parentId, fi );
175 |
176 | //
177 | // handle root nodes;
178 | // non-roots are handled below a children:
179 | //
180 | if( !equipmentParents.ContainsKey( fi.Id ) )
181 | {
182 | mapParentToChildren.Add( nullId, fi );
183 | }
184 |
185 | foreach( Connector c in fi.MEPModel.ConnectorManager.Connectors )
186 | {
187 | ConnectorSet refs = c.AllRefs;
188 | foreach( Connector c2 in refs )
189 | {
190 | Debug.Assert( null != c2.Owner,
191 | "expected valid connector owner" );
192 |
193 | Debug.Assert( c2.Owner is ElectricalSystem,
194 | "expected panel element to be electrical system" );
195 |
196 | ElectricalSystem eq = c2.Owner as ElectricalSystem;
197 | mapParentToChildren.Add( fi.Id, eq );
198 | foreach( Element e2 in eq.Elements )
199 | {
200 | Debug.Assert( e2 is FamilyInstance,
201 | "expected electrical system element to be family instance" );
202 |
203 | if( !e2.Id.Equals( fi.Id ) )
204 | {
205 | mapParentToChildren.Add( eq.Id, e2 );
206 | }
207 | }
208 | }
209 | }
210 | }
211 |
212 | #region Test code
213 | #if TEST_CODE
214 | //
215 | // retrieve electrical systems:
216 | //
217 | List systems = new List();
218 | doc.get_Elements( typeof( ElectricalSystem ), systems );
219 | n = systems.Count;
220 | Debug.WriteLine( string.Format( "Retrieved {0} electrical system{1}{2}",
221 | n, Util.PluralSuffix( n ), Util.DotOrColon( n ) ) );
222 | //
223 | // iterate over all electrical systems and recursively add
224 | // connected ecomponents starting from the system base equipment:
225 | //
226 | /*
227 | Dictionary systemDict = new Dictionary( n );
228 | foreach( ElectricalSystem s in systems )
229 | {
230 | systemDict[s.Name] = s;
231 | }
232 | List keys = new List( systemDict.Keys );
233 | keys.Sort();
234 | foreach( string key in keys )
235 | {
236 | FamilyInstance b = systemDict[key].BaseEquipment;
237 | if( null != b )
238 | {
239 | mapParentToChildren.Add( nullId, b ); // root node
240 | PopulateChildren( mapParentToChildren, b );
241 | }
242 | }
243 | foreach( ElectricalSystem s in systems )
244 | {
245 | FamilyInstance b = s.BaseEquipment;
246 | if( null != b )
247 | {
248 | mapParentToChildren.Add( nullId, b ); // root node
249 | PopulateChildren( mapParentToChildren, b );
250 | }
251 | }
252 | #endif // TEST_CODE
253 | #endregion // Test code
254 |
255 | //
256 | // get the electrical equipment category id:
257 | //
258 | Categories categories = doc.Settings.Categories;
259 | ElementId electricalEquipmentCategoryId = categories.get_Item(
260 | BuiltInCategory.OST_ElectricalEquipment ).Id;
261 |
262 | //
263 | // display hierarchical structure in tree view:
264 | //
265 | CmdInspectElectricalForm2 dialog
266 | = new CmdInspectElectricalForm2(
267 | mapParentToChildren, electricalEquipmentCategoryId, equipment );
268 |
269 | dialog.Show();
270 | return Result.Failed;
271 | }
272 | }
273 | }
274 |
--------------------------------------------------------------------------------
/AdnRme/CmdElectricalHierarchy2.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | #region Namespaces
26 | using System;
27 | using System.Collections.Generic;
28 | using System.Diagnostics;
29 | using TreeNode = System.Windows.Forms.TreeNode;
30 | using Autodesk.Revit.ApplicationServices;
31 | using Autodesk.Revit.Attributes;
32 | using Autodesk.Revit.DB;
33 | using Autodesk.Revit.DB.Electrical;
34 | using Autodesk.Revit.UI;
35 | #endregion // Namespaces
36 |
37 | namespace AdnRme
38 | {
39 | #region MapParentToChildren
40 | ///
41 | /// Map tree node parents to their children.
42 | ///
43 | /// The various possible combinations of parent and child
44 | /// element types include:
45 | ///
46 | /// null --> root panels
47 | /// panel --> systems
48 | /// system --> circuit elements, further panels, ...
49 | ///
50 | /// This map is populated as follows: as we iterate over all the relevant
51 | /// electrical equipment, systems, and circuit objects. Each object
52 | /// attempts to identify its parent, i.e. its destination parent node
53 | /// in the tree and registers itself in the parent's list of elements.
54 | /// We attempted to use the parent element itself as a key, but that
55 | /// does not work, so we reverted to using the parent element id as
56 | /// a key instead.
57 | ///
58 | public class MapParentToChildren : Dictionary>
59 | {
60 | ///
61 | /// Add a new parent, or a new child to a parent, ensuring that a new container
62 | /// list is created if this parent has not yet been registered.
63 | ///
64 | /// Parent element id
65 | /// New child element
66 | public void Add( ElementId parentId, Element child )
67 | {
68 | if( !this.ContainsKey( parentId ) )
69 | {
70 | this.Add( parentId, new List() );
71 | }
72 | if( null != child )
73 | {
74 | this[parentId].Add( child );
75 | }
76 | }
77 | }
78 |
79 | #region Using Element as Key
80 | ///
81 | /// I tried to use the Element instance itself as a key into this map,
82 | /// but apparently the comparison does not always work correctly, so I
83 | /// had to revert to using the element id instead.
84 | ///
85 | public class MapParentToChildren2 : Dictionary>
86 | {
87 | Element _root;
88 |
89 | public MapParentToChildren2( Element root )
90 | {
91 | _root = root;
92 | }
93 |
94 | public Element Root
95 | {
96 | get
97 | {
98 | return _root;
99 | }
100 | }
101 |
102 | public void Add( Element parent, Element child )
103 | {
104 | if( !this.ContainsKey( parent ) )
105 | {
106 | this.Add( parent, new List() );
107 | }
108 | this[parent].Add( child );
109 | }
110 | }
111 | #endregion // Using Element as Key
112 | #endregion // MapParentToChildren
113 |
114 | #region CmdElectricalHierarchy2
115 | ///
116 | /// Inspect the electrical system.
117 | ///
118 | /// Analyse the electrical system connection graph and display it in
119 | /// tree view in a a modeless dialogue, i.e. it remains visible after
120 | /// the command has completed.
121 | ///
122 | /// This presents a more direct approach than the first implementation
123 | /// in CmdElectricalSystemBrowser. In this implementation, we directly
124 | /// build the tree hierarchy in a MapParentToChildren dictionary from
125 | /// the element relationships. Also, we use element ids wherever
126 | /// possible, instead of key strings of the form
127 | /// "panel name : circuit or system name".
128 | ///
129 | /// Note: this sample was written before the introduction of the
130 | /// Connector and ConnectionManager classes. The complex determination
131 | /// of the connection hierarchy based on parameter values performed
132 | /// here can be much simplified using the connectors, as demonstrated
133 | /// by CmdElectricalConnectors.
134 | ///
135 | [Transaction( TransactionMode.ReadOnly )]
136 | class CmdElectricalHierarchy2 : IExternalCommand
137 | {
138 | public Result Execute(
139 | ExternalCommandData commandData,
140 | ref String message,
141 | ElementSet elements )
142 | {
143 | try
144 | {
145 | //
146 | // dictionary defining tree view info displayed in modeless
147 | // dialogue mapping parent node to all its circuit elements:
148 | // null --> root panels
149 | // panel --> systems
150 | // system --> circuit elements, panels, ...
151 | //
152 | MapParentToChildren mapParentToChildren = new MapParentToChildren();
153 | ElementId electricalEquipmentCategoryId = ElementId.InvalidElementId;
154 | List equipment;
155 | {
156 | //
157 | // run the analysis in its own scope, so the wait cursor
158 | // disappears before we display the modeless dialogue:
159 | //
160 | WaitCursor waitCursor = new WaitCursor();
161 | UIApplication app = commandData.Application;
162 | Document doc = app.ActiveUIDocument.Document;
163 | ElementId nullId = ElementId.InvalidElementId;
164 | //
165 | // retrieve electrical equipment instances:
166 | //
167 | equipment = Util.GetElectricalEquipment( doc );
168 | int n = equipment.Count;
169 | Debug.WriteLine( string.Format( "Retrieved {0} electrical equipment instance{1}{2}",
170 | n, Util.PluralSuffix( n ), Util.DotOrColon( n ) ) );
171 | Dictionary mapPanel = new Dictionary();
172 | foreach( FamilyInstance e in equipment )
173 | {
174 | //
175 | // ensure that every panel shows up in the list,
176 | // even if it does not have children:
177 | //
178 | mapParentToChildren.Add( e.Id, null );
179 | mapPanel[e.Name] = e;
180 | MEPModel mepModel = e.MEPModel;
181 | //ElectricalSystemSet systems2 = mepModel.ElectricalSystems; // 2020
182 | ISet systems2 = mepModel.GetElectricalSystems(); // 2021
183 | string panelAndSystem = string.Empty;
184 | if( null == systems2 )
185 | {
186 | panelAndSystem = CmdElectricalSystemBrowser.Unassigned; // this is a root node
187 | }
188 | else
189 | {
190 | Debug.Assert( 1 == systems2.Count,
191 | "expected equipment to belong to one single panel and system" );
192 |
193 | foreach( ElectricalSystem system in systems2 )
194 | {
195 | if( 0 < panelAndSystem.Length )
196 | {
197 | panelAndSystem += ", ";
198 | }
199 | panelAndSystem += system.PanelName + ":" + system.Name + ":" + system.Id.IntegerValue.ToString();
200 | }
201 | }
202 | Debug.WriteLine( " " + Util.ElementDescriptionAndId( e ) + " " + panelAndSystem );
203 | }
204 | //
205 | // retrieve electrical systems:
206 | // these are also returned by Util.GetCircuitElements(), by the way,
207 | // since they have the parameters RBS_ELEC_CIRCUIT_PANEL_PARAM and
208 | // RBS_ELEC_CIRCUIT_NUMBER that we use to identify those.
209 | //
210 | FilteredElementCollector c = new FilteredElementCollector( doc );
211 | IList systems = c.OfClass( typeof( ElectricalSystem ) ).ToElements();
212 | n = systems.Count;
213 | Debug.WriteLine( string.Format( "Retrieved {0} electrical system{1}{2}",
214 | n, Util.PluralSuffix( n ), Util.DotOrColon( n ) ) );
215 | foreach( ElectricalSystem system in systems )
216 | {
217 | string panelName = system.PanelName;
218 | if( 0 == panelName.Length )
219 | {
220 | panelName = CmdElectricalSystemBrowser.Unassigned; // will not appear in tree
221 | }
222 | else
223 | {
224 | //
225 | // todo: is there a more direct way to identify
226 | // what panel a system belongs to? this seems error
227 | // prone ... what if a panel name occurs multiple times?
228 | // how do we identify which one to use?
229 | //
230 | FamilyInstance panel = mapPanel[panelName];
231 | mapParentToChildren.Add( panel.Id, system );
232 | }
233 | string panelAndSystem = panelName + ":" + system.Name + ":" + system.Id.IntegerValue.ToString();
234 | Debug.WriteLine( " " + Util.ElementDescriptionAndId( system ) + " " + panelAndSystem );
235 | Debug.Assert( system.ConnectorManager.Owner.Id.Equals( system.Id ), "expected electrical system's connector manager owner to be system itself" );
236 | }
237 | //
238 | // now we have the equipment and systems,
239 | // we can build the non-leaf levels of the tree:
240 | //
241 | foreach( FamilyInstance e in equipment )
242 | {
243 | MEPModel mepModel = e.MEPModel;
244 | //ElectricalSystemSet systems2 = mepModel.ElectricalSystems; // 2020
245 | ISet systems2 = mepModel.GetElectricalSystems(); // 2021
246 | if( null == systems2 )
247 | {
248 | mapParentToChildren.Add( nullId, e ); // root node
249 | }
250 | else
251 | {
252 | Debug.Assert( 1 == systems2.Count, "expected equipment to belong to one single panel and system" );
253 | foreach( ElectricalSystem system in systems2 )
254 | {
255 | mapParentToChildren.Add( system.Id, e );
256 | }
257 | }
258 | }
259 | //
260 | // list all circuit elements:
261 | //
262 | BuiltInParameter bipPanel = BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM;
263 | BuiltInParameter bipCircuit = BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER;
264 | IList circuitElements = Util.GetCircuitElements( doc );
265 | n = circuitElements.Count;
266 | Debug.WriteLine( string.Format( "Retrieved {0} circuit element{1}...",
267 | n, Util.PluralSuffix( n ) ) );
268 | n = 0;
269 | foreach( Element e in circuitElements )
270 | {
271 | if( e is ElectricalSystem )
272 | {
273 | ++n;
274 | }
275 | else
276 | {
277 | string circuitName = e.get_Parameter( bipCircuit ).AsString();
278 | string panelName = e.get_Parameter( bipPanel ).AsString();
279 | string key = panelName + ":" + circuitName;
280 | string panelAndSystem = string.Empty;
281 | FamilyInstance inst = e as FamilyInstance;
282 | Debug.Assert( null != inst, "expected all circuit elements to be family instances" );
283 | MEPModel mepModel = inst.MEPModel;
284 | //ElectricalSystemSet systems2 = mepModel.ElectricalSystems; // 2020
285 | ISet systems2 = mepModel.GetElectricalSystems(); // 2021
286 | Debug.Assert( null != systems2, "expected circuit element to belong to an electrical system" );
287 | Debug.Assert( 0 < systems2.Count, "expected circuit element to belong to an electrical system" );
288 |
289 | // this fails in "2341_MEP - 2009 Central.rvt", says martin:
290 | //
291 | // a circuit element can belong to several systems ... imagine
292 | // a piece of telephone equipment which hooks up to a phone line
293 | // and also requires power ... so i removed this assertion:
294 | //
295 | //Debug.Assert( 1 == systems2.Size, "expected circuit element to belong to one single system" );
296 |
297 | foreach( ElectricalSystem system in systems2 )
298 | {
299 | if( 0 < panelAndSystem.Length )
300 | {
301 | panelAndSystem += ", ";
302 | }
303 | panelAndSystem += system.PanelName + ":" + system.Name + ":" + system.Id.IntegerValue.ToString();
304 | Debug.Assert( system.PanelName == panelName, "expected same panel name in parameter and electrical system" );
305 | // this fails in "2341_MEP - 2009 Central.rvt", says martin:
306 | //Debug.Assert( system.Name == circuitName, "expected same name in circuit parameter and system" );
307 | mapParentToChildren.Add( system.Id, e );
308 | }
309 | Debug.WriteLine( string.Format( " {0} panel:circuit {1}", Util.ElementDescriptionAndId( e ), panelAndSystem ) );
310 | }
311 | }
312 | Debug.WriteLine( string.Format( "{0} circuit element{1} were the electrical systems.",
313 | n, Util.PluralSuffix( n ) ) );
314 | //
315 | // get the electrical equipment category id:
316 | //
317 | Categories categories = doc.Settings.Categories;
318 | electricalEquipmentCategoryId = categories.get_Item( BuiltInCategory.OST_ElectricalEquipment ).Id;
319 | }
320 | //
321 | // we have assembled the entire required tree view structure, so let us display it:
322 | //
323 | CmdInspectElectricalForm2 dialog = new CmdInspectElectricalForm2( mapParentToChildren, electricalEquipmentCategoryId, equipment );
324 | dialog.Show();
325 | return Result.Succeeded;
326 | }
327 | catch( Exception ex )
328 | {
329 | message = ex.Message;
330 | return Result.Failed;
331 | }
332 | }
333 | }
334 | #endregion // CmdElectricalHierarchy2
335 | }
336 |
--------------------------------------------------------------------------------
/AdnRme/CmdElectricalSystemBrowser.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | #region Namespaces
26 | using System;
27 | using System.Collections.Generic;
28 | using System.Diagnostics;
29 | using Autodesk.Revit.ApplicationServices;
30 | using Autodesk.Revit.Attributes;
31 | using Autodesk.Revit.DB;
32 | using Autodesk.Revit.DB.Electrical;
33 | using Autodesk.Revit.UI;
34 | #endregion // Namespaces
35 |
36 | namespace AdnRme
37 | {
38 | #region CmdElectricalSystemBrowser
39 | ///
40 | /// Inspect the electrical system.
41 | ///
42 | /// We reproduce the information provided in the Power section of the
43 | /// Revit MEP mechanical system browser and display it in a modeless
44 | /// dialogue, i.e. it remains visible after the command has completed.
45 | ///
46 | /// The challenge here is to reproduce all the nodes, and the sorting order.
47 | ///
48 | /// The system browser has three levels of nodes, panel > system > element,
49 | /// as well as one 'Unassigned' top level node, where 'Unassigned' replaces
50 | /// the panel. System may also be circuit number.
51 | ///
52 | /// In this implementation, the nodes come from two sources:
53 | ///
54 | /// - electrical equipment, which always has a system name and is
55 | /// either unassigned or has a panel name
56 | /// - circuit elements, which have a non-empty circuit number
57 | /// parameter value.
58 | ///
59 | /// The electrical equipment can be selected by filtering for its type,
60 | /// ElectricalEquipment, the circuit elements by filtering for
61 | /// BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER.
62 | ///
63 | /// Each of these two sets can be sorted into dictionaries using the keys
64 | ///
65 | /// panel:circuit number or
66 | /// panel:system name or
67 | /// Unassigned:system name
68 | ///
69 | /// and mapping these to the connected elements.
70 | ///
71 | /// These two dictionaries, merged together and appropriately sorted,
72 | /// represent the same information as the system browser.
73 | ///
74 | /// Important note: this whole sample was implemented while exploring
75 | /// how the systm is actually hooked up. Once that is fully understood,
76 | /// a much more straightforward and efficient algorithm for traversing
77 | /// and displaying it can be implemented. So please don't simply reuse
78 | /// this code, understand it first and then rewrite it.
79 | ///
80 | /// Important note 2: this sample was originally written for Revit 2008,
81 | /// before the introduction of the Connector and ConnectionManager classes,
82 | /// or even any MEP-specific API at all. The complex determination of the
83 | /// connection hierarchy based on parameter values performed here can be
84 | /// much simplified using the connectors, as demonstrated by
85 | /// CmdElectricalConnectors.
86 | ///
87 | [Transaction( TransactionMode.ReadOnly )]
88 | class CmdElectricalSystemBrowser : IExternalCommand
89 | {
90 | public const string Unassigned = "Unassigned";
91 |
92 | #region Sorting comparers
93 |
94 | #region NumericalComparer
95 | ///
96 | /// Helper class for sorting strings numerically by number.
97 | ///
98 | class NumericalComparer : IComparer
99 | {
100 | public int Compare( string x, string y )
101 | {
102 | return int.Parse( x ) - int.Parse( y );
103 | }
104 | }
105 | #endregion // NumericalComparer
106 |
107 | #region PanelCircuitComparer
108 | ///
109 | /// Helper class for sorting panel:circuit key strings
110 | /// alphabetically by panel name and numerically by circuit number.
111 | /// We also need to handle the format "MDP:1,3,5".
112 | /// 2010-06-11: we need to handle "<unnamed>".
113 | ///
114 | class PanelCircuitComparer : IComparer
115 | {
116 | public int Compare( string x, string y )
117 | {
118 | int d = x.CompareTo( y );
119 | if( 0 != d )
120 | {
121 | string[] a = x.Split( ':' );
122 | string[] b = y.Split( ':' );
123 | d = a[0].CompareTo( b[0] );
124 | if( 0 == d )
125 | {
126 | string[] a2 = a[1].Split( ',' );
127 | string[] b2 = b[1].Split( ',' );
128 | d = a2.Length - b2.Length;
129 | if( 0 == d )
130 | {
131 | for( int i = 0; i < a2.Length && 0 == d; ++i )
132 | {
133 | d = int.Parse( a2[0] ) - int.Parse( b2[0] );
134 | }
135 | }
136 | }
137 | }
138 | return d;
139 | }
140 | }
141 | #endregion // PanelCircuitComparer
142 |
143 | #region PanelSystemComparer
144 | ///
145 | /// Helper class for sorting panel:system key strings,
146 | /// first alphabetically by panel name, second either
147 | /// alphabetically by system name or numerically by
148 | /// circuit number.
149 | ///
150 | public class PanelSystemComparer : IComparer
151 | {
152 | #region JtIsDigit
153 | //
154 | // JtIsDigit is faster than using char.IsDigit() in a lop, cf.
155 | // http://weblogs.asp.net/justin_rogers/archive/2004/03/29/100982.aspx
156 | // Performance: Different methods for testing string input for numeric values...
157 | // by Justin Rogers
158 | //
159 | ///
160 | /// Test whether all characters in given string are decimal digits.
161 | ///
162 | public static bool JtIsDigit( string s )
163 | {
164 | foreach( char a in s )
165 | {
166 | if( a < '0' || '9' < a )
167 | {
168 | return false;
169 | }
170 | }
171 | return true;
172 | }
173 |
174 | public static bool JtIsDigitOrComma( string s )
175 | {
176 | foreach( char a in s )
177 | {
178 | if( (a < '0' || '9' < a) && (',' != a) )
179 | {
180 | return false;
181 | }
182 | }
183 | return true;
184 | }
185 | #endregion // JtIsDigit
186 |
187 | int CompareCommaDelimitedIntegerLists( string x, string y )
188 | {
189 | int nx = x.IndexOf( ',' );
190 | int ny = y.IndexOf( ',' );
191 | int ix = ( 0 < nx ) ? int.Parse( x.Substring( 0, nx ) ) : int.Parse( x );
192 | int iy = ( 0 < ny ) ? int.Parse( y.Substring( 0, ny ) ) : int.Parse( y );
193 | int d = ix - iy;
194 | return ( 0 == d && 0 < nx && 0 < ny )
195 | ? CompareCommaDelimitedIntegerLists( x.Substring( nx + 1 ), y.Substring( ny + 1 ) )
196 | : (0 == d ? nx - ny : d);
197 | }
198 |
199 | public int Compare( string x, string y )
200 | {
201 | string[] a = x.Split( ':' );
202 | string[] b = y.Split( ':' );
203 | int d = a[0].CompareTo( b[0] );
204 | if( 0 == d
205 | && 1 < a.GetLength( 0 )
206 | && 1 < b.GetLength( 0 ) )
207 | {
208 | d = ( JtIsDigitOrComma( a[1] ) && JtIsDigitOrComma( b[1] ) )
209 | ? CompareCommaDelimitedIntegerLists( a[1], b[1] )
210 | : a[1].CompareTo( b[1] );
211 | }
212 | return d;
213 | }
214 | }
215 | #endregion // PanelSystemComparer
216 | #endregion // Sorting comparers
217 |
218 | #region ListEquipment
219 | ///
220 | /// List an electrical equipment instance and insert its data into
221 | /// the dictionary mapping panel + system name to equipment instances.
222 | ///
223 | static void ListEquipment(
224 | FamilyInstance elecEqip,
225 | IDictionary> mapPanelAndSystemToEquipment )
226 | {
227 | MEPModel mepModel = elecEqip.MEPModel;
228 | //ElectricalSystemSet systems = mepModel.ElectricalSystems; // 2020
229 | ISet systems = mepModel.GetElectricalSystems(); // 2021
230 | string s = string.Empty;
231 | if( null == systems )
232 | {
233 | s = Unassigned + ":" + elecEqip.Name;
234 | }
235 | else
236 | {
237 | Debug.Assert( 1 == systems.Count,
238 | "expected equipment to belong to one single panel and system" );
239 |
240 | foreach( ElectricalSystem system in systems )
241 | {
242 | if( 0 < s.Length )
243 | {
244 | s += ", ";
245 | }
246 | s += system.PanelName + ":" + system.Name;
247 | }
248 | }
249 | Debug.WriteLine( " " + elecEqip.Name + ": " + s );
250 | Debug.Assert( !mapPanelAndSystemToEquipment.ContainsKey( s ), "expected each panel and system to occur in one equipment element only" );
251 | if( !mapPanelAndSystemToEquipment.ContainsKey( s ) )
252 | {
253 | mapPanelAndSystemToEquipment.Add( s, new List() );
254 | }
255 | mapPanelAndSystemToEquipment[s].Add( elecEqip );
256 | }
257 | #endregion // ListEquipment
258 |
259 | static public Result Execute2(
260 | ExternalCommandData commandData,
261 | ref String message,
262 | ElementSet elements,
263 | bool populateFullHierarchy )
264 | {
265 | try
266 | {
267 | WaitCursor waitCursor = new WaitCursor();
268 | UIApplication app = commandData.Application;
269 | Document doc = app.ActiveUIDocument.Document;
270 | //
271 | // display electrical equipment instance data,
272 | // i.e. equipment_name:system_name, and convert it to
273 | // a map from key = panel:circuit --> equipment:
274 | //
275 | List equipment = Util.GetElectricalEquipment( doc );
276 | int n = equipment.Count;
277 | Debug.WriteLine( string.Format( "Retrieved {0} electrical equipment instance{1}{2}",
278 | n, Util.PluralSuffix( n ), Util.DotOrColon( n ) ) );
279 | Dictionary> mapPanelAndSystemToEquipment = new Dictionary>();
280 | foreach( FamilyInstance elecEqip in equipment )
281 | {
282 | ListEquipment( elecEqip, mapPanelAndSystemToEquipment );
283 | }
284 | //
285 | // determine mapping from panel to circuit == electrical system:
286 | //
287 | Dictionary> mapPanelToSystems
288 | = new Dictionary>();
289 |
290 | IList systems = Util.GetElectricalSystems( doc );
291 | n = systems.Count;
292 | Debug.WriteLine( string.Format( "Retrieved {0} electrical system{1}.",
293 | n, Util.PluralSuffix( n ) ) );
294 | //
295 | // all circuits which are fed from the same family instance have
296 | // the same panel name, so you can retrieve all of these circuits.
297 | //
298 | // todo: there is an issue here if there are several different panels
299 | // with the same name! they will get merged in the tree view,
300 | // but they should stay separate. possible workaround: add the
301 | // element id to keep them separate, and then remove it again
302 | // when displaying in tree view.
303 | //
304 | foreach( ElectricalSystem system in systems )
305 | {
306 | string panelName = system.PanelName;
307 |
308 | Debug.WriteLine( " system " + system.Name + ": panel " + panelName
309 | + " load classifications " + system.LoadClassifications );
310 |
311 | if( !mapPanelToSystems.ContainsKey( panelName ) )
312 | {
313 | mapPanelToSystems.Add( panelName,
314 | new SortedSet() );
315 | }
316 | mapPanelToSystems[panelName].Add( system );
317 | }
318 | n = mapPanelToSystems.Count;
319 | //Debug.WriteLine( string.Format( "Mapping from the {0} panel{1} to systems, system name :circuit name(connectors/unused connectors):", n, Util.PluralSuffix( n ) ) );
320 | Debug.WriteLine( string.Format( "Mapping from the {0} panel{1} to electrical systems == circuits:",
321 | n, Util.PluralSuffix( n ) ) );
322 | List keys = new List( mapPanelToSystems.Keys );
323 | keys.Sort();
324 | string s;
325 | foreach( string panelName in keys )
326 | {
327 | s = string.Empty;
328 | foreach( ElectricalSystem system in mapPanelToSystems[panelName] )
329 | {
330 | ConnectorManager cmgr = system.ConnectorManager;
331 |
332 | // the connector manager does not include any logical connectors
333 | // in the Revit 2009 fcs and wu1 API, only physical ones:
334 | //Debug.Assert( 0 == cmgr.Connectors.Size,
335 | // "electrical connector count is always zero" );
336 |
337 | Debug.Assert( cmgr.UnusedConnectors.Size <= cmgr.Connectors.Size,
338 | "unused connectors is a subset of connectors" );
339 |
340 | Debug.Assert( system.Name.Equals( system.CircuitNumber ),
341 | "ElectricalSystem Name and CircuitNumber properties are always identical" );
342 |
343 | //s += ( 0 < s.Length ? ", " : ": " ) + system.Name;
344 |
345 | s += ( 0 < s.Length ? ", " : ": " ) + system.Name // + ":" + system.CircuitNumber
346 | + "(" + cmgr.Connectors.Size.ToString()
347 | + "/" + cmgr.UnusedConnectors.Size.ToString() + ")";
348 | }
349 | Debug.WriteLine( " " + panelName + s );
350 | }
351 | /*
352 | Debug.WriteLine( "Mapping from panels to systems to connected elements:" );
353 | foreach( string panelName in keys )
354 | {
355 | Debug.WriteLine( " panel " + panelName + ":" );
356 | foreach( ElectricalSystem system in mapPanelToSystems[panelName] )
357 | {
358 | ConnectorManager cmgr = system.ConnectorManager;
359 | n = cmgr.Connectors.Size;
360 | Debug.WriteLine( string.Format( " system {0} has {1} connector{2}{3}", system.Name, n, Util.PluralSuffix( n ), Util.DotOrColon( n ) ) );
361 | foreach( Connector connector in system.ConnectorManager.Connectors )
362 | {
363 | Element owner = connector.Owner;
364 | Debug.WriteLine( string.Format( " owner {0} {1}, domain {2}", owner.Name, owner.Id.IntegerValue, connector.Domain ) );
365 | }
366 | }
367 | }
368 | */
369 |
370 | //
371 | // list all circuit elements:
372 | //
373 | // this captures all elements in circuits H-2: 2, 4, 6 etc,
374 | // but not the element T2 in H-2:1,3,5, because it has no circuit number,
375 | // just a panel number.
376 | //
377 | BuiltInParameter bipPanel = BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM;
378 | BuiltInParameter bipCircuit = BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER;
379 | IList circuitElements = Util.GetCircuitElements( doc );
380 | n = circuitElements.Count;
381 | Debug.WriteLine( string.Format( "Retrieved {0} circuit element{1}{2}",
382 | n, Util.PluralSuffix( n ), Util.DotOrColon( n ) ) );
383 | Dictionary> mapPanelAndCircuitToElements = new Dictionary>();
384 | foreach( Element e in circuitElements )
385 | {
386 | string circuitName = e.get_Parameter( bipCircuit ).AsString();
387 | //
388 | // do not map an electrical system to itself:
389 | //
390 | if( !(e is ElectricalSystem && e.Name.Equals( circuitName )) )
391 | {
392 | string panelName = e.get_Parameter( bipPanel ).AsString();
393 | string key = panelName + ":" + circuitName;
394 | Debug.WriteLine( string.Format( " {0} <{1} {2}> panel:circuit {3}", e.GetType().Name, e.Name, e.Id.IntegerValue, key ) );
395 | if( !mapPanelAndCircuitToElements.ContainsKey( key ) )
396 | {
397 | mapPanelAndCircuitToElements.Add( key, new List() );
398 | }
399 | mapPanelAndCircuitToElements[key].Add( e );
400 | }
401 | }
402 | n = mapPanelAndCircuitToElements.Count;
403 | Debug.WriteLine( string.Format( "Mapped circuit elements to {0} panel:circuit{1}{2}",
404 | n, Util.PluralSuffix( n ), Util.DotOrColon( n ) ) );
405 | keys.Clear();
406 | keys.AddRange( mapPanelAndCircuitToElements.Keys );
407 | keys.Sort( new PanelCircuitComparer() );
408 | foreach( string panelAndCircuit in keys )
409 | {
410 | List a = new List( mapPanelAndCircuitToElements[panelAndCircuit].Count );
411 | foreach( Element e in mapPanelAndCircuitToElements[panelAndCircuit] )
412 | {
413 | FamilyInstance inst = e as FamilyInstance;
414 | a.Add( ( null == inst ? e.Category.Name : inst.Symbol.Family.Name) + " " + e.Name );
415 | }
416 | a.Sort();
417 | s = string.Join( ", ", a.ToArray() );
418 | Debug.WriteLine( " " + panelAndCircuit + ": " + s );
419 | }
420 |
421 | #region Aborted attempt to use RBS_ELEC_CIRCUIT_PANEL_PARAM
422 | #if USE_RBS_ELEC_CIRCUIT_PANEL_PARAM
423 | //
424 | // list all panel elements:
425 | //
426 | // selecting all elements with a BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER
427 | // captures all elements in circuits H-2: 2, 4, 6 etc, but not the element
428 | // T2 in H-2:1,3,5, because it has no circuit number, just a panel number.
429 | //
430 | // so grab everything with a panel number instead.
431 | //
432 | // all this added to the selection was lots of wires, so forget it again.
433 | //
434 | BuiltInParameter bipCircuit = BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER;
435 | BuiltInParameter bipPanel = BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM;
436 | List circuitElements = new List();
437 | Util.GetElementsWithParameter( circuitElements, bipPanel, app );
438 | n = circuitElements.Count;
439 | Debug.WriteLine( string.Format( "Retrieved {0} circuit element{1}{2}",
440 | n, Util.PluralSuffix( n ), Util.DotOrColon( n ) ) );
441 | Dictionary> mapCircuitToElements = new Dictionary>();
442 | foreach( Element e in circuitElements )
443 | {
444 | string panelName = e.get_Parameter( bipPanel ).AsString();
445 | Parameter p = e.get_Parameter( bipCircuit );
446 | if( null == p )
447 | {
448 | Debug.WriteLine( string.Format( " {0} <{1} {2}> panel:circuit {3}:null", e.GetType().Name, e.Name, e.Id.IntegerValue, panelName ) );
449 | }
450 | else
451 | {
452 | string circuitName = p.AsString();
453 | //
454 | // do not map an electrical system to itself:
455 | //
456 | if( !( e is ElectricalSystem && e.Name.Equals( circuitName ) ) )
457 | {
458 | string key = panelName + ":" + circuitName;
459 | Debug.WriteLine( string.Format( " {0} <{1} {2}> panel:circuit {3}", e.GetType().Name, e.Name, e.Id.IntegerValue, key ) );
460 | if( !mapCircuitToElements.ContainsKey( key ) )
461 | {
462 | mapCircuitToElements.Add( key, new List() );
463 | }
464 | mapCircuitToElements[key].Add( e );
465 | }
466 | }
467 | }
468 | n = mapCircuitToElements.Count;
469 | Debug.WriteLine( string.Format( "Mapped circuit elements to {0} panel:circuit{1}{2}",
470 | n, Util.PluralSuffix( n ), Util.DotOrColon( n ) ) );
471 | keys.Clear();
472 | keys.AddRange( mapCircuitToElements.Keys );
473 | keys.Sort( new PanelCircuitComparer() );
474 | foreach( string circuitName in keys )
475 | {
476 | List a = new List( mapCircuitToElements[circuitName].Count );
477 | foreach( Element e in mapCircuitToElements[circuitName] )
478 | {
479 | FamilyInstance inst = e as FamilyInstance;
480 | a.Add( ( null == inst ? e.Category.Name : inst.Symbol.Family.Name ) + " " + e.Name );
481 | }
482 | a.Sort();
483 | s = string.Join( ", ", a.ToArray() );
484 | Debug.WriteLine( " " + circuitName + ": " + s );
485 | }
486 | #endif // USE_RBS_ELEC_CIRCUIT_PANEL_PARAM
487 | #endregion // Aborted attempt to use RBS_ELEC_CIRCUIT_PANEL_PARAM
488 |
489 | //
490 | // merge the two trees of equipment and circuit elements
491 | // to reproduce the content of the system browser ... the
492 | // hardest part of this is setting up the PanelSystemComparer
493 | // to generate the same sort order as the system browser:
494 | //
495 | //n = mapPanelAndSystemToEquipment.Count + mapPanelAndCircuitToElements.Count;
496 | //Dictionary> mapSystemBrowser = new Dictionary>( n );
497 | Dictionary> mapSystemBrowser = new Dictionary>( mapPanelAndCircuitToElements );
498 | foreach( KeyValuePair> pair in mapPanelAndSystemToEquipment )
499 | {
500 | mapSystemBrowser[pair.Key] = pair.Value;
501 | }
502 | n = mapSystemBrowser.Count;
503 | Debug.WriteLine( string.Format( "Mapped equipment + circuit elements to {0} panel:system{1}{2}",
504 | n, Util.PluralSuffix( n ), Util.DotOrColon( n ) ) );
505 | keys.Clear();
506 | keys.AddRange( mapSystemBrowser.Keys );
507 | keys.Sort( new PanelSystemComparer() );
508 | foreach( string panelAndSystem in keys )
509 | {
510 | List a = new List( mapSystemBrowser[panelAndSystem].Count );
511 | foreach( Element e in mapSystemBrowser[panelAndSystem] )
512 | {
513 | a.Add( Util.BrowserDescription( e ) );
514 | }
515 | a.Sort();
516 | s = string.Join( ", ", a.ToArray() );
517 | Debug.WriteLine( string.Format( " {0}({1}): ", panelAndSystem, a.Count ) + s );
518 | }
519 | //
520 | // get the electrical equipment category id:
521 | //
522 | Categories categories = doc.Settings.Categories;
523 | ElementId electricalEquipmentCategoryId = categories.get_Item( BuiltInCategory.OST_ElectricalEquipment ).Id;
524 | //
525 | // we have assembled the required information and structured it
526 | // sufficiently for the tree view, so now let us go ahead and display it:
527 | //
528 | CmdInspectElectricalForm dialog = new CmdInspectElectricalForm( mapSystemBrowser, electricalEquipmentCategoryId, populateFullHierarchy );
529 | dialog.Show();
530 | return Result.Succeeded;
531 | }
532 | catch (Exception ex)
533 | {
534 | message = ex.Message;
535 | return Result.Failed;
536 | }
537 | }
538 |
539 | public Result Execute(
540 | ExternalCommandData commandData,
541 | ref String message,
542 | ElementSet elements )
543 | {
544 | return Execute2( commandData, ref message, elements, false );
545 | }
546 | }
547 | #endregion // CmdElectricalSystemBrowser
548 |
549 | #region CmdElectricalHierarchy
550 | [Transaction( TransactionMode.ReadOnly )]
551 | class CmdElectricalHierarchy : IExternalCommand
552 | {
553 | public Result Execute(
554 | ExternalCommandData commandData,
555 | ref String message,
556 | ElementSet elements )
557 | {
558 | return CmdElectricalSystemBrowser.Execute2( commandData, ref message, elements, true );
559 | }
560 | }
561 | #endregion // CmdElectricalHierarchy
562 | }
563 |
--------------------------------------------------------------------------------
/AdnRme/CmdInspectElectricalForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace AdnRme
2 | {
3 | partial class CmdInspectElectricalForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose( bool disposing )
15 | {
16 | if( disposing && ( components != null ) )
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose( disposing );
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.tv = new System.Windows.Forms.TreeView();
32 | this.SuspendLayout();
33 | //
34 | // tv
35 | //
36 | this.tv.Anchor = ( ( System.Windows.Forms.AnchorStyles ) ( ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom )
37 | | System.Windows.Forms.AnchorStyles.Left )
38 | | System.Windows.Forms.AnchorStyles.Right ) ) );
39 | this.tv.Location = new System.Drawing.Point( 0, 0 );
40 | this.tv.Name = "tv";
41 | this.tv.Size = new System.Drawing.Size( 294, 276 );
42 | this.tv.TabIndex = 0;
43 | //
44 | // CmdInspectElectricaForm
45 | //
46 | this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F );
47 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
48 | this.ClientSize = new System.Drawing.Size( 292, 273 );
49 | this.Controls.Add( this.tv );
50 | this.Name = "CmdInspectElectricaForm";
51 | this.Text = "Inspect Electrical System";
52 | this.ResumeLayout( false );
53 |
54 | }
55 |
56 | #endregion
57 |
58 | private System.Windows.Forms.TreeView tv;
59 | }
60 | }
--------------------------------------------------------------------------------
/AdnRme/CmdInspectElectricalForm.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeremytammik/AdnRme/d2764222508f2dce275815bf95b755ae94754415/AdnRme/CmdInspectElectricalForm.cs
--------------------------------------------------------------------------------
/AdnRme/CmdInspectElectricalForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/AdnRme/CmdInspectElectricallForm2.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | #region Namespaces
26 | using System;
27 | using System.Collections.Generic;
28 | using System.Diagnostics;
29 | using System.Drawing;
30 | using System.Windows.Forms;
31 | using WinForm = System.Windows.Forms.Form;
32 | using Autodesk.Revit.Attributes;
33 | using Autodesk.Revit.DB;
34 | using Autodesk.Revit.DB.Electrical;
35 | using Autodesk.Revit.UI;
36 | #endregion // Namespaces
37 |
38 | namespace AdnRme
39 | {
40 | ///
41 | /// Form displaying electrical system elements in a tree view
42 | /// according to their connection hierarchy, and a list view
43 | /// of electrical equipment providing immediate access to jump
44 | /// directly into the appropriate location in the tree view.
45 | ///
46 | public partial class CmdInspectElectricalForm2 : WinForm
47 | {
48 | ElementId _electricalEquipmentCategoryId;
49 | Dictionary _done = new Dictionary();
50 | ElectricalElementComparer _comparer;
51 |
52 | static public string ElectricalElementText( Element e, ElementId electricalEquipmentCategoryId )
53 | {
54 | bool isCircuit = e is ElectricalSystem;
55 | bool isEquipment = e.Category.Id.Equals( electricalEquipmentCategoryId );
56 | return ( isEquipment || isCircuit ) ? e.Name : Util.BrowserDescription( e );
57 | }
58 |
59 | #region PopulateFromMapParentToChildren
60 | void PopulateFromMapParentToChildren(
61 | TreeNodeCollection tnc,
62 | ElementId parentId,
63 | MapParentToChildren map )
64 | {
65 | if( map.ContainsKey( parentId ) )
66 | {
67 | List children = map[parentId];
68 | children.Sort( _comparer );
69 | string key, text;
70 | bool isEquipment; // isCircuit
71 | foreach( Element e in children )
72 | {
73 | if( !_done.ContainsKey( e.Id ) )
74 | {
75 | _done[e.Id] = 1;
76 | //isCircuit = e is ElectricalSystem;
77 | isEquipment = e.Category.Id.Equals( _electricalEquipmentCategoryId );
78 | key = Util.ElementDescriptionAndId( e );
79 | //text = ( isEquipment || isCircuit ) ? e.Name : Util.BrowserDescription( e );
80 | text = ElectricalElementText( e, _electricalEquipmentCategoryId );
81 | TreeNode tn = tnc.Add( key, text );
82 | CmdInspectElectricalForm.AddLoadNodes( tn, e );
83 | if( map.ContainsKey( e.Id ) )
84 | {
85 | //
86 | // highlight circuit e.g. electrical system node that has
87 | // electrical equipment connected to it; also avoid setting
88 | // it to bold multiple times over:
89 | //
90 | if( isEquipment )
91 | {
92 | TreeNode p = tn.Parent;
93 | listBox1.Items.Add( new PanelTreeNodeHelper( e, tn ) );
94 | if( null != p && ( null == p.NodeFont || !p.NodeFont.Bold ) )
95 | {
96 | p.NodeFont = new System.Drawing.Font( this.Font, FontStyle.Bold );
97 | }
98 | }
99 | PopulateFromMapParentToChildren( tn.Nodes, e.Id, map );
100 | }
101 | }
102 | }
103 | }
104 | }
105 | #endregion // PopulateFromMapParentToChildren
106 |
107 | #region Constructor
108 | ///
109 | /// Constructor used to populate from a dictionary mapping element ids
110 | /// to a list of child elements.
111 | ///
112 | public CmdInspectElectricalForm2(
113 | MapParentToChildren map,
114 | ElementId electricalEquipmentCategoryId,
115 | IList electricalEquipment )
116 | {
117 | _electricalEquipmentCategoryId = electricalEquipmentCategoryId;
118 | _comparer = new ElectricalElementComparer( electricalEquipmentCategoryId );
119 | InitializeComponent();
120 | tv.BeginUpdate();
121 | PopulateFromMapParentToChildren( tv.Nodes, ElementId.InvalidElementId, map );
122 | tv.EndUpdate();
123 | //listBox1.SelectedIndex = 0;
124 | }
125 | #endregion // Constructor
126 |
127 | #region Selected equipment changed
128 | private void listBox1_SelectedIndexChanged( object sender, EventArgs e )
129 | {
130 | PanelTreeNodeHelper ptnh = listBox1.SelectedItem as PanelTreeNodeHelper;
131 | if( null != ptnh )
132 | {
133 | TreeNode tn = ptnh.TreeNode;
134 | tv.CollapseAll();
135 | tv.SelectedNode = tn;
136 | tv.Select();
137 | tn.Expand();
138 | }
139 | }
140 | #endregion // Selected equipment changed
141 | }
142 |
143 | ///
144 | /// Helper class for string comparison of child elements for sorting the tree node order.
145 | ///
146 | class ElectricalElementComparer : IComparer
147 | {
148 | ElementId _electricalEquipmentCategoryId;
149 |
150 | public ElectricalElementComparer( ElementId electricalEquipmentCategoryId )
151 | {
152 | _electricalEquipmentCategoryId = electricalEquipmentCategoryId;
153 | }
154 |
155 | public int Compare( Element x, Element y )
156 | {
157 | string sx = CmdInspectElectricalForm2.ElectricalElementText( x, _electricalEquipmentCategoryId );
158 | string sy = CmdInspectElectricalForm2.ElectricalElementText( y, _electricalEquipmentCategoryId );
159 | return sx.CompareTo( sy );
160 | }
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/AdnRme/CmdInspectElectricallForm2.designer.cs:
--------------------------------------------------------------------------------
1 | namespace AdnRme
2 | {
3 | partial class CmdInspectElectricalForm2
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.splitContainer1 = new System.Windows.Forms.SplitContainer();
32 | this.listBox1 = new System.Windows.Forms.ListBox();
33 | this.tv = new System.Windows.Forms.TreeView();
34 | this.splitContainer1.Panel1.SuspendLayout();
35 | this.splitContainer1.Panel2.SuspendLayout();
36 | this.splitContainer1.SuspendLayout();
37 | this.SuspendLayout();
38 | //
39 | // splitContainer1
40 | //
41 | this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
42 | this.splitContainer1.Location = new System.Drawing.Point( 0, 0 );
43 | this.splitContainer1.Name = "splitContainer1";
44 | //
45 | // splitContainer1.Panel1
46 | //
47 | this.splitContainer1.Panel1.Controls.Add( this.listBox1 );
48 | //
49 | // splitContainer1.Panel2
50 | //
51 | this.splitContainer1.Panel2.Controls.Add( this.tv );
52 | this.splitContainer1.Size = new System.Drawing.Size( 459, 556 );
53 | this.splitContainer1.SplitterDistance = 153;
54 | this.splitContainer1.TabIndex = 0;
55 | //
56 | // listBox1
57 | //
58 | this.listBox1.Dock = System.Windows.Forms.DockStyle.Fill;
59 | this.listBox1.FormattingEnabled = true;
60 | this.listBox1.Location = new System.Drawing.Point( 0, 0 );
61 | this.listBox1.Name = "listBox1";
62 | this.listBox1.Size = new System.Drawing.Size( 153, 550 );
63 | this.listBox1.Sorted = true;
64 | this.listBox1.TabIndex = 0;
65 | this.listBox1.SelectedIndexChanged += new System.EventHandler( this.listBox1_SelectedIndexChanged );
66 | //
67 | // tv
68 | //
69 | this.tv.Dock = System.Windows.Forms.DockStyle.Fill;
70 | this.tv.Location = new System.Drawing.Point( 0, 0 );
71 | this.tv.Name = "tv";
72 | this.tv.Size = new System.Drawing.Size( 302, 556 );
73 | this.tv.TabIndex = 0;
74 | //
75 | // CmdInspectElectricalForm2
76 | //
77 | this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F );
78 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
79 | this.ClientSize = new System.Drawing.Size( 459, 556 );
80 | this.Controls.Add( this.splitContainer1 );
81 | this.Name = "CmdInspectElectricalForm2";
82 | this.Text = "Electrical System Inspector";
83 | this.splitContainer1.Panel1.ResumeLayout( false );
84 | this.splitContainer1.Panel2.ResumeLayout( false );
85 | this.splitContainer1.ResumeLayout( false );
86 | this.ResumeLayout( false );
87 |
88 | }
89 |
90 | #endregion
91 |
92 | private System.Windows.Forms.SplitContainer splitContainer1;
93 | private System.Windows.Forms.ListBox listBox1;
94 | private System.Windows.Forms.TreeView tv;
95 | }
96 | }
--------------------------------------------------------------------------------
/AdnRme/CmdInspectElectricallForm2.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/AdnRme/CmdPopulateCfmPerSf.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | #region Namespaces
26 | using System;
27 | using System.Collections.Generic;
28 | using System.Diagnostics;
29 | using Autodesk.Revit.Attributes;
30 | using Autodesk.Revit.DB;
31 | using Autodesk.Revit.DB.Mechanical;
32 | using Autodesk.Revit.UI;
33 | #endregion // Namespaces
34 |
35 | namespace AdnRme
36 | {
37 | [Transaction( TransactionMode.Manual )]
38 | class CmdPopulateCfmPerSf : IExternalCommand
39 | {
40 | #region Set CFM/SF
41 | ///
42 | /// Populate the value of the 'CFM per SF' variable on the given space.
43 | /// Throws an exception if something goes wrong.
44 | ///
45 | /// Given space element
46 | static void SetCfmPerSf( Space space )
47 | {
48 | double flow = Util.GetSpaceParameterValue( space, Bip.Airflow, "Actual Supply Airflow" );
49 | double area = Util.GetSpaceParameterValue( space, Bip.Area, "Area" );
50 | double cfm = Const.SecondsPerMinute * flow;
51 | double cfmPerSf = cfm / area;
52 | Debug.WriteLine( string.Format( "Space {0} flow {1} CFM / area {2} f^2 --> {3} CFM/SF",
53 | space.Number, Util.RealString( cfm ), Util.RealString( area ), Util.RealString( cfmPerSf ) ) );
54 | Parameter pCfmPerSf = Util.GetSpaceParameter( space, ParameterName.CfmPerSf );
55 | pCfmPerSf.Set( cfmPerSf );
56 | }
57 | #endregion // Set CFM/SF
58 |
59 | #region Execute Command
60 | public Result Execute(
61 | ExternalCommandData commandData,
62 | ref string message,
63 | ElementSet elements )
64 | {
65 | try
66 | {
67 | WaitCursor waitCursor = new WaitCursor();
68 |
69 | UIApplication app = commandData.Application;
70 | Document doc = app.ActiveUIDocument.Document;
71 |
72 | //ElementIterator it = doc.get_Elements( typeof( Room ) );
73 | //ElementIterator it = doc.get_Elements( typeof( Space ) ); // changed Room to Space
74 | //FilteredElementCollector spaces = new FilteredElementCollector( doc );
75 | //spaces.OfClass( typeof( Space ) );
76 |
77 | using( Transaction tx = new Transaction( doc ) )
78 | {
79 | tx.Start( "Set Air Flow per SqFt on Spaces" );
80 | List spaces = Util.GetSpaces( doc );
81 |
82 | foreach( Space space in spaces )
83 | {
84 | SetCfmPerSf( space ); // set CFM/SF on the space AFTER assigning flow to the terminals
85 | }
86 | tx.Commit();
87 | }
88 | return Result.Succeeded;
89 | }
90 | catch( Exception ex )
91 | {
92 | message = ex.Message;
93 | return Result.Failed;
94 | }
95 | }
96 | #endregion // Execute Command
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/AdnRme/CmdResetDemo.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | #region Namespaces
26 | using System;
27 | using System.Collections.Generic;
28 | using Autodesk.Revit.Attributes;
29 | using Autodesk.Revit.DB;
30 | using Autodesk.Revit.DB.Mechanical;
31 | using Autodesk.Revit.UI;
32 | #endregion // Namespaces
33 |
34 | namespace AdnRme
35 | {
36 | [Transaction( TransactionMode.Manual )]
37 | class CmdResetDemo : IExternalCommand
38 | {
39 | #region Execute Command
40 | ///
41 | /// Reset the Revit model to pre-demo conditions.
42 | ///
43 | public Result Execute(
44 | ExternalCommandData commandData,
45 | ref String message,
46 | ElementSet elements )
47 | {
48 | try
49 | {
50 | UIApplication app = commandData.Application;
51 | Document doc = app.ActiveUIDocument.Document;
52 |
53 | using( Transaction tx = new Transaction( doc ) )
54 | {
55 | tx.Start( "Reset Demo" );
56 | ResetSupplyAirTerminals( doc );
57 | SetSpaceCfmPerSfToZero( doc );
58 | tx.Commit();
59 | }
60 | return Result.Succeeded;
61 | }
62 | catch( Exception ex )
63 | {
64 | message = ex.Message;
65 | return Result.Failed;
66 | }
67 | }
68 |
69 | private void SetSpaceCfmPerSfToZero( Document doc )
70 | {
71 | //FilteredElementCollector collector = new FilteredElementCollector( doc );
72 | //collector.OfClass( typeof( Space ) );
73 | //IList spaces = collector.ToElements();
74 | //int n = spaces.Count;
75 |
76 | List spaces = Util.GetSpaces( doc );
77 | int n = spaces.Count;
78 |
79 | string s = "{0} of " + n.ToString() + " spaces reset...";
80 |
81 | using( ProgressForm pf = new ProgressForm( "Reset parameter", s, n ) )
82 | {
83 | foreach( Space space in spaces )
84 | {
85 | SetCfmPerSf( space, 0.0 );
86 | pf.Increment();
87 | }
88 | }
89 | }
90 |
91 | static void SetCfmPerSf( Space space, double value )
92 | {
93 | Parameter pCfmPerSf = Util.GetSpaceParameter( space, ParameterName.CfmPerSf );
94 | pCfmPerSf.Set( value );
95 | }
96 |
97 | private void ResetSupplyAirTerminals( Document doc )
98 | {
99 | WaitCursor waitCursor = new WaitCursor();
100 | FilteredElementCollector collector = Util.GetSupplyAirTerminals( doc );
101 |
102 | IList terminals = collector.ToElements();
103 | int n = terminals.Count;
104 |
105 | string s = "{0} of " + n.ToString() + " terminals reset...";
106 | string caption = "Resetting Supply Air Termainal Flows and Sizes";
107 |
108 | using( ProgressForm pf = new ProgressForm( caption, s, n ) )
109 | {
110 | foreach( FamilyInstance terminal in terminals )
111 | {
112 | // Reset flow
113 |
114 | Parameter p = Util.GetTerminalFlowParameter( terminal );
115 | p.Set( 0 );
116 |
117 | // Reset size
118 |
119 | ISet symbolIds
120 | = terminal.Symbol.Family
121 | .GetFamilySymbolIds();
122 |
123 | foreach( ElementId id in symbolIds )
124 | {
125 | FamilySymbol sym = doc.GetElement( id )
126 | as FamilySymbol;
127 |
128 | terminal.Symbol = sym; // simply set to first symbol found
129 |
130 | break; // done after getting the first symbol
131 | }
132 | pf.Increment();
133 | }
134 | }
135 | }
136 | #endregion // Execute Command
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/AdnRme/CmdUnhostedElements.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | #region Namespaces
26 | using System;
27 | using System.Collections.Generic;
28 | using System.Diagnostics;
29 | using Autodesk.Revit.ApplicationServices;
30 | using Autodesk.Revit.Attributes;
31 | using Autodesk.Revit.DB;
32 | using Autodesk.Revit.UI;
33 | #endregion // Namespaces
34 |
35 | namespace AdnRme
36 | {
37 | [Transaction( TransactionMode.ReadOnly )]
38 | class CmdUnhostedElements : IExternalCommand
39 | {
40 | #region Determine unhosted elements
41 | static bool IsValidHost( string hostValue )
42 | {
43 | bool rc = ( "" != hostValue )
44 | && ( "None" != hostValue );
45 | return rc;
46 | }
47 |
48 | ///
49 | /// Determine unhosted elements.
50 | ///
51 | static bool DetermineUnhostedElements( Document doc )
52 | {
53 | int nHosted = 0;
54 | int nUnhosted = 0;
55 | bool needHeader = true;
56 | List unhosted = new List();
57 | {
58 | WaitCursor waitCursor = new WaitCursor();
59 | FilteredElementCollector collector = new FilteredElementCollector( doc );
60 | collector.OfClass( typeof( FamilyInstance ) );
61 | //int j = 0;
62 |
63 | // temporary problem: running this in rac_basic_sample_project.rvt throws an exception
64 | // Unable to cast object of type 'Autodesk.Revit.DB.Panel' to type 'Autodesk.Revit.DB.FamilyInstance'.
65 | // fixed in http://srd.autodesk.com/srdapp/ReportForm.asp?number=176141
66 |
67 | foreach( FamilyInstance inst in collector )
68 | {
69 | //Debug.WriteLine( ++j );
70 | Parameter p = inst.get_Parameter( Bip.Host );
71 | if( null != p )
72 | {
73 | if( needHeader )
74 | {
75 | Debug.WriteLine( "\nHosted and unhosted elements:" );
76 | needHeader = false;
77 | }
78 | string description = Util.ElementDescriptionAndId( inst );
79 | string hostValue = p.AsString();
80 | bool hosted = IsValidHost( hostValue );
81 | if( hosted ) { ++nHosted; }
82 | else
83 | {
84 | ++nUnhosted;
85 | //if( null == unhosted )
86 | //{
87 | // unhosted = new string[1];
88 | // unhosted[0] = description;
89 | //}
90 | //else
91 | //{
92 | // unhosted.se
93 | //}
94 | unhosted.Add( description );
95 | }
96 | Debug.WriteLine( string.Format( "{0} {1} host is '{2}' --> {3}hosted",
97 | description, inst.Id.IntegerValue, hostValue, hosted ? "" : "un" ) );
98 | }
99 | }
100 | }
101 | if( 0 < nHosted + nUnhosted )
102 | {
103 | Debug.WriteLine( string.Format( "{0} hosted and {1} unhosted elements.", nHosted, nUnhosted ) );
104 | }
105 | if( 0 < nUnhosted )
106 | {
107 | string[] a = new string[unhosted.Count];
108 | int i = 0;
109 | foreach( string s in unhosted )
110 | {
111 | a[i++] = s;
112 | }
113 | // todo: present the element ids in a separete edit box for easier copy and paste:
114 | string msg = string.Format( "{0} unhosted element{1}:\n\n", nUnhosted, Util.PluralSuffix( nUnhosted ) )
115 | + string.Join( "\n", a );
116 | Util.InfoMsg( msg );
117 | }
118 | return true;
119 | }
120 | #endregion // Determine unhosted elements
121 |
122 | #region Execute Command
123 | public Result Execute(
124 | ExternalCommandData commandData,
125 | ref String message,
126 | ElementSet elements )
127 | {
128 | try
129 | {
130 | UIApplication app = commandData.Application;
131 | Document doc = app.ActiveUIDocument.Document;
132 | //
133 | // 5. determine unhosted elements (cf. SPR 134098).
134 | // list all hosted versus unhosted elements:
135 | //
136 | bool rc = DetermineUnhostedElements( doc );
137 | return Result.Cancelled;
138 | }
139 | catch( Exception ex )
140 | {
141 | message = ex.Message;
142 | return Result.Failed;
143 | }
144 | }
145 | #endregion // Execute Command
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/AdnRme/Command.cs:
--------------------------------------------------------------------------------
1 | #region Namespaces
2 | using System;
3 | using System.Collections.Generic;
4 | using Autodesk.Revit.ApplicationServices;
5 | using Autodesk.Revit.Attributes;
6 | using Autodesk.Revit.DB;
7 | using Autodesk.Revit.UI;
8 | #endregion
9 |
10 | namespace AdnRme
11 | {
12 | [Transaction( TransactionMode.Manual )]
13 | public class Command : IExternalCommand
14 | {
15 | public Result Execute(
16 | ExternalCommandData commandData,
17 | ref string message,
18 | ElementSet elements )
19 | {
20 | return Result.Succeeded;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/AdnRme/Const.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | namespace AdnRme
26 | {
27 | class Const
28 | {
29 | ///
30 | /// Unit conversion factor for calculating CFM/SF from CFS internal units
31 | ///
32 | public const double SecondsPerMinute = 60;
33 | ///
34 | /// Round-up factor factor for rounding up terminal flow
35 | ///
36 | public const double RoundTerminalFlowTo = 5;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/AdnRme/FamilySelector.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace AdnRme
2 | {
3 | partial class FamilySelector
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose( bool disposing )
15 | {
16 | if( disposing && ( components != null ) )
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose( disposing );
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.checkedListBox1 = new System.Windows.Forms.CheckedListBox();
32 | this.btnOk = new System.Windows.Forms.Button();
33 | this.btnCancel = new System.Windows.Forms.Button();
34 | this.SuspendLayout();
35 | //
36 | // checkedListBox1
37 | //
38 | this.checkedListBox1.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom )
39 | | System.Windows.Forms.AnchorStyles.Left )
40 | | System.Windows.Forms.AnchorStyles.Right ) ) );
41 | this.checkedListBox1.FormattingEnabled = true;
42 | this.checkedListBox1.Location = new System.Drawing.Point( 9, 11 );
43 | this.checkedListBox1.Name = "checkedListBox1";
44 | this.checkedListBox1.Size = new System.Drawing.Size( 224, 109 );
45 | this.checkedListBox1.TabIndex = 0;
46 | //
47 | // btnOk
48 | //
49 | this.btnOk.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left ) ) );
50 | this.btnOk.DialogResult = System.Windows.Forms.DialogResult.OK;
51 | this.btnOk.Location = new System.Drawing.Point( 9, 132 );
52 | this.btnOk.Name = "btnOk";
53 | this.btnOk.Size = new System.Drawing.Size( 104, 32 );
54 | this.btnOk.TabIndex = 1;
55 | this.btnOk.Text = "OK";
56 | this.btnOk.UseVisualStyleBackColor = true;
57 | //
58 | // btnCancel
59 | //
60 | this.btnCancel.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left ) ) );
61 | this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
62 | this.btnCancel.Location = new System.Drawing.Point( 136, 132 );
63 | this.btnCancel.Name = "btnCancel";
64 | this.btnCancel.Size = new System.Drawing.Size( 97, 34 );
65 | this.btnCancel.TabIndex = 2;
66 | this.btnCancel.Text = "Cancel";
67 | this.btnCancel.UseVisualStyleBackColor = true;
68 | //
69 | // FamilySelector
70 | //
71 | this.AcceptButton = this.btnOk;
72 | this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F );
73 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
74 | this.CancelButton = this.btnCancel;
75 | this.ClientSize = new System.Drawing.Size( 243, 174 );
76 | this.Controls.Add( this.btnCancel );
77 | this.Controls.Add( this.btnOk );
78 | this.Controls.Add( this.checkedListBox1 );
79 | this.MinimumSize = new System.Drawing.Size( 251, 201 );
80 | this.Name = "FamilySelector";
81 | this.Text = "Please Select Families to Resize";
82 | this.ResumeLayout( false );
83 |
84 | }
85 |
86 | #endregion
87 |
88 | private System.Windows.Forms.CheckedListBox checkedListBox1;
89 | private System.Windows.Forms.Button btnOk;
90 | private System.Windows.Forms.Button btnCancel;
91 | }
92 | }
--------------------------------------------------------------------------------
/AdnRme/FamilySelector.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | #region Namespaces
26 | using System;
27 | using System.Collections;
28 | using System.Diagnostics;
29 | using System.Windows.Forms;
30 | #endregion // Namespaces
31 |
32 | namespace AdnRme
33 | {
34 | public partial class FamilySelector : Form
35 | {
36 | public FamilySelector( IEnumerable a )
37 | {
38 | InitializeComponent();
39 | foreach( string s in a )
40 | {
41 | checkedListBox1.Items.Add( s, true );
42 | }
43 | }
44 |
45 | public bool IsChecked( string s )
46 | {
47 | int i = checkedListBox1.Items.IndexOf( s );
48 | Debug.Assert( -1 < i, "expected item to be contained in listbox" );
49 | return ( -1 < i ) ? checkedListBox1.GetItemChecked( i ) : false;
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/AdnRme/FamilySelector.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/AdnRme/PanelTreeNodeHelper.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.Revit.DB;
2 |
3 | namespace AdnRme
4 | {
5 | class PanelTreeNodeHelper
6 | {
7 | System.Windows.Forms.TreeNode _tn;
8 | Autodesk.Revit.DB.Element _element;
9 |
10 | public PanelTreeNodeHelper( Element e )
11 | {
12 | _element = e;
13 | }
14 |
15 | public PanelTreeNodeHelper( Element e, System.Windows.Forms.TreeNode tn )
16 | {
17 | _element = e;
18 | _tn = tn;
19 | }
20 |
21 | public System.Windows.Forms.TreeNode TreeNode
22 | {
23 | get { return _tn; }
24 | //set { _tn = value; }
25 | }
26 |
27 | public Element Element
28 | {
29 | get { return _element; }
30 | //set { _element = value; }
31 | }
32 |
33 | public override string ToString()
34 | {
35 | return Element.Name;
36 | }
37 |
38 |
39 | public static int CompareByName( PanelTreeNodeHelper x, PanelTreeNodeHelper y )
40 | {
41 | return string.Compare( x.ToString(), y.ToString() );
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/AdnRme/ParameterName.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | namespace AdnRme
26 | {
27 | class ParameterName
28 | {
29 | //
30 | // used for display only
31 | //
32 | public const string CalculatedSupplyAirFlow = "Calculated Supply Air Flow";
33 | //
34 | // The "CFM per SF" is a project parameter, and as such, there is no enumeration for this;
35 | // In 2009, "Calculated Supply Airflow per area" exists, built-in parameter
36 | // ROOM_CALCULATED_SUPPLY_AIRFLOW_PER_AREA_PARAM:
37 | //
38 | public const string CfmPerSf = "CFM per SF";
39 | //
40 | // The other issue regarding the two 'Flow' params is quite simple ...
41 | // the Flow we are accessing is not a Built-in-Parameter of the Air Terminal itself ...
42 | // the Flow is simply a Family Parameter that is mapped to the Connector on the Air Terminal ...
43 | // I would guess that the 'Flow' that is the built-in-parameter is actually the Flow on the connector
44 | // (and/or - perhaps it is the Flow parameter of a Duct object) ...
45 | // at this point, the API doesn't expose Connector objects, so to get the Flow from the connector,
46 | // we have to get it via the Family parameter on the terminal.
47 | // The Flow in our case could be named anything, i.e., it could be "SomeFlowParameter" ...
48 | // it really just depends on how the Family is created, which in our case could be problematic
49 | // if the user is using a custom Family that doesn't have the parameter named "Flow" ...
50 | // but they could also create an air terminal that has >1 connector ...
51 | // would they actually do that? Hmm ... likely not, but you never know :).
52 | //
53 | // The way the "Flow" family parameter is mapped to the Flow built-in-parameter of the Connector
54 | // is through Family Editor (FE). In FE, select the connector object, click Element Properties,
55 | // and note that the Flow parameter here has a button in the right hand column ...
56 | // click this, and you will see that the "Flow" family parameter is selected.
57 | //
58 | public const string Flow = "Flow";
59 | //
60 | // air terminal family symbol parameters used in CmdChangeSize:
61 | //
62 | public const string MaxFlow = "Max Flow";
63 | public const string MinFlow = "Min Flow";
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/AdnRme/ParameterValue.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | namespace AdnRme
26 | {
27 | class ParameterValue
28 | {
29 | //
30 | // In Revit 2008, there are built-in parameters to access the actual,
31 | // calculated and specified supply airflows, but not for the "Supply Air":
32 | //
33 | // Actual Supply Airflow : ROOM_ACTUAL_SUPPLY_AIRFLOW_PARAM = Double: 2.08333333333333
34 | // Calculated Supply Airflow : ROOM_CALCULATED_SUPPLY_AIRFLOW_PARAM = Double: 2.29236666666667
35 | // Specified Supply Airflow : ROOM_DESIGN_SUPPLY_AIRFLOW_PARAM = Double: 2.29236666666667
36 | //
37 | public const string SupplyAir = "Supply Air";
38 | //
39 | // Revit 2009 provides Autodesk.Revit.MEP.Enums.DuctSystemType.SupplyAir.
40 | // But that is not a parameter value, and I do not see where it can be queried.
41 | //
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/AdnRme/ProgressForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace AdnRme
2 | {
3 | partial class ProgressForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.progressBar1 = new System.Windows.Forms.ProgressBar();
32 | this.label1 = new System.Windows.Forms.Label();
33 | this.SuspendLayout();
34 | //
35 | // progressBar1
36 | //
37 | this.progressBar1.Location = new System.Drawing.Point( 11, 25 );
38 | this.progressBar1.Name = "progressBar1";
39 | this.progressBar1.Size = new System.Drawing.Size( 406, 23 );
40 | this.progressBar1.TabIndex = 0;
41 | //
42 | // label1
43 | //
44 | this.label1.AutoSize = true;
45 | this.label1.Location = new System.Drawing.Point( 8, 7 );
46 | this.label1.Name = "label1";
47 | this.label1.Size = new System.Drawing.Size( 68, 13 );
48 | this.label1.TabIndex = 1;
49 | this.label1.Text = "Processing...";
50 | //
51 | // ProgressForm
52 | //
53 | this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F );
54 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
55 | this.ClientSize = new System.Drawing.Size( 429, 61 );
56 | this.ControlBox = false;
57 | this.Controls.Add( this.label1 );
58 | this.Controls.Add( this.progressBar1 );
59 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
60 | this.MaximizeBox = false;
61 | this.MinimizeBox = false;
62 | this.Name = "ProgressForm";
63 | this.ShowIcon = false;
64 | this.ShowInTaskbar = false;
65 | this.Text = "Working...";
66 | this.TopMost = true;
67 | this.ResumeLayout( false );
68 | this.PerformLayout();
69 |
70 | }
71 |
72 | #endregion
73 |
74 | private System.Windows.Forms.Label label1;
75 | private System.Windows.Forms.ProgressBar progressBar1;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/AdnRme/ProgressForm.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | #region Namespaces
26 | using System;
27 | using System.Windows.Forms;
28 | #endregion // Namespaces
29 |
30 | namespace AdnRme
31 | {
32 | public partial class ProgressForm : Form
33 | {
34 | string _format;
35 |
36 | ///
37 | /// Set up progress bar form and immediately display it modelessly.
38 | ///
39 | /// Form caption
40 | /// Progress message string
41 | /// Number of elements to process
42 | public ProgressForm( string caption, string format, int max )
43 | {
44 | _format = format;
45 | InitializeComponent();
46 | Text = caption;
47 | label1.Text = (null == format) ? caption : string.Format( format, 0 );
48 | progressBar1.Minimum = 0;
49 | progressBar1.Maximum = max;
50 | progressBar1.Value = 0;
51 | Show();
52 | Application.DoEvents();
53 | }
54 |
55 | public void Increment()
56 | {
57 | ++progressBar1.Value;
58 |
59 | if( null != _format )
60 | {
61 | label1.Text = string.Format( _format, progressBar1.Value );
62 | }
63 | Application.DoEvents();
64 | }
65 |
66 | #if USE_MARTINS_PROGRESS_FORM
67 | public void SetText(string text)
68 | {
69 | label1.Text = text;
70 | System.Windows.Forms.Application.DoEvents();
71 | }
72 |
73 | public void SetProgressBarMinMax(int min, int max)
74 | {
75 | progressBar1.Minimum = min;
76 | progressBar1.Maximum = max;
77 | progressBar1.Value = 0;
78 | }
79 |
80 | public void IncrementProgressBar()
81 | {
82 | progressBar1.Value++;
83 | System.Windows.Forms.Application.DoEvents();
84 | }
85 |
86 | public void HideProgressBar()
87 | {
88 | progressBar1.Visible = false;
89 | System.Windows.Forms.Application.DoEvents();
90 | }
91 |
92 | public void ShowProgressBar()
93 | {
94 | progressBar1.Visible = true;
95 | System.Windows.Forms.Application.DoEvents();
96 | }
97 | #endif // USE_MARTINS_PROGRESS_FORM
98 |
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/AdnRme/ProgressForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/AdnRme/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle( "Revit MEP Sample Application" )]
9 | [assembly: AssemblyDescription
10 | ( "Demonstrate use of the Revit API for MEP: "
11 | + "1. use of the generic API for HVAC specific tasks: "
12 | + "determine air terminals for each space; "
13 | + "assign flow to the air terminals depending on the space's calculated supply air flow; "
14 | + "change size of diffuser based on flow; "
15 | + "populate the value of the 'CFM per SF' variable on all spaces; "
16 | + "determine unhosted elements; "
17 | + "reset demo. "
18 | + "2. use of the MEP specific API to traverse an electrical system "
19 | + "and display its hierarchy in a tree view." )]
20 | [assembly: AssemblyConfiguration( "" )]
21 | [assembly: AssemblyCompany( "ADN Autodesk Developer Network, Autodesk, Inc." )]
22 | [assembly: AssemblyProduct( "Revit MEP Sample Application" )]
23 | [assembly: AssemblyCopyright( "Copyright © 2007-2021 by Jeremy Tammik, Autodesk, Inc." )]
24 | [assembly: AssemblyTrademark( "" )]
25 | [assembly: AssemblyCulture( "" )]
26 |
27 | // Setting ComVisible to false makes the types in this assembly not visible
28 | // to COM components. If you need to access a type in this assembly from
29 | // COM, set the ComVisible attribute to true on that type.
30 | [assembly: ComVisible( false )]
31 |
32 | // The following GUID is for the ID of the typelib if this project is exposed to COM
33 | [assembly: Guid( "118f7279-630d-4661-afe5-c23c23acf46f" )]
34 |
35 | // Version information for an assembly consists of the following four values:
36 | //
37 | // Major Version
38 | // Minor Version
39 | // Build Number
40 | // Revision
41 | //
42 | // You can specify all the values or you can default the Build and Revision Numbers
43 | // by using the '*' as shown below:
44 | // [assembly: AssemblyVersion("1.0.*")]
45 | //
46 | // History:
47 | // 2014-09-02 2015.0.0.2 reformatted before removing obsolete API usage
48 | // 2014-09-02 2015.0.0.3 removed obsolete API usage, specifically replaced Family.Symbols property by GetFamilySymbolIds
49 | // 2014-09-02 2015.0.0.4 bumped the copyright message year from 2013 or whatever to 2014
50 | // 2015-02-02 2015.0.0.5 bumped the copyright message year from 2014 to 2015
51 | // 2015-06-04 2016.0.0.0 flat migration to Revit 2016
52 | // 2016-04-13 2016.0.0.1 incremented copyright year from 2015 to 2016
53 | // 2018-02-02 2018.0.0.0 migrated to Revit 2018, incremented copyright year, eliminated automatic transactions
54 | // 2018-04-18 2019.0.0.0 migrated to Revit 2019
55 | // 2020-11-05 2020.0.0.0 migrated to Revit 2020
56 | // 2020-11-05 2021.0.0.0 flat migration to Revit 2021 API produces 11 deprecated API usage warnings
57 | // 2020-11-05 2021.0.0.1 eliminated deprecated API usage
58 | // 2021-01-11 2021.0.0.2 incremented copyright year
59 | //
60 | [assembly: AssemblyVersion( "2021.0.0.2" )]
61 | [assembly: AssemblyFileVersion( "2021.0.0.2" )]
62 |
--------------------------------------------------------------------------------
/AdnRme/Util.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | // Revit MEP API sample application
3 | //
4 | // Copyright (C) 2007-2021 by Jeremy Tammik, Autodesk, Inc.
5 | //
6 | // Permission to use, copy, modify, and distribute this software
7 | // for any purpose and without fee is hereby granted, provided
8 | // that the above copyright notice appears in all copies and
9 | // that both that copyright notice and the limited warranty and
10 | // restricted rights notice below appear in all supporting
11 | // documentation.
12 | //
13 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
14 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
15 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
16 | // AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE
17 | // PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
18 | //
19 | // Use, duplication, or disclosure by the U.S. Government is subject
20 | // to restrictions set forth in FAR 52.227-19 (Commercial Computer
21 | // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
22 | // (Rights in Technical Data and Computer Software), as applicable.
23 | #endregion // Header
24 |
25 | #region Namespaces
26 | using System;
27 | using System.Collections.Generic;
28 | using System.Diagnostics;
29 | using System.Linq;
30 | using WinForms = System.Windows.Forms;
31 | using Autodesk.Revit.ApplicationServices;
32 | using Autodesk.Revit.DB;
33 | using Autodesk.Revit.DB.Electrical;
34 | using Autodesk.Revit.DB.Mechanical;
35 | #endregion // Namespaces
36 |
37 | namespace AdnRme
38 | {
39 | class Util
40 | {
41 | #region Exceptions
42 | public class ParameterException : Exception
43 | {
44 | public ParameterException( string parameterName, string description, Element elem )
45 | : base( string.Format( "'{0}' parameter not defined for {1} {2}", parameterName, description, elem.Id.IntegerValue.ToString() ) )
46 | {
47 | }
48 | }
49 |
50 | public class SpaceParameterException : Exception
51 | {
52 | public SpaceParameterException( string parameterName, Space space )
53 | : base( string.Format( "'{0}' parameter not defined for space {1}", parameterName, space.Number ) )
54 | {
55 | }
56 | }
57 |
58 | public class TerminalParameterException : ParameterException
59 | {
60 | public TerminalParameterException( string parameterName, FamilyInstance terminal )
61 | : base( parameterName, "terminal", terminal )
62 | {
63 | }
64 | }
65 | #endregion // Exceptions
66 |
67 | #region Formatting
68 | public static string PluralSuffix( int n )
69 | {
70 | return 1 == n ? "" : "s";
71 | }
72 |
73 | public static string DotOrColon( int n )
74 | {
75 | return 0 == n ? "." : ":";
76 | }
77 |
78 | public static string IdList( IList elements )
79 | {
80 | string s = string.Empty;
81 | foreach( Element e in elements )
82 | {
83 | if( 0 < s.Length )
84 | {
85 | s += ", ";
86 | }
87 | s += e.Id.IntegerValue.ToString();
88 | }
89 | return s;
90 | }
91 |
92 | ///
93 | /// Format a real number and return its string representation.
94 | ///
95 | public static string RealString( double a )
96 | {
97 | return a.ToString( "0.##" );
98 | }
99 |
100 | ///
101 | /// Return a description string for a given element.
102 | ///
103 | public static string ElementDescription( Element e )
104 | {
105 | string description = ( null == e.Category )
106 | ? e.GetType().Name
107 | : e.Category.Name;
108 | if( null != e.Name )
109 | {
110 | description += " '" + e.Name + "'";
111 | }
112 | return description;
113 | }
114 |
115 | ///
116 | /// Return a description string including element id for a given element.
117 | ///
118 | public static string ElementDescriptionAndId( Element e )
119 | {
120 | string description = e.GetType().Name;
121 | if( null != e.Category )
122 | {
123 | description += " " + e.Category.Name;
124 | }
125 | string identity = e.Id.IntegerValue.ToString();
126 | if( null != e.Name )
127 | {
128 | identity = e.Name + " " + identity;
129 | }
130 | return string.Format( "{0} <{1}>", description, identity );
131 | }
132 |
133 | ///
134 | /// Return an element description string for an electrical system browser leaf node.
135 | ///
136 | public static string BrowserDescription( Element e )
137 | {
138 | FamilyInstance inst = e as FamilyInstance;
139 | return ( null == inst ? e.Category.Name : inst.Symbol.Family.Name ) + " " + e.Name;
140 | }
141 | #endregion // Formatting
142 |
143 | #region Message
144 | const string _caption = "Revit MEP API Sample";
145 |
146 | ///
147 | /// MessageBox wrapper for informational message.
148 | ///
149 | ///
150 | public static void InfoMsg( string msg )
151 | {
152 | WinForms.MessageBox.Show( msg, _caption, WinForms.MessageBoxButtons.OK, WinForms.MessageBoxIcon.Information );
153 | }
154 |
155 | ///
156 | /// MessageBox wrapper for error message.
157 | ///
158 | ///
159 | public static void ErrorMsg( string msg )
160 | {
161 | WinForms.MessageBox.Show( msg, _caption, WinForms.MessageBoxButtons.OK, WinForms.MessageBoxIcon.Error );
162 | }
163 |
164 | ///
165 | /// MessageBox wrapper for question message.
166 | ///
167 | public static bool QuestionMsg( string msg )
168 | {
169 | return WinForms.DialogResult.Yes
170 | == WinForms.MessageBox.Show( msg, _caption, WinForms.MessageBoxButtons.YesNo, WinForms.MessageBoxIcon.Question );
171 | }
172 | #endregion // Message
173 |
174 | #region Parameter Access
175 | ///
176 | /// Helper to get a specific parameter by name.
177 | ///
178 | static Parameter GetParameterFromName( Element elem, string name )
179 | {
180 | foreach( Parameter p in elem.Parameters )
181 | {
182 | if( p.Definition.Name == name )
183 | {
184 | return p;
185 | }
186 | }
187 | return null;
188 | }
189 |
190 | public static Definition GetParameterDefinitionFromName( Element elem, string name )
191 | {
192 | Parameter p = GetParameterFromName( elem, name );
193 | return ( null == p ) ? null : p.Definition;
194 | }
195 |
196 | public static double GetParameterValueFromName( Element elem, string name )
197 | {
198 | Parameter p = GetParameterFromName( elem, name );
199 | if( null == p )
200 | {
201 | throw new ParameterException( name, "element", elem );
202 | }
203 | return p.AsDouble();
204 | }
205 |
206 | public static string GetStringParameterValueFromName(Element elem, string name)
207 | {
208 | Parameter p = GetParameterFromName(elem, name);
209 | if (null == p)
210 | {
211 | throw new ParameterException(name, "element", elem);
212 | }
213 | return p.AsString();
214 | }
215 |
216 | static void DumpParameters( Element elem )
217 | {
218 | foreach( Parameter p in elem.Parameters )
219 | {
220 | Debug.WriteLine( p.Definition.ParameterType + " " + p.Definition.Name );
221 | }
222 | }
223 |
224 | public static double GetSpaceParameterValue( Space space, BuiltInParameter bip, string name )
225 | {
226 | Parameter p = space.get_Parameter( bip );
227 | if( null == p )
228 | {
229 | throw new SpaceParameterException( name, space );
230 | }
231 | return p.AsDouble();
232 | }
233 |
234 | public static Parameter GetSpaceParameter( Space space, string name )
235 | {
236 | Parameter p = GetParameterFromName( space, name );
237 | if( null == p )
238 | {
239 | throw new SpaceParameterException( name, space );
240 | }
241 | return p;
242 | }
243 |
244 | public static double GetSpaceParameterValue( Space space, string name )
245 | {
246 | Parameter p = GetSpaceParameter( space, name );
247 | return p.AsDouble();
248 | }
249 |
250 | #if NEED_IS_SUPPLY_AIR_METHOD
251 | public static bool IsSupplyAir( FamilyInstance terminal )
252 | {
253 | Parameter p = terminal.get_Parameter( Bip.SystemType );
254 | if( null == p )
255 | {
256 | throw new TerminalParameterException( Bip.SystemType.ToString(), terminal );
257 | }
258 | bool rc = p.AsString().Equals( ParameterValue.SupplyAir );
259 |
260 | #if DEBUG
261 | ElementId typeId = terminal.GetTypeId();
262 | ElementType t = terminal.Document.get_Element( typeId ) as ElementType;
263 | MEPSystemType t2 = terminal.Document.get_Element( typeId ) as MEPSystemType;
264 | Debug.Assert( (MEPSystemClassification.SupplyAir == t2.SystemClassification) == rc,
265 | "expected parameter check to return correct system classification" );
266 | #endif // DEBUG
267 |
268 | return rc;
269 | }
270 | #endif // NEED_IS_SUPPLY_AIR_METHOD
271 |
272 | public static Parameter GetTerminalFlowParameter( FamilyInstance terminal )
273 | {
274 | //
275 | // the built-in parameter "Flow" is read-only:
276 | //
277 | //Parameter p = terminal.get_Parameter( _bipFlow );
278 | //
279 | // The parameter we are interested in is not the BuiltInParameter...
280 | //
281 | Definition d = Util.GetParameterDefinitionFromName( terminal, ParameterName.Flow );
282 | Parameter p = terminal.get_Parameter( d );
283 | if( null == p )
284 | {
285 | throw new Util.TerminalParameterException( ParameterName.Flow, terminal );
286 | }
287 | return p;
288 | }
289 | #endregion // Parameter Access
290 |
291 | #region HVAC Element Access
292 | ///
293 | /// Retrieve all supply air terminals from given document.
294 | /// Select all family instance elements of BuiltInCategory
295 | /// OST_DuctTerminal with system type equal to suppy air.
296 | ///
297 | public static FilteredElementCollector GetSupplyAirTerminals( Document doc )
298 | {
299 | FilteredElementCollector collector = new FilteredElementCollector( doc );
300 | collector.OfCategory( BuiltInCategory.OST_DuctTerminal );
301 | collector.OfClass( typeof( FamilyInstance ) );
302 |
303 | //int n1 = collector.ToElements().Count; // 61 in sample model
304 |
305 | // ensure that system type equals supply air:
306 | //
307 | // in Revit 2009 and 2010 API, this did it:
308 | //
309 | //ParameterFilter parameterFilter = a.Filter.NewParameterFilter(
310 | // Bip.SystemType, CriteriaFilterType.Equal, ParameterValue.SupplyAir );
311 |
312 | // in Revit 2011, create an ElementParameter filter.
313 | // Create filter by provider and evaluator:
314 |
315 | ParameterValueProvider provider = new ParameterValueProvider( new ElementId( Bip.SystemType ) );
316 | FilterStringRuleEvaluator evaluator = new FilterStringEquals();
317 | string ruleString = ParameterValue.SupplyAir;
318 | FilterRule rule = new FilterStringRule( provider, evaluator, ruleString, false );
319 | ElementParameterFilter filter = new ElementParameterFilter( rule );
320 |
321 | collector.WherePasses( filter );
322 |
323 | //int n2 = collector.ToElements().Count; // 51 in sample model
324 |
325 | return collector;
326 | }
327 |
328 | ///
329 | /// Retrieve all spaces in given document.
330 | ///
331 | public static List GetSpaces( Document doc )
332 | {
333 | FilteredElementCollector collector
334 | = new FilteredElementCollector( doc );
335 |
336 | // trying to collect all spaces directly causes
337 | // the following error:
338 | //
339 | // Input type is of an element type that exists
340 | // in the API, but not in Revit's native object
341 | // model. Try using Autodesk.Revit.DB.Enclosure
342 | // instead, and then postprocessing the results
343 | // to find the elements of interest.
344 | //
345 | //collector.OfClass( typeof( Space ) );
346 |
347 | collector.OfClass( typeof( SpatialElement ) );
348 |
349 | //return ( from e in collector.ToElements() // 2011
350 | // where e is Space
351 | // select e as Space )
352 | // .ToList();
353 |
354 | return collector.ToElements().OfType().ToList(); // 2012
355 | }
356 | #endregion // HVAC Element Access
357 |
358 | #region Electrical Element Access
359 | ///
360 | /// Return all elements of the requested class i.e. System.Type
361 | /// matching the given built-in category in the active document.
362 | ///
363 | public static FilteredElementCollector GetElementsOfType(
364 | Document doc,
365 | Type type,
366 | BuiltInCategory bic )
367 | {
368 | FilteredElementCollector collector
369 | = new FilteredElementCollector( doc );
370 |
371 | collector.OfCategory( bic );
372 | collector.OfClass( type );
373 |
374 | return collector;
375 | }
376 |
377 | ///
378 | /// Retrieve all electrical equipment elements in the given document,
379 | /// identified by the built-in category OST_ElectricalEquipment.
380 | ///
381 | public static List GetElectricalEquipment(
382 | Document doc )
383 | {
384 | FilteredElementCollector collector
385 | = GetElementsOfType( doc, typeof( FamilyInstance ),
386 | BuiltInCategory.OST_ElectricalEquipment );
387 |
388 | // return a List instead of IList, because we need the method Exists() on it:
389 |
390 | return new List( collector.ToElements() );
391 | }
392 |
393 | ///
394 | /// Retrieve all electrical system elements in the given document.
395 | ///
396 | public static IList GetElectricalSystems( Document doc )
397 | {
398 | FilteredElementCollector collector = new FilteredElementCollector( doc );
399 | collector.OfClass( typeof( ElectricalSystem ) );
400 | return collector.ToElements();
401 | }
402 |
403 | ///
404 | /// Retrieve all circuit elements in current active document,
405 | /// which we identify as all family instance or electrical system
406 | /// elements with a non-empty RBS_ELEC_CIRCUIT_NUMBER or "Circuit Number"
407 | /// parameter.
408 | ///
409 | public static IList GetCircuitElements( Document doc )
410 | {
411 | //
412 | // prepend as many 'fast' filters as possible, because parameter access is 'slow':
413 | //
414 | ElementClassFilter f1 = new ElementClassFilter( typeof( FamilyInstance ) );
415 | ElementClassFilter f2 = new ElementClassFilter( typeof( ElectricalSystem ) );
416 | LogicalOrFilter f3 = new LogicalOrFilter( f1, f2 );
417 | FilteredElementCollector collector = new FilteredElementCollector( doc ).WherePasses( f3 );
418 |
419 | BuiltInParameter bip = BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER;
420 |
421 | #if DEBUG
422 | int n1 = collector.ToElements().Count;
423 |
424 | List a = new List();
425 | foreach( Element e in collector )
426 | {
427 | Parameter p = e.get_Parameter( BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER );
428 | if( null != p && 0 < p.AsString().Length )
429 | {
430 | a.Add( e );
431 | }
432 | }
433 | int n2 = a.Count;
434 | Debug.Assert( n1 > n2, "expected filter to eliminate something" );
435 |
436 | List b = (
437 | from e in collector.ToElements()
438 | where ( null != e.get_Parameter( bip ) ) && ( 0 < e.get_Parameter( bip ).AsString().Length )
439 | select e ).ToList();
440 |
441 | int n3 = b.Count;
442 | Debug.Assert( n2 == n3, "expected to reproduce same result" );
443 | #endif // DEBUG
444 |
445 | //
446 | // this is unclear ... negating the rule that says the parameter
447 | // exists and is empty could mean that elements pass if the parameter
448 | // is non-empty, but also if the parameter does not exist ...
449 | // so maybe returning the collection b instead of c would be a safer bet?
450 | //
451 | ParameterValueProvider provider = new ParameterValueProvider( new ElementId( bip ) );
452 | FilterStringRuleEvaluator evaluator = new FilterStringEquals();
453 | FilterRule rule = new FilterStringRule( provider, evaluator, string.Empty, false );
454 | ElementParameterFilter filter = new ElementParameterFilter( rule, true );
455 |
456 | collector.WherePasses( filter );
457 | IList c = collector.ToElements();
458 | int n4 = c.Count;
459 | Debug.Assert( n2 == n4, "expected to reproduce same result" );
460 |
461 | return c;
462 | }
463 |
464 | ///
465 | /// Return the one and only project information element using Revit 2009 filtering
466 | /// by searching for the "Project Information" category. Only one such element exists.
467 | ///
468 | public static Element GetProjectInfoElem( Document doc )
469 | {
470 | //Filter filterCategory = app.Create.Filter.NewCategoryFilter( BuiltInCategory.OST_ProjectInformation );
471 | //ElementIterator i = app.ActiveDocument.get_Elements( filterCategory );
472 | //i.MoveNext();
473 | //Element e = i.Current as Element;
474 |
475 | FilteredElementCollector collector = new FilteredElementCollector( doc );
476 | collector.OfCategory( BuiltInCategory.OST_ProjectInformation );
477 | Debug.Assert( 1 == collector.ToElements().Count, "expected one single element to be returned" );
478 | Element e = collector.FirstElement();
479 | Debug.Assert( null != e, "expected valid project information element" );
480 | return e;
481 | }
482 | #endregion // Electrical Element Access
483 | }
484 | }
485 |
--------------------------------------------------------------------------------
/AdnRme/WaitCursor.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Forms;
2 |
3 | namespace AdnRme
4 | {
5 | class WaitCursor
6 | {
7 | Cursor _oldCursor;
8 |
9 | public WaitCursor()
10 | {
11 | _oldCursor = Cursor.Current;
12 | Cursor.Current = Cursors.WaitCursor;
13 | }
14 |
15 | ~WaitCursor()
16 | {
17 | Cursor.Current = _oldCursor;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014-2015 Jeremy Tammik
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AdnRme
2 |
3 | 
4 | 
5 | 
6 | [](http://opensource.org/licenses/MIT)
7 |
8 | Revit MEP Sample Application for Revit MEP HVAC and electrical.
9 |
10 | Demonstrate use of the Revit API for MEP specific tasks.
11 |
12 | Keywords: Revit API C# .NET add-in.
13 |
14 | ## HVAC
15 |
16 | Use of the generic Revit API for HVAC specific tasks, using only standard Revit element properties and parameters:
17 |
18 | - Determine air terminals for each space.
19 | - Assign flow to the air terminals depending on the space's calculated supply air flow.
20 | - Change size of diffuser based on flow.
21 | - Populate the value of the 'CFM per SF' variable on all spaces.
22 | - Determine unhosted elements.
23 | - Reset demo.
24 |
25 | ## Electrical
26 |
27 | Use of the MEP specific API to traverse an electrical system and display its hierarchy in a tree view.
28 |
29 | ## Documentation
30 |
31 | - The Building Coder topic group for
32 | [The ADN Revit MEP HVAC and Electrical Sample AdnRme](https://thebuildingcoder.typepad.com/blog/about-the-author.html#5.40)
33 | - [The Revit MEP API](http://thebuildingcoder.typepad.com/blog/2009/06/revit-mep-api.html)
34 | - [MEP Sample Ribbon Panel](http://thebuildingcoder.typepad.com/blog/2009/08/mep-sample-ribbon-panel.html)
35 | - [The Revit MEP API](http://thebuildingcoder.typepad.com/blog/2009/09/the-revit-mep-api.html)
36 | - [The Revit MEP 2011 API](http://thebuildingcoder.typepad.com/blog/2010/05/the-revit-mep-2011-api.html)
37 | - Summary of [AU 2010 Session ID 1573 – *All Systems Go in Revit MEP Programming*](http://thebuildingcoder.typepad.com/blog/2010/05/voting-open-for-au-2010-sessions.html)
38 | - [AU 2010 Classes](http://thebuildingcoder.typepad.com/blog/2010/09/autodesk-university-2010-classes.html)
39 | - [Autodesk University 2010 Class Materials](https://thebuildingcoder.typepad.com/blog/2010/11/autodesk-university-2010-class-materials.html)
40 | for *CP316-3U All Systems Go in Autodesk Revit MEP Programming*
41 | - [MEP Sample Code for Revit 2012](https://thebuildingcoder.typepad.com/blog/2011/08/mep-sample-code-for-revit-2012.html)
42 | - [The ADN MEP Sample AdnRme for Revit MEP 2013](http://thebuildingcoder.typepad.com/blog/2012/05/the-adn-mep-sample-adnrme-for-revit-mep-2013.html)
43 | - [Updated Revit MEP 2013 Material](http://thebuildingcoder.typepad.com/blog/2012/08/updated-revit-mep-2013-material.html)
44 | - [AU Classes on the View, MEP and Link APIs](http://thebuildingcoder.typepad.com/blog/2012/11/au-classes-on-the-view-mep-and-link-apis.html)
45 | - [The ADN Sample AdnRme for Revit MEP 2014](http://thebuildingcoder.typepad.com/blog/2013/06/the-adn-sample-adnrme-for-revit-mep-2014.html)
46 | - [AdnRme Migrated to Revit MEP 2015 on GitHub](http://thebuildingcoder.typepad.com/blog/2014/06/adnrme-migrated-to-revit-mep-2015-on-github.html)
47 | - [ArchSample, Active Transaction and AdnRme for 2016](http://thebuildingcoder.typepad.com/blog/2015/06/archsample-active-transaction-and-adnrme-for-revit-mep-2016.html)
48 |
49 | ## Author
50 |
51 | Jeremy Tammik,
52 | [The Building Coder](http://thebuildingcoder.typepad.com),
53 | [ADN](http://www.autodesk.com/adn)
54 | [Open](http://www.autodesk.com/adnopen),
55 | [Autodesk Inc.](http://www.autodesk.com)
56 |
57 |
58 | ## License
59 |
60 | This sample is licensed under the terms of the [MIT License](http://opensource.org/licenses/MIT).
61 | Please see the [LICENSE](LICENSE) file for full details.
62 |
--------------------------------------------------------------------------------