/// <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); } }
/// <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); }
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); } } } }
/// <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); }
/// <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; }
/// <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); }
/// <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); }
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; }
/// <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); } }
/// <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); }
/// <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; }
/// <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); } } }