private static void CreateDirectShape(Document doc, IList <GeometryObject> geometry) { DirectShapeLibrary directShapeLibrary = DirectShapeLibrary.GetDirectShapeLibrary(doc); DirectShapeType directShapeType = DirectShapeType.Create(doc, "NavisWorksShape", new ElementId(BuiltInCategory.OST_GenericModel)); directShapeType.SetShape(geometry); directShapeLibrary.AddDefinitionType("NavisWorksShape", directShapeType.Id); DirectShape ds = DirectShape.CreateElementInstance(doc, directShapeType.Id, directShapeType.Category.Id, "NavisWorksShape", Transform.Identity); ds.SetTypeId(directShapeType.Id); ds.ApplicationId = Assembly.GetExecutingAssembly().GetType().GUID.ToString(); ds.ApplicationDataId = Guid.NewGuid().ToString(); DirectShapeOptions dsOptions = ds.GetOptions(); dsOptions.ReferencingOption = DirectShapeReferencingOption.Referenceable; ds.SetOptions(dsOptions); ds.SetShape(geometry); }
/// <summary> /// 模板生成 /// </summary> /// <param name="doc"></param> /// <param name="face"></param> /// <param name="drt"></param> /// <param name="HostELemID"></param> /// <returns></returns> public static ElementId SurfaceLayerGernerate(Document doc, Face face, DirectShapeType drt, ElementId HostELemID) { DirectShape dsElem = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_Parts), Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); XYZ faceNormal = face.ComputeNormal(new UV(0, 0)); if (face is CylindricalFace) { return(null); //如果是圆柱面则排除 } IList <CurveLoop> faceLoopList = face.GetEdgesAsCurveLoops(); Solid sd = GeometryCreationUtilities.CreateExtrusionGeometry(faceLoopList, faceNormal, 5 / 304.8); //模板尺寸判断,矩形标尺寸,非矩形不标 string tpSize = null; double last = sd.Volume; //catch { SWF.MessageBox.Show(HostELemID.IntegerValue + ""); } //对于生成的solid进行预处理 sd = SolidHandle(doc, HostELemID, sd); double now = sd.Volume; if (now == 0) { return(null); } if (last == now) { if (faceLoopList.Count == 1) { List <Curve> curveList = faceLoopList[0].ToList(); tpSize = bc.RectTangleSize(curveList); } else { tpSize = "非矩形板"; } } else { tpSize = "非矩形板"; } dsElem.SetShape(new List <GeometryObject>() { sd }); dsElem.SetTypeId(drt.Id); dsElem.LookupParameter("HostElemID").Set(HostELemID.IntegerValue); dsElem.LookupParameter("模板面积").Set(sd.Volume / (5 / 304.8)); Parameter dsParamter = dsElem.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS); try { if (faceNormal.IsAlmostEqualTo(-XYZ.BasisZ)) { if (doc.GetElement(HostELemID) is Floor) { dsParamter.Set("楼板底模板"); } else if (doc.GetElement(HostELemID).Category.Id == new ElementId(BuiltInCategory.OST_StructuralFraming)) { dsParamter.Set("梁底模板"); } else if (doc.GetElement(HostELemID) is Wall) { dsParamter.Set("墙洞顶模板"); } else if (doc.GetElement(HostELemID) is Stairs) { dsParamter.Set("平台底模板"); } } else if (faceNormal.IsAlmostEqualTo(XYZ.BasisZ)) { //墙 if (doc.GetElement(HostELemID) is Wall) { dsParamter.Set("墙洞底模板"); } } else { if (doc.GetElement(HostELemID) is Floor) { dsParamter.Set("楼板侧模板"); } else if (doc.GetElement(HostELemID).Category.Id == new ElementId(BuiltInCategory.OST_StructuralFraming)) { dsParamter.Set("梁侧模板"); } else if (doc.GetElement(HostELemID).Category.Id == new ElementId(BuiltInCategory.OST_StructuralColumns)) { dsParamter.Set("柱侧模板"); } else if (doc.GetElement(HostELemID) is Wall) { dsParamter.Set("墙侧模板"); } else if (doc.GetElement(HostELemID) is Stairs) { dsParamter.Set("楼梯侧模板"); } else if (doc.GetElement(HostELemID).Category.Id == new ElementId(BuiltInCategory.OST_StructuralFoundation)) { dsParamter.Set("基础侧模板"); } } } catch (Exception e) { SWF.MessageBox.Show(e.ToString()); } dsElem.LookupParameter("模板尺寸").Set(tpSize); dsElem.LookupParameter("X").Set(faceNormal.X); dsElem.LookupParameter("Y").Set(faceNormal.Y); dsElem.LookupParameter("Z").Set(faceNormal.Z); doc.ActiveView.PartsVisibility = PartsVisibility.ShowPartsOnly; return(dsElem.Id); }
/// <summary> /// Creates or populates Revit elements based on the information contained in this class. /// </summary> /// <param name="doc">The document.</param> protected override void Create(Document doc) { Transform lcs = (ObjectLocation != null) ? ObjectLocation.TotalTransform : Transform.Identity; if (ProductRepresentation != null) { if (ProductRepresentation.IsValid()) { using (IFCImportShapeEditScope shapeEditScope = IFCImportShapeEditScope.Create(doc, this)) { shapeEditScope.GraphicsStyleId = m_GraphicsStyleId; shapeEditScope.CategoryId = CategoryId; // The name can be added as well. but it is usually less useful than 'oid' string myId = GlobalId; // + "(" + Name + ")"; ProductRepresentation.CreateProductRepresentation(shapeEditScope, lcs, lcs, myId); int numSolids = Solids.Count; int numVoids = Voids.Count; if ((numSolids > 0) && (numVoids > 0)) { // We may have some GeometryInstances. These need to be "exploded" to do the cutting. for (int solidIdx = 0; solidIdx < numSolids; solidIdx++) { if (Solids[solidIdx].GeometryObject is GeometryInstance) { //// This code currently doesn't work, so commented out. //GeometryInstance geomInst = Solids[solidIdx].GeometryObject as GeometryInstance; //GeometryElement geomElem = geomInst.GetInstanceGeometry(); //foreach (GeometryObject geomObj in geomElem) //{ //if (geomObj is Solid) //Solids.Add(IFCSolidInfo.Create(Solids[solidIdx].Id, geomObj as Solid)); //else if (geomObj is Mesh) //Solids.Add(IFCSolidInfo.Create(Solids[solidIdx].Id, geomObj as Mesh)); //else if (geomObj is GeometryInstance) //IFCImportFile.TheLog.LogError(Solids[solidIdx].Id, "Can't cut nested mapped items, ignoring " + numVoids + " void(s).", false); // Other items are irrelevant here. //} //Solids.RemoveAt(solidIdx); //solidIdx--; //numSolids--; } } // This may be different than before, with the addition of solids from FamilyInstances. numSolids = Solids.Count; // Attempt to cut each solid with each void. for (int solidIdx = 0; solidIdx < numSolids; solidIdx++) { if (!(Solids[solidIdx].GeometryObject is Solid)) { // Assume that we only deal with solids, meshes and instances. string typeName = (Solids[solidIdx].GeometryObject is Mesh) ? "mesh" : "instance"; IFCImportFile.TheLog.LogError(Id, "Can't cut " + typeName + " geometry, ignoring " + numVoids + " void(s).", false); continue; } for (int voidIdx = 0; voidIdx < numVoids; voidIdx++) { if (!(Voids[voidIdx].GeometryObject is Solid)) { IFCImportFile.TheLog.LogError(Id, "Can't cut Solid geometry with a Mesh (# " + Voids[voidIdx].Id + "), ignoring.", false); continue; } Solids[solidIdx].GeometryObject = IFCGeometryUtil.ExecuteSafeBooleanOperation(Solids[solidIdx].Id, Voids[voidIdx].Id, Solids[solidIdx].GeometryObject as Solid, Voids[voidIdx].GeometryObject as Solid, BooleanOperationsType.Difference); if ((Solids[solidIdx].GeometryObject as Solid).Faces.IsEmpty) { Solids.RemoveAt(solidIdx); solidIdx--; numSolids--; break; } } } } bool addedCurves = shapeEditScope.AddPlanViewCurves(FootprintCurves, Id); if ((numSolids > 0 || addedCurves)) { if (GlobalId != null) { // If the GlobalId is null, this is a fake IfcProduct that we don't want to create into a DirectShape, or // add to the caches in any way. We only wanted to gather its geometry. DirectShape shape = Importer.TheCache.UseElementByGUID <DirectShape>(doc, GlobalId); if (shape == null) { shape = IFCElementUtil.CreateElement(doc, CategoryId, Importer.ImportAppGUID(), GlobalId); } List <GeometryObject> directShapeGeometries = new List <GeometryObject>(); foreach (IFCSolidInfo geometryObject in Solids) { // We need to check if the solid created is good enough for DirectShape. If not, warn and use a fallback Mesh. GeometryObject currObject = geometryObject.GeometryObject; if (currObject is Solid) { Solid solid = currObject as Solid; if (!shape.IsValidGeometry(solid)) { IFCImportFile.TheLog.LogWarning(Id, "Couldn't create valid solid, reverting to mesh.", false); directShapeGeometries.AddRange(IFCGeometryUtil.CreateMeshesFromSolid(solid)); currObject = null; } } if (currObject != null) { directShapeGeometries.Add(currObject); } } // We will use the first IfcTypeObject id, if it exists. In general, there should be 0 or 1. ElementId typeId = ElementId.InvalidElementId; foreach (IFCTypeObject typeObject in TypeObjects) { if (typeObject.IsValidForCreation && typeObject.CreatedElementId != ElementId.InvalidElementId) { typeId = typeObject.CreatedElementId; break; } } shape.SetShape(directShapeGeometries); shapeEditScope.SetPlanViewRep(shape); if (typeId != ElementId.InvalidElementId) { shape.SetTypeId(typeId); } PresentationLayerNames.UnionWith(shapeEditScope.PresentationLayerNames); m_CreatedElementId = shape.Id; } } } } else { IFCImportFile.TheLog.LogWarning(Id, "There is no valid geometry for this " + EntityType.ToString() + "; entity will not be built.", false); } } base.Create(doc); }
/// <summary> /// Creates or populates Revit elements based on the information contained in this class. /// </summary> /// <param name="doc">The document.</param> protected override void Create(Document doc) { bool preventInstances = false; IFCElement element = this as IFCElement; if (element != null) { preventInstances = this is IFCOpeningElement; foreach (IFCFeatureElement opening in element.Openings) { try { preventInstances = true; // Create the actual Revit element based on the IFCFeatureElement here. ElementId openingId = CreateElement(doc, opening); // This gets around the issue that the Boolean operation between the void(s) in the IFCFeatureElement and // the solid(s) in the IFCElement may use the Graphics Style of the voids in the resulting Solid(s), meaning // that some faces may disappear when we turn off the visibility of IfcOpeningElements. IList <IFCSolidInfo> voids = IFCElement.CloneElementGeometry(doc, opening, this, true); if (voids != null) { foreach (IFCSolidInfo voidGeom in voids) { IFCVoidInfo voidInfo = new IFCVoidInfo(voidGeom); if (!Importer.TheProcessor.ApplyTransforms) { // If we aren't applying transforms, then the Voids and Solids will be // in different coordinate spaces, so we need the transform of the // void, so we can transform it into the Solid coordinate space voidInfo.TotalTransform = opening?.ObjectLocation?.TotalTransform; } Voids.Add(voidInfo); } } } catch (Exception ex) { Importer.TheLog.LogError(opening.Id, ex.Message, false); } } } if (HasValidTopLevelGeometry()) { using (IFCImportShapeEditScope shapeEditScope = IFCImportShapeEditScope.Create(doc, this)) { shapeEditScope.GraphicsStyleId = GraphicsStyleId; shapeEditScope.CategoryId = CategoryId; shapeEditScope.PreventInstances = preventInstances; // The name can be added as well. but it is usually less useful than 'oid' string myId = GlobalId; // + "(" + Name + ")"; Transform lcs = IFCImportFile.TheFile.IFCProject.WorldCoordinateSystem; if (lcs == null) { lcs = (ObjectLocation != null) ? ObjectLocation.TotalTransform : Transform.Identity; } else if (ObjectLocation != null) { lcs = lcs.Multiply(ObjectLocation.TotalTransform); } // If we are not applying transforms to the geometry, then pass in the identity matrix. // Lower down this method we then pass lcs to the consumer element, so that it can apply // the transform as required. Transform transformToUse = Importer.TheProcessor.ApplyTransforms ? lcs : Transform.Identity; ProductRepresentation.CreateProductRepresentation(shapeEditScope, transformToUse, transformToUse, myId); int numSolids = Solids.Count; // Attempt to cut each solid with each void. for (int solidIdx = 0; solidIdx < numSolids; solidIdx++) { if (!CutSolidByVoids(Solids[solidIdx])) { Solids.RemoveAt(solidIdx); solidIdx--; numSolids--; } } bool addedCurves = shapeEditScope.AddPlanViewCurves(FootprintCurves, Id); if ((numSolids > 0 || addedCurves)) { if (GlobalId != null) { // If the GlobalId is null, this is a fake IfcProduct that we don't want to create into a DirectShape, or // add to the caches in any way. We only wanted to gather its geometry. DirectShape shape = Importer.TheCache.UseElementByGUID <DirectShape>(doc, GlobalId); if (shape == null) { shape = IFCElementUtil.CreateElement(doc, CategoryId, GlobalId, null, Id, EntityType); } List <GeometryObject> directShapeGeometries = new List <GeometryObject>(); foreach (IFCSolidInfo geometryObject in Solids) { // We need to check if the solid created is good enough for DirectShape. If not, warn and use a fallback Mesh. GeometryObject currObject = geometryObject.GeometryObject; if (currObject is Solid) { Solid solid = currObject as Solid; if (!shape.IsValidGeometry(solid)) { Importer.TheLog.LogWarning(Id, "Couldn't create valid solid, reverting to mesh.", false); directShapeGeometries.AddRange(IFCGeometryUtil.CreateMeshesFromSolid(solid)); currObject = null; } } if (currObject != null) { directShapeGeometries.Add(currObject); } } // We will use the first IfcTypeObject id, if it exists. In general, there should be 0 or 1. IFCTypeObject typeObjectToUse = null; foreach (IFCTypeObject typeObject in TypeObjects) { if (typeObject.IsValidForCreation && typeObject.CreatedElementId != ElementId.InvalidElementId) { typeObjectToUse = typeObject; break; } } if (!Importer.TheProcessor.PostProcessProduct(Id, typeObjectToUse?.Id, lcs, directShapeGeometries)) { if (shape != null) { shape.SetShape(directShapeGeometries); shapeEditScope.SetPlanViewRep(shape); if (typeObjectToUse != null && typeObjectToUse.CreatedElementId != ElementId.InvalidElementId) { shape.SetTypeId(typeObjectToUse.CreatedElementId); } } } PresentationLayerNames.UnionWith(shapeEditScope.PresentationLayerNames); CreatedElementId = shape.Id; CreatedGeometry = directShapeGeometries; } } } } else { if (this is IFCElement || this is IFCGrid) { IList <IFCEntity> visitedEntities = new List <IFCEntity>(); visitedEntities.Add(this); if (!HasValidSubElementGeometry(visitedEntities)) { // We will not warn if this is an IfcSpatialStructureElement; those aren't expected to have their own geometry. Importer.TheLog.LogWarning(Id, "There is no valid geometry for this " + EntityType.ToString() + "; entity will not be built.", false); } } } base.Create(doc); }
/// <summary> /// Creates or populates Revit elements based on the information contained in this class. /// </summary> /// <param name="doc">The document.</param> protected override void Create(Document doc) { bool preventInstances = false; IFCElement element = this as IFCElement; if (element != null) { IFCOpeningElement openingElement = element as IFCOpeningElement; if (openingElement != null) { preventInstances = true; } foreach (IFCFeatureElement opening in element.Openings) { try { preventInstances = true; // Create the actual Revit element based on the IFCFeatureElement here. ElementId openingId = CreateElement(doc, opening); // This gets around the issue that the Boolean operation between the void(s) in the IFCFeatureElement and // the solid(s) in the IFCElement may use the Graphics Style of the voids in the resulting Solid(s), meaning // that some faces may disappear when we turn off the visibility of IfcOpeningElements. IList <IFCSolidInfo> voids = IFCElement.CloneElementGeometry(doc, opening, this, true); if (voids != null) { foreach (IFCSolidInfo voidGeom in voids) { Voids.Add(voidGeom); } } } catch (Exception ex) { Importer.TheLog.LogError(opening.Id, ex.Message, false); } } } if (HasValidTopLevelGeometry()) { using (IFCImportShapeEditScope shapeEditScope = IFCImportShapeEditScope.Create(doc, this)) { shapeEditScope.GraphicsStyleId = GraphicsStyleId; shapeEditScope.CategoryId = CategoryId; shapeEditScope.PreventInstances = preventInstances; // The name can be added as well. but it is usually less useful than 'oid' string myId = GlobalId; // + "(" + Name + ")"; Transform lcs = IFCImportFile.TheFile.IFCProject.WorldCoordinateSystem; if (lcs == null) { lcs = (ObjectLocation != null) ? ObjectLocation.TotalTransform : Transform.Identity; } else if (ObjectLocation != null) { lcs = lcs.Multiply(ObjectLocation.TotalTransform); } ProductRepresentation.CreateProductRepresentation(shapeEditScope, lcs, lcs, myId); int numSolids = Solids.Count; int numVoids = Voids.Count; if ((numSolids > 0) && (numVoids > 0)) { // This may be different than before, with the addition of solids from FamilyInstances. numSolids = Solids.Count; // Attempt to cut each solid with each void. for (int solidIdx = 0; solidIdx < numSolids; solidIdx++) { // We only cut body representation items. if (Solids[solidIdx].RepresentationType != IFCRepresentationIdentifier.Body) { continue; } if (!(Solids[solidIdx].GeometryObject is Solid)) { string typeName = (Solids[solidIdx].GeometryObject is Mesh) ? "mesh" : "instance"; Importer.TheLog.LogError(Id, "Can't cut " + typeName + " geometry, ignoring " + numVoids + " void(s).", false); continue; } for (int voidIdx = 0; voidIdx < numVoids; voidIdx++) { if (!(Voids[voidIdx].GeometryObject is Solid)) { Importer.TheLog.LogError(Id, "Can't cut Solid geometry with a Mesh (# " + Voids[voidIdx].Id + "), ignoring.", false); continue; } Solids[solidIdx].GeometryObject = IFCGeometryUtil.ExecuteSafeBooleanOperation(Solids[solidIdx].Id, Voids[voidIdx].Id, Solids[solidIdx].GeometryObject as Solid, Voids[voidIdx].GeometryObject as Solid, BooleanOperationsType.Difference, null); if ((Solids[solidIdx].GeometryObject as Solid).Faces.IsEmpty) { Solids.RemoveAt(solidIdx); solidIdx--; numSolids--; break; } } } } bool addedCurves = shapeEditScope.AddPlanViewCurves(FootprintCurves, Id); if ((numSolids > 0 || addedCurves)) { if (GlobalId != null) { // If the GlobalId is null, this is a fake IfcProduct that we don't want to create into a DirectShape, or // add to the caches in any way. We only wanted to gather its geometry. DirectShape shape = Importer.TheCache.UseElementByGUID <DirectShape>(doc, GlobalId); if (shape == null) { shape = IFCElementUtil.CreateElement(doc, CategoryId, GlobalId, null, Id); } List <GeometryObject> directShapeGeometries = new List <GeometryObject>(); foreach (IFCSolidInfo geometryObject in Solids) { // We need to check if the solid created is good enough for DirectShape. If not, warn and use a fallback Mesh. GeometryObject currObject = geometryObject.GeometryObject; if (currObject is Solid) { Solid solid = currObject as Solid; if (!shape.IsValidGeometry(solid)) { Importer.TheLog.LogWarning(Id, "Couldn't create valid solid, reverting to mesh.", false); directShapeGeometries.AddRange(IFCGeometryUtil.CreateMeshesFromSolid(solid)); currObject = null; } } if (currObject != null) { directShapeGeometries.Add(currObject); } } // We will use the first IfcTypeObject id, if it exists. In general, there should be 0 or 1. ElementId typeId = ElementId.InvalidElementId; foreach (IFCTypeObject typeObject in TypeObjects) { if (typeObject.IsValidForCreation && typeObject.CreatedElementId != ElementId.InvalidElementId) { typeId = typeObject.CreatedElementId; break; } } shape.SetShape(directShapeGeometries); shapeEditScope.SetPlanViewRep(shape); if (typeId != ElementId.InvalidElementId) { shape.SetTypeId(typeId); } PresentationLayerNames.UnionWith(shapeEditScope.PresentationLayerNames); CreatedElementId = shape.Id; CreatedGeometry = directShapeGeometries; } } } } else { if (this is IFCElement || this is IFCGrid) { IList <IFCEntity> visitedEntities = new List <IFCEntity>(); visitedEntities.Add(this); if (!HasValidSubElementGeometry(visitedEntities)) { // We will not warn if this is an IfcSpatialStructureElement; those aren't expected to have their own geometry. Importer.TheLog.LogWarning(Id, "There is no valid geometry for this " + EntityType.ToString() + "; entity will not be built.", false); } } } base.Create(doc); }