├── GroupClashes
├── Images
│ ├── GroupClashesIcon_Large.ico
│ └── GroupClashesIcon_Small.ico
├── en-US
│ ├── GroupClashes.name
│ └── GroupClashes.xaml
├── GroupClashesPane.cs
├── Properties
│ └── AssemblyInfo.cs
├── GroupClashesHostingControl.Designer.cs
├── GroupClashesHostingControl.cs
├── PostBuild.ps1
├── GroupClashes.cs
├── PackageContents.xml
├── GroupClashesHostingControl.resx
├── GroupClashesInterface.xaml
├── GroupClashesInterface.xaml.cs
├── GroupClashes.csproj
└── GroupingFunctions.cs
├── .gitattributes
├── LICENSE.md
├── README.md
├── GroupClashes.sln
└── .gitignore
/GroupClashes/Images/GroupClashesIcon_Large.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simonmoreau/GroupClashes/HEAD/GroupClashes/Images/GroupClashesIcon_Large.ico
--------------------------------------------------------------------------------
/GroupClashes/Images/GroupClashesIcon_Small.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simonmoreau/GroupClashes/HEAD/GroupClashes/Images/GroupClashesIcon_Small.ico
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/GroupClashes/en-US/GroupClashes.name:
--------------------------------------------------------------------------------
1 | # Local names for ribbon tab, panel, and controls
2 | $utf8
3 |
4 | DisplayName=
5 | NNAW Ribbon Local Name
6 |
7 | ID_GroupClashesTab.DisplayName=
8 | Group Clashes
9 |
10 | ID_GroupClashesButton.DisplayName=
11 | Group Clashes
12 |
13 | ID_GroupClashesButton.ToolTip=
14 | Groups clashes according to the items involved
15 |
16 | ID_GroupClashesButton.ExtendedToolTip=
17 | Select a clash test, a grouping mode and click on Group
18 |
--------------------------------------------------------------------------------
/GroupClashes/GroupClashesPane.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Forms;
7 | using Autodesk.Navisworks.Api.Plugins;
8 |
9 | namespace GroupClashes
10 | {
11 | [Plugin("GroupClashes.GroupClashesPane", "BM42",DisplayName = "Group Clashes",ToolTip = "Group clashes")]
12 | [DockPanePlugin(300, 380)]
13 | class GroupClashesPane : DockPanePlugin
14 | {
15 | public override Control CreateControlPane()
16 | {
17 | //create the control that will be used to display in the pane
18 | GroupClashesHostingControl control = new GroupClashesHostingControl();
19 |
20 | control.Dock = DockStyle.Fill;
21 |
22 | //create the control
23 | control.CreateControl();
24 |
25 | return control;
26 | }
27 |
28 | public override void DestroyControlPane(Control pane)
29 | {
30 | pane.Dispose();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) [2016] [Simon Moreau]
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.
--------------------------------------------------------------------------------
/GroupClashes/en-US/GroupClashes.xaml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/GroupClashes/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("GroupClashes")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("GroupClashes")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("3876fa5d-2b66-4859-a4cd-12f9020b4c29")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/GroupClashes/GroupClashesHostingControl.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace GroupClashes
2 | {
3 | partial class GroupClashesHostingControl
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 Component 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.SuspendLayout();
32 | //
33 | // GroupClashesHostingControl
34 | //
35 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
36 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
37 | this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
38 | this.Name = "GroupClashesHostingControl";
39 | this.Size = new System.Drawing.Size(246, 427);
40 | this.Load += new System.EventHandler(this.Form1_Load);
41 | this.ResumeLayout(false);
42 |
43 | }
44 |
45 | #endregion
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Group Clashes
2 |
3 | A Navisworks Manage plugin for rule-based clash results grouping.
4 |
5 | ## Getting Started
6 |
7 | This plugin will help you to group clash result in a given Navisworks clash test. For now, you can group clashes by:
8 | * Nearest level
9 | * Nearest grid intersection
10 | * Element belonging to a model
11 | * Status, approval or assignment
12 |
13 | Open the Group Clashes window by clicking on the Group Clashes button
14 | Select a clash test. The two selections involved in the clash test are displayed below.
15 | Select one or two clash rule. Since Navisworks Manage does not support subgroup for clashes, the group name will include the result of the two rules.
16 | Click on Group.
17 | For a full description of each grouping rule, visit [bim42.com](http://bim42.com/2016/10/group-clashes/).
18 |
19 | ### Prerequisities
20 |
21 | This application is devellop with Visual Studio 2015.
22 | To run this plugin, you will need Navisworks Manage 2015, 2016 or 2017. Just compile the solution and paste the resulting dll in the Navisworks Manage Plugin folder.
23 | Before modifying anything, I advise you to check the Navisworks Manage SDK on the [Autodesk Developer Network](http://usa.autodesk.com/adsk/servlet/index?id=15024694&siteID=123112).
24 |
25 | ## Built With
26 |
27 | * [Visual Studio 2015](https://www.visualstudio.com/vs/community/) - My tool of choice
28 |
29 | ## Contributing
30 |
31 | Please feel free to submit pull request in any manner you want.
32 |
33 | ## Authors
34 |
35 | * **Simon Moreau** - *Initial work* - [BIM 42](https://bim42.com)
36 |
37 | ## License
38 |
39 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
40 |
41 | ## Acknowledgments
42 |
43 | * Thanks to the team behind the Navisworks Manage SDK for providing me the idea with the tools to implementing it.
44 |
45 |
--------------------------------------------------------------------------------
/GroupClashes/GroupClashesHostingControl.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Drawing;
5 | using System.Data;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 | using System.Windows;
11 | using System.Windows.Forms.Integration;
12 | using System.Windows.Media;
13 | using System.Windows.Interop;
14 |
15 | namespace GroupClashes
16 | {
17 |
18 |
19 | public partial class GroupClashesHostingControl : UserControl
20 | {
21 | private ElementHost _ctrlHost;
22 | private GroupClashesInterface _wpfAddressCtrl;
23 | private Panel _hostPanel;
24 |
25 | public GroupClashesHostingControl()
26 | {
27 | InitializeComponent();
28 | }
29 |
30 | private void Form1_Load(object sender, EventArgs e)
31 | {
32 | _ctrlHost = new ElementHost();
33 | this.Controls.Add(_ctrlHost);
34 | _ctrlHost.Dock = DockStyle.Fill;
35 |
36 | _wpfAddressCtrl = new GroupClashesInterface();
37 | _wpfAddressCtrl.InitializeComponent();
38 | _ctrlHost.Child = _wpfAddressCtrl;
39 | _ctrlHost.AutoSize = true;
40 | }
41 |
42 | protected override void OnVisibleChanged(EventArgs e)
43 | {
44 | base.OnVisibleChanged(e);
45 |
46 | _hostPanel = (Panel)Parent;
47 | _hostPanel.SizeChanged += (hostPanel_SizeChanged);
48 | ResizeControl();
49 | }
50 |
51 | private void hostPanel_SizeChanged(object sender, EventArgs e)
52 | {
53 | ResizeControl();
54 | }
55 |
56 | public void ResizeControl()
57 | {
58 | Width = _hostPanel.Width;
59 | Height = _hostPanel.Height;
60 | }
61 |
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/GroupClashes/PostBuild.ps1:
--------------------------------------------------------------------------------
1 | param ($Configuration, $TargetName, $ProjectDir, $TargetPath, $TargetDir)
2 | write-host $Configuration
3 | write-host $TargetName
4 | write-host $ProjectDir
5 | write-host $TargetPath
6 | write-host $TargetDir
7 |
8 | # sign the dll
9 | $thumbPrint = "e729567d4e9be8ffca04179e3375b7669bccf272"
10 | $cert=Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert | Where { $_.Thumbprint -eq $thumbPrint}
11 |
12 | Set-AuthenticodeSignature -FilePath $TargetPath -Certificate $cert -IncludeChain All -TimestampServer "http://timestamp.comodoca.com/authenticode"
13 |
14 | function CopyToFolder($revitVersion, $addinFolder) {
15 |
16 | if (Test-Path $addinFolder) {
17 | try {
18 | # Remove previous versions
19 | Get-ChildItem -Path $addinFolder | Remove-Item -Recurse
20 |
21 | # Copy the addin file
22 | Write-Host "copy all files" + ($TargetDir) + $addinFolder
23 | xcopy ($TargetDir) ($addinFolder) /s /e /y
24 | }
25 | catch {
26 | Write-Host "An error occurred:"
27 | Write-Host $_
28 | }
29 | }
30 | }
31 |
32 |
33 | $revitVersion = $Configuration.replace('Debug','').replace('Release','')
34 |
35 | # Copy to Addin folder for debug
36 | $addinMainFolder = ($env:APPDATA + "\Autodesk\ApplicationPlugins\GroupClashes.BM42.bundle\")
37 | xcopy /Y ($ProjectDir + "PackageContents.xml") $addinMainFolder
38 | $addinFolder = ($addinMainFolder + "Contents\" + $revitVersion + "\")
39 | Write-Host "addin folder" + $addinFolder
40 | CopyToFolder $revitVersion $addinFolder
41 |
42 |
43 | # Copy to release folder for building the package
44 | $ReleasePath="G:\My Drive\05 - Travail\Revit Dev\GroupClashes\Releases\Current Release\GroupClashes.BM42.bundle\"
45 | xcopy /Y ($ProjectDir + "PackageContents.xml") $ReleasePath
46 | $releaseFolder = ($ReleasePath + "Contents\" + $revitVersion + "\")
47 | Write-Host "release folder" + $releaseFolder
48 | CopyToFolder $revitVersion $releaseFolder
49 |
50 |
51 | ## Zip the package
52 |
53 | $BundleFolder = (get-item $ReleasePath ).parent.FullName
54 |
55 | $ReleaseZip = ($BundleFolder + "\" + $TargetName + ".zip")
56 | if (Test-Path $ReleaseZip) { Remove-Item $ReleaseZip }
57 |
58 | if ( Test-Path -Path $ReleasePath ) {
59 | 7z a -tzip $ReleaseZip ($BundleFolder + "\GroupClashes.BM42.bundle\")
60 | }
--------------------------------------------------------------------------------
/GroupClashes/GroupClashes.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Reflection;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using Autodesk.Navisworks.Api.Plugins;
10 |
11 | namespace GroupClashes
12 | {
13 | [Plugin("GroupClashes", "BM42", DisplayName = "Group Clashes")]
14 | [Strings("GroupClashes.name")]
15 | [RibbonLayout("GroupClashes.xaml")]
16 | [RibbonTab("ID_GroupClashesTab",
17 | DisplayName = "Group Clashes")]
18 | [Command("ID_GroupClashesButton",
19 | Icon = "GroupClashesIcon_Small.ico", LargeIcon = "GroupClashesIcon_Large.ico",
20 | DisplayName = "Group Clashes")]
21 |
22 | class RibbonHandler : CommandHandlerPlugin
23 | {
24 | private bool m_toShowTab;
25 | private bool m_toEnableButton;
26 |
27 | public RibbonHandler()
28 | {
29 | m_toShowTab = false; // to show tab or not
30 | m_toEnableButton = false; // to enable button or not
31 | }
32 |
33 | public override int ExecuteCommand(string commandId, params string[] parameters)
34 | {
35 | if (Autodesk.Navisworks.Api.Application.IsAutomated)
36 | {
37 | throw new InvalidOperationException("Invalid when running using Automation");
38 | }
39 |
40 | //Find the plugin
41 | PluginRecord pr = Autodesk.Navisworks.Api.Application.Plugins.FindPlugin("GroupClashes.GroupClashesPane.BM42");
42 |
43 | if (pr != null && pr is DockPanePluginRecord && pr.IsEnabled)
44 | {
45 | //check if it needs loading
46 | if (pr.LoadedPlugin == null)
47 | {
48 | pr.LoadPlugin();
49 | }
50 |
51 | DockPanePlugin dpp = pr.LoadedPlugin as DockPanePlugin;
52 | if (dpp != null)
53 | {
54 | //switch the Visible flag
55 | dpp.Visible = !dpp.Visible;
56 | }
57 | }
58 |
59 | //groupClashesInterface.ShowDialog();
60 | return 0;
61 | }
62 |
63 | public override CommandState CanExecuteCommand(String commandId)
64 | {
65 | CommandState state = new CommandState();
66 | state.IsVisible = true;
67 | state.IsEnabled = true;
68 | state.IsChecked = true;
69 |
70 | return state;
71 | }
72 |
73 | public override bool CanExecuteRibbonTab(string name)
74 | {
75 | return true;
76 | }
77 |
78 | public override bool TryShowCommandHelp(string name)
79 | {
80 | //FileInfo dllFileInfo = new FileInfo(Assembly.GetExecutingAssembly().Location);
81 | //string pathToHtmlFile = Path.Combine(dllFileInfo.Directory.FullName, @"Help\Help.html");
82 | string helpUrl = @"https://witty-river-01a861010.2.azurestaticapps.net/GroupClashes/GroupClashes.html";
83 | System.Diagnostics.Process.Start(helpUrl);
84 | return true;
85 | }
86 |
87 |
88 | }
89 | }
90 |
91 |
92 |
--------------------------------------------------------------------------------
/GroupClashes.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.4.33103.184
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GroupClashes", "GroupClashes\GroupClashes.csproj", "{3876FA5D-2B66-4859-A4CD-12F9020B4C29}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | 2019Debug|Any CPU = 2019Debug|Any CPU
11 | 2019Release|Any CPU = 2019Release|Any CPU
12 | 2020Debug|Any CPU = 2020Debug|Any CPU
13 | 2020Release|Any CPU = 2020Release|Any CPU
14 | 2021Debug|Any CPU = 2021Debug|Any CPU
15 | 2021Release|Any CPU = 2021Release|Any CPU
16 | 2022Debug|Any CPU = 2022Debug|Any CPU
17 | 2022Release|Any CPU = 2022Release|Any CPU
18 | 2023Debug|Any CPU = 2023Debug|Any CPU
19 | 2023Release|Any CPU = 2023Release|Any CPU
20 | 2024Debug|Any CPU = 2024Debug|Any CPU
21 | 2024Release|Any CPU = 2024Release|Any CPU
22 | EndGlobalSection
23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2019Debug|Any CPU.ActiveCfg = 2019Debug|Any CPU
25 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2019Debug|Any CPU.Build.0 = 2019Debug|Any CPU
26 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2019Release|Any CPU.ActiveCfg = 2019Release|Any CPU
27 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2019Release|Any CPU.Build.0 = 2019Release|Any CPU
28 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2020Debug|Any CPU.ActiveCfg = 2020Debug|Any CPU
29 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2020Debug|Any CPU.Build.0 = 2020Debug|Any CPU
30 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2020Release|Any CPU.ActiveCfg = 2020Release|Any CPU
31 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2020Release|Any CPU.Build.0 = 2020Release|Any CPU
32 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2021Debug|Any CPU.ActiveCfg = 2021Debug|Any CPU
33 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2021Debug|Any CPU.Build.0 = 2021Debug|Any CPU
34 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2021Release|Any CPU.ActiveCfg = 2021Release|Any CPU
35 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2021Release|Any CPU.Build.0 = 2021Release|Any CPU
36 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2022Debug|Any CPU.ActiveCfg = 2022Debug|Any CPU
37 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2022Debug|Any CPU.Build.0 = 2022Debug|Any CPU
38 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2022Release|Any CPU.ActiveCfg = 2022Release|Any CPU
39 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2022Release|Any CPU.Build.0 = 2022Release|Any CPU
40 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2023Debug|Any CPU.ActiveCfg = 2023Debug|Any CPU
41 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2023Debug|Any CPU.Build.0 = 2023Debug|Any CPU
42 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2023Release|Any CPU.ActiveCfg = 2023Release|Any CPU
43 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2023Release|Any CPU.Build.0 = 2023Release|Any CPU
44 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2024Debug|Any CPU.ActiveCfg = 2024Debug|Any CPU
45 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2024Debug|Any CPU.Build.0 = 2024Debug|Any CPU
46 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2024Release|Any CPU.ActiveCfg = 2024Release|Any CPU
47 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}.2024Release|Any CPU.Build.0 = 2024Release|Any CPU
48 | EndGlobalSection
49 | GlobalSection(SolutionProperties) = preSolution
50 | HideSolutionNode = FALSE
51 | EndGlobalSection
52 | GlobalSection(ExtensibilityGlobals) = postSolution
53 | SolutionGuid = {FE360883-270B-4C5D-9065-60489BF12513}
54 | EndGlobalSection
55 | EndGlobal
56 |
--------------------------------------------------------------------------------
/GroupClashes/PackageContents.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/GroupClashes/GroupClashesHostingControl.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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/.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 | *.userosscache
8 | *.sln.docstates
9 | /TestFiles
10 | /Icons
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # DNX
46 | project.lock.json
47 | artifacts/
48 |
49 | *_i.c
50 | *_p.c
51 | *_i.h
52 | *.ilk
53 | *.meta
54 | *.obj
55 | *.pch
56 | *.pdb
57 | *.pgc
58 | *.pgd
59 | *.rsp
60 | *.sbr
61 | *.tlb
62 | *.tli
63 | *.tlh
64 | *.tmp
65 | *.tmp_proj
66 | *.log
67 | *.vspscc
68 | *.vssscc
69 | .builds
70 | *.pidb
71 | *.svclog
72 | *.scc
73 |
74 | # Chutzpah Test files
75 | _Chutzpah*
76 |
77 | # Visual C++ cache files
78 | ipch/
79 | *.aps
80 | *.ncb
81 | *.opendb
82 | *.opensdf
83 | *.sdf
84 | *.cachefile
85 | *.VC.db
86 | *.VC.VC.opendb
87 |
88 | # Visual Studio profiler
89 | *.psess
90 | *.vsp
91 | *.vspx
92 | *.sap
93 |
94 | # TFS 2012 Local Workspace
95 | $tf/
96 |
97 | # Guidance Automation Toolkit
98 | *.gpState
99 |
100 | # ReSharper is a .NET coding add-in
101 | _ReSharper*/
102 | *.[Rr]e[Ss]harper
103 | *.DotSettings.user
104 |
105 | # JustCode is a .NET coding add-in
106 | .JustCode
107 |
108 | # TeamCity is a build add-in
109 | _TeamCity*
110 |
111 | # DotCover is a Code Coverage Tool
112 | *.dotCover
113 |
114 | # NCrunch
115 | _NCrunch_*
116 | .*crunch*.local.xml
117 | nCrunchTemp_*
118 |
119 | # MightyMoose
120 | *.mm.*
121 | AutoTest.Net/
122 |
123 | # Web workbench (sass)
124 | .sass-cache/
125 |
126 | # Installshield output folder
127 | [Ee]xpress/
128 |
129 | # DocProject is a documentation generator add-in
130 | DocProject/buildhelp/
131 | DocProject/Help/*.HxT
132 | DocProject/Help/*.HxC
133 | DocProject/Help/*.hhc
134 | DocProject/Help/*.hhk
135 | DocProject/Help/*.hhp
136 | DocProject/Help/Html2
137 | DocProject/Help/html
138 |
139 | # Click-Once directory
140 | publish/
141 |
142 | # Publish Web Output
143 | *.[Pp]ublish.xml
144 | *.azurePubxml
145 | # TODO: Comment the next line if you want to checkin your web deploy settings
146 | # but database connection strings (with potential passwords) will be unencrypted
147 | *.pubxml
148 | *.publishproj
149 |
150 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
151 | # checkin your Azure Web App publish settings, but sensitive information contained
152 | # in these scripts will be unencrypted
153 | PublishScripts/
154 |
155 | # NuGet Packages
156 | *.nupkg
157 | # The packages folder can be ignored because of Package Restore
158 | **/packages/*
159 | # except build/, which is used as an MSBuild target.
160 | !**/packages/build/
161 | # Uncomment if necessary however generally it will be regenerated when needed
162 | #!**/packages/repositories.config
163 | # NuGet v3's project.json files produces more ignoreable files
164 | *.nuget.props
165 | *.nuget.targets
166 |
167 | # Microsoft Azure Build Output
168 | csx/
169 | *.build.csdef
170 |
171 | # Microsoft Azure Emulator
172 | ecf/
173 | rcf/
174 |
175 | # Windows Store app package directories and files
176 | AppPackages/
177 | BundleArtifacts/
178 | Package.StoreAssociation.xml
179 | _pkginfo.txt
180 |
181 | # Visual Studio cache files
182 | # files ending in .cache can be ignored
183 | *.[Cc]ache
184 | # but keep track of directories ending in .cache
185 | !*.[Cc]ache/
186 |
187 | # Others
188 | ClientBin/
189 | ~$*
190 | *~
191 | *.dbmdl
192 | *.dbproj.schemaview
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # =========================
257 | # Operating System Files
258 | # =========================
259 |
260 | # OSX
261 | # =========================
262 |
263 | .DS_Store
264 | .AppleDouble
265 | .LSOverride
266 |
267 | # Thumbnails
268 | ._*
269 |
270 | # Files that might appear in the root of a volume
271 | .DocumentRevisions-V100
272 | .fseventsd
273 | .Spotlight-V100
274 | .TemporaryItems
275 | .Trashes
276 | .VolumeIcon.icns
277 |
278 | # Directories potentially created on remote AFP share
279 | .AppleDB
280 | .AppleDesktop
281 | Network Trash Folder
282 | Temporary Items
283 | .apdisk
284 |
285 | # Windows
286 | # =========================
287 |
288 | # Windows image file caches
289 | Thumbs.db
290 | ehthumbs.db
291 |
292 | # Folder config file
293 | Desktop.ini
294 |
295 | # Recycle Bin used on file shares
296 | $RECYCLE.BIN/
297 |
298 | # Windows Installer files
299 | *.cab
300 | *.msi
301 | *.msm
302 | *.msp
303 |
304 | # Windows shortcuts
305 | *.lnk
306 |
--------------------------------------------------------------------------------
/GroupClashes/GroupClashesInterface.xaml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
17 |
23 |
31 |
39 |
46 |
52 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
90 |
93 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
114 |
115 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
129 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/GroupClashes/GroupClashesInterface.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using WIN = System.Windows;
8 | using System.Windows.Controls;
9 | using System.ComponentModel;
10 | using System.Diagnostics;
11 | using System.Windows.Markup;
12 | using System.Windows.Data;
13 | using System.Windows.Documents;
14 | using System.Windows.Input;
15 | using System.Windows.Media;
16 | using System.Windows.Media.Imaging;
17 | using System.Windows.Navigation;
18 | using System.Windows.Shapes;
19 |
20 | using Autodesk.Navisworks.Api.Clash;
21 | using Autodesk.Navisworks.Api;
22 |
23 | namespace GroupClashes
24 | {
25 | ///
26 | /// Interaction logic for GroupClashesInterface.xaml
27 | ///
28 | public partial class GroupClashesInterface : UserControl
29 | {
30 | public ObservableCollection ClashTests { get; set; }
31 | public ObservableCollection GroupByList { get; set; }
32 | public ObservableCollection GroupThenList { get; set; }
33 | public ClashTest SelectedClashTest { get; set; }
34 |
35 | public GroupClashesInterface()
36 | {
37 | InitializeComponent();
38 |
39 | ClashTests = new ObservableCollection();
40 | GroupByList = new ObservableCollection();
41 | GroupThenList = new ObservableCollection();
42 |
43 | RegisterChanges();
44 |
45 | this.DataContext = this;
46 | }
47 |
48 | private void Group_Button_Click(object sender, WIN.RoutedEventArgs e)
49 | {
50 | if (ClashTestListBox.SelectedItems.Count != 0)
51 | {
52 | //Unsubscribe temporarly
53 | UnRegisterChanges();
54 |
55 | foreach (object selectedItem in ClashTestListBox.SelectedItems)
56 | {
57 | CustomClashTest selectedClashTest = (CustomClashTest)selectedItem;
58 | ClashTest clashTest = selectedClashTest.ClashTest;
59 |
60 | if (clashTest.Children.Count != 0)
61 | {
62 | //Some selection check
63 | if (comboBoxGroupBy.SelectedItem == null) comboBoxGroupBy.SelectedItem = GroupingMode.None;
64 | if (comboBoxThenBy.SelectedItem == null) comboBoxThenBy.SelectedItem = GroupingMode.None;
65 |
66 | if ((GroupingMode)comboBoxThenBy.SelectedItem != GroupingMode.None
67 | || (GroupingMode)comboBoxGroupBy.SelectedItem != GroupingMode.None)
68 | {
69 |
70 | if ((GroupingMode)comboBoxThenBy.SelectedItem == GroupingMode.None
71 | && (GroupingMode)comboBoxGroupBy.SelectedItem != GroupingMode.None)
72 | {
73 | GroupingMode mode = (GroupingMode)comboBoxGroupBy.SelectedItem;
74 | GroupingFunctions.GroupClashes(clashTest, mode, GroupingMode.None, (bool)keepExistingGroupsCheckBox.IsChecked);
75 | }
76 | else if ((GroupingMode)comboBoxGroupBy.SelectedItem == GroupingMode.None
77 | && (GroupingMode)comboBoxThenBy.SelectedItem != GroupingMode.None)
78 | {
79 | GroupingMode mode = (GroupingMode)comboBoxThenBy.SelectedItem;
80 | GroupingFunctions.GroupClashes(clashTest, mode, GroupingMode.None, (bool)keepExistingGroupsCheckBox.IsChecked);
81 | }
82 | else
83 | {
84 | GroupingMode byMode = (GroupingMode)comboBoxGroupBy.SelectedItem;
85 | GroupingMode thenByMode = (GroupingMode)comboBoxThenBy.SelectedItem;
86 | GroupingFunctions.GroupClashes(clashTest, byMode, thenByMode, (bool)keepExistingGroupsCheckBox.IsChecked);
87 | }
88 | }
89 |
90 | }
91 | }
92 |
93 | //Resubscribe
94 | RegisterChanges();
95 | }
96 |
97 | }
98 |
99 | private void Ungroup_Button_Click(object sender, WIN.RoutedEventArgs e)
100 | {
101 | if (ClashTestListBox.SelectedItems.Count != 0)
102 | {
103 | //Unsubscribe temporarly
104 | UnRegisterChanges();
105 |
106 | foreach (object selectedItem in ClashTestListBox.SelectedItems)
107 | {
108 | CustomClashTest selectedClashTest = (CustomClashTest)selectedItem;
109 | ClashTest clashTest = selectedClashTest.ClashTest;
110 |
111 | if (clashTest.Children.Count != 0)
112 | {
113 | GroupingFunctions.UnGroupClashes(clashTest);
114 | }
115 | }
116 |
117 | //Resubscribe
118 | RegisterChanges();
119 |
120 | }
121 | }
122 |
123 | private void RegisterChanges()
124 | {
125 | //When the document change
126 | Application.MainDocument.Database.Changed += DocumentClashTests_Changed;
127 |
128 | //When a clash test change
129 | DocumentClashTests dct = Application.MainDocument.GetClash().TestsData;
130 | //Register
131 | dct.Changed += DocumentClashTests_Changed;
132 |
133 | //Get all clash tests and check up to date
134 | GetClashTests();
135 | CheckPlugin();
136 | LoadComboBox();
137 | }
138 |
139 | private void UnRegisterChanges()
140 | {
141 | //When the document change
142 | Application.MainDocument.Database.Changed -= DocumentClashTests_Changed;
143 |
144 | //When a clash test change
145 | DocumentClashTests dct = Application.MainDocument.GetClash().TestsData;
146 | //Register
147 | dct.Changed -= DocumentClashTests_Changed;
148 | }
149 |
150 | void DocumentClashTests_Changed(object sender, EventArgs e)
151 | {
152 | GetClashTests();
153 | CheckPlugin();
154 | LoadComboBox();
155 |
156 | }
157 |
158 | private void GetClashTests()
159 | {
160 | DocumentClashTests dct = Application.MainDocument.GetClash().TestsData;
161 | ClashTests.Clear();
162 |
163 | foreach (SavedItem savedItem in dct.Tests)
164 | {
165 | if (savedItem.GetType() == typeof(ClashTest))
166 | {
167 | ClashTests.Add(new CustomClashTest(savedItem as ClashTest));
168 | }
169 | }
170 | }
171 |
172 | private void CheckPlugin()
173 | {
174 | //Inactive if there is no document open or there are no clash tests
175 | if (Application.MainDocument == null
176 | || Application.MainDocument.IsClear
177 | || Application.MainDocument.GetClash() == null
178 | || Application.MainDocument.GetClash().TestsData.Tests.Count == 0)
179 | {
180 | Group_Button.IsEnabled = false;
181 | comboBoxGroupBy.IsEnabled = false;
182 | comboBoxThenBy.IsEnabled = false;
183 | Ungroup_Button.IsEnabled = false;
184 | }
185 | else
186 | {
187 | Group_Button.IsEnabled = true;
188 | comboBoxGroupBy.IsEnabled = true;
189 | comboBoxThenBy.IsEnabled = true;
190 | Ungroup_Button.IsEnabled = true;
191 | }
192 | }
193 |
194 | private void LoadComboBox()
195 | {
196 | GroupByList.Clear();
197 | GroupThenList.Clear();
198 |
199 | foreach (GroupingMode mode in Enum.GetValues(typeof(GroupingMode)).Cast())
200 | {
201 | GroupThenList.Add(mode);
202 | GroupByList.Add(mode);
203 | }
204 |
205 | if (Application.MainDocument.Grids.ActiveSystem == null)
206 | {
207 | GroupByList.Remove(GroupingMode.GridIntersection);
208 | GroupByList.Remove(GroupingMode.Level);
209 | GroupThenList.Remove(GroupingMode.GridIntersection);
210 | GroupThenList.Remove(GroupingMode.Level);
211 | }
212 |
213 | comboBoxGroupBy.SelectedIndex = 0;
214 | comboBoxThenBy.SelectedIndex = 0;
215 | }
216 | }
217 |
218 | public class CustomClashTest
219 | {
220 | public CustomClashTest(ClashTest test)
221 | {
222 | _clashTest = test;
223 | }
224 |
225 | public string DisplayName { get { return _clashTest.DisplayName; } }
226 |
227 | private ClashTest _clashTest;
228 | public ClashTest ClashTest { get { return _clashTest; } }
229 |
230 | public string SelectionAName
231 | {
232 | get { return GetSelectedItem(_clashTest.SelectionA); }
233 | }
234 |
235 | public string SelectionBName
236 | {
237 | get { return GetSelectedItem(_clashTest.SelectionB); }
238 | }
239 |
240 | private string GetSelectedItem(ClashSelection selection)
241 | {
242 | string result = "";
243 | if (selection.Selection.HasSelectionSources)
244 | {
245 | result = selection.Selection.SelectionSources.FirstOrDefault().ToString();
246 | if (result.Contains("lcop_selection_set_tree\\"))
247 | {
248 | result = result.Replace("lcop_selection_set_tree\\", "");
249 | }
250 |
251 | if (selection.Selection.SelectionSources.Count > 1)
252 | {
253 | result = result + " (and other selection sets)";
254 | }
255 |
256 | }
257 | else if (selection.Selection.GetSelectedItems().Count == 0)
258 | {
259 | result = "No item have been selected.";
260 | }
261 | else if (selection.Selection.GetSelectedItems().Count == 1)
262 | {
263 | result = selection.Selection.GetSelectedItems().FirstOrDefault().DisplayName;
264 | }
265 | else
266 | {
267 | result = selection.Selection.GetSelectedItems().FirstOrDefault().DisplayName;
268 | foreach (ModelItem item in selection.Selection.GetSelectedItems().Skip(1))
269 | {
270 | result = result + "; " + item.DisplayName;
271 | }
272 | }
273 |
274 | return result;
275 | }
276 |
277 | }
278 | }
279 |
--------------------------------------------------------------------------------
/GroupClashes/GroupClashes.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {3876FA5D-2B66-4859-A4CD-12F9020B4C29}
8 | Library
9 | Properties
10 | GroupClashes
11 | GroupClashes.BM42
12 | v4.8
13 | 512
14 |
15 |
16 |
17 | true
18 | bin\2024Debug\
19 | DEBUG;TRACE;Version2024
20 | full
21 | x64
22 | 7.3
23 | prompt
24 | $(PROGRAMFILES)\Autodesk\Navisworks Manage 2024\Roamer.exe
25 | Program
26 |
27 |
28 | bin\2024Release\
29 | TRACE;Version2024
30 | true
31 | pdbonly
32 | x64
33 | 7.3
34 | prompt
35 | $(PROGRAMFILES)\Autodesk\Navisworks Manage 2024\Roamer.exe
36 | Program
37 |
38 |
39 | true
40 | bin\2023Debug\
41 | DEBUG;TRACE;Version2023
42 | full
43 | x64
44 | 7.3
45 | prompt
46 | $(PROGRAMFILES)\Autodesk\Navisworks Manage 2023\Roamer.exe
47 | Program
48 |
49 |
50 | bin\2023Release\
51 | TRACE;Version2023
52 | true
53 | pdbonly
54 | x64
55 | 7.3
56 | prompt
57 | $(PROGRAMFILES)\Autodesk\Navisworks Manage 2023\Roamer.exe
58 | Program
59 |
60 |
61 | true
62 | bin\2022Debug\
63 | DEBUG;TRACE;Version2022
64 | full
65 | x64
66 | 7.3
67 | prompt
68 | $(PROGRAMFILES)\Autodesk\Navisworks Manage 2022\Roamer.exe
69 | Program
70 |
71 |
72 | bin\2022Release\
73 | TRACE;Version2022
74 | true
75 | pdbonly
76 | x64
77 | 7.3
78 | prompt
79 | $(PROGRAMFILES)\Autodesk\Navisworks Manage 2022\Roamer.exe
80 | Program
81 |
82 |
83 | true
84 | bin\2021Debug\
85 | DEBUG;TRACE;Version2021
86 | full
87 | x64
88 | 7.3
89 | prompt
90 | $(PROGRAMFILES)\Autodesk\Navisworks Manage 2021\Roamer.exe
91 | Program
92 |
93 |
94 | bin\2021Release\
95 | TRACE;Version2021
96 | true
97 | pdbonly
98 | x64
99 | 7.3
100 | prompt
101 | $(PROGRAMFILES)\Autodesk\Navisworks Manage 2021\Roamer.exe
102 | Program
103 |
104 |
105 | true
106 | bin\2020Debug\
107 | DEBUG;TRACE;Version2020
108 | full
109 | x64
110 | 7.3
111 | prompt
112 | $(PROGRAMFILES)\Autodesk\Navisworks Manage 2020\Roamer.exe
113 | Program
114 |
115 |
116 | bin\2020Release\
117 | TRACE;Version2020
118 | true
119 | pdbonly
120 | x64
121 | 7.3
122 | prompt
123 | $(PROGRAMFILES)\Autodesk\Navisworks Manage 2020\Roamer.exe
124 | Program
125 |
126 |
127 | true
128 | bin\2019Debug\
129 | DEBUG;TRACE;Version2019
130 | full
131 | x64
132 | 7.3
133 | prompt
134 | $(PROGRAMFILES)\Autodesk\Navisworks Manage 2019\Roamer.exe
135 | Program
136 |
137 |
138 | bin\2019Release\
139 | TRACE;Version2019
140 | true
141 | pdbonly
142 | x64
143 | 7.3
144 | prompt
145 | $(PROGRAMFILES)\Autodesk\Navisworks Manage 2019\Roamer.exe
146 | Program
147 |
148 |
149 |
150 |
151 | False
152 | $(ProgramW6432)\Autodesk\Navisworks Manage 2024\Autodesk.Navisworks.Api.dll
153 | False
154 |
155 |
156 | False
157 | $(ProgramW6432)\Autodesk\Navisworks Manage 2024\Autodesk.Navisworks.Clash.dll
158 | False
159 |
160 |
161 |
162 | False
163 | $(ProgramW6432)\Autodesk\Navisworks Manage 2023\Autodesk.Navisworks.Api.dll
164 | False
165 |
166 |
167 | False
168 | $(ProgramW6432)\Autodesk\Navisworks Manage 2023\Autodesk.Navisworks.Clash.dll
169 | False
170 |
171 |
172 |
173 | False
174 | $(ProgramW6432)\Autodesk\Navisworks Manage 2022\Autodesk.Navisworks.Api.dll
175 | False
176 |
177 |
178 | False
179 | $(ProgramW6432)\Autodesk\Navisworks Manage 2022\Autodesk.Navisworks.Clash.dll
180 | False
181 |
182 |
183 |
184 | False
185 | $(ProgramW6432)\Autodesk\Navisworks Manage 2021\Autodesk.Navisworks.Api.dll
186 | False
187 |
188 |
189 | False
190 | $(ProgramW6432)\Autodesk\Navisworks Manage 2021\Autodesk.Navisworks.Clash.dll
191 | False
192 |
193 |
194 |
195 | False
196 | $(ProgramW6432)\Autodesk\Navisworks Manage 2020\Autodesk.Navisworks.Api.dll
197 | False
198 |
199 |
200 | False
201 | $(ProgramW6432)\Autodesk\Navisworks Manage 2020\Autodesk.Navisworks.Clash.dll
202 | False
203 |
204 |
205 |
206 | False
207 | $(ProgramW6432)\Autodesk\Navisworks Manage 2020\Autodesk.Navisworks.Api.dll
208 | False
209 |
210 |
211 | False
212 | $(ProgramW6432)\Autodesk\Navisworks Manage 2020\Autodesk.Navisworks.Clash.dll
213 | False
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 | UserControl
239 |
240 |
241 | GroupClashesHostingControl.cs
242 |
243 |
244 | GroupClashesInterface.xaml
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 | Designer
253 | MSBuild:Compile
254 |
255 |
256 |
257 |
258 | GroupClashesHostingControl.cs
259 |
260 |
261 |
262 |
263 | Always
264 |
265 |
266 | Always
267 |
268 |
269 | Designer
270 |
271 |
272 |
273 |
274 | Always
275 |
276 |
277 | Designer
278 | MSBuild:Compile
279 | Always
280 |
281 |
282 |
283 |
284 |
285 | powershell -ExecutionPolicy Unrestricted $(ProjectDir)PostBuild.ps1 -Configuration $(Configuration) -TargetName $(TargetName) -ProjectDir $(ProjectDir) -TargetPath $(TargetPath) -TargetDir $(TargetDir)
286 |
287 |
294 |
--------------------------------------------------------------------------------
/GroupClashes/GroupingFunctions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Autodesk.Navisworks.Api.Clash;
7 | using Autodesk.Navisworks.Api;
8 | using System.ComponentModel;
9 |
10 | namespace GroupClashes
11 | {
12 | class GroupingFunctions
13 | {
14 | public static void GroupClashes(ClashTest selectedClashTest, GroupingMode groupingMode, GroupingMode subgroupingMode, bool keepExistingGroups)
15 | {
16 | //Get existing clash result
17 | List clashResults = GetIndividualClashResults(selectedClashTest,keepExistingGroups).ToList();
18 | List clashResultGroups = new List();
19 |
20 | //Create groups according to the first grouping mode
21 | CreateGroup(ref clashResultGroups, groupingMode, clashResults,"");
22 |
23 | //Optionnaly, create subgroups
24 | if (subgroupingMode != GroupingMode.None)
25 | {
26 | CreateSubGroups(ref clashResultGroups, subgroupingMode);
27 | }
28 |
29 | //Remove groups with only one clash
30 | List ungroupedClashResults = RemoveOneClashGroup(ref clashResultGroups);
31 |
32 | //Backup the existing group, if necessary
33 | if (keepExistingGroups) clashResultGroups.AddRange(BackupExistingClashGroups(selectedClashTest));
34 |
35 | //Process these groups and clashes into the clash test
36 | ProcessClashGroup(clashResultGroups, ungroupedClashResults, selectedClashTest);
37 | }
38 |
39 | private static void CreateGroup(ref List clashResultGroups, GroupingMode groupingMode, List clashResults, string initialName)
40 | {
41 | //group all clashes
42 | switch (groupingMode)
43 | {
44 | case GroupingMode.None:
45 | return;
46 | case GroupingMode.Level:
47 | clashResultGroups = GroupByLevel(clashResults, initialName);
48 | break;
49 | case GroupingMode.GridIntersection:
50 | clashResultGroups = GroupByGridIntersection(clashResults, initialName);
51 | break;
52 | case GroupingMode.SelectionA:
53 | case GroupingMode.SelectionB:
54 | clashResultGroups = GroupByElementOfAGivenSelection(clashResults, groupingMode, initialName);
55 | break;
56 | case GroupingMode.ModelA:
57 | case GroupingMode.ModelB:
58 | clashResultGroups = GroupByElementOfAGivenModel(clashResults, groupingMode, initialName);
59 | break;
60 | case GroupingMode.ApprovedBy:
61 | case GroupingMode.AssignedTo:
62 | case GroupingMode.Status:
63 | clashResultGroups = GroupByProperties(clashResults, groupingMode, initialName);
64 | break;
65 | }
66 | }
67 |
68 | private static void CreateSubGroups(ref List clashResultGroups, GroupingMode mode)
69 | {
70 | List clashResultSubGroups = new List();
71 |
72 | foreach (ClashResultGroup group in clashResultGroups)
73 | {
74 |
75 | List clashResults = new List();
76 |
77 | foreach (SavedItem item in group.Children)
78 | {
79 | ClashResult clashResult = item as ClashResult;
80 | if (clashResult != null)
81 | {
82 | clashResults.Add(clashResult);
83 | }
84 | }
85 |
86 | List clashResultTempSubGroups = new List();
87 | CreateGroup(ref clashResultTempSubGroups, mode, clashResults,group.DisplayName + "_");
88 | clashResultSubGroups.AddRange(clashResultTempSubGroups);
89 | }
90 |
91 | clashResultGroups = clashResultSubGroups;
92 | }
93 |
94 | public static void UnGroupClashes(ClashTest selectedClashTest)
95 | {
96 | List groups = new List();
97 | List results = GetIndividualClashResults(selectedClashTest,false).ToList();
98 | List copiedResult = new List();
99 |
100 | foreach (ClashResult result in results)
101 | {
102 | copiedResult.Add((ClashResult)result.CreateCopy());
103 | }
104 |
105 | //Process this empty group list and clashes into the clash test
106 | ProcessClashGroup(groups, copiedResult, selectedClashTest);
107 |
108 | }
109 |
110 | #region grouping functions
111 | private static List GroupByLevel(List results, string initialName)
112 | {
113 | //I already checked if it exists
114 | GridSystem gridSystem = Application.MainDocument.Grids.ActiveSystem;
115 | Dictionary groups = new Dictionary();
116 | ClashResultGroup currentGroup;
117 |
118 | //Create a group for the null GridIntersection
119 | ClashResultGroup nullGridGroup = new ClashResultGroup();
120 | nullGridGroup.DisplayName = initialName + "No Level";
121 |
122 | foreach (ClashResult result in results)
123 | {
124 | //Cannot add original result to new clash test, so I create a copy
125 | ClashResult copiedResult = (ClashResult)result.CreateCopy();
126 |
127 | if (gridSystem.ClosestIntersection(copiedResult.Center) != null)
128 | {
129 | GridLevel closestLevel = gridSystem.ClosestIntersection(copiedResult.Center).Level;
130 |
131 | if (!groups.TryGetValue(closestLevel, out currentGroup))
132 | {
133 | currentGroup = new ClashResultGroup();
134 | string displayName = closestLevel.DisplayName;
135 | if (string.IsNullOrEmpty(displayName)) { displayName = "Unnamed Level"; }
136 | currentGroup.DisplayName = initialName + displayName;
137 | groups.Add(closestLevel, currentGroup);
138 | }
139 | currentGroup.Children.Add(copiedResult);
140 | }
141 | else
142 | {
143 | nullGridGroup.Children.Add(copiedResult);
144 | }
145 | }
146 |
147 | IOrderedEnumerable> list = groups.OrderBy(key => key.Key.Elevation);
148 | groups = list.ToDictionary((keyItem) => keyItem.Key, (valueItem) => valueItem.Value);
149 |
150 | List groupsByLevel = groups.Values.ToList();
151 | if (nullGridGroup.Children.Count != 0) groupsByLevel.Add(nullGridGroup);
152 |
153 | return groupsByLevel;
154 | }
155 |
156 | private static List GroupByGridIntersection(List results, string initialName)
157 | {
158 | //I already check if it exists
159 | GridSystem gridSystem = Application.MainDocument.Grids.ActiveSystem;
160 | Dictionary groups = new Dictionary();
161 | ClashResultGroup currentGroup;
162 |
163 | //Create a group for the null GridIntersection
164 | ClashResultGroup nullGridGroup = new ClashResultGroup();
165 | nullGridGroup.DisplayName = initialName + "No Grid intersection";
166 |
167 | foreach (ClashResult result in results)
168 | {
169 | //Cannot add original result to new clash test, so I create a copy
170 | ClashResult copiedResult = (ClashResult)result.CreateCopy();
171 |
172 | if (gridSystem.ClosestIntersection(copiedResult.Center) != null)
173 | {
174 | GridIntersection closestGridIntersection = gridSystem.ClosestIntersection(copiedResult.Center);
175 |
176 | if (!groups.TryGetValue(closestGridIntersection, out currentGroup))
177 | {
178 | currentGroup = new ClashResultGroup();
179 | string displayName = closestGridIntersection.DisplayName;
180 | if (string.IsNullOrEmpty(displayName)) { displayName = "Unnamed Grid Intersection"; }
181 | currentGroup.DisplayName = initialName + displayName;
182 | groups.Add(closestGridIntersection, currentGroup);
183 | }
184 | currentGroup.Children.Add(copiedResult);
185 | }
186 | else
187 | {
188 | nullGridGroup.Children.Add(copiedResult);
189 | }
190 | }
191 |
192 | IOrderedEnumerable> list = groups.OrderBy(key => key.Key.Position.X).OrderBy(key => key.Key.Level.Elevation);
193 | groups = list.ToDictionary((keyItem) => keyItem.Key, (valueItem) => valueItem.Value);
194 |
195 | List groupsByGridIntersection = groups.Values.ToList();
196 | if (nullGridGroup.Children.Count != 0) groupsByGridIntersection.Add(nullGridGroup);
197 |
198 | return groupsByGridIntersection;
199 | }
200 |
201 | private static List GroupByElementOfAGivenSelection(List results, GroupingMode mode, string initialName)
202 | {
203 | Dictionary groups = new Dictionary();
204 | ClashResultGroup currentGroup;
205 | List emptyClashResultGroups = new List();
206 |
207 | foreach (ClashResult result in results)
208 | {
209 |
210 | //Cannot add original result to new clash test, so I create a copy
211 | ClashResult copiedResult = (ClashResult)result.CreateCopy();
212 | ModelItem modelItem = null;
213 |
214 | if (mode == GroupingMode.SelectionA)
215 | {
216 | if (copiedResult.CompositeItem1 != null)
217 | {
218 | modelItem = GetSignificantAncestorOrSelf(copiedResult.CompositeItem1);
219 | }
220 | else if (copiedResult.CompositeItem2 != null)
221 | {
222 | modelItem = GetSignificantAncestorOrSelf(copiedResult.CompositeItem2);
223 | }
224 | }
225 | else if (mode == GroupingMode.SelectionB)
226 | {
227 | if (copiedResult.CompositeItem2 != null)
228 | {
229 | modelItem = GetSignificantAncestorOrSelf(copiedResult.CompositeItem2);
230 | }
231 | else if (copiedResult.CompositeItem1 != null)
232 | {
233 | modelItem = GetSignificantAncestorOrSelf(copiedResult.CompositeItem1);
234 | }
235 | }
236 |
237 | string displayName = "Empty clash";
238 | if (modelItem != null)
239 | {
240 | displayName = modelItem.DisplayName;
241 | //Create a group
242 | if (!groups.TryGetValue(modelItem, out currentGroup))
243 | {
244 | currentGroup = new ClashResultGroup();
245 | if (string.IsNullOrEmpty(displayName)){ displayName = modelItem.Parent.DisplayName; }
246 | if (string.IsNullOrEmpty(displayName)) { displayName = "Unnamed Parent"; }
247 | currentGroup.DisplayName = initialName + displayName;
248 | groups.Add(modelItem, currentGroup);
249 | }
250 |
251 | //Add to the group
252 | currentGroup.Children.Add(copiedResult);
253 | }
254 | else
255 | {
256 | System.Diagnostics.Debug.WriteLine("test");
257 | ClashResultGroup oneClashResultGroup = new ClashResultGroup();
258 | oneClashResultGroup.DisplayName = "Empty clash";
259 | oneClashResultGroup.Children.Add(copiedResult);
260 | emptyClashResultGroups.Add(oneClashResultGroup);
261 | }
262 |
263 |
264 |
265 |
266 | }
267 |
268 | List allGroups = groups.Values.ToList();
269 | allGroups.AddRange(emptyClashResultGroups);
270 | return allGroups;
271 | }
272 |
273 | private static List GroupByElementOfAGivenModel(List results, GroupingMode mode, string initialName)
274 | {
275 | Dictionary groups = new Dictionary();
276 | ClashResultGroup currentGroup;
277 | List emptyClashResultGroups = new List();
278 |
279 | foreach (ClashResult result in results)
280 | {
281 |
282 | //Cannot add original result to new clash test, so I create a copy
283 | ClashResult copiedResult = (ClashResult)result.CreateCopy();
284 | // ModelItem modelItem = null;
285 | ModelItem rootModel = null;
286 |
287 | if (mode == GroupingMode.ModelA)
288 | {
289 | if (copiedResult.CompositeItem1 != null)
290 | {
291 | rootModel = GetFileAncestor(copiedResult.CompositeItem1);
292 | }
293 | else if (copiedResult.CompositeItem2 != null)
294 | {
295 | rootModel = GetFileAncestor(copiedResult.CompositeItem2);
296 | }
297 | }
298 | else if (mode == GroupingMode.ModelB)
299 | {
300 | if (copiedResult.CompositeItem2 != null)
301 | {
302 | rootModel = GetFileAncestor(copiedResult.CompositeItem2);
303 | }
304 | else if (copiedResult.CompositeItem1 != null)
305 | {
306 | rootModel = GetFileAncestor(copiedResult.CompositeItem1);
307 | }
308 | }
309 |
310 | string displayName = "Empty clash";
311 | if (rootModel != null)
312 | {
313 | displayName = rootModel.DisplayName;
314 | //Create a group
315 | if (!groups.TryGetValue(rootModel, out currentGroup))
316 | {
317 | currentGroup = new ClashResultGroup();
318 | // if (string.IsNullOrEmpty(displayName)) { displayName = rootModel.Parent.DisplayName; }
319 | if (string.IsNullOrEmpty(displayName)) { displayName = "Unnamed Model"; }
320 | currentGroup.DisplayName = initialName + displayName;
321 | groups.Add(rootModel, currentGroup);
322 | }
323 |
324 | //Add to the group
325 | currentGroup.Children.Add(copiedResult);
326 | }
327 | else
328 | {
329 | System.Diagnostics.Debug.WriteLine("test");
330 | ClashResultGroup oneClashResultGroup = new ClashResultGroup();
331 | oneClashResultGroup.DisplayName = "Empty clash";
332 | oneClashResultGroup.Children.Add(copiedResult);
333 | emptyClashResultGroups.Add(oneClashResultGroup);
334 | }
335 | }
336 |
337 | List allGroups = groups.Values.ToList();
338 | allGroups.AddRange(emptyClashResultGroups);
339 | return allGroups;
340 | }
341 |
342 | private static List GroupByProperties(List results, GroupingMode mode, string initialName)
343 | {
344 | Dictionary groups = new Dictionary();
345 | ClashResultGroup currentGroup;
346 |
347 | foreach (ClashResult result in results)
348 | {
349 | //Cannot add original result to new clash test, so I create a copy
350 | ClashResult copiedResult = (ClashResult)result.CreateCopy();
351 | string clashProperty = null;
352 |
353 | if (mode == GroupingMode.ApprovedBy)
354 | {
355 | clashProperty = copiedResult.ApprovedBy;
356 | }
357 | else if (mode == GroupingMode.AssignedTo)
358 | {
359 | clashProperty = copiedResult.AssignedTo;
360 | }
361 | else if (mode == GroupingMode.Status)
362 | {
363 | clashProperty = copiedResult.Status.ToString();
364 | }
365 |
366 | if (string.IsNullOrEmpty(clashProperty)) { clashProperty = "Unspecified"; }
367 |
368 | if (!groups.TryGetValue(clashProperty, out currentGroup))
369 | {
370 | currentGroup = new ClashResultGroup();
371 | currentGroup.DisplayName = initialName + clashProperty;
372 | groups.Add(clashProperty, currentGroup);
373 | }
374 | currentGroup.Children.Add(copiedResult);
375 | }
376 |
377 | return groups.Values.ToList();
378 | }
379 |
380 | #endregion
381 |
382 |
383 | #region helpers
384 | private static void ProcessClashGroup(List clashGroups, List ungroupedClashResults, ClashTest selectedClashTest)
385 | {
386 | using (Transaction tx = Application.MainDocument.BeginTransaction("Group clashes"))
387 | {
388 | ClashTest copiedClashTest = (ClashTest)selectedClashTest.CreateCopyWithoutChildren();
389 | //When we replace theTest with our new test, theTest will be disposed. If the operation is cancelled, we need a non-disposed copy of theTest with children to sub back in.
390 | ClashTest BackupTest = (ClashTest)selectedClashTest.CreateCopy();
391 | DocumentClash documentClash = Application.MainDocument.GetClash();
392 | int indexOfClashTest = documentClash.TestsData.Tests.IndexOf(selectedClashTest);
393 | documentClash.TestsData.TestsReplaceWithCopy(indexOfClashTest, copiedClashTest);
394 |
395 | int CurrentProgress = 0;
396 | int TotalProgress = ungroupedClashResults.Count + clashGroups.Count;
397 | Progress ProgressBar = Application.BeginProgress("Copying Results", "Copying results from " + selectedClashTest.DisplayName + " to the Group Clashes pane...");
398 | foreach (ClashResultGroup clashResultGroup in clashGroups)
399 | {
400 | if (ProgressBar.IsCanceled) break;
401 | documentClash.TestsData.TestsAddCopy((GroupItem)documentClash.TestsData.Tests[indexOfClashTest], clashResultGroup);
402 | CurrentProgress++;
403 | ProgressBar.Update((double)CurrentProgress / TotalProgress);
404 | }
405 | foreach (ClashResult clashResult in ungroupedClashResults)
406 | {
407 | if (ProgressBar.IsCanceled) break;
408 | documentClash.TestsData.TestsAddCopy((GroupItem)documentClash.TestsData.Tests[indexOfClashTest], clashResult);
409 | CurrentProgress++;
410 | ProgressBar.Update((double)CurrentProgress / TotalProgress);
411 | }
412 | if (ProgressBar.IsCanceled) documentClash.TestsData.TestsReplaceWithCopy(indexOfClashTest, BackupTest);
413 | tx.Commit();
414 | Application.EndProgress();
415 | }
416 | }
417 |
418 | private static List RemoveOneClashGroup(ref List clashResultGroups)
419 | {
420 | List ungroupedClashResults = new List();
421 | List temporaryClashResultGroups = new List();
422 | temporaryClashResultGroups.AddRange(clashResultGroups);
423 |
424 | foreach (ClashResultGroup group in temporaryClashResultGroups)
425 | {
426 | if (group.Children.Count == 1)
427 | {
428 | ClashResult result = (ClashResult)group.Children.FirstOrDefault();
429 | //result.DisplayName = group.DisplayName;
430 | ungroupedClashResults.Add(result);
431 | clashResultGroups.Remove(group);
432 | }
433 | }
434 |
435 | return ungroupedClashResults;
436 | }
437 |
438 | private static IEnumerable GetIndividualClashResults(ClashTest clashTest, bool keepExistingGroup)
439 | {
440 | for (var i = 0; i < clashTest.Children.Count; i++)
441 | {
442 | if (clashTest.Children[i].IsGroup)
443 | {
444 | if (!keepExistingGroup)
445 | {
446 | IEnumerable GroupResults = GetGroupResults((ClashResultGroup)clashTest.Children[i]);
447 | foreach (ClashResult clashResult in GroupResults)
448 | {
449 | yield return clashResult;
450 | }
451 | }
452 | }
453 | else yield return (ClashResult)clashTest.Children[i];
454 | }
455 | }
456 |
457 | private static IEnumerable BackupExistingClashGroups(ClashTest clashTest)
458 | {
459 | for (var i = 0; i < clashTest.Children.Count; i++)
460 | {
461 | if (clashTest.Children[i].IsGroup)
462 | {
463 | yield return (ClashResultGroup)clashTest.Children[i].CreateCopy();
464 | }
465 | }
466 | }
467 |
468 | private static IEnumerable GetGroupResults(ClashResultGroup clashResultGroup)
469 | {
470 | for (var i = 0; i < clashResultGroup.Children.Count; i++)
471 | {
472 | yield return (ClashResult)clashResultGroup.Children[i];
473 | }
474 | }
475 |
476 | private static ModelItem GetSignificantAncestorOrSelf(ModelItem item)
477 | {
478 | ModelItem originalItem = item;
479 | ModelItem currentComposite = null;
480 |
481 | //Get last composite item.
482 | while (item.Parent != null)
483 | {
484 | item = item.Parent;
485 | if (item.IsComposite) currentComposite = item;
486 | }
487 |
488 | return currentComposite ?? originalItem;
489 | }
490 |
491 | private static ModelItem GetFileAncestor(ModelItem item)
492 | {
493 | ModelItem originalItem = item;
494 |
495 | ModelItem currentComposite = null;
496 |
497 | //Get last composite item.
498 | while (item.Parent != null)
499 | {
500 | item = item.Parent;
501 | if (item.HasModel)
502 | {
503 | currentComposite = item;
504 | break;
505 | }
506 | }
507 |
508 | return currentComposite ?? originalItem;
509 | }
510 |
511 | #endregion
512 |
513 | }
514 |
515 | public enum GroupingMode
516 | {
517 | [Description("")]
518 | None,
519 | [Description("Level")]
520 | Level,
521 | [Description("Grid Intersection")]
522 | GridIntersection,
523 | [Description("Selection A")]
524 | SelectionA,
525 | [Description("Selection B")]
526 | SelectionB,
527 | [Description("Model A")]
528 | ModelA,
529 | [Description("Model B")]
530 | ModelB,
531 | [Description("Assigned To")]
532 | AssignedTo,
533 | [Description("Approved By")]
534 | ApprovedBy,
535 | [Description("Status")]
536 | Status
537 | }
538 |
539 | }
540 |
--------------------------------------------------------------------------------