Create direct shape definitions

This commit is contained in:
oguzhankoral
2024-09-30 16:53:23 +03:00
parent 9edba5d992
commit bce9ed7a6f
2 changed files with 114 additions and 14 deletions
@@ -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<GeometryObject>)
{
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<Matrix4x4>) 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<GeometryObject> 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()
{
@@ -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<GeometryObject> geometry, string? category)