/// <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)
        {
            // If we created an element above, then we will set the shape of it to be the same of the shapes of the contained spaces.
            IList <GeometryObject> geomObjs = new List <GeometryObject>();

            foreach (IFCObjectDefinition objDef in RelatedObjects)
            {
                if (!(objDef is IFCSpace))
                {
                    continue;
                }

                // This lets us create a copy of the space geometry with the Zone graphics style.
                IList <IFCSolidInfo> solids = IFCElement.CloneElementGeometry(doc, objDef as IFCProduct, this, false);
                if (solids != null)
                {
                    foreach (IFCSolidInfo solidGeom in solids)
                    {
                        geomObjs.Add(solidGeom.GeometryObject);
                    }
                }
            }

            DirectShape zoneElement = IFCElementUtil.CreateElement(doc, CategoryId, GlobalId, geomObjs);

            if (zoneElement != null)
            {
                CreatedElementId = zoneElement.Id;
                CreatedGeometry  = geomObjs;
            }

            base.Create(doc);
        }
Exemple #2
0
        /// <summary>
        /// Gets the elements hosted by this host element, if any.
        /// </summary>
        /// <param name="hostElement">The host element.</param>
        /// <returns>The hosted elements, or null.  An unfilled opening counts as a hosted element.</returns>
        static public IList<IFCElement> GetHostedElements(IFCElement hostElement)
        {
            if (hostElement == null)
                return null;

            ICollection<IFCFeatureElementSubtraction> openings = hostElement.Openings;
            if (openings == null || (openings.Count == 0))
                return null;

            IList<IFCElement> hostedElements = new List<IFCElement>();
            foreach (IFCFeatureElementSubtraction opening in openings)
            {
                if (!(opening is IFCOpeningElement))
                    hostedElements.Add(opening);
                else
                {
                    IFCOpeningElement openingElement = opening as IFCOpeningElement;
                    if (openingElement.FilledByElement != null)
                        hostedElements.Add(openingElement.FilledByElement);
                    else
                        hostedElements.Add(openingElement);
                }
            }

            return hostedElements;
        }
        /// <summary>
        /// Processes IfcOpeningElement attributes.
        /// </summary>
        /// <param name="ifcOpeningElement">The IfcOpeningElement handle.</param>
        protected override void Process(IFCAnyHandle ifcOpeningElement)
        {
            base.Process(ifcOpeningElement);

            ICollection <IFCAnyHandle> hasFillings = IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(ifcOpeningElement, "HasFillings");

            if (hasFillings != null)
            {
                // Assume that there is only one filling for the opening, and take first found.
                foreach (IFCAnyHandle hasFilling in hasFillings)
                {
                    IFCAnyHandle relatedFillingElement = IFCAnyHandleUtil.GetInstanceAttribute(hasFilling, "RelatedBuildingElement");
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(relatedFillingElement))
                    {
                        continue;
                    }

                    IFCEntity filledByElement;
                    IFCImportFile.TheFile.EntityMap.TryGetValue(relatedFillingElement.StepId, out filledByElement);
                    if (filledByElement == null)
                    {
                        FilledByElement = IFCElement.ProcessIFCElement(relatedFillingElement);
                    }
                    else
                    {
                        FilledByElement = filledByElement as IFCElement;
                    }
                    FilledByElement.FillsOpening = this;
                    break;
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Processes an IFCElementComponent object.
        /// </summary>
        /// <param name="ifcElementComponent">The IfcElementComponent handle.</param>
        /// <returns>The IFCElementComponent object.</returns>
        /// <remarks>IFCBuildingElementPart has changed from a subtype of the abstract IFCBuildingElement to IFCElementComponent from IFC2x3 to IFC4.
        /// Instead of having different parents, we will keep IFCBuildingElementPart as a child of IFCBuildingElement.  This means, though, that
        /// this function can only return an IFCElement, the (normally) abstract parent of each.</remarks>
        public static IFCElement ProcessIFCElementComponent(IFCAnyHandle ifcElementComponent)
        {
            if (IFCAnyHandleUtil.IsNullOrHasNoValue(ifcElementComponent))
            {
                Importer.TheLog.LogNullError(IFCEntityType.IfcElementComponent);
                return(null);
            }

            IFCEntity elementComponent;

            IFCImportFile.TheFile.EntityMap.TryGetValue(ifcElementComponent.StepId, out elementComponent);
            if (elementComponent != null)
            {
                return(elementComponent as IFCElement);
            }

            IFCElement newIFCElementComponent = null;

            // other subclasses not handled yet.
            if (IFCImportFile.TheFile.SchemaVersionAtLeast(IFCSchemaVersion.IFC4Obsolete) && IFCAnyHandleUtil.IsValidSubTypeOf(ifcElementComponent, IFCEntityType.IfcBuildingElementPart))
            {
                newIFCElementComponent = IFCBuildingElementPart.ProcessIFCBuildingElementPart(ifcElementComponent);
            }
            else
            {
                newIFCElementComponent = new IFCElementComponent(ifcElementComponent);
            }
            return(newIFCElementComponent);
        }
Exemple #5
0
        private IList <GeometryObject> GetOrCloneGeometry(Document doc, IFCObjectDefinition objectDefinition)
        {
            if (!(objectDefinition is IFCBuildingElementPart))
            {
                return(objectDefinition.CreatedGeometry);
            }

            // In the case of IFCBuildingElementPart, we want the container to have a copy of the geometry in the category of the parent,
            // as otherwise the geometry will be controlled by default by the Parts category instead of the parent category.
            IList <IFCSolidInfo> clonedGeometry = IFCElement.CloneElementGeometry(doc, objectDefinition as IFCProduct, this, false);

            if (clonedGeometry == null)
            {
                return(null);
            }

            IList <GeometryObject> geomObjs = new List <GeometryObject>();

            foreach (IFCSolidInfo solid in clonedGeometry)
            {
                geomObjs.Add(solid.GeometryObject);
            }

            return(geomObjs);
        }
        /// <summary>
        /// Processes IfcOpeningElement attributes.
        /// </summary>
        /// <param name="ifcOpeningElement">The IfcOpeningElement handle.</param>
        protected override void Process(IFCAnyHandle ifcOpeningElement)
        {
            base.Process(ifcOpeningElement);

            ICollection<IFCAnyHandle> hasFillings = IFCAnyHandleUtil.GetAggregateInstanceAttribute<List<IFCAnyHandle>>(ifcOpeningElement, "HasFillings");
            if (hasFillings != null)
            {
                // Assume that there is only one filling for the opening, and take first found.
                foreach (IFCAnyHandle hasFilling in hasFillings)
                {
                    IFCAnyHandle relatedFillingElement = IFCAnyHandleUtil.GetInstanceAttribute(hasFilling, "RelatedBuildingElement");
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(relatedFillingElement))
                        continue;

                    IFCEntity filledByElement;
                    IFCImportFile.TheFile.EntityMap.TryGetValue(relatedFillingElement.StepId, out filledByElement);
                    if (filledByElement == null)
                        FilledByElement = IFCElement.ProcessIFCElement(relatedFillingElement);
                    else
                        FilledByElement = filledByElement as IFCElement;
                    FilledByElement.FillsOpening = this;
                    break;
                }
            } 
        }
Exemple #7
0
        /// <summary>
        /// Processes an IfcElement object.
        /// </summary>
        /// <param name="ifcElement">The IfcElement handle.</param>
        /// <returns>The IFCElement object.</returns>
        public static IFCElement ProcessIFCElement(IFCAnyHandle ifcElement)
        {
            if (IFCAnyHandleUtil.IsNullOrHasNoValue(ifcElement))
            {
                IFCImportFile.TheLog.LogNullError(IFCEntityType.IfcElement);
                return(null);
            }

            IFCEntity cachedIFCElement;

            IFCImportFile.TheFile.EntityMap.TryGetValue(ifcElement.StepId, out cachedIFCElement);
            if (cachedIFCElement != null)
            {
                return(cachedIFCElement as IFCElement);
            }

            IFCElement newIFCElement = null;

            // other subclasses not handled yet!
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcElement, IFCEntityType.IfcFeatureElement))
            {
                newIFCElement = IFCFeatureElement.ProcessIFCFeatureElement(ifcElement);
            }
            else
            {
                newIFCElement = new IFCElement(ifcElement);
            }
            return(newIFCElement);
        }
Exemple #8
0
        /// <summary>
        /// Create a copying of the geometry of an entity with a different graphics style.
        /// </summary>
        /// <param name="doc">The document.</param>
        /// <param name="original">The IFCProduct we are partially copying.</param>
        /// <param name="parentEntity">The IFCObjectDefinition we are going to add the geometry to.</param>
        /// <param name="cloneParentMaterial">Determine whether to use the one material of the parent entity, if it exists and is unique.</param>
        /// <returns>The list of geometries created with a new category and possibly material.</returns>
        public static IList <IFCSolidInfo> CloneElementGeometry(Document doc, IFCProduct original, IFCObjectDefinition parentEntity, bool cloneParentMaterial)
        {
            using (TemporaryDisableLogging disableLogging = new TemporaryDisableLogging())
            {
                IFCElement clone = new IFCElement();

                // Note that the GlobalId is left to null here; this allows us to later decide not to create a DirectShape for the result.

                // Get the ObjectLocation and ProductRepresentation from the original entity, which is all we need to create geometry.
                clone.ObjectLocation        = original.ObjectLocation;
                clone.ProductRepresentation = original.ProductRepresentation;
                clone.MaterialSelect        = original.MaterialSelect;

                // Get the EntityType and PredefinedType from the parent to ensure that it "matches" the category and graphics style of the parent.
                clone.EntityType     = parentEntity.EntityType;
                clone.PredefinedType = parentEntity.PredefinedType;

                if (cloneParentMaterial)
                {
                    // This will only work if the parent entity has one material.
                    IFCMaterial parentMaterial = parentEntity.GetTheMaterial();
                    if (parentMaterial != null)
                    {
                        clone.MaterialSelect = parentMaterial;
                    }
                }

                IList <GeometryObject> geomObjs = new List <GeometryObject>();
                CreateElement(doc, clone);
                return(clone.Solids);
            }
        }
Exemple #9
0
        /// <summary>
        /// Gets the host of a hosted element, if any.
        /// </summary>
        /// <param name="hostedElement">The hosted element.</param>
        /// <returns>The host, or null.</returns>
        static public IFCElement GetHost(IFCElement hostedElement)
        {
            if (hostedElement == null)
                return null;

            IFCFeatureElementSubtraction fillsOpening = hostedElement.FillsOpening;
            if (fillsOpening == null)
                return null;

            return fillsOpening.VoidsElement;
        }
Exemple #10
0
        /// <summary>
        /// Post-process IfcPort attributes.
        /// </summary>
        public override void PostProcess()
        {
            base.PostProcess();

            // Force ContainedIn, ConnectedFrom and ConnectedTo to be created in the respective getters.

            IFCElement containedIn = ContainedIn;

            IFCPort connectedFrom = ConnectedFrom;

            IFCPort connectedTo = ConnectedTo;
        }
Exemple #11
0
        /// <summary>
        /// Processes an IfcProduct object.
        /// </summary>
        /// <param name="ifcProduct">The IfcProduct handle.</param>
        /// <returns>The IFCProduct object.</returns>
        public static IFCProduct ProcessIFCProduct(IFCAnyHandle ifcProduct)
        {
            if (IFCAnyHandleUtil.IsNullOrHasNoValue(ifcProduct))
            {
                Importer.TheLog.LogNullError(IFCEntityType.IfcProduct);
                return(null);
            }

            try
            {
                IFCEntity cachedProduct;
                if (IFCImportFile.TheFile.EntityMap.TryGetValue(ifcProduct.StepId, out cachedProduct))
                {
                    return(cachedProduct as IFCProduct);
                }

                if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcProduct, IFCEntityType.IfcSpatialStructureElement))
                {
                    return(IFCSpatialStructureElement.ProcessIFCSpatialStructureElement(ifcProduct));
                }

                if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcProduct, IFCEntityType.IfcElement))
                {
                    return(IFCElement.ProcessIFCElement(ifcProduct));
                }

                if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcProduct, IFCEntityType.IfcGrid))
                {
                    return(IFCGrid.ProcessIFCGrid(ifcProduct));
                }

                if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcProduct, IFCEntityType.IfcProxy))
                {
                    return(IFCProxy.ProcessIFCProxy(ifcProduct));
                }

                if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcProduct, IFCEntityType.IfcDistributionPort))
                {
                    return(IFCDistributionPort.ProcessIFCDistributionPort(ifcProduct));
                }
            }
            catch (Exception ex)
            {
                HandleError(ex.Message, ifcProduct, true);
                return(null);
            }

            Importer.TheLog.LogUnhandledSubTypeError(ifcProduct, IFCEntityType.IfcProduct, false);
            return(null);
        }
Exemple #12
0
        /// <summary>
        /// Creates or populates Revit element params based on the information contained in this class.
        /// </summary>
        /// <param name="doc">The document.</param>
        /// <param name="element">The element.</param>
        protected override void CreateParametersInternal(Document doc, Element element)
        {
            base.CreateParametersInternal(doc, element);

            if (element != null)
            {
                Category category = IFCPropertySet.GetCategoryForParameterIfValid(element, Id);

                // Set "Tag" parameter.
                string ifcTag = Tag;
                if (!string.IsNullOrWhiteSpace(ifcTag))
                {
                    IFCPropertySet.AddParameterString(doc, element, category, "IfcTag", ifcTag, Id);
                }

                IFCFeatureElementSubtraction ifcFeatureElementSubtraction = FillsOpening;
                if (ifcFeatureElementSubtraction != null)
                {
                    IFCElement ifcElement = ifcFeatureElementSubtraction.VoidsElement;
                    if (ifcElement != null)
                    {
                        string ifcContainerName = ifcElement.Name;
                        IFCPropertySet.AddParameterString(doc, element, category, "IfcContainedInHost", ifcContainerName, Id);
                    }
                }

                // Create two parameters for each port: one for name, and one for GUID.
                // Note that Ports will never be null, as it is initialized the first time it is accessed.
                int numPorts = 0;
                foreach (IFCPort port in Ports)
                {
                    string name = port.Name;
                    string guid = port.GlobalId;

                    if (!string.IsNullOrWhiteSpace(name))
                    {
                        string parameterName = "IfcElement HasPorts Name " + ((numPorts == 0) ? "" : (numPorts + 1).ToString());
                        IFCPropertySet.AddParameterString(doc, element, category, parameterName, name, Id);
                    }

                    if (!string.IsNullOrWhiteSpace(guid))
                    {
                        string parameterName = "IfcElement HasPorts IfcGUID " + ((numPorts == 0) ? "" : (numPorts + 1).ToString());
                        IFCPropertySet.AddParameterString(doc, element, category, parameterName, guid, Id);
                    }

                    numPorts++;
                }
            }
        }
Exemple #13
0
        /// <summary>
        /// Create a simplified copy of a IFCFeatureElement, intended explicitly for the purpose of voiding a particular IFCElement.
        /// </summary>
        /// <param name="original">The IFCFeatureElement we are partially copying.</param>
        /// <param name="parentEntity">The IFCElement we are voiding.</param>
        /// <returns>A new IFCFeatureElement that is a minimal copy of original with influence by parentEntity.</returns>
        public static IFCFeatureElement CreateOpeningClone(IFCFeatureElement original, IFCElement parentEntity)
        {
            IFCFeatureElement clone = new IFCFeatureElement();

            // Note that the GlobalId is left to null here; this allows us to later decide not to create a DirectShape for the result.

            // Get the ObjectLocation and ProductRepresentation from the original entity, which is all we need to create geometry.
            clone.ObjectLocation = original.ObjectLocation;
            clone.ProductRepresentation = original.ProductRepresentation;

            // Get the EntityType and ShapeType from the parent to ensure that it "matches" the category and graphics style of the parent.
            clone.EntityType = parentEntity.EntityType;
            clone.ShapeType = parentEntity.ShapeType;

            // Copy the material of the parent entity to try to match the color of the opening faces.  
            // This will work nicely if the parent entity is one material.
            IFCMaterial parentMaterial = parentEntity.GetTheMaterial();
            if (parentMaterial != null)
                clone.MaterialSelect = parentMaterial;

            return clone;
        }
Exemple #14
0
        /// <summary>
        /// Create a simplified copy of a IFCFeatureElement, intended explicitly for the purpose of voiding a particular IFCElement.
        /// </summary>
        /// <param name="original">The IFCFeatureElement we are partially copying.</param>
        /// <param name="parentEntity">The IFCElement we are voiding.</param>
        /// <returns>A new IFCFeatureElement that is a minimal copy of original with influence by parentEntity.</returns>
        public static IFCFeatureElement CreateOpeningClone(IFCFeatureElement original, IFCElement parentEntity)
        {
            IFCFeatureElement clone = new IFCFeatureElement();

            // Note that the GlobalId is left to null here; this allows us to later decide not to create a DirectShape for the result.

            // Get the ObjectLocation and ProductRepresentation from the original entity, which is all we need to create geometry.
            clone.ObjectLocation        = original.ObjectLocation;
            clone.ProductRepresentation = original.ProductRepresentation;

            // Get the EntityType and ShapeType from the parent to ensure that it "matches" the category and graphics style of the parent.
            clone.EntityType = parentEntity.EntityType;
            clone.ShapeType  = parentEntity.ShapeType;

            // Copy the material of the parent entity to try to match the color of the opening faces.
            // This will work nicely if the parent entity is one material.
            IFCMaterial parentMaterial = parentEntity.GetTheMaterial();

            if (parentMaterial != null)
            {
                clone.MaterialSelect = parentMaterial;
            }

            return(clone);
        }
      /// <summary>
      /// Create a copying of the geometry of an entity with a different graphics style.
      /// </summary>
      /// <param name="doc">The document.</param>
      /// <param name="original">The IFCProduct we are partially copying.</param>
      /// <param name="parentEntity">The IFCObjectDefinition we are going to add the geometry to.</param>
      /// <param name="cloneParentMaterial">Determine whether to use the one material of the parent entity, if it exists and is unique.</param>
      /// <returns>The list of geometries created with a new category and possibly material.</returns>
      public static IList<IFCSolidInfo> CloneElementGeometry(Document doc, IFCProduct original, IFCObjectDefinition parentEntity, bool cloneParentMaterial)
      {
         using (TemporaryDisableLogging disableLogging = new TemporaryDisableLogging())
         {
            IFCElement clone = new IFCElement();

            // Note that the GlobalId is left to null here; this allows us to later decide not to create a DirectShape for the result.

            // Get the ObjectLocation and ProductRepresentation from the original entity, which is all we need to create geometry.
            clone.ObjectLocation = original.ObjectLocation;
            clone.ProductRepresentation = original.ProductRepresentation;
            clone.MaterialSelect = original.MaterialSelect;

            // Get the EntityType and PredefinedType from the parent to ensure that it "matches" the category and graphics style of the parent.
            clone.EntityType = parentEntity.EntityType;
            clone.PredefinedType = parentEntity.PredefinedType;

            if (cloneParentMaterial)
            {
               // This will only work if the parent entity has one material.
               IFCMaterial parentMaterial = parentEntity.GetTheMaterial();
               if (parentMaterial != null)
                  clone.MaterialSelect = parentMaterial;
            }

            IList<GeometryObject> geomObjs = new List<GeometryObject>();
            CreateElement(doc, clone);
            return clone.Solids;
         }
      }
Exemple #16
0
        /// <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);
        }
Exemple #17
0
        /// <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);
        }
      /// <summary>
      /// Processes an IfcElement object.
      /// </summary>
      /// <param name="ifcElement">The IfcElement handle.</param>
      /// <returns>The IFCElement object.</returns>
      public static IFCElement ProcessIFCElement(IFCAnyHandle ifcElement)
      {
         if (IFCAnyHandleUtil.IsNullOrHasNoValue(ifcElement))
         {
            Importer.TheLog.LogNullError(IFCEntityType.IfcElement);
            return null;
         }

         IFCEntity cachedIFCElement;
         IFCImportFile.TheFile.EntityMap.TryGetValue(ifcElement.StepId, out cachedIFCElement);
         if (cachedIFCElement != null)
            return (cachedIFCElement as IFCElement);

         IFCElement newIFCElement = null;
         // other subclasses not handled yet.
         if (IFCAnyHandleUtil.IsSubTypeOf(ifcElement, IFCEntityType.IfcBuildingElement))
            newIFCElement = IFCBuildingElement.ProcessIFCBuildingElement(ifcElement);
         else if (IFCAnyHandleUtil.IsSubTypeOf(ifcElement, IFCEntityType.IfcFeatureElement))
            newIFCElement = IFCFeatureElement.ProcessIFCFeatureElement(ifcElement);
         else if (IFCAnyHandleUtil.IsSubTypeOf(ifcElement, IFCEntityType.IfcElementAssembly))
            newIFCElement = IFCElementAssembly.ProcessIFCElementAssembly(ifcElement);
         else if (IFCAnyHandleUtil.IsSubTypeOf(ifcElement, IFCEntityType.IfcElementComponent))
            newIFCElement = IFCElementComponent.ProcessIFCElementComponent(ifcElement);
         else
            newIFCElement = new IFCElement(ifcElement);
         return newIFCElement;
      }