Compare commits
7 Commits
main
...
design-explorer
| Author | SHA1 | Date | |
|---|---|---|---|
| df6e2070b0 | |||
| b49884e211 | |||
| 1b9640954e | |||
| 3d24a7b16b | |||
| 9f3a333beb | |||
| 6c2a98c1d4 | |||
| 4cbf5628b1 |
+52
@@ -1,4 +1,5 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using GH_IO.Serialization;
|
||||
using Grasshopper.Kernel;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
@@ -16,6 +17,24 @@ public class SpeckleDataObjectPassthrough()
|
||||
ComponentCategories.OBJECTS
|
||||
)
|
||||
{
|
||||
private const string DESIGN_OPTION_KEY = "isDesignOption";
|
||||
private bool _isDesignOption;
|
||||
private bool IsDesignOption
|
||||
{
|
||||
get => _isDesignOption;
|
||||
set
|
||||
{
|
||||
if (_isDesignOption == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_isDesignOption = value;
|
||||
UpdateMessage();
|
||||
ExpireSolution(true);
|
||||
}
|
||||
}
|
||||
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
protected override Bitmap Icon => Resources.speckle_objects_dataobject;
|
||||
public override GH_Exposure Exposure => GH_Exposure.secondary;
|
||||
@@ -186,6 +205,11 @@ public class SpeckleDataObjectPassthrough()
|
||||
result.ApplicationId ??= Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
if (_isDesignOption)
|
||||
{
|
||||
result.DataObject[DESIGN_OPTION_KEY] = true;
|
||||
}
|
||||
|
||||
// get the path
|
||||
string? path =
|
||||
result.Path.Count > 1 ? string.Join(Constants.LAYER_PATH_DELIMITER, result.Path) : result.Path.FirstOrDefault();
|
||||
@@ -198,4 +222,32 @@ public class SpeckleDataObjectPassthrough()
|
||||
da.SetData(4, path);
|
||||
SetApplicationIdOutput(da, result.ApplicationId);
|
||||
}
|
||||
|
||||
public override void AppendAdditionalMenuItems(ToolStripDropDown menu)
|
||||
{
|
||||
base.AppendAdditionalMenuItems(menu);
|
||||
Menu_AppendSeparator(menu);
|
||||
Menu_AppendItem(menu, "Mark as Design Option", (_, _) => IsDesignOption = !IsDesignOption, true, IsDesignOption);
|
||||
}
|
||||
|
||||
public override bool Write(GH_IWriter writer)
|
||||
{
|
||||
var result = base.Write(writer);
|
||||
writer.SetBoolean("IsDesignOption", _isDesignOption);
|
||||
return result;
|
||||
}
|
||||
|
||||
public override bool Read(GH_IReader reader)
|
||||
{
|
||||
var result = base.Read(reader);
|
||||
bool isDesignOption = false;
|
||||
if (reader.TryGetBoolean("IsDesignOption", ref isDesignOption))
|
||||
{
|
||||
_isDesignOption = isDesignOption;
|
||||
UpdateMessage();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void UpdateMessage() => Message = _isDesignOption ? "Design Option" : string.Empty;
|
||||
}
|
||||
|
||||
@@ -318,32 +318,16 @@ public sealed class DisplayValueExtractor
|
||||
);
|
||||
}
|
||||
|
||||
foreach (var curve in collections.Curves)
|
||||
foreach (var (curve, accumulatedTransform) in collections.Curves)
|
||||
{
|
||||
if (curveTransform is not null)
|
||||
{
|
||||
using var transformedCurve = curve.CreateTransformed(curveTransform);
|
||||
displayValue.Add(DisplayValueResult.WithoutTransform(GetCurveDisplayValue(transformedCurve)));
|
||||
}
|
||||
else
|
||||
{
|
||||
displayValue.Add(DisplayValueResult.WithoutTransform(GetCurveDisplayValue(curve)));
|
||||
}
|
||||
using var resolvedCurve = ResolveCurveTransforms(curve, accumulatedTransform, curveTransform);
|
||||
displayValue.Add(DisplayValueResult.WithoutTransform(GetCurveDisplayValue(resolvedCurve)));
|
||||
}
|
||||
|
||||
foreach (var polyline in collections.Polylines)
|
||||
foreach (var (polyline, accumulatedTransform) in collections.Polylines)
|
||||
{
|
||||
if (curveTransform is not null)
|
||||
{
|
||||
var coords = polyline.GetCoordinates();
|
||||
var transformedCoords = coords.Select(coord => curveTransform.OfPoint(coord)).ToList();
|
||||
using var transformedPolyline = DB.PolyLine.Create(transformedCoords);
|
||||
displayValue.Add(DisplayValueResult.WithoutTransform(_polylineConverter.Convert(transformedPolyline)));
|
||||
}
|
||||
else
|
||||
{
|
||||
displayValue.Add(DisplayValueResult.WithoutTransform(_polylineConverter.Convert(polyline)));
|
||||
}
|
||||
using var resolvedPolyline = ResolvePolylineTransforms(polyline, accumulatedTransform, curveTransform);
|
||||
displayValue.Add(DisplayValueResult.WithoutTransform(_polylineConverter.Convert(resolvedPolyline)));
|
||||
}
|
||||
|
||||
foreach (var point in collections.Points)
|
||||
@@ -498,13 +482,15 @@ public sealed class DisplayValueExtractor
|
||||
break;
|
||||
|
||||
case DB.Curve curve:
|
||||
// curves are stored as-is; transforms are applied later in ProcessGeometryCollections
|
||||
collections.Curves.Add(curve);
|
||||
// store the curve together with whatever accumulatedTransform is active at this
|
||||
// recursion depth. See GeometryCollections remarks for why we do this rather than
|
||||
// applying the transform here the way we do for meshes and solids.
|
||||
collections.Curves.Add((curve, accumulatedTransform));
|
||||
break;
|
||||
|
||||
case DB.PolyLine polyline:
|
||||
// polylines also handled later during display value processing
|
||||
collections.Polylines.Add(polyline);
|
||||
// same reasoning as curves above
|
||||
collections.Polylines.Add((polyline, accumulatedTransform));
|
||||
break;
|
||||
|
||||
case DB.Point point:
|
||||
@@ -758,22 +744,87 @@ public sealed class DisplayValueExtractor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents sorted collections of different geometry types extracted from an element.
|
||||
/// Used to pass multiple geometry collections as a single parameter to improve code readability
|
||||
/// and reduce the risk of parameter ordering errors.
|
||||
/// Applies up to two transforms to a curve in order:
|
||||
/// 1. accumulatedTransform — the GeometryInstance transform from SortGeometry.
|
||||
/// Only set for DirectShape elements (linked IFC/DWG) where the real position
|
||||
/// lives inside a nested GeometryInstance rather than on the element itself.
|
||||
/// 2. curveTransform — the instance transform (localToDocument).
|
||||
/// Only set for FamilyInstance elements.
|
||||
/// </summary>
|
||||
private DB.Curve ResolveCurveTransforms(
|
||||
DB.Curve curve,
|
||||
DB.Transform? accumulatedTransform,
|
||||
DB.Transform? curveTransform
|
||||
)
|
||||
{
|
||||
var result = accumulatedTransform is not null ? curve.CreateTransformed(accumulatedTransform) : curve;
|
||||
|
||||
if (curveTransform is not null)
|
||||
{
|
||||
var next = result.CreateTransformed(curveTransform);
|
||||
if (accumulatedTransform is not null)
|
||||
{
|
||||
result.Dispose();
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Same two-step transform logic as <see cref="ResolveCurveTransforms"/>.
|
||||
/// Operates on raw XYZ coordinates since PolyLine has no CreateTransformed API.
|
||||
/// </summary>
|
||||
private DB.PolyLine ResolvePolylineTransforms(
|
||||
DB.PolyLine polyline,
|
||||
DB.Transform? accumulatedTransform,
|
||||
DB.Transform? curveTransform
|
||||
)
|
||||
{
|
||||
DB.Transform? combined = (accumulatedTransform, curveTransform) switch
|
||||
{
|
||||
(not null, not null) => curveTransform.Multiply(accumulatedTransform),
|
||||
_ => accumulatedTransform ?? curveTransform
|
||||
};
|
||||
|
||||
var coords = polyline.GetCoordinates();
|
||||
|
||||
if (combined is null || combined.IsIdentity)
|
||||
{
|
||||
return DB.PolyLine.Create(coords);
|
||||
}
|
||||
|
||||
var transformed = new List<DB.XYZ>(coords.Count);
|
||||
foreach (var pt in coords)
|
||||
{
|
||||
transformed.Add(combined.OfPoint(pt));
|
||||
}
|
||||
|
||||
return DB.PolyLine.Create(transformed);
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// <see cref="Solids"/> and <see cref="Meshes"/> are transformed to symbol space in SortGeometry.
|
||||
/// <see cref="Curves"/>, <see cref="Polylines"/>, and <see cref="Points"/> remain in their original coordinate space
|
||||
/// and receive only the instance transform (if any) in ProcessGeometryCollections - reference point
|
||||
/// transform is handled by the point converters during conversion.
|
||||
/// Solids and meshes are transformed to world space inline in SortGeometry.
|
||||
/// Curves and polylines can't follow the same pattern because their transform
|
||||
/// path splits by element type — see ResolveCurveTransforms for details.
|
||||
/// The AccumulatedTransform in each tuple carries the GeometryInstance transform
|
||||
/// that SortGeometry would otherwise drop.
|
||||
/// </remarks>
|
||||
private sealed record GeometryCollections
|
||||
{
|
||||
public List<DB.Solid> Solids { get; } = new();
|
||||
public List<DB.Mesh> Meshes { get; } = new();
|
||||
public List<DB.Curve> Curves { get; } = new();
|
||||
public List<DB.PolyLine> Polylines { get; } = new();
|
||||
|
||||
// The transform stored alongside each curve/polyline is the accumulatedTransform that was
|
||||
// active when SortGeometry encountered it. For FamilyInstance this will be identity (the
|
||||
// instance and its inverse cancel out), so applying it is a no-op. For DirectShape elements
|
||||
// from linked IFC/DWG files it carries the real GeometryInstance transform that would
|
||||
// otherwise be silently dropped, placing curves at the origin instead of their correct position.
|
||||
public List<(DB.Curve Curve, DB.Transform? AccumulatedTransform)> Curves { get; } = new();
|
||||
public List<(DB.PolyLine Polyline, DB.Transform? AccumulatedTransform)> Polylines { get; } = new();
|
||||
|
||||
public List<DB.Point> Points { get; } = new();
|
||||
|
||||
public int TotalCount => Solids.Count + Meshes.Count + Curves.Count + Polylines.Count + Points.Count;
|
||||
|
||||
+5
@@ -203,6 +203,11 @@ public class MaterialQuantitiesToSpeckleLite : ITypedConverter<DB.Element, Dicti
|
||||
matName = "";
|
||||
if (_converterSettings.Current.Document.GetElement(matId) is DB.Material material)
|
||||
{
|
||||
// No API to identify light-cone materials by ID; exclude by well-known default name.
|
||||
if (material.Name == "Default Light Source")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
materialQuantity["materialName"] = material.Name;
|
||||
materialQuantity["materialCategory"] = material.MaterialCategory;
|
||||
materialQuantity["materialClass"] = material.MaterialClass;
|
||||
|
||||
Reference in New Issue
Block a user