From 5fddfd92a3d443a6360232ef4770821be5a3c695 Mon Sep 17 00:00:00 2001 From: connorivy <43247197+connorivy@users.noreply.github.com> Date: Wed, 3 Jul 2024 10:33:49 -0500 Subject: [PATCH] Dui3 177 receive levels in Revit (#3553) * Auto stash before checking out "origin/dui3/alpha" * Fix Rhino lock * address pr comments * add level receive (and top level send) * fix merge * fix rebase operation --------- Co-authored-by: Connor Ivy Co-authored-by: Adam Hathcock --- .../RevitConverterModule.cs | 2 + .../RevitRootToHostConverter.cs | 28 +++++++ .../Speckle.Converters.RevitShared.projitems | 4 +- .../TopLevel/LevelToHostTopLevelConverter.cs | 77 +++++++++++++++++++ .../LevelTopLevelConverterToSpeckle.cs} | 7 +- 5 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/RevitRootToHostConverter.cs create mode 100644 DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/ToHost/TopLevel/LevelToHostTopLevelConverter.cs rename DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/{Raw/LevelConversionToSpeckle.cs => TopLevel/LevelTopLevelConverterToSpeckle.cs} (68%) diff --git a/DUI3-DX/Converters/Revit/Speckle.Converters.Revit2023.DependencyInjection/RevitConverterModule.cs b/DUI3-DX/Converters/Revit/Speckle.Converters.Revit2023.DependencyInjection/RevitConverterModule.cs index 54203e1e03..e82fe0100a 100644 --- a/DUI3-DX/Converters/Revit/Speckle.Converters.Revit2023.DependencyInjection/RevitConverterModule.cs +++ b/DUI3-DX/Converters/Revit/Speckle.Converters.Revit2023.DependencyInjection/RevitConverterModule.cs @@ -1,5 +1,6 @@ using Autodesk.Revit.DB; using Speckle.Autofac.DependencyInjection; +using Speckle.Converters.Common; using Speckle.Converters.Common.DependencyInjection; using Speckle.Converters.RevitShared; using Speckle.Converters.RevitShared.Helpers; @@ -18,6 +19,7 @@ public void Load(SpeckleContainerBuilder builder) // register all application converters builder.AddApplicationConverters(); + builder.AddScoped(); builder.AddSingleton(new RevitContext()); // POC: do we need ToSpeckleScalingService as is, do we need to interface it out? diff --git a/DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/RevitRootToHostConverter.cs b/DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/RevitRootToHostConverter.cs new file mode 100644 index 0000000000..f6284b930f --- /dev/null +++ b/DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/RevitRootToHostConverter.cs @@ -0,0 +1,28 @@ +using Speckle.Converters.Common; +using Speckle.Converters.Common.Objects; +using Speckle.Core.Models; + +namespace Speckle.Converters.RevitShared; + +public class RevitRootToHostConverter : IRootToHostConverter +{ + private readonly IConverterResolver _converterResolver; + + public RevitRootToHostConverter(IConverterResolver converterResolver) + { + _converterResolver = converterResolver; + } + + public object Convert(Base target) + { + var objectConverter = _converterResolver.GetConversionForType(target.GetType()); + + if (objectConverter == null) + { + throw new SpeckleConversionException($"No conversion found for {target.GetType().Name}"); + } + + return objectConverter.Convert(target) + ?? throw new SpeckleConversionException($"Conversion of object with type {target.GetType()} returned null"); + } +} diff --git a/DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/Speckle.Converters.RevitShared.projitems b/DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/Speckle.Converters.RevitShared.projitems index 2db6172222..e33ba9046a 100644 --- a/DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/Speckle.Converters.RevitShared.projitems +++ b/DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/Speckle.Converters.RevitShared.projitems @@ -23,6 +23,7 @@ + @@ -36,6 +37,7 @@ + @@ -60,7 +62,7 @@ - + diff --git a/DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/ToHost/TopLevel/LevelToHostTopLevelConverter.cs b/DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/ToHost/TopLevel/LevelToHostTopLevelConverter.cs new file mode 100644 index 0000000000..69f72e4f18 --- /dev/null +++ b/DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/ToHost/TopLevel/LevelToHostTopLevelConverter.cs @@ -0,0 +1,77 @@ +using Speckle.Converters.Common; +using Speckle.Converters.RevitShared.Helpers; +using Speckle.Converters.RevitShared.ToSpeckle; +using Speckle.Converters.RevitShared.Services; + +namespace Speckle.Converters.RevitShared.ToHost.ToLevel; + +[NameAndRankValue(nameof(SOBE.Level), 0)] +public class LevelToHostTopLevelConverter : BaseTopLevelConverterToHost +{ + private readonly IRevitConversionContextStack _contextStack; + private readonly ScalingServiceToHost _scalingService; + + public LevelToHostTopLevelConverter(IRevitConversionContextStack contextStack, ScalingServiceToHost scalingService) + { + _contextStack = contextStack; + _scalingService = scalingService; + } + + public override DB.Level Convert(SOBE.Level target) + { + using var documentLevelCollector = new DB.FilteredElementCollector(_contextStack.Current.Document); + var docLevels = documentLevelCollector.OfClass(typeof(DB.Level)).ToElements().Cast(); + + // POC : I'm not really understanding the linked use case for this. Do we want to bring this over? + + //bool elevationMatch = true; + ////level by name component + //if (target is RevitLevel speckleRevitLevel && speckleRevitLevel.referenceOnly) + //{ + // //see: https://speckle.community/t/revit-connector-levels-and-spaces/2824/5 + // elevationMatch = false; + // if (GetExistingLevelByName(docLevels, target.name) is DB.Level existingLevelWithSameName) + // { + // return existingLevelWithSameName; + // } + //} + + DB.Level revitLevel; + var targetElevation = _scalingService.ScaleToNative(target.elevation, target.units); + + if (GetExistingLevelByElevation(docLevels, targetElevation) is DB.Level existingLevel) + { + revitLevel = existingLevel; + } + else + { + revitLevel = DB.Level.Create(_contextStack.Current.Document, targetElevation); + revitLevel.Name = target.name; + + if (target is SOBR.RevitLevel rl && rl.createView) + { + using var viewPlan = CreateViewPlan(target.name, revitLevel.Id); + } + } + + return revitLevel; + } + + private static DB.Level GetExistingLevelByElevation(IEnumerable docLevels, double elevation) + { + return docLevels.FirstOrDefault(l => Math.Abs(l.Elevation - elevation) < RevitConversionContextStack.TOLERANCE); + } + + private DB.ViewPlan CreateViewPlan(string name, DB.ElementId levelId) + { + using var collector = new DB.FilteredElementCollector(_contextStack.Current.Document); + var vt = collector + .OfClass(typeof(DB.ViewFamilyType)) + .First(el => ((DB.ViewFamilyType)el).ViewFamily == DB.ViewFamily.FloorPlan); + + var view = DB.ViewPlan.Create(_contextStack.Current.Document, vt.Id, levelId); + view.Name = name; + + return view; + } +} diff --git a/DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Raw/LevelConversionToSpeckle.cs b/DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/TopLevel/LevelTopLevelConverterToSpeckle.cs similarity index 68% rename from DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Raw/LevelConversionToSpeckle.cs rename to DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/TopLevel/LevelTopLevelConverterToSpeckle.cs index 33e1d7fea2..2916415bb3 100644 --- a/DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Raw/LevelConversionToSpeckle.cs +++ b/DUI3-DX/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/TopLevel/LevelTopLevelConverterToSpeckle.cs @@ -1,9 +1,10 @@ -using Speckle.Converters.Common.Objects; +using Speckle.Converters.Common; using Speckle.Converters.RevitShared.Services; namespace Speckle.Converters.RevitShared.ToSpeckle; -public class LevelConversionToSpeckle : ITypedConverter +[NameAndRankValue(nameof(DB.Level), 0)] +public class LevelConversionToSpeckle : BaseTopLevelConverterToSpeckle { private readonly ScalingServiceToSpeckle _scalingService; @@ -12,7 +13,7 @@ public LevelConversionToSpeckle(ScalingServiceToSpeckle scalingService) _scalingService = scalingService; } - public SOBR.RevitLevel Convert(DB.Level target) + public override SOBR.RevitLevel Convert(DB.Level target) { SOBR.RevitLevel level = new()