Пример #1
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);
            }
        }
Пример #2
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);
        }
Пример #3
0
        protected override void Process(IFCAnyHandle ifcMaterialLayer)
        {
            base.Process(ifcMaterialLayer);

            IFCAnyHandle ifcMaterial = IFCImportHandleUtil.GetOptionalInstanceAttribute(ifcMaterialLayer, "Material");

            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(ifcMaterial))
            {
                Material = IFCMaterial.ProcessIFCMaterial(ifcMaterial);
            }

            bool found = false;

            LayerThickness = IFCImportHandleUtil.GetRequiredScaledLengthAttribute(ifcMaterialLayer, "LayerThickness", out found);
            if (!found)
            {
                return;
            }

            // GetOptionalLogicalAttribute defaults to Unknown.  We want to default to false here.
            IsVentilated = IFCImportHandleUtil.GetOptionalLogicalAttribute(ifcMaterialLayer, "IsVentilated", out found);
            if (!found)
            {
                IsVentilated = IFCLogical.False;
            }
        }
        protected override void Process(IFCAnyHandle ifcMaterialProfile)
        {
            base.Process(ifcMaterialProfile);

            IFCAnyHandle ifcMaterial = IFCImportHandleUtil.GetOptionalInstanceAttribute(ifcMaterialProfile, "Material");

            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(ifcMaterial))
            {
                Material = IFCMaterial.ProcessIFCMaterial(ifcMaterial);
            }

            IFCAnyHandle profileHnd = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcMaterialProfile, "Profile", true);

            if (profileHnd != null)
            {
                Profile = IFCProfileDef.ProcessIFCProfileDef(profileHnd);
            }

            Name        = IFCImportHandleUtil.GetOptionalStringAttribute(ifcMaterialProfile, "Name", null);
            Description = IFCImportHandleUtil.GetOptionalStringAttribute(ifcMaterialProfile, "Description", null);
            double prio = IFCImportHandleUtil.GetOptionalRealAttribute(ifcMaterialProfile, "Priority", -1);

            if (prio >= 0)
            {
                Priority = prio;
            }
            Category = IFCImportHandleUtil.GetOptionalStringAttribute(ifcMaterialProfile, "Category", null);

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

            Name = IFCImportHandleUtil.GetOptionalStringAttribute(ifcProductRepresentation, "Name", null);

            Description = IFCImportHandleUtil.GetOptionalStringAttribute(ifcProductRepresentation, "Description", null);

            List <IFCAnyHandle> representations =
                IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(ifcProductRepresentation, "Representations");

            if (representations != null)
            {
                foreach (IFCAnyHandle representationHnd in representations)
                {
                    try
                    {
                        IFCRepresentation representation = IFCRepresentation.ProcessIFCRepresentation(representationHnd);
                        if (representation != null)
                        {
                            if (representation.RepresentationItems.Count > 0 || representation.BoundingBox != null)
                            {
                                Representations.Add(representation);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        string msg = ex.Message;
                        // Ignore some specific errors.
                        if (msg != null)
                        {
                            if (!msg.Contains("not imported"))
                            {
                                Importer.TheLog.LogError(Id, msg, false);
                            }
                        }
                    }
                }
            }

            if (IFCImportFile.TheFile.SchemaVersion >= IFCSchemaVersion.IFC2x3)
            {
                if (IFCAnyHandleUtil.IsSubTypeOf(ifcProductRepresentation, IFCEntityType.IfcMaterialDefinitionRepresentation))
                {
                    IFCAnyHandle representedMaterial = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcProductRepresentation, "RepresentedMaterial", false);
                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(representedMaterial))
                    {
                        RepresentedMaterial = IFCMaterial.ProcessIFCMaterial(representedMaterial);
                    }
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Processes an IfcMaterial object.
        /// </summary>
        /// <param name="ifcMaterial">The IfcMaterial handle.</param>
        /// <returns>The IFCMaterial object.</returns>
        public static IFCMaterial ProcessIFCMaterial(IFCAnyHandle ifcMaterial)
        {
            if (IFCAnyHandleUtil.IsNullOrHasNoValue(ifcMaterial))
            {
                Importer.TheLog.LogNullError(IFCEntityType.IfcMaterial);
                return(null);
            }

            IFCEntity material;

            if (!IFCImportFile.TheFile.EntityMap.TryGetValue(ifcMaterial.StepId, out material))
            {
                material = new IFCMaterial(ifcMaterial);
            }
            return(material as IFCMaterial);
        }
Пример #7
0
        /// <summary>
        /// Cleans out the IFCEntity to save memory.
        /// </summary>
        public override void CleanEntity()
        {
            base.CleanEntity();

            m_ComposedObjectDefinitions = null;

            m_AssignmentGroups = null;

            m_ShapeType = null;

            m_MaterialSelect = null;

            m_TheMaterial = null;

            m_TheMaterialIsSet = false;
        }
Пример #8
0
        /// <summary>
        /// Gets the one material associated with this object.
        /// </summary>
        /// <returns>The material, if there is identically one; otherwise, null.</returns>
        public IFCMaterial GetTheMaterial()
        {
            if (!m_TheMaterialIsSet)
            {
                IList <IFCMaterial> materials = GetMaterials();

                m_TheMaterialIsSet = true;
                IFCMaterial theMaterial = null;
                if (materials.Count > 1)
                {
                    return(null);
                }

                if (materials.Count == 1)
                {
                    theMaterial = materials[0];
                }

                if (this is IFCObject)
                {
                    IFCObject asObject = this as IFCObject;
                    foreach (IFCTypeObject typeObject in asObject.TypeObjects)
                    {
                        IList <IFCMaterial> typeMaterials = typeObject.GetMaterials();

                        if (typeMaterials.Count > 1)
                        {
                            return(null);
                        }

                        if (typeMaterials.Count == 1)
                        {
                            if (theMaterial != null && theMaterial.Id != typeMaterials[0].Id)
                            {
                                return(null);
                            }
                            theMaterial = typeMaterials[0];
                        }
                    }
                }

                m_TheMaterial = theMaterial;
            }

            return(m_TheMaterial);
        }
Пример #9
0
        /// <summary>
        /// Returns the associated material id, if any.
        /// </summary>
        /// <param name="scope">The containing creation scope.</param>
        /// <returns>The element id of the material, if any.</returns>
        public virtual ElementId GetMaterialElementId(IFCImportShapeEditScope scope)
        {
            ElementId materialId = scope.GetCurrentMaterialId();

            if (materialId != ElementId.InvalidElementId)
            {
                return(materialId);
            }

            if (scope.Creator != null)
            {
                IFCMaterial creatorMaterial = scope.Creator.GetTheMaterial();
                if (creatorMaterial != null)
                {
                    return(creatorMaterial.GetMaterialElementId());
                }
            }

            return(ElementId.InvalidElementId);
        }
Пример #10
0
        protected override void Process(IFCAnyHandle ifcMaterialList)
        {
            base.Process(ifcMaterialList);

            IList <IFCAnyHandle> ifcMaterials =
                IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(ifcMaterialList, "Materials");

            if (ifcMaterials == null)
            {
                IFCImportFile.TheLog.LogError(ifcMaterialList.Id, "Expected at least 1 IfcMaterial, found none.", false);
                return;
            }

            foreach (IFCAnyHandle ifcMaterial in ifcMaterials)
            {
                IFCMaterial material = IFCMaterial.ProcessIFCMaterial(ifcMaterial);
                if (material != null)
                {
                    Materials.Add(material);
                }
            }
        }
        protected override void Process(IFCAnyHandle ifcMaterialConstituent)
        {
            base.Process(ifcMaterialConstituent);

            IFCAnyHandle ifcMaterial = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcMaterialConstituent, "Material", true);

            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(ifcMaterial))
            {
                Material = IFCMaterial.ProcessIFCMaterial(ifcMaterial);
            }

            Name        = IFCImportHandleUtil.GetOptionalStringAttribute(ifcMaterialConstituent, "Name", null);
            Description = IFCImportHandleUtil.GetOptionalStringAttribute(ifcMaterialConstituent, "Description", null);
            double fraction = IFCImportHandleUtil.GetOptionalRealAttribute(ifcMaterialConstituent, "Fraction", -1);

            if (fraction >= 0)
            {
                Fraction = fraction;
            }
            Category = IFCImportHandleUtil.GetOptionalStringAttribute(ifcMaterialConstituent, "Category", null);
            return;
        }
Пример #12
0
        /// <summary>
        /// Processes IfcRelAssociatesMaterial.
        /// </summary>
        /// <param name="ifcRelAssociatesMaterial">The IfcRelAssociatesMaterial handle.</param>
        void ProcessIFCRelAssociatesMaterial(IFCAnyHandle ifcRelAssociatesMaterial)
        {
            IFCAnyHandle ifcMaterialSelect = IFCAnyHandleUtil.GetInstanceAttribute(ifcRelAssociatesMaterial, "RelatingMaterial");

            if (IFCAnyHandleUtil.IsNullOrHasNoValue(ifcMaterialSelect))
            {
                IFCImportFile.TheLog.LogNullError(IFCEntityType.IfcRelAssociatesMaterial);
                return;
            }

            // Deal with various types of IFCMaterialSelect.
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcMaterialSelect, IFCEntityType.IfcMaterial))
            {
                MaterialSelect = IFCMaterial.ProcessIFCMaterial(ifcMaterialSelect);
            }
            else if (IFCAnyHandleUtil.IsSubTypeOf(ifcMaterialSelect, IFCEntityType.IfcMaterialLayer))
            {
                MaterialSelect = IFCMaterialLayer.ProcessIFCMaterialLayer(ifcMaterialSelect);
            }
            else if (IFCAnyHandleUtil.IsSubTypeOf(ifcMaterialSelect, IFCEntityType.IfcMaterialLayerSet))
            {
                MaterialSelect = IFCMaterialLayerSet.ProcessIFCMaterialLayerSet(ifcMaterialSelect);
            }
            else if (IFCAnyHandleUtil.IsSubTypeOf(ifcMaterialSelect, IFCEntityType.IfcMaterialLayerSetUsage))
            {
                MaterialSelect = IFCMaterialLayerSetUsage.ProcessIFCMaterialLayerSetUsage(ifcMaterialSelect);
            }
            else if (IFCAnyHandleUtil.IsSubTypeOf(ifcMaterialSelect, IFCEntityType.IfcMaterialList))
            {
                MaterialSelect = IFCMaterialList.ProcessIFCMaterialList(ifcMaterialSelect);
            }
            else
            {
                IFCImportFile.TheLog.LogUnhandledSubTypeError(ifcMaterialSelect, "IfcMaterialSelect", false);
            }
        }
Пример #13
0
        /// <summary>
        /// Create the material associated to the element, and return the id.
        /// </summary>
        /// <param name="doc">The document.</param>
        /// <param name="forcedName">An optional name that sets the name of the material created, regardless of surface style name.</param>
        /// <param name="suggestedName">An optional name that suggests the name of the material created, if the surface style name is null.</param>
        /// <param name="idOverride">The id of the parent item, used if forcedName is used.</param>
        /// <returns>The material id.</returns>
        /// <remarks>If forcedName is not null, this will not store the created element id in this class.</remarks>
        public ElementId Create(Document doc, string forcedName, string suggestedName, int idOverride)
        {
            try
            {
                bool overrideName = (forcedName != null) && (string.Compare(forcedName, Name) != 0);
                if (!overrideName && m_CreatedElementId != ElementId.InvalidElementId)
                {
                    return(m_CreatedElementId);
                }

                string name = overrideName ? forcedName : Name;
                if (string.IsNullOrEmpty(name))
                {
                    if (!string.IsNullOrEmpty(suggestedName))
                    {
                        name = suggestedName;
                    }
                    else
                    {
                        name = "IFC Surface Style";
                    }
                }
                int id = overrideName ? idOverride : Id;

                if (IsValidForCreation)
                {
                    Color color        = null;
                    int?  transparency = null;
                    int?  shininess    = null;
                    int?  smoothness   = null;

                    IFCSurfaceStyleShading shading = ShadingStyle;
                    if (shading != null)
                    {
                        color        = shading.GetSurfaceColor();
                        transparency = (int)(shading.Transparency * 100 + 0.5);
                        shininess    = shading.GetShininess();
                        smoothness   = shading.GetSmoothness();
                    }

                    IFCMaterialInfo materialInfo =
                        IFCMaterialInfo.Create(color, transparency, shininess, smoothness, ElementId.InvalidElementId);
                    ElementId createdElementId = IFCMaterial.CreateMaterialElem(doc, id, name, materialInfo);
                    if (!overrideName)
                    {
                        m_CreatedElementId = createdElementId;
                    }
                    return(createdElementId);
                }
                else
                {
                    IsValidForCreation = false;
                }
            }
            catch (Exception ex)
            {
                IsValidForCreation = false;
                Importer.TheLog.LogCreationError(this, ex.Message, false);
            }

            return(ElementId.InvalidElementId);
        }
        private GeometryObject CreateGeometryFromMateriaProfile(IFCImportShapeEditScope shapeEditScope,
                                                                IList <CurveLoop> loops, XYZ extrusionDirection, double currDepth, SolidOptions solidOptions, out bool shouldWarn)
        {
            GeometryObject extrusionSolid = null;

            try
            {
                shouldWarn = true; // invalid input

                IIFCMaterialSelect materialSelect = shapeEditScope.Creator.MaterialSelect;
                if (materialSelect == null)
                {
                    return(null);
                }

                IFCMaterialProfileSetUsage matProfSetUsage = materialSelect as IFCMaterialProfileSetUsage;
                if (matProfSetUsage == null)
                {
                    return(null);
                }

                IFCMaterialProfileSet matProfSet = matProfSetUsage.ForProfileSet;
                if (matProfSet == null)
                {
                    return(null);
                }

                IList <IFCMaterialProfile> matProfList = matProfSet.MaterialProfileSet;
                if (matProfList.Count == 0)
                {
                    return(null);
                }

                Transform         transformByOffset = Transform.Identity;
                IList <CurveLoop> newloops          = new List <CurveLoop>();

                ElementId materialId = null;
                foreach (IFCMaterialProfile matProf in matProfList)
                {
                    if (this.SweptArea.Id == matProf.Profile.Id)
                    {
                        // This is the same id (same profile), use the material name for creation of this geometry
                        IFCMaterial theMaterial = matProf.Material;
                        if (theMaterial != null)
                        {
                            materialId = theMaterial.GetMaterialElementId();
                            solidOptions.MaterialId = materialId; // Override the original option if the profile has a specific material id
                        }

                        // Here we will handle special case if the Material Profile has Offset
                        if (matProf is IFCMaterialProfileWithOffsets)
                        {
                            IFCMaterialProfileWithOffsets matProfOffset = matProf as IFCMaterialProfileWithOffsets;
                            double startOffset = matProfOffset.OffsetValues[0];
                            double endOffset   = 0;
                            if (matProfOffset.OffsetValues.Count > 1)
                            {
                                endOffset = matProfOffset.OffsetValues[1];
                            }

                            // To handle offset, we need to move the start point (extrusion position) to the startOffset value along the axis (extrusion direction)
                            // For the end offset, we will have to re-calculate the extrusion
                            currDepth = currDepth - startOffset + endOffset;
                            transformByOffset.Origin += startOffset * extrusionDirection;
                            foreach (CurveLoop loop in loops)
                            {
                                CurveLoop newLoop = CurveLoop.CreateViaTransform(loop, transformByOffset);
                                newloops.Add(newLoop);
                            }
                        }
                        break;
                    }
                }

                if (newloops.Count == 0)
                {
                    extrusionSolid = GeometryCreationUtilities.CreateExtrusionGeometry(loops, extrusionDirection, currDepth, solidOptions);
                }
                else
                {
                    extrusionSolid = GeometryCreationUtilities.CreateExtrusionGeometry(newloops, extrusionDirection, currDepth, solidOptions);
                }
            }
            catch
            {
                // Ignore the specific exception, but let the user know there was a problem processing the IfcMaterialLayerSetUsage.
                shouldWarn = true;
                return(null);
            }

            return(extrusionSolid);
        }
Пример #15
0
        /// <summary>
        /// Processes an IfcMaterial object.
        /// </summary>
        /// <param name="ifcMaterial">The IfcMaterial handle.</param>
        /// <returns>The IFCMaterial object.</returns>
        public static IFCMaterial ProcessIFCMaterial(IFCAnyHandle ifcMaterial)
        {
            if (IFCAnyHandleUtil.IsNullOrHasNoValue(ifcMaterial))
            {
                Importer.TheLog.LogNullError(IFCEntityType.IfcMaterial);
                return null;
            }

            IFCEntity material;
            if (!IFCImportFile.TheFile.EntityMap.TryGetValue(ifcMaterial.StepId, out material))
                material = new IFCMaterial(ifcMaterial);
            return (material as IFCMaterial);
        }
        // This routine may return null geometry for one of three reasons:
        // 1. Invalid input.
        // 2. No IfcMaterialLayerUsage.
        // 3. The IfcMaterialLayerUsage isn't handled.
        // If the reason is #1 or #3, we want to warn the user.  If it is #2, we don't.  Pass back shouldWarn to let the caller know.
        private IList <GeometryObject> CreateGeometryFromMaterialLayerUsage(IFCImportShapeEditScope shapeEditScope, Transform extrusionPosition,
                                                                            IList <CurveLoop> loops, XYZ extrusionDirection, double currDepth, out ElementId materialId, out bool shouldWarn)
        {
            IList <GeometryObject> extrusionSolids = null;

            materialId = ElementId.InvalidElementId;

            try
            {
                shouldWarn = true; // Invalid input.

                // Check for valid input.
                if (shapeEditScope == null ||
                    extrusionPosition == null ||
                    loops == null ||
                    loops.Count() == 0 ||
                    extrusionDirection == null ||
                    !Application.IsValidThickness(currDepth))
                {
                    return(null);
                }

                IFCProduct creator = shapeEditScope.Creator;
                if (creator == null)
                {
                    return(null);
                }

                shouldWarn = false; // Missing, empty, or optimized out IfcMaterialLayerSetUsage - valid reason to stop.

                IIFCMaterialSelect materialSelect = creator.MaterialSelect;
                if (materialSelect == null)
                {
                    return(null);
                }

                IFCMaterialLayerSetUsage materialLayerSetUsage = materialSelect as IFCMaterialLayerSetUsage;
                if (materialLayerSetUsage == null)
                {
                    return(null);
                }

                IFCMaterialLayerSet materialLayerSet = materialLayerSetUsage.MaterialLayerSet;
                if (materialLayerSet == null)
                {
                    return(null);
                }

                IList <IFCMaterialLayer> materialLayers = materialLayerSet.MaterialLayers;
                if (materialLayers == null || materialLayers.Count == 0)
                {
                    return(null);
                }

                // Optimization: if there is only one layer, use the standard method, with possibly an overloaded material.
                ElementId baseMaterialId = GetMaterialElementId(shapeEditScope);
                if (materialLayers.Count == 1)
                {
                    IFCMaterial oneMaterial = materialLayers[0].Material;
                    if (oneMaterial == null)
                    {
                        return(null);
                    }

                    materialId = oneMaterial.GetMaterialElementId();
                    if (materialId != ElementId.InvalidElementId)
                    {
                        // We will not override the material of the element if the layer material has no color.
                        if (Importer.TheCache.MaterialsWithNoColor.Contains(materialId))
                        {
                            materialId = ElementId.InvalidElementId;
                        }
                    }

                    return(null);
                }

                // Anything below here is something we should report to the user, with the exception of the total thickness
                // not matching the extrusion thickness.  This would require more analysis to determine that it is actually
                // an error condition.
                shouldWarn = true;

                IList <IFCMaterialLayer> realMaterialLayers = new List <IFCMaterialLayer>();
                double totalThickness = 0.0;
                foreach (IFCMaterialLayer materialLayer in materialLayers)
                {
                    double depth = materialLayer.LayerThickness;
                    if (MathUtil.IsAlmostZero(depth))
                    {
                        continue;
                    }

                    if (depth < 0.0)
                    {
                        return(null);
                    }

                    realMaterialLayers.Add(materialLayer);
                    totalThickness += depth;
                }

                // Axis3 means that the material layers are stacked in the Z direction.  This is common for floor slabs.
                bool isAxis3 = (materialLayerSetUsage.Direction == IFCLayerSetDirection.Axis3);

                // For elements extruded in the Z direction, if the extrusion layers don't have the same thickness as the extrusion,
                // this could be one of two reasons:
                // 1. There is a discrepancy between the extrusion depth and the material layer set usage calculated depth.
                // 2. There are multiple extrusions in the body definition.
                // In either case, we will use the extrusion geometry over the calculated material layer set usage geometry.
                // In the future, we may decide to allow for case #1 by passing in a flag to allow for this.
                if (isAxis3 && !MathUtil.IsAlmostEqual(totalThickness, currDepth))
                {
                    shouldWarn = false;
                    return(null);
                }

                int numLayers = realMaterialLayers.Count();
                if (numLayers == 0)
                {
                    return(null);
                }
                // We'll use this initial value for the Axis2 case, so read it here.
                double baseOffsetForLayer = materialLayerSetUsage.Offset;

                // Needed for Axis2 case only.  The axisCurve is the curve defined in the product representation representing
                // a base curve (an axis) for the footprint of the element.
                Curve axisCurve = null;

                // The oriented cuve list represents the 4 curves of supported Axis2 footprint in the following order:
                // 1. curve along length of object closest to the first material layer with the orientation of the axis curve
                // 2. connecting end curve
                // 3. curve along length of object closest to the last material layer with the orientation opposite of the axis curve
                // 4. connecting end curve.
                IList <Curve> orientedCurveList = null;

                if (!isAxis3)
                {
                    // Axis2 means that the material layers are stacked inthe Y direction.  This is by definition for IfcWallStandardCase,
                    // which has a local coordinate system whose Y direction is orthogonal to the length of the wall.
                    if (materialLayerSetUsage.Direction == IFCLayerSetDirection.Axis2)
                    {
                        axisCurve = GetAxisCurve(creator, extrusionPosition);
                        if (axisCurve == null)
                        {
                            return(null);
                        }

                        orientedCurveList = GetOrientedCurveList(loops, axisCurve, extrusionPosition.BasisZ, baseOffsetForLayer, totalThickness);
                        if (orientedCurveList == null)
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        return(null); // Not handled.
                    }
                }

                extrusionSolids = new List <GeometryObject>();

                bool positiveOrientation = (materialLayerSetUsage.DirectionSense == IFCDirectionSense.Positive);

                // Always extrude in the positive direction for Axis2.
                XYZ materialExtrusionDirection = (positiveOrientation || !isAxis3) ? extrusionDirection : -extrusionDirection;

                // Axis2 repeated values.
                // The IFC concept of offset direction is reversed from Revit's.
                XYZ    normalDirectionForAxis2 = positiveOrientation ? -extrusionPosition.BasisZ : extrusionPosition.BasisZ;
                bool   axisIsCyclic            = (axisCurve == null) ? false : axisCurve.IsCyclic;
                double axisCurvePeriod         = axisIsCyclic ? axisCurve.Period : 0.0;

                Transform curveLoopTransform = Transform.Identity;

                IList <CurveLoop> currLoops  = null;
                double            depthSoFar = 0.0;

                for (int ii = 0; ii < numLayers; ii++)
                {
                    IFCMaterialLayer materialLayer = materialLayers[ii];

                    // Ignore 0 thickness layers.  No need to warn.
                    double depth = materialLayer.LayerThickness;
                    if (MathUtil.IsAlmostZero(depth))
                    {
                        continue;
                    }

                    // If the thickness is non-zero but invalid, fail.
                    if (!Application.IsValidThickness(depth))
                    {
                        return(null);
                    }

                    double extrusionDistance = 0.0;
                    if (isAxis3)
                    {
                        // Offset the curve loops if necessary, using the base extrusionDirection, regardless of the direction sense
                        // of the MaterialLayerSetUsage.
                        double offsetForLayer = positiveOrientation ? baseOffsetForLayer + depthSoFar : baseOffsetForLayer - depthSoFar;
                        if (!MathUtil.IsAlmostZero(offsetForLayer))
                        {
                            curveLoopTransform.Origin = offsetForLayer * extrusionDirection;

                            currLoops = new List <CurveLoop>();
                            foreach (CurveLoop loop in loops)
                            {
                                CurveLoop newLoop = CurveLoop.CreateViaTransform(loop, curveLoopTransform);
                                if (newLoop == null)
                                {
                                    return(null);
                                }

                                currLoops.Add(newLoop);
                            }
                        }
                        else
                        {
                            currLoops = loops;
                        }

                        extrusionDistance = depth;
                    }
                    else
                    {
                        // startClipCurve, firstEndCapCurve, endClipCurve, secondEndCapCurve.
                        Curve[]    outline       = new Curve[4];
                        double[][] endParameters = new double[4][];

                        double startClip = depthSoFar;
                        double endClip   = depthSoFar + depth;

                        outline[0] = orientedCurveList[0].CreateOffset(startClip, normalDirectionForAxis2);
                        outline[1] = orientedCurveList[1].Clone();
                        outline[2] = orientedCurveList[2].CreateOffset(totalThickness - endClip, normalDirectionForAxis2);
                        outline[3] = orientedCurveList[3].Clone();

                        for (int jj = 0; jj < 4; jj++)
                        {
                            outline[jj].MakeUnbound();
                            endParameters[jj]    = new double[2];
                            endParameters[jj][0] = 0.0;
                            endParameters[jj][1] = 0.0;
                        }

                        // Trim/Extend the curves so that they make a closed loop.
                        for (int jj = 0; jj < 4; jj++)
                        {
                            IntersectionResultArray resultArray = null;
                            outline[jj].Intersect(outline[(jj + 1) % 4], out resultArray);
                            if (resultArray == null || resultArray.Size == 0)
                            {
                                return(null);
                            }

                            int numResults = resultArray.Size;
                            if ((numResults > 1 && !axisIsCyclic) || (numResults > 2))
                            {
                                return(null);
                            }

                            UV intersectionPoint = resultArray.get_Item(0).UVPoint;
                            endParameters[jj][1]           = intersectionPoint.U;
                            endParameters[(jj + 1) % 4][0] = intersectionPoint.V;

                            if (numResults == 2)
                            {
                                // If the current result is closer to the end of the curve, keep it.
                                UV newIntersectionPoint = resultArray.get_Item(1).UVPoint;

                                int    endParamIndex   = (jj % 2);
                                double newParamToCheck = newIntersectionPoint[endParamIndex];
                                double oldParamToCheck = (endParamIndex == 0) ? endParameters[jj][1] : endParameters[(jj + 1) % 4][0];
                                double currentEndPoint = (endParamIndex == 0) ?
                                                         orientedCurveList[jj].GetEndParameter(1) : orientedCurveList[(jj + 1) % 4].GetEndParameter(0);

                                // Put in range of [-Period/2, Period/2].
                                double newDist = (currentEndPoint - newParamToCheck) % axisCurvePeriod;
                                if (newDist < -axisCurvePeriod / 2.0)
                                {
                                    newDist += axisCurvePeriod;
                                }
                                if (newDist > axisCurvePeriod / 2.0)
                                {
                                    newDist -= axisCurvePeriod;
                                }

                                double oldDist = (currentEndPoint - oldParamToCheck) % axisCurvePeriod;
                                if (oldDist < -axisCurvePeriod / 2.0)
                                {
                                    oldDist += axisCurvePeriod;
                                }
                                if (oldDist > axisCurvePeriod / 2.0)
                                {
                                    oldDist -= axisCurvePeriod;
                                }

                                if (Math.Abs(newDist) < Math.Abs(oldDist))
                                {
                                    endParameters[jj][1]           = newIntersectionPoint.U;
                                    endParameters[(jj + 1) % 4][0] = newIntersectionPoint.V;
                                }
                            }
                        }

                        CurveLoop newCurveLoop = new CurveLoop();
                        for (int jj = 0; jj < 4; jj++)
                        {
                            if (endParameters[jj][1] < endParameters[jj][0])
                            {
                                if (!outline[jj].IsCyclic)
                                {
                                    return(null);
                                }
                                endParameters[jj][1] += Math.Floor(endParameters[jj][0] / axisCurvePeriod + 1.0) * axisCurvePeriod;
                            }

                            outline[jj].MakeBound(endParameters[jj][0], endParameters[jj][1]);
                            newCurveLoop.Append(outline[jj]);
                        }

                        currLoops = new List <CurveLoop>();
                        currLoops.Add(newCurveLoop);

                        extrusionDistance = currDepth;
                    }

                    // Determine the material id.
                    IFCMaterial material        = materialLayer.Material;
                    ElementId   layerMaterialId = (material == null) ? ElementId.InvalidElementId : material.GetMaterialElementId();

                    // The second option here is really for Referencing.  Without a UI (yet) to determine whether to show the base
                    // extusion or the layers for objects with material layer sets, we've chosen to display the base material if the layer material
                    // has no color information.  This means that the layer is assigned the "wrong" material, but looks better on screen.
                    // We will reexamine this decision (1) for the Open case, (2) if there is UI to toggle between layers and base extrusion, or
                    // (3) based on user feedback.
                    if (layerMaterialId == ElementId.InvalidElementId || Importer.TheCache.MaterialsWithNoColor.Contains(layerMaterialId))
                    {
                        layerMaterialId = baseMaterialId;
                    }

                    SolidOptions solidOptions = new SolidOptions(layerMaterialId, shapeEditScope.GraphicsStyleId);

                    // Create the extrusion for the material layer.
                    GeometryObject extrusionSolid = GeometryCreationUtilities.CreateExtrusionGeometry(
                        currLoops, materialExtrusionDirection, extrusionDistance, solidOptions);
                    if (extrusionSolid == null)
                    {
                        return(null);
                    }

                    extrusionSolids.Add(extrusionSolid);
                    depthSoFar += depth;
                }
            }
            catch
            {
                // Ignore the specific exception, but let the user know there was a problem processing the IfcMaterialLayerSetUsage.
                shouldWarn = true;
                return(null);
            }

            return(extrusionSolids);
        }
      /// <summary>
      /// Gets the one material associated with this object.
      /// </summary>
      /// <returns>The material, if there is identically one; otherwise, null.</returns>
      public IFCMaterial GetTheMaterial()
      {
         if (!m_TheMaterialIsSet)
         {
            IList<IFCMaterial> materials = GetMaterials();

            m_TheMaterialIsSet = true;
            IFCMaterial theMaterial = null;
            if (materials.Count > 1)
               return null;

            if (materials.Count == 1)
               theMaterial = materials[0];

            if (this is IFCObject)
            {
               IFCObject asObject = this as IFCObject;
               foreach (IFCTypeObject typeObject in asObject.TypeObjects)
               {
                  IList<IFCMaterial> typeMaterials = typeObject.GetMaterials();

                  if (typeMaterials.Count > 1)
                     return null;

                  if (typeMaterials.Count == 1)
                  {
                     if (theMaterial != null && theMaterial.Id != typeMaterials[0].Id)
                        return null;
                     theMaterial = typeMaterials[0];
                  }
               }
            }

            m_TheMaterial = theMaterial;
         }

         return m_TheMaterial;
      }
Пример #18
0
        /// <summary>
        /// Processes IfcProductRepresentation attributes.
        /// </summary>
        /// <param name="ifcProductRepresentation">The IfcProductRepresentation handle.</param>
        protected override void Process(IFCAnyHandle ifcProductRepresentation)
        {
            base.Process(ifcProductRepresentation);

            Name = IFCImportHandleUtil.GetOptionalStringAttribute(ifcProductRepresentation, "Name", null);

            Description = IFCImportHandleUtil.GetOptionalStringAttribute(ifcProductRepresentation, "Description", null);

            List<IFCAnyHandle> representations =
                IFCAnyHandleUtil.GetAggregateInstanceAttribute<List<IFCAnyHandle>>(ifcProductRepresentation, "Representations");
            if (representations != null)
            {
                foreach (IFCAnyHandle representationHnd in representations)
                {
                    try
                    {
                        IFCRepresentation representation = IFCRepresentation.ProcessIFCRepresentation(representationHnd);
                        if (representation != null)
                        {
                            if (representation.RepresentationItems.Count > 0)
                                Representations.Add(representation);
                        }
                    }
                    catch (Exception ex)
                    {
                        string msg = ex.Message;
                        // Ignore some specific errors.
                        if (msg != null)
                        {
                            if (!msg.Contains("not imported"))
                                IFCImportFile.TheLog.LogError(Id, msg, false);
                        }
                    }
                }
            }

            if (IFCImportFile.TheFile.SchemaVersion >= IFCSchemaVersion.IFC2x3)
            {
                if (IFCAnyHandleUtil.IsSubTypeOf(ifcProductRepresentation, IFCEntityType.IfcMaterialDefinitionRepresentation))
                {
                    IFCAnyHandle representedMaterial = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcProductRepresentation, "RepresentedMaterial", false);
                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(representedMaterial))
                        RepresentedMaterial = IFCMaterial.ProcessIFCMaterial(representedMaterial);
                }
            }
        }
Пример #19
0
        /// <summary>
        /// Cleans out the IFCEntity to save memory.
        /// </summary>
        public override void CleanEntity()
        {
            base.CleanEntity();

            m_ComposedObjectDefinitions = null;

            m_AssignmentGroups = null;

            m_ShapeType = null;

            m_MaterialSelect = null;

            m_TheMaterial = null;
        
            m_TheMaterialIsSet = false;
        }