static IList <GeometryObject> ImportObject(File3dm model, GeometryBase geometry, ObjectAttributes attributes, Document doc, Dictionary <string, Autodesk.Revit.DB.Material> materials, double scaleFactor) { var layer = model.AllLayers.FindIndex(attributes.LayerIndex); if (layer?.IsVisible ?? false) { using (var ctx = Convert.Context.Push()) { switch (attributes.MaterialSource) { case ObjectMaterialSource.MaterialFromObject: { var modelMaterial = attributes.MaterialIndex < 0 ? Rhino.DocObjects.Material.DefaultMaterial : model.AllMaterials.FindIndex(attributes.MaterialIndex); ctx.MaterialId = ToHost(modelMaterial, doc, materials); break; } case ObjectMaterialSource.MaterialFromLayer: { var modelLayer = model.AllLayers.FindIndex(attributes.LayerIndex); var modelMaterial = modelLayer.RenderMaterialIndex < 0 ? Rhino.DocObjects.Material.DefaultMaterial : model.AllMaterials.FindIndex(modelLayer.RenderMaterialIndex); ctx.MaterialId = ToHost(modelMaterial, doc, materials); break; } } if (geometry is InstanceReferenceGeometry instance) { if (model.AllInstanceDefinitions.FindId(instance.ParentIdefId) is InstanceDefinitionGeometry definition) { var definitionId = definition.Id.ToString(); var library = DirectShapeLibrary.GetDirectShapeLibrary(doc); if (!library.Contains(definitionId)) { var objectIds = definition.GetObjectIds(); var GNodes = objectIds. Select(x => model.Objects.FindId(x)). Cast <File3dmObject>(). SelectMany(x => ImportObject(model, x.Geometry, x.Attributes, doc, materials, scaleFactor)); library.AddDefinition(definitionId, GNodes.ToArray()); } var xform = instance.Xform.ChangeUnits(scaleFactor); return(DirectShape.CreateGeometryInstance(doc, definitionId, xform.ToHost())); } } else { return(geometry.ToHostMultiple(scaleFactor).ToList()); } } } return(new GeometryObject[0]); }
public static Result Import3DMFile(string filePath, Document doc, BuiltInCategory builtInCategory) { try { DirectShapeLibrary.GetDirectShapeLibrary(doc).Reset(); using (var model = File3dm.Read(filePath)) { var scaleFactor = RhinoMath.UnitScale(model.Settings.ModelUnitSystem, Revit.ModelUnitSystem); using (var trans = new Transaction(doc, "Import 3D Model")) { if (trans.Start() == TransactionStatus.Started) { var categoryId = new ElementId(builtInCategory); var materials = GetMaterialsByName(doc); var type = DirectShapeType.Create(doc, Path.GetFileName(filePath), categoryId); foreach (var obj in model.Objects.Where(x => !x.Attributes.IsInstanceDefinitionObject && x.Attributes.Space == ActiveSpace.ModelSpace)) { if (!obj.Attributes.Visible) { continue; } var geometryList = ImportObject(model, obj.Geometry, obj.Attributes, doc, materials, scaleFactor).ToArray(); if (geometryList == null) { continue; } try { type.AppendShape(geometryList); } catch (Autodesk.Revit.Exceptions.ArgumentException) { } } var ds = DirectShape.CreateElement(doc, type.Category.Id); ds.SetTypeId(type.Id); var library = DirectShapeLibrary.GetDirectShapeLibrary(doc); if (!library.ContainsType(type.UniqueId)) { library.AddDefinitionType(type.UniqueId, type.Id); } ds.SetShape(DirectShape.CreateGeometryInstance(doc, type.UniqueId, Autodesk.Revit.DB.Transform.Identity)); if (trans.Commit() == TransactionStatus.Committed) { var elements = new ElementId[] { ds.Id }; Revit.ActiveUIDocument.Selection.SetElementIds(elements); Revit.ActiveUIDocument.ShowElements(elements); return(Result.Succeeded); } } } } } finally { DirectShapeLibrary.GetDirectShapeLibrary(doc).Reset(); } return(Result.Failed); }
static IList <GeometryObject> ImportObject(File3dm model, GeometryBase geometry, ObjectAttributes attributes, Document doc, Dictionary <string, Autodesk.Revit.DB.Material> materials, double scaleFactor) { using (var ga = Convert.GraphicAttributes.Push()) { switch (attributes.MaterialSource) { case ObjectMaterialSource.MaterialFromObject: { var modelMaterial = attributes.MaterialIndex < 0 ? Rhino.DocObjects.Material.DefaultMaterial : model.AllMaterials.FindIndex(attributes.MaterialIndex); ga.MaterialId = ToHost(modelMaterial, doc, materials); break; } case ObjectMaterialSource.MaterialFromLayer: { var modelLayer = model.AllLayers.FindIndex(attributes.LayerIndex); var modelMaterial = modelLayer.RenderMaterialIndex < 0 ? Rhino.DocObjects.Material.DefaultMaterial : model.AllMaterials.FindIndex(modelLayer.RenderMaterialIndex); ga.MaterialId = ToHost(modelMaterial, doc, materials); break; } } if (geometry is InstanceReferenceGeometry instance) { if (model.AllInstanceDefinitions.FindId(instance.ParentIdefId) is InstanceDefinitionGeometry definition) { var objectIds = definition.GetObjectIds(); // Compute a definition ID that includes InstanceDefinition Name, Id and content object Ids var definitionId = definition.Name; { var data = new byte[(objectIds.Length + 1) * 16]; Buffer.BlockCopy(instance.ParentIdefId.ToByteArray(), 0, data, 0, 16); for (int i = 0; i < objectIds.Length; i++) { Buffer.BlockCopy(objectIds[i].ToByteArray(), 0, data, (i * 16), 16); } using (var sha256 = System.Security.Cryptography.SHA256.Create()) definitionId += $"[{ByteArrayToString(sha256.ComputeHash(data))}]"; } var library = DirectShapeLibrary.GetDirectShapeLibrary(doc); if (!library.Contains(definitionId)) { var GNodes = objectIds. Select(x => model.Objects.FindId(x)). Cast <File3dmObject>(). SelectMany(x => ImportObject(model, x.Geometry, x.Attributes, doc, materials, scaleFactor)); library.AddDefinition(definitionId, GNodes.ToArray()); } var xform = instance.Xform; xform.Affineize(); xform.DecomposeAffine(out Vector3d translation, out var linear); xform = Rhino.Geometry.Transform.Translation(translation * scaleFactor) * linear; return(DirectShape.CreateGeometryInstance(doc, definitionId, xform.ToHost())); } return(new GeometryObject[0]); } else { return(geometry.ToHost(scaleFactor).ToList()); } } }
/// <summary> /// Create geometry for a particular representation item. /// </summary> /// <param name="shapeEditScope">The geometry creation scope.</param> /// <param name="lcs">Local coordinate system for the geometry, without scale.</param> /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param> /// <param name="guid">The guid of an element for which represntation is being created.</param> protected override void CreateShapeInternal(IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid) { base.CreateShapeInternal(shapeEditScope, lcs, scaledLcs, guid); // Check scale; if it is uniform, create an instance. If not, create a shape directly. // TODO: Instead allow creation of instances based on similar scaling. double scaleX = MappingTarget.Scale; double scaleY = MappingTarget.ScaleY.HasValue ? MappingTarget.ScaleY.Value : scaleX; double scaleZ = MappingTarget.ScaleZ.HasValue ? MappingTarget.ScaleZ.Value : scaleX; bool isUnitScale = (MathUtil.IsAlmostEqual(scaleX, 1.0) && MathUtil.IsAlmostEqual(scaleY, 1.0) && MathUtil.IsAlmostEqual(scaleZ, 1.0)); Transform mappingTransform = MappingTarget.Transform; Transform newLcs = (mappingTransform == null) ? lcs : (lcs?.Multiply(mappingTransform) ?? mappingTransform); Transform newScaledLcs = (mappingTransform == null) ? scaledLcs : (scaledLcs?.Multiply(mappingTransform) ?? mappingTransform); bool isFootprint = (shapeEditScope.ContainingRepresentation.Identifier == IFCRepresentationIdentifier.FootPrint); bool canCreateType = !shapeEditScope.PreventInstances && !isFootprint && isUnitScale && (newLcs?.IsConformal ?? true) && (newScaledLcs?.IsConformal ?? true) && (shapeEditScope.ContainingRepresentation != null); if (canCreateType) { int mappingSourceId = MappingSource.Id; int geometrySourceId = FindAlternateGeometrySource(mappingSourceId); MappingSource.CreateShape(shapeEditScope, null, null, guid); if (shapeEditScope.Creator != null) { Importer.TheProcessor.PostProcessMappedItem(shapeEditScope.Creator.Id, shapeEditScope.Creator.GlobalId, shapeEditScope.Creator.EntityType.ToString(), shapeEditScope.Creator.CategoryId, geometrySourceId, newLcs); } // NAVIS_TODO: Figure out how not to do this. IList <GeometryObject> instances = DirectShape.CreateGeometryInstance( shapeEditScope.Document, mappingSourceId.ToString(), newLcs); foreach (GeometryObject instance in instances) { shapeEditScope.AddGeometry(IFCSolidInfo.Create(Id, instance)); } } else { if (!isUnitScale) { XYZ xScale = new XYZ(scaleX, 0.0, 0.0); XYZ yScale = new XYZ(0.0, scaleY, 0.0); XYZ zScale = new XYZ(0.0, 0.0, scaleZ); Transform scaleTransform = Transform.Identity; scaleTransform.set_Basis(0, xScale); scaleTransform.set_Basis(1, yScale); scaleTransform.set_Basis(2, zScale); newScaledLcs = newScaledLcs.Multiply(scaleTransform); } MappingSource.CreateShape(shapeEditScope, newLcs, newScaledLcs, guid); } }
/// <summary> /// Create geometry for a particular representation item. /// </summary> /// <param name="shapeEditScope">The geometry creation scope.</param> /// <param name="lcs">Local coordinate system for the geometry, without scale.</param> /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param> /// <param name="guid">The guid of an element for which represntation is being created.</param> protected override void CreateShapeInternal(IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid) { base.CreateShapeInternal(shapeEditScope, lcs, scaledLcs, guid); // Check scale; if it is uniform, create an instance. If not, create a shape directly. // TODO: Instead allow creation of instances based on similar scaling. double scaleX = MappingTarget.Scale; double scaleY = MappingTarget.ScaleY.HasValue ? MappingTarget.ScaleY.Value : scaleX; double scaleZ = MappingTarget.ScaleZ.HasValue ? MappingTarget.ScaleZ.Value : scaleX; bool isUnitScale = (MathUtil.IsAlmostEqual(scaleX, 1.0) && MathUtil.IsAlmostEqual(scaleY, 1.0) && MathUtil.IsAlmostEqual(scaleZ, 1.0)); Transform mappingTransform = MappingTarget.Transform; Transform newLcs = null; if (lcs == null) { newLcs = mappingTransform; } else if (mappingTransform == null) { newLcs = lcs; } else { newLcs = lcs.Multiply(mappingTransform); } Transform newScaledLcs = null; if (scaledLcs == null) { newScaledLcs = mappingTransform; } else if (mappingTransform == null) { newScaledLcs = scaledLcs; } else { newScaledLcs = scaledLcs.Multiply(mappingTransform); } // Pass in newLCS = null, use newLCS for instance. bool isFootprint = (shapeEditScope.ContainingRepresentation.Identifier == IFCRepresentationIdentifier.FootPrint); bool canCreateType = (newLcs != null && newLcs.IsConformal) && (newScaledLcs != null && newScaledLcs.IsConformal) && isUnitScale && (shapeEditScope.ContainingRepresentation != null && !isFootprint); if (canCreateType) { MappingSource.CreateShape(shapeEditScope, null, null, guid); IList <GeometryObject> instances = DirectShape.CreateGeometryInstance(shapeEditScope.Document, MappingSource.Id.ToString(), newLcs); foreach (GeometryObject instance in instances) { shapeEditScope.AddGeometry(IFCSolidInfo.Create(Id, instance)); } } else { if (!isUnitScale) { XYZ xScale = new XYZ(scaleX, 0.0, 0.0); XYZ yScale = new XYZ(0.0, scaleY, 0.0); XYZ zScale = new XYZ(0.0, 0.0, scaleZ); Transform scaleTransform = Transform.Identity; scaleTransform.set_Basis(0, xScale); scaleTransform.set_Basis(1, yScale); scaleTransform.set_Basis(2, zScale); newScaledLcs = newScaledLcs.Multiply(scaleTransform); } MappingSource.CreateShape(shapeEditScope, newLcs, newScaledLcs, guid); } }