Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        // 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);
        }