diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Receive/RevitHostObjectBuilder.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Receive/RevitHostObjectBuilder.cs index a74c4b8ca..65fb634fb 100644 --- a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Receive/RevitHostObjectBuilder.cs +++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Receive/RevitHostObjectBuilder.cs @@ -13,6 +13,7 @@ using Speckle.Objects.Geometry; using Speckle.Sdk; using Speckle.Sdk.Logging; using Speckle.Sdk.Models; +using Speckle.DoubleNumerics; namespace Speckle.Connectors.Revit.Operations.Receive; @@ -197,28 +198,53 @@ internal sealed class RevitHostObjectBuilder : IHostObjectBuilder, IDisposable try { using var activity = _activityFactory.Start("BakeObject"); - var atomicObject = _localToGlobalConverterUtils.TransformObjects( - localToGlobalMap.AtomicObject, - localToGlobalMap.Matrix - ); - var result = _converter.Convert(atomicObject); + // var atomicObject = _localToGlobalConverterUtils.TransformObjects( + // localToGlobalMap.AtomicObject, + // localToGlobalMap.Matrix + // ); + var result = _converter.Convert(localToGlobalMap.AtomicObject); onOperationProgressed?.Invoke("Converting", (double)++count / localToGlobalMaps.Count); + if (result is List) + { + Transform combinedTransform = Transform.Identity; + + foreach (Matrix4x4 matrix in localToGlobalMap.Matrix) + { + Transform revitTransform = ConvertMatrixToRevitTransform(matrix); + combinedTransform = combinedTransform.Multiply(revitTransform); + } + + var transformedGeometries = DirectShape.CreateGeometryInstance(_converterSettings.Current.Document, + localToGlobalMap.AtomicObject.applicationId ?? localToGlobalMap.AtomicObject.id, combinedTransform); + DirectShape directShapes = CreateDirectShape(transformedGeometries, localToGlobalMap.AtomicObject["category"] as string); + + bakedObjectIds.Add(directShapes.UniqueId.ToString()); + _groupBaker.AddToGroupMapping(localToGlobalMap.TraversalContext, directShapes); + if (localToGlobalMap.AtomicObject is IRawEncodedObject && localToGlobalMap.AtomicObject is Base myBase) + { + toPaintLater.Add((directShapes, myBase.applicationId ?? myBase.id)); + } + conversionResults.Add(new(Status.SUCCESS, localToGlobalMap.AtomicObject, directShapes.UniqueId, "Direct Shape")); + } + // Note: our current converter always returns a DS for now if (result is DirectShape ds) { + // TODO: here I want to apply transformations (List) to my direct shape, is it possible? + bakedObjectIds.Add(ds.UniqueId.ToString()); _groupBaker.AddToGroupMapping(localToGlobalMap.TraversalContext, ds); - if (atomicObject is IRawEncodedObject && atomicObject is Base myBase) + if (localToGlobalMap.AtomicObject is IRawEncodedObject && localToGlobalMap.AtomicObject is Base myBase) { toPaintLater.Add((ds, myBase.applicationId ?? myBase.id)); } } - else - { - throw new SpeckleConversionException($"Failed to cast {result.GetType()} to Direct Shape."); - } - conversionResults.Add(new(Status.SUCCESS, atomicObject, ds.UniqueId, "Direct Shape")); + // else + // { + // throw new SpeckleConversionException($"Failed to cast {result.GetType()} to Direct Shape."); + // } + // conversionResults.Add(new(Status.SUCCESS, localToGlobalMap.AtomicObject, ds.UniqueId, "Direct Shape")); } catch (Exception ex) when (!ex.IsFatal()) { @@ -227,12 +253,84 @@ internal sealed class RevitHostObjectBuilder : IHostObjectBuilder, IDisposable } return (new(bakedObjectIds, conversionResults), toPaintLater); } + + private Transform ConvertMatrixToRevitTransform(Matrix4x4 matrix) + { + // Scale??? + var translation = new XYZ(matrix.M14, matrix.M24, matrix.M34); + var basisX = new XYZ(matrix.M11, matrix.M21, matrix.M31); + var basisY = new XYZ(matrix.M12, matrix.M22, matrix.M32); + var basisZ = new XYZ(matrix.M13, matrix.M23, matrix.M33); + + var transform = Transform.Identity; + transform.BasisX = basisX; + transform.BasisY = basisY; + transform.BasisZ = basisZ; + transform.Origin = translation; + + return transform; + } private void PreReceiveDeepClean(string baseGroupName) { _groupBaker.PurgeGroups(baseGroupName); _materialBaker.PurgeMaterials(baseGroupName); } + + private DirectShape CreateDirectShape(IList geometry, string? category) + { + // set ds category + var dsCategory = BuiltInCategory.OST_GenericModel; + if (category is string categoryString) + { + var res = Enum.TryParse($"OST_{categoryString}", out BuiltInCategory cat); + if (res) + { + var c = Category.GetCategory(_converterSettings.Current.Document, cat); + if (c is not null && DirectShape.IsValidCategoryId(c.Id, _converterSettings.Current.Document)) + { + dsCategory = cat; + } + } + } + + var result = DirectShape.CreateElement(_converterSettings.Current.Document, new ElementId(dsCategory)); + + // check for valid geometry + if (!result.IsValidShape(geometry)) + { + _converterSettings.Current.Document.Delete(result.Id); + throw new SpeckleConversionException("Invalid geometry (eg unbounded curves) found for creating directshape."); + } + + result.SetShape(geometry); + + // if (originalObject is SOG.IRawEncodedObject) + // { + // var materialId = DB.ElementId.InvalidElementId; + // if ( + // _revitToHostCacheSingleton.MaterialsByObjectId.TryGetValue(originalObject.applicationId ?? originalObject.id, out var mappedElementId) + // ) + // { + // materialId = mappedElementId; + // } + // + // // if(materialId == DB.ElementId.InvalidElementId) + // var elGeometry = result.get_Geometry(new Options() { DetailLevel = ViewDetailLevel.Undefined }); + // foreach (var geo in elGeometry) + // { + // if (geo is Solid s) + // { + // foreach (Face face in s.Faces) + // { + // _converterSettings.Current.Document.Paint(result.Id, face, materialId); + // } + // } + // } + // } + + return result; + } public void Dispose() { diff --git a/Converters/Revit/Speckle.Converters.RevitShared/RevitRootToHostConverter.cs b/Converters/Revit/Speckle.Converters.RevitShared/RevitRootToHostConverter.cs index d69bc0371..f2f8951eb 100644 --- a/Converters/Revit/Speckle.Converters.RevitShared/RevitRootToHostConverter.cs +++ b/Converters/Revit/Speckle.Converters.RevitShared/RevitRootToHostConverter.cs @@ -32,11 +32,13 @@ public class RevitRootToHostConverter : IRootToHostConverter { throw new SpeckleConversionException($"No supported conversion for {target.speckle_type} found."); } + + DB.DirectShapeLibrary.GetDirectShapeLibrary(_converterSettings.Current.Document).AddDefinition(target.applicationId ?? target.id, geometryObjects); // create direct shape from geometries - DB.DirectShape result = CreateDirectShape(geometryObjects, target["category"] as string); - - return result; + //DB.DirectShape result = CreateDirectShape(geometryObjects, target["category"] as string); + + return geometryObjects; } private DB.DirectShape CreateDirectShape(List geometry, string? category)