-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'dev' into update-progress-receive
- Loading branch information
Showing
7 changed files
with
397 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
170 changes: 170 additions & 0 deletions
170
Connectors/Navisworks/Speckle.Connectors.NavisworksShared/HostApp/NavisworksColorUnpacker.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
using Microsoft.Extensions.Logging; | ||
using Speckle.Connector.Navisworks.Services; | ||
using Speckle.Converter.Navisworks.Helpers; | ||
using Speckle.Converter.Navisworks.Settings; | ||
using Speckle.Converters.Common; | ||
using Speckle.Sdk; | ||
using Speckle.Sdk.Models.Proxies; | ||
using ComApi = Autodesk.Navisworks.Api.Interop.ComApi; | ||
using ComBridge = Autodesk.Navisworks.Api.ComApi.ComApiBridge; | ||
|
||
namespace Speckle.Connector.Navisworks.HostApp; | ||
|
||
public class NavisworksColorUnpacker( | ||
ILogger<NavisworksColorUnpacker> logger, | ||
IConverterSettingsStore<NavisworksConversionSettings> converterSettings, | ||
IElementSelectionService selectionService | ||
) | ||
{ | ||
private static T Select<T>(RepresentationMode mode, T active, T permanent, T original, T defaultValue) => | ||
mode switch | ||
{ | ||
RepresentationMode.Active => active, | ||
RepresentationMode.Permanent => permanent, | ||
RepresentationMode.Original => original, | ||
_ => defaultValue, | ||
}; | ||
|
||
internal List<ColorProxy> UnpackColor( | ||
IReadOnlyList<NAV.ModelItem> navisworksObjects, | ||
Dictionary<string, List<NAV.ModelItem>> groupedNodes | ||
) | ||
{ | ||
if (navisworksObjects == null) | ||
{ | ||
throw new ArgumentNullException(nameof(navisworksObjects)); | ||
} | ||
|
||
if (groupedNodes == null) | ||
{ | ||
throw new ArgumentNullException(nameof(groupedNodes)); | ||
} | ||
|
||
Dictionary<string, ColorProxy> colorProxies = []; | ||
Dictionary<string, string> mergedIds = []; | ||
|
||
// Build mergedIds map once | ||
foreach (var group in groupedNodes) | ||
{ | ||
foreach (var node in group.Value) | ||
{ | ||
mergedIds[selectionService.GetModelItemPath(node)] = group.Key; | ||
} | ||
} | ||
|
||
foreach (NAV.ModelItem navisworksObject in navisworksObjects) | ||
{ | ||
try | ||
{ | ||
// Skip non-2D elements | ||
if (!Is2DElement(navisworksObject)) | ||
{ | ||
continue; | ||
} | ||
|
||
var navisworksObjectId = selectionService.GetModelItemPath(navisworksObject); | ||
var finalId = mergedIds.TryGetValue(navisworksObjectId, out var mergedId) ? mergedId : navisworksObjectId; | ||
|
||
var geometry = navisworksObject.Geometry; | ||
var mode = converterSettings.Current.User.VisualRepresentationMode; | ||
|
||
using var defaultColor = new NAV.Color(1.0, 1.0, 1.0); | ||
|
||
var representationColor = Select( | ||
mode, | ||
geometry.ActiveColor, | ||
geometry.PermanentColor, | ||
geometry.OriginalColor, | ||
defaultColor | ||
); | ||
|
||
var colorId = Select( | ||
mode, | ||
$"{geometry.ActiveColor.GetHashCode()}_{geometry.ActiveTransparency}".GetHashCode(), | ||
$"{geometry.PermanentColor.GetHashCode()}_{geometry.PermanentTransparency}".GetHashCode(), | ||
$"{geometry.OriginalColor.GetHashCode()}_{geometry.OriginalTransparency}".GetHashCode(), | ||
0 | ||
); | ||
|
||
var colorName = ColorConverter.NavisworksColorToColor(representationColor).Name; | ||
|
||
if (colorProxies.TryGetValue(colorId.ToString(), out ColorProxy? colorProxy)) | ||
{ | ||
colorProxy.objects.Add(finalId); | ||
} | ||
else | ||
{ | ||
colorProxies[colorId.ToString()] = new ColorProxy | ||
{ | ||
value = ColorConverter.NavisworksColorToColor(representationColor).ToArgb(), | ||
name = colorName, | ||
applicationId = colorId.ToString(), | ||
objects = [finalId] | ||
}; | ||
} | ||
} | ||
catch (Exception ex) when (!ex.IsFatal()) | ||
{ | ||
logger.LogError(ex, "Failed to unpack color for Navisworks object"); | ||
} | ||
} | ||
|
||
return colorProxies.Values.ToList(); | ||
} | ||
|
||
private static bool Is2DElement(NAV.ModelItem modelItem) | ||
{ | ||
if (!modelItem.HasGeometry) | ||
{ | ||
return false; | ||
} | ||
|
||
var primitiveChecker = new PrimitiveChecker(); | ||
|
||
var comSelection = ComBridge.ToInwOpSelection([modelItem]); | ||
try | ||
{ | ||
foreach (ComApi.InwOaPath path in comSelection.Paths()) | ||
{ | ||
GC.KeepAlive(path); | ||
|
||
foreach (ComApi.InwOaFragment3 fragment in path.Fragments()) | ||
{ | ||
GC.KeepAlive(fragment); | ||
|
||
fragment.GenerateSimplePrimitives(ComApi.nwEVertexProperty.eNORMAL, primitiveChecker); | ||
|
||
// Exit early if triangles are found | ||
if (primitiveChecker.HasTriangles) | ||
{ | ||
return false; | ||
} | ||
} | ||
} | ||
|
||
// Return true if any 2D primitives are found | ||
return primitiveChecker.HasLines || primitiveChecker.HasPoints || primitiveChecker.HasSnapPoints; | ||
} | ||
finally | ||
{ | ||
System.Runtime.InteropServices.Marshal.ReleaseComObject(comSelection); | ||
} | ||
} | ||
} | ||
|
||
public class PrimitiveChecker : ComApi.InwSimplePrimitivesCB | ||
{ | ||
public bool HasTriangles { get; private set; } | ||
public bool HasLines { get; private set; } | ||
public bool HasPoints { get; private set; } | ||
public bool HasSnapPoints { get; private set; } | ||
|
||
public void Line(ComApi.InwSimpleVertex v1, ComApi.InwSimpleVertex v2) => HasLines = true; | ||
|
||
public void Point(ComApi.InwSimpleVertex v1) => HasPoints = true; | ||
|
||
public void SnapPoint(ComApi.InwSimpleVertex v1) => HasSnapPoints = true; | ||
|
||
public void Triangle(ComApi.InwSimpleVertex v1, ComApi.InwSimpleVertex v2, ComApi.InwSimpleVertex v3) => | ||
HasTriangles = true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.