Application: Navisworks API
Category: Clash Detection & Coordination
Difficulty: Advanced
Language: C#
You need to automate clash detection workflows in Navisworks - running clash tests, filtering results, generating reports, and integrating with issue tracking systems for large coordination projects.
Use the Navisworks .NET API to programmatically run clash tests, access results, apply filters, and export reports. This enables batch processing and integration with external systems.
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Clash;
using Autodesk.Navisworks.Api.DocumentParts;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace NavisworksClashAutomation
{
public class ClashDetectionAutomation
{
public void RunClashTests()
{
// Get active document
Document doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (doc == null)
{
Console.WriteLine("No active document found.");
return;
}
// Get clash test document
DocumentClash clashDoc = doc.GetClash();
DocumentClashTests clashTests = clashDoc.TestsData;
Console.WriteLine($"Found {clashTests.Tests.Count} clash tests");
// Run all tests
foreach (ClashTest test in clashTests.Tests)
{
Console.WriteLine($"\nRunning clash test: {test.DisplayName}");
// Run the test
test.Run();
// Get results
ClashResultRoot results = test.Children;
int clashCount = CountClashes(results);
Console.WriteLine($" Total clashes found: {clashCount}");
// Export results
ExportClashResults(test, @"C:\Temp\ClashReports");
}
}
private int CountClashes(ClashResultRoot results)
{
int count = 0;
foreach (ClashResult result in results)
{
if (result is ClashResultItem)
{
count++;
}
else if (result is ClashResultGroup group)
{
count += CountClashes(group.Children);
}
}
return count;
}
private void ExportClashResults(ClashTest test, string outputFolder)
{
if (!Directory.Exists(outputFolder))
Directory.CreateDirectory(outputFolder);
string fileName = $"{test.DisplayName}_{DateTime.Now:yyyyMMdd_HHmmss}.html";
string filePath = Path.Combine(outputFolder, fileName);
// Export to HTML
test.Export(filePath, ClashReportFormat.Html);
Console.WriteLine($" Report exported: {filePath}");
}
}
}
public class ClashAnalysis
{
public void AnalyzeClashes()
{
Document doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
DocumentClash clashDoc = doc.GetClash();
foreach (ClashTest test in clashDoc.TestsData.Tests)
{
Console.WriteLine($"\n=== Analyzing: {test.DisplayName} ===");
var clashStats = new Dictionary<string, int>
{
{ "New", 0 },
{ "Active", 0 },
{ "Reviewed", 0 },
{ "Approved", 0 },
{ "Resolved", 0 }
};
var severityStats = new Dictionary<string, int>
{
{ "Hard", 0 },
{ "Clearance", 0 }
};
// Analyze clash results
AnalyzeClashResults(test.Children, clashStats, severityStats);
// Print statistics
Console.WriteLine("\nStatus Breakdown:");
foreach (var stat in clashStats)
{
Console.WriteLine($" {stat.Key}: {stat.Value}");
}
Console.WriteLine("\nSeverity Breakdown:");
foreach (var stat in severityStats)
{
Console.WriteLine($" {stat.Key}: {stat.Value}");
}
}
}
private void AnalyzeClashResults(
ClashResultRoot results,
Dictionary<string, int> statusStats,
Dictionary<string, int> severityStats)
{
foreach (ClashResult result in results)
{
if (result is ClashResultItem item)
{
// Count by status
string status = item.Status.ToString();
if (statusStats.ContainsKey(status))
statusStats[status]++;
// Count by severity
string severity = item.IsHard ? "Hard" : "Clearance";
severityStats[severity]++;
}
else if (result is ClashResultGroup group)
{
AnalyzeClashResults(group.Children, statusStats, severityStats);
}
}
}
}
public class CreateClashTest
{
public void CreateStructuralMEPClashTest()
{
Document doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
DocumentClash clashDoc = doc.GetClash();
DocumentClashTests clashTests = clashDoc.TestsData;
// Create new clash test
ClashTest newTest = new ClashTest();
newTest.DisplayName = "Structural vs MEP";
newTest.TestType = ClashTestType.Hard;
newTest.Tolerance = 0.01; // 10mm tolerance
// Set selection sets for test
// Selection A: Structural elements
Search structuralSearch = new Search();
structuralSearch.Selection.SelectAll();
structuralSearch.SearchConditions.Add(
SearchCondition.HasCategoryEquals("Structural"));
newTest.SelectionA.Selection = structuralSearch.FindAll(doc, false);
// Selection B: MEP elements
Search mepSearch = new Search();
mepSearch.Selection.SelectAll();
mepSearch.SearchConditions.Add(
SearchCondition.HasCategoryEquals("MEP"));
newTest.SelectionB.Selection = mepSearch.FindAll(doc, false);
// Add test to document
clashTests.Tests.Add(newTest);
// Run the test
newTest.Run();
Console.WriteLine($"Created and ran clash test: {newTest.DisplayName}");
Console.WriteLine($"Found {CountClashes(newTest.Children)} clashes");
}
private int CountClashes(ClashResultRoot results)
{
int count = 0;
foreach (ClashResult result in results)
{
if (result is ClashResultItem)
count++;
else if (result is ClashResultGroup group)
count += CountClashes(group.Children);
}
return count;
}
}
using OfficeOpenXml;
public class ExportClashesToExcel
{
public void ExportToExcel(string outputPath)
{
Document doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
DocumentClash clashDoc = doc.GetClash();
using (ExcelPackage package = new ExcelPackage())
{
foreach (ClashTest test in clashDoc.TestsData.Tests)
{
// Create worksheet for each test
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(test.DisplayName);
// Add headers
worksheet.Cells[1, 1].Value = "Clash Name";
worksheet.Cells[1, 2].Value = "Status";
worksheet.Cells[1, 3].Value = "Distance";
worksheet.Cells[1, 4].Value = "Item 1";
worksheet.Cells[1, 5].Value = "Item 2";
worksheet.Cells[1, 6].Value = "Assigned To";
worksheet.Cells[1, 7].Value = "Description";
worksheet.Cells[1, 8].Value = "Grid Location";
// Add data
int row = 2;
ExportClashItems(test.Children, worksheet, ref row);
// Auto-fit columns
worksheet.Cells.AutoFitColumns();
}
// Save file
FileInfo file = new FileInfo(outputPath);
package.SaveAs(file);
}
Console.WriteLine($"Clash data exported to: {outputPath}");
}
private void ExportClashItems(
ClashResultRoot results,
ExcelWorksheet worksheet,
ref int row)
{
foreach (ClashResult result in results)
{
if (result is ClashResultItem item)
{
worksheet.Cells[row, 1].Value = item.DisplayName;
worksheet.Cells[row, 2].Value = item.Status.ToString();
worksheet.Cells[row, 3].Value = item.Distance;
worksheet.Cells[row, 4].Value = GetItemPath(item.Item1);
worksheet.Cells[row, 5].Value = GetItemPath(item.Item2);
worksheet.Cells[row, 6].Value = item.AssignedTo;
worksheet.Cells[row, 7].Value = item.Description;
worksheet.Cells[row, 8].Value = item.GridLocation;
row++;
}
else if (result is ClashResultGroup group)
{
ExportClashItems(group.Children, worksheet, ref row);
}
}
}
private string GetItemPath(ModelItem item)
{
if (item == null) return string.Empty;
List<string> path = new List<string>();
ModelItem current = item;
while (current != null)
{
path.Insert(0, current.DisplayName);
current = current.Parent;
}
return string.Join(" > ", path);
}
}
public class BatchClashDetection
{
public void ProcessMultipleModels(string[] modelPaths, string outputFolder)
{
foreach (string modelPath in modelPaths)
{
try
{
Console.WriteLine($"\nProcessing: {Path.GetFileName(modelPath)}");
// Open model
Document doc = Autodesk.Navisworks.Api.Application.OpenDocumentFile(modelPath);
// Run clash tests
DocumentClash clashDoc = doc.GetClash();
foreach (ClashTest test in clashDoc.TestsData.Tests)
{
Console.WriteLine($" Running test: {test.DisplayName}");
test.Run();
// Export results
string reportName = $"{Path.GetFileNameWithoutExtension(modelPath)}_{test.DisplayName}.html";
string reportPath = Path.Combine(outputFolder, reportName);
test.Export(reportPath, ClashReportFormat.Html);
}
// Save model with updated clash results
doc.SaveFile(modelPath);
// Close document
doc.Dispose();
Console.WriteLine($" ✓ Completed");
}
catch (Exception ex)
{
Console.WriteLine($" ✗ Error: {ex.Message}");
}
}
}
}
Mistake: Not running test before accessing results
// WRONG - results may be outdated
int count = CountClashes(test.Children);
// CORRECT - run test first
test.Run();
int count = CountClashes(test.Children);
Mistake: Forgetting to handle groups in results
// WRONG - only counts top-level items
int count = test.Children.Count;
// CORRECT - recursively count all items
int count = CountClashes(test.Children); // Recursive function
Mistake: Not disposing documents in batch processing
// WRONG - memory leak
Document doc = Application.OpenDocumentFile(path);
// ... process ...
// Document never closed!
// CORRECT - dispose properly
Document doc = Application.OpenDocumentFile(path);
try
{
// ... process ...
}
finally
{
doc.Dispose();
}
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Clash;
using Autodesk.Navisworks.Api.DocumentParts;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace NavisworksClashAutomation
{
public class ClashDetectionAutomation
{
public void RunClashTests()
{
// Get active document
Document doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (doc == null)
{
Console.WriteLine("No active document found.");
return;
}
// Get clash test document
DocumentClash clashDoc = doc.GetClash();
DocumentClashTests clashTests = clashDoc.TestsData;
Console.WriteLine($"Found {clashTests.Tests.Count} clash tests");
// Run all tests
foreach (ClashTest test in clashTests.Tests)
{
Console.WriteLine($"\nRunning clash test: {test.DisplayName}");
// Run the test
test.Run();
// Get results
ClashResultRoot results = test.Children;
int clashCount = CountClashes(results);
Console.WriteLine($" Total clashes found: {clashCount}");
// Export results
ExportClashResults(test, @"C:\Temp\ClashReports");
}
}
private int CountClashes(ClashResultRoot results)
{
int count = 0;
foreach (ClashResult result in results)
{
if (result is ClashResultItem)
{
count++;
}
else if (result is ClashResultGroup group)
{
count += CountClashes(group.Children);
}
}
return count;
}
private void ExportClashResults(ClashTest test, string outputFolder)
{
if (!Directory.Exists(outputFolder))
Directory.CreateDirectory(outputFolder);
string fileName = $"{test.DisplayName}_{DateTime.Now:yyyyMMdd_HHmmss}.html";
string filePath = Path.Combine(outputFolder, fileName);
// Export to HTML
test.Export(filePath, ClashReportFormat.Html);
Console.WriteLine($" Report exported: {filePath}");
}
}
}