From 217fecb5d730a9e830a9fcbd801b5e1847aaf2db Mon Sep 17 00:00:00 2001 From: Claire Kuang Date: Tue, 14 Nov 2023 14:19:52 +0000 Subject: [PATCH] fix(revit): extrusion roof and freeform elements conversion (#3045) * Update ConvertFreeformElement.cs * fixes extrusion roof conversion * Update ConvertRoof.cs --- .../Partial Classes/ConvertFreeformElement.cs | 12 ++++-- .../Partial Classes/ConvertGeometry.cs | 10 ++++- .../Partial Classes/ConvertRoof.cs | 38 ++++++++++--------- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/Partial Classes/ConvertFreeformElement.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/Partial Classes/ConvertFreeformElement.cs index abf6c3ab82..b534116cc6 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/Partial Classes/ConvertFreeformElement.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/Partial Classes/ConvertFreeformElement.cs @@ -52,6 +52,7 @@ public ApplicationObject FreeformElementToNative(Objects.BuiltElements.Revit.Fre appObj.Update(status: ApplicationObject.State.Failed); return appObj; } + Doc.LoadFamily(tempPath, new FamilyLoadOption(), out var fam); var symbol = Doc.GetElement(fam.GetFamilySymbolIds().First()) as DB.FamilySymbol; symbol.Activate(); @@ -186,10 +187,12 @@ private string CreateFreeformElementFamily(List solids, string name, o t.Start(); //by default free form elements are always generic models - BuiltInCategory bic = BuiltInCategory.OST_GenericModel; - Category cat = famDoc.Settings.Categories.get_Item(bic); + Category cat = null; if (freeformElement is not null && !string.IsNullOrEmpty(freeformElement.subcategory)) { + BuiltInCategory bic = BuiltInCategory.OST_GenericModel; + cat = famDoc.Settings.Categories.get_Item(bic); + //subcategory if (cat.SubCategories.Contains(freeformElement.subcategory)) { @@ -204,7 +207,10 @@ private string CreateFreeformElementFamily(List solids, string name, o foreach (var s in solids) { var f = DB.FreeFormElement.Create(famDoc, s); - f.Subcategory = cat; + if (cat is not null) + { + f.Subcategory = cat; + } } t.Commit(); diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/Partial Classes/ConvertGeometry.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/Partial Classes/ConvertGeometry.cs index 663f8d4661..7863a9a5c3 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/Partial Classes/ConvertGeometry.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/Partial Classes/ConvertGeometry.cs @@ -743,9 +743,17 @@ public XYZ GetPerpendicular(XYZ xyz) var xn = new XYZ(1, 0, 0); if (ixn.IsAlmostEqualTo(xn)) + { xn = new XYZ(0, 1, 0); + } + else if (ixn.Negate().IsAlmostEqualTo(xn)) + { + xn = new XYZ(0, -1, 0); + } + + var cross = ixn.CrossProduct(xn); - return ixn.CrossProduct(xn).Normalize(); + return cross.Normalize(); } public Geometry.Surface FaceToSpeckle(DB.Face face, DB.BoundingBoxUV uvBox, Document doc, string units = null) diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/Partial Classes/ConvertRoof.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/Partial Classes/ConvertRoof.cs index 5ec5ff2e3f..446f9aaee1 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/Partial Classes/ConvertRoof.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/Partial Classes/ConvertRoof.cs @@ -29,19 +29,26 @@ public ApplicationObject RoofToNative(Roof speckleRoof) return appObj; } - // outline is required for roofs, except for Extrusion roofs - CurveArray outline = null; - if (speckleRoof.outline is null) + // outline is required for footprint roofs + // referenceLine is required for for Extrusion roofs + CurveArray roofCurve = null; + if (speckleRoof is RevitExtrusionRoof extrusionRoof) { - if (speckleRoof is not RevitExtrusionRoof) + if (extrusionRoof.referenceLine is null) { - appObj.Update(status: ApplicationObject.State.Failed, logItem: "Roof outline was null"); + appObj.Update(status: ApplicationObject.State.Failed, logItem: "Extrusion roof profile was null"); return appObj; } + roofCurve = CurveToNative(extrusionRoof.referenceLine); } else { - outline = CurveToNative(speckleRoof.outline); + if (speckleRoof.outline is null) + { + appObj.Update(status: ApplicationObject.State.Failed, logItem: "Roof outline was null"); + return appObj; + } + roofCurve = CurveToNative(speckleRoof.outline); } // retrieve the level @@ -49,8 +56,8 @@ public ApplicationObject RoofToNative(Roof speckleRoof) double baseOffset = 0.0; DB.Level level = speckleRoof.level is not null ? ConvertLevelToRevit(speckleRoof.level, out levelState) - : outline is not null - ? ConvertLevelToRevit(outline.get_Item(0), out levelState, out baseOffset) + : roofCurve is not null + ? ConvertLevelToRevit(roofCurve.get_Item(0), out levelState, out baseOffset) : null; var speckleRevitRoof = speckleRoof as RevitRoof; @@ -72,6 +79,7 @@ public ApplicationObject RoofToNative(Roof speckleRoof) { case RevitExtrusionRoof speckleExtrusionRoof: { + // get the norm var referenceLine = LineToNative(speckleExtrusionRoof.referenceLine); var norm = GetPerpendicular(referenceLine.GetEndPoint(0) - referenceLine.GetEndPoint(1)).Negate(); ReferencePlane plane = Doc.Create.NewReferencePlane( @@ -81,16 +89,10 @@ public ApplicationObject RoofToNative(Roof speckleRoof) Doc.ActiveView ); - // get level if null - if (level is null) - { - level = ConvertLevelToRevit(referenceLine, out levelState, out baseOffset); - } - - //create floor without a type + //create floor without a type with the profile var start = ScaleToNative(speckleExtrusionRoof.start, speckleExtrusionRoof.units); var end = ScaleToNative(speckleExtrusionRoof.end, speckleExtrusionRoof.units); - revitRoof = Doc.Create.NewExtrusionRoof(outline, plane, level, roofType, start, end); + revitRoof = Doc.Create.NewExtrusionRoof(roofCurve, plane, level, roofType, start, end); // sometimes Revit flips the roof so the start offset is the end and vice versa. // In that case, delete the created roof, flip the referencePlane and recreate it. @@ -99,14 +101,14 @@ public ApplicationObject RoofToNative(Roof speckleRoof) { Doc.Delete(revitRoof.Id); plane.Flip(); - revitRoof = Doc.Create.NewExtrusionRoof(outline, plane, level, roofType, start, end); + revitRoof = Doc.Create.NewExtrusionRoof(roofCurve, plane, level, roofType, start, end); } break; } case RevitFootprintRoof speckleFootprintRoof: { ModelCurveArray curveArray = new ModelCurveArray(); - var revitFootprintRoof = Doc.Create.NewFootPrintRoof(outline, level, roofType, out curveArray); + var revitFootprintRoof = Doc.Create.NewFootPrintRoof(roofCurve, level, roofType, out curveArray); // if the roof is a curtain roof then set the mullions at the borders var nestedElements = speckleFootprintRoof.elements;