public BlockDefinition BlockDefinitionToSpeckle(RH.InstanceDefinition definition) { var geometry = new List <Base>(); foreach (var obj in definition.GetObjects()) { if (CanConvertToSpeckle(obj)) { Base converted = ConvertToSpeckle(obj); if (converted != null) { converted["Layer"] = Doc.Layers[obj.Attributes.LayerIndex].FullPath; geometry.Add(converted); } } } var _definition = new BlockDefinition() { name = definition.Name, basePoint = PointToSpeckle(Point3d.Origin), // rhino by default sets selected block def base pt at world origin geometry = geometry, units = ModelUnits }; return(_definition); }
public InstanceDefinition BlockDefinitionToNative(BlockDefinition definition) { // get modified definition name with commit info var commitInfo = GetCommitInfo(); var blockName = $"{commitInfo} - {definition.name}"; // see if block name already exists and return if so if (Doc.InstanceDefinitions.Find(blockName) is InstanceDefinition def) { return(def); } // base point Point3d basePoint = PointToNative(definition.basePoint).Location; // geometry and attributes var geometry = new List <GeometryBase>(); var attributes = new List <ObjectAttributes>(); foreach (var geo in definition.geometry) { if (CanConvertToNative(geo)) { GeometryBase converted = null; switch (geo) { case BlockInstance _: var instance = (InstanceObject)ConvertToNative(geo); converted = instance.Geometry; Doc.Objects.Delete(instance); break; default: converted = (GeometryBase)ConvertToNative(geo); break; } if (converted == null) { continue; } var layerName = $"{commitInfo}{Layer.PathSeparator}{geo["Layer"] as string}"; int index = 1; if (layerName != null) { GetLayer(Doc, layerName, out index, true); } var attribute = new ObjectAttributes() { LayerIndex = index }; geometry.Add(converted); attributes.Add(attribute); } } int definitionIndex = Doc.InstanceDefinitions.Add(blockName, string.Empty, basePoint, geometry, attributes); if (definitionIndex < 0) { return(null); } var blockDefinition = Doc.InstanceDefinitions[definitionIndex]; return(blockDefinition); }
// TODO: fix unit conversions since block geometry is being converted inside a new family document, which potentially has different unit settings from the main doc. // This could be done by passing in an option Document argument for all conversions that defaults to the main doc (annoying) // I suspect this also needs to be fixed for freeform elements private string BlockDefinitionToNative(BlockDefinition definition) { // convert definition geometry to native var solids = new List <DB.Solid>(); var curves = new List <DB.Curve>(); var blocks = new List <BlockInstance>(); foreach (var geometry in definition.geometry) { switch (geometry) { case Brep brep: try { var solid = BrepToNative(geometry as Brep); solids.Add(solid); } catch (Exception e) { ConversionErrors.Add(new SpeckleException($"Could not convert block {definition.id} brep to native, falling back to mesh representation.", e)); var brepMeshSolids = MeshToNative(brep.displayMesh, DB.TessellatedShapeBuilderTarget.Solid, DB.TessellatedShapeBuilderFallback.Abort) .Select(m => m as DB.Solid); solids.AddRange(brepMeshSolids); } break; case Mesh mesh: var meshSolids = MeshToNative(mesh, DB.TessellatedShapeBuilderTarget.Solid, DB.TessellatedShapeBuilderFallback.Abort) .Select(m => m as DB.Solid); solids.AddRange(meshSolids); break; case ICurve curve: try { var modelCurves = CurveToNative(geometry as ICurve); foreach (DB.Curve modelCurve in modelCurves) { curves.Add(modelCurve); } } catch (Exception e) { ConversionErrors.Add(new SpeckleException($"Could not convert block {definition.id} curve to native.", e)); } break; case BlockInstance instance: blocks.Add(instance); break; } } // create a family to represent a block definition // TODO: package our own generic model rft so this path will always work (need to change for freeform elem too) // TODO: match the rft unit to the main doc unit system (ie if main doc is in feet, pick the English Generic Model) // TODO: rename block with stream commit info prefix taken from UI - need to figure out cleanest way of storing this in the doc for retrieval by converter var famPath = Path.Combine(Doc.Application.FamilyTemplatePath, @"Metric Generic Model.rft"); if (!File.Exists(famPath)) { throw new Exception($"Could not find file Metric Generic Model.rft - {famPath}"); } var famDoc = Doc.Application.NewFamilyDocument(famPath); using (DB.Transaction t = new DB.Transaction(famDoc, "Create Block Geometry Elements")) { t.Start(); solids.ForEach(o => { DB.FreeFormElement.Create(famDoc, o); }); curves.ForEach(o => { famDoc.FamilyCreate.NewModelCurve(o, NewSketchPlaneFromCurve(o, famDoc)); }); blocks.ForEach(o => { BlockInstanceToNative(o, famDoc); }); t.Commit(); } var famName = "SpeckleBlock_" + definition.name; string familyPath = Path.Combine(Path.GetTempPath(), famName + ".rfa"); var so = new DB.SaveAsOptions(); so.OverwriteExistingFile = true; famDoc.SaveAs(familyPath, so); famDoc.Close(); return(familyPath); }