private HashSet <IFCAnyHandle> GetContainedItemsForHandle(IFCAnyHandle container, string guid)
 {
     if (!Cache.TryGetValue(container, out HashSet <IFCAnyHandle> containedItems))
     {
         ContainerGUIDs[container] = guid ??
                                     GUIDUtil.GenerateIFCGuidFrom(IFCEntityType.IfcRelContainedInSpatialStructure, container);
         containedItems   = new HashSet <IFCAnyHandle>();
         Cache[container] = containedItems;
     }
     return(containedItems);
 }
Beispiel #2
0
        private static string CreateOpeningGUID(Element openingElem, IFCRange range, int openingIndex,
                                                int solidIndex)
        {
            // GUID_TODO: Range can be potentially unstable; getting the corresponding level would be
            // better.
            string openingId = (range != null) ?
                               "(" + range.Start.ToString() + ":" + range.End.ToString() + ")" :
                               string.Empty;

            openingId += "Opening:" + openingIndex.ToString() + "Solid:" + solidIndex.ToString();
            return(GUIDUtil.GenerateIFCGuidFrom(openingElem, openingId));
        }
        /// <summary>
        /// Excutes the creator.
        /// </summary>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="doc">The document.</param>
        public void Execute(ExporterIFC exporterIFC, Document doc)
        {
            IFCAnyHandle hostObjHnd = !IFCAnyHandleUtil.IsNullOrHasNoValue(HostHnd) ? HostHnd :
                                      DoorWindowUtil.GetHndForHostAndLevel(exporterIFC, HostId, LevelId);

            if (IFCAnyHandleUtil.IsNullOrHasNoValue(hostObjHnd))
            {
                return;
            }

            IList <DoorWindowOpeningInfo> doorWindowOpeningInfoList = new List <DoorWindowOpeningInfo>();

            Element doorElem    = doc.GetElement(InsertId);
            string  openingGUID = GUIDUtil.CreateSubElementGUID(doorElem, (int)IFCDoorSubElements.DoorOpening);

            if (ExtrusionData != null)
            {
                foreach (IFCExtrusionData extrusionData in ExtrusionData)
                {
                    int index = doorWindowOpeningInfoList.Count;
                    if (index > 0)
                    {
                        openingGUID = GUIDUtil.GenerateIFCGuidFrom(doorElem, "IfcOpeningElement: " + index.ToString());
                    }
                    DoorWindowOpeningInfo openingInfo = DoorWindowUtil.CreateOpeningForDoorWindow(exporterIFC, doc, hostObjHnd,
                                                                                                  HostId, InsertId, openingGUID, extrusionData.GetLoops()[0], extrusionData.ExtrusionDirection,
                                                                                                  UnitUtil.UnscaleLength(extrusionData.ScaledExtrusionLength), PosHingeSide, IsRecess);
                    if (openingInfo != null && !IFCAnyHandleUtil.IsNullOrHasNoValue(openingInfo.OpeningHnd))
                    {
                        doorWindowOpeningInfoList.Add(openingInfo);
                    }
                }
            }

            if (Solids != null)
            {
                foreach (Solid solid in Solids)
                {
                    int index = doorWindowOpeningInfoList.Count;
                    if (index > 0)
                    {
                        openingGUID = GUIDUtil.GenerateIFCGuidFrom(doorElem, "IfcOpeningElement: " + index.ToString());
                    }
                    DoorWindowOpeningInfo openingInfo = DoorWindowUtil.CreateOpeningForDoorWindow(exporterIFC, doc, hostObjHnd,
                                                                                                  HostId, InsertId, openingGUID, solid, ScaledHostWidth, IsRecess);
                    if (openingInfo != null && !IFCAnyHandleUtil.IsNullOrHasNoValue(openingInfo.OpeningHnd))
                    {
                        doorWindowOpeningInfoList.Add(openingInfo);
                    }
                }
            }

            if (IFCAnyHandleUtil.IsNullOrHasNoValue(DoorWindowHnd))
            {
                return;
            }

            bool foundOpening          = false;
            bool foundHeight           = false;
            bool foundWidth            = false;
            bool?isDoorOrWindowOpening = null;

            foreach (DoorWindowOpeningInfo openingInfo in doorWindowOpeningInfoList)
            {
                // If we've updated the door/window placement, and set its height and width, there's nothing more to do here.
                if (foundOpening && foundHeight && foundWidth)
                {
                    break;
                }

                // update original door or window to be relative to the first opening we find.
                // We only allow one IfcRelFillsElement per door or window, so only do this for the first opening.
                if (!foundOpening)
                {
                    IFCFile      file         = exporterIFC.GetFile();
                    IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle;

                    IFCAnyHandle openingHnd = openingInfo.OpeningHnd;

                    foundOpening = true;
                    string relGUID = GUIDUtil.GenerateIFCGuidFrom(IFCEntityType.IfcRelFillsElement, openingHnd, DoorWindowHnd);
                    IFCInstanceExporter.CreateRelFillsElement(file, relGUID, ownerHistory, null, null, openingHnd, DoorWindowHnd);

                    IFCAnyHandle openingPlacement = IFCAnyHandleUtil.GetObjectPlacement(openingHnd);
                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(openingPlacement))
                    {
                        IFCAnyHandle origObjectPlacement = IFCAnyHandleUtil.GetObjectPlacement(DoorWindowHnd);
                        Transform    relTransform        = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(origObjectPlacement, openingPlacement);

                        IFCAnyHandle newLocalPlacement = ExporterUtil.CreateLocalPlacement(file, openingPlacement,
                                                                                           relTransform.Origin, relTransform.BasisZ, relTransform.BasisX);

                        IFCAnyHandleUtil.SetAttribute(DoorWindowHnd, "ObjectPlacement", newLocalPlacement);
                        IFCAnyHandleUtil.Delete(origObjectPlacement);
                    }
                }

                // The first entry for a particular door may not have the height or width set, so keep looking until we find an entry that does.
                if (!isDoorOrWindowOpening.HasValue)
                {
                    isDoorOrWindowOpening = IFCAnyHandleUtil.IsTypeOf(DoorWindowHnd, IFCEntityType.IfcDoor) || IFCAnyHandleUtil.IsTypeOf(DoorWindowHnd, IFCEntityType.IfcWindow);
                }

                if (!(foundHeight && foundWidth) && isDoorOrWindowOpening.Value)
                {
                    double openingHeight = openingInfo.OpeningHeight;
                    double openingWidth  = openingInfo.OpeningWidth;

                    if (openingHeight > MathUtil.Eps())
                    {
                        foundHeight = true;
                        IFCAnyHandleUtil.SetAttribute(DoorWindowHnd, "OverallHeight", UnitUtil.ScaleLength(openingHeight));
                    }

                    if (openingWidth > MathUtil.Eps())
                    {
                        foundWidth = true;
                        IFCAnyHandleUtil.SetAttribute(DoorWindowHnd, "OverallWidth", UnitUtil.ScaleLength(openingWidth));
                    }
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Creates an opening from extrusion data.
        /// </summary>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="hostObjHnd">The host handle.</param>
        /// <param name="hostPlacement">The host placement.</param>
        /// <param name="hostElement">The host element.</param>
        /// <param name="insertElement">The opening element.</param>
        /// <param name="openingGUID">The opening GUID.</param>
        /// <param name="extrusionData">The extrusion data.</param>
        /// <param name="lcs">The local coordinate system of the base of the extrusion.</param>
        /// <param name="isRecess">True if it is a recess.</param>
        /// <returns>The opening handle.</returns>
        static public IFCAnyHandle CreateOpening(ExporterIFC exporterIFC, IFCAnyHandle hostObjHnd, IFCAnyHandle hostPlacement, Element hostElement,
                                                 Element insertElement, string openingGUID, IFCExtrusionData extrusionData, Transform lcs, bool isRecess,
                                                 PlacementSetter setter, ProductWrapper localWrapper)
        {
            IFCFile file = exporterIFC.GetFile();

            IList <CurveLoop> curveLoops = extrusionData.GetLoops();

            if (curveLoops.Count == 0)
            {
                return(null);
            }

            if (lcs == null)
            {
                // assumption: first curve loop defines the plane.
                if (!curveLoops[0].HasPlane())
                {
                    return(null);
                }
                lcs = GeometryUtil.CreateTransformFromPlane(curveLoops[0].GetPlane());
            }

            ElementId catId = CategoryUtil.GetSafeCategoryId(insertElement);

            IFCAnyHandle openingProdRepHnd = RepresentationUtil.CreateExtrudedProductDefShape(exporterIFC, insertElement, catId,
                                                                                              curveLoops, lcs, extrusionData.ExtrusionDirection, extrusionData.ScaledExtrusionLength);

            string       openingObjectType = isRecess ? "Recess" : "Opening";
            IFCAnyHandle ownerHistory      = ExporterCacheManager.OwnerHistoryHandle;
            string       openingName       = NamingUtil.GetNameOverride(insertElement, null);

            if (string.IsNullOrEmpty(openingName))
            {
                openingName = NamingUtil.GetNameOverride(hostElement, NamingUtil.CreateIFCObjectName(exporterIFC, hostElement));
            }
            string       openingDescription = NamingUtil.GetDescriptionOverride(insertElement, null);
            string       openingTag         = NamingUtil.GetTagOverride(insertElement);
            IFCAnyHandle openingHnd         = IFCInstanceExporter.CreateOpeningElement(exporterIFC,
                                                                                       openingGUID, ownerHistory, openingName, openingDescription, openingObjectType,
                                                                                       ExporterUtil.CreateLocalPlacement(file, hostPlacement, null), openingProdRepHnd, openingTag);
            IFCExportInfoPair        exportInfo = new IFCExportInfoPair(IFCEntityType.IfcOpeningElement, openingObjectType);
            IFCExtrusionCreationData ecData     = null;

            if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities)
            {
                double height, width;
                ecData = new IFCExtrusionCreationData();
                if (GeometryUtil.ComputeHeightWidthOfCurveLoop(curveLoops[0], lcs, out height, out width))
                {
                    ecData.ScaledHeight = UnitUtil.ScaleLength(height);
                    ecData.ScaledWidth  = UnitUtil.ScaleLength(width);
                }
                else
                {
                    double area = ExporterIFCUtils.ComputeAreaOfCurveLoops(curveLoops);
                    ecData.ScaledArea = UnitUtil.ScaleArea(area);
                }
                PropertyUtil.CreateOpeningQuantities(exporterIFC, openingHnd, ecData);
            }

            if (localWrapper != null)
            {
                Element elementForProperties = null;
                if (GUIDUtil.IsGUIDFor(insertElement, openingGUID))
                {
                    elementForProperties = insertElement;
                }

                localWrapper.AddElement(elementForProperties, openingHnd, setter, ecData, false, exportInfo);
            }

            string voidGuid = GUIDUtil.GenerateIFCGuidFrom(IFCEntityType.IfcRelVoidsElement,
                                                           hostObjHnd, openingHnd);

            IFCInstanceExporter.CreateRelVoidsElement(file, voidGuid, ownerHistory, null, null,
                                                      hostObjHnd, openingHnd);
            return(openingHnd);
        }
Beispiel #5
0
        /// <summary>
        /// Creates openings if there is necessary.
        /// </summary>
        /// <param name="elementHandle">The element handle to create openings.</param>
        /// <param name="element">The element to create openings.</param>
        /// <param name="info">The extrusion data.</param>
        /// <param name="extraParams">The extrusion creation data.</param>
        /// <param name="offsetTransform">The offset transform from ExportBody, or the identity transform.</param>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="originalPlacement">The original placement handle.</param>
        /// <param name="setter">The PlacementSetter.</param>
        /// <param name="wrapper">The ProductWrapper.</param>
        private static void CreateOpeningsIfNecessaryBase(IFCAnyHandle elementHandle, Element element, IList <IFCExtrusionData> info,
                                                          IFCExtrusionCreationData extraParams, Transform offsetTransform, ExporterIFC exporterIFC,
                                                          IFCAnyHandle originalPlacement, PlacementSetter setter, ProductWrapper wrapper)
        {
            if (IFCAnyHandleUtil.IsNullOrHasNoValue(elementHandle))
            {
                return;
            }

            int sz = info.Count;

            if (sz == 0)
            {
                return;
            }

            using (TransformSetter transformSetter = TransformSetter.Create())
            {
                if (offsetTransform != null)
                {
                    transformSetter.Initialize(exporterIFC, offsetTransform.Inverse);
                }

                IFCFile   file       = exporterIFC.GetFile();
                ElementId categoryId = CategoryUtil.GetSafeCategoryId(element);

                string openingObjectType = "Opening";

                int openingNumber = 1;
                for (int curr = info.Count - 1; curr >= 0; curr--)
                {
                    IFCAnyHandle extrusionHandle =
                        ExtrusionExporter.CreateExtrudedSolidFromExtrusionData(exporterIFC, element,
                                                                               info[curr], out _);
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(extrusionHandle))
                    {
                        continue;
                    }

                    // Openings shouldn't have surface styles for their geometry.
                    HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>()
                    {
                        extrusionHandle
                    };

                    IFCAnyHandle representationHnd = RepresentationUtil.CreateSweptSolidRep(exporterIFC,
                                                                                            element, categoryId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null);
                    IList <IFCAnyHandle> representations = IFCAnyHandleUtil.IsNullOrHasNoValue(representationHnd) ?
                                                           null : new List <IFCAnyHandle>()
                    {
                        representationHnd
                    };

                    IFCAnyHandle openingRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null,
                                                                                               null, representations);

                    IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, originalPlacement);
                    string       guid             = GUIDUtil.GenerateIFCGuidFrom(IFCEntityType.IfcOpeningElement,
                                                                                 openingNumber.ToString(), elementHandle);
                    IFCAnyHandle ownerHistory       = ExporterCacheManager.OwnerHistoryHandle;
                    string       openingName        = NamingUtil.GetIFCNamePlusIndex(element, openingNumber++);
                    string       openingDescription = NamingUtil.GetDescriptionOverride(element, null);
                    string       openingTag         = NamingUtil.GetTagOverride(element);

                    IFCAnyHandle openingElement = IFCInstanceExporter.CreateOpeningElement(exporterIFC,
                                                                                           guid, ownerHistory, openingName, openingDescription, openingObjectType,
                                                                                           openingPlacement, openingRep, openingTag);
                    IFCExportInfoPair exportInfo = new IFCExportInfoPair(IFCEntityType.IfcOpeningElement);
                    wrapper.AddElement(null, openingElement, setter, extraParams, true, exportInfo);

                    if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities && (extraParams != null))
                    {
                        PropertyUtil.CreateOpeningQuantities(exporterIFC, openingElement, extraParams);
                    }

                    string voidGuid = GUIDUtil.GenerateIFCGuidFrom(IFCEntityType.IfcRelVoidsElement,
                                                                   elementHandle, openingElement);
                    IFCInstanceExporter.CreateRelVoidsElement(file, voidGuid, ownerHistory, null, null,
                                                              elementHandle, openingElement);
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Creates an opening from a solid.
        /// </summary>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="hostObjHnd">The host object handle.</param>
        /// <param name="hostElement">The host element.</param>
        /// <param name="insertElement">The insert element.</param>
        /// <param name="openingGUID">The GUID for the opening, depending on how the opening is created.</param>
        /// <param name="solid">The solid.</param>
        /// <param name="scaledHostWidth">The scaled host width.</param>
        /// <param name="isRecess">True if it is recess.</param>
        /// <param name="extrusionCreationData">The extrusion creation data.</param>
        /// <param name="setter">The placement setter.</param>
        /// <param name="localWrapper">The product wrapper.</param>
        /// <returns>The created opening handle.</returns>
        static public IFCAnyHandle CreateOpening(ExporterIFC exporterIFC, IFCAnyHandle hostObjHnd, Element hostElement, Element insertElement, string openingGUID,
                                                 Solid solid, double scaledHostWidth, bool isRecess, IFCExtrusionCreationData extrusionCreationData, PlacementSetter setter, ProductWrapper localWrapper)
        {
            IFCFile file = exporterIFC.GetFile();

            ElementId catId = CategoryUtil.GetSafeCategoryId(insertElement);

            XYZ  prepToWall;
            bool isLinearWall = GetOpeningDirection(hostElement, out prepToWall);

            if (isLinearWall)
            {
                extrusionCreationData.CustomAxis            = prepToWall;
                extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryCustom;
            }

            BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow);

            bodyExporterOptions.CreatingVoid = true;
            BodyData bodyData = BodyExporter.ExportBody(exporterIFC, insertElement, catId, ElementId.InvalidElementId,
                                                        solid, bodyExporterOptions, extrusionCreationData);

            IFCAnyHandle openingRepHnd = bodyData.RepresentationHnd;

            if (IFCAnyHandleUtil.IsNullOrHasNoValue(openingRepHnd))
            {
                extrusionCreationData.ClearOpenings();
                return(null);
            }
            IList <IFCAnyHandle> representations = new List <IFCAnyHandle>();

            representations.Add(openingRepHnd);
            IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations);

            IFCAnyHandle openingPlacement    = extrusionCreationData.GetLocalPlacement();
            IFCAnyHandle hostObjPlacementHnd = IFCAnyHandleUtil.GetObjectPlacement(hostObjHnd);
            Transform    relTransform        = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(openingPlacement, hostObjPlacementHnd);

            openingPlacement = ExporterUtil.CreateLocalPlacement(file, hostObjPlacementHnd,
                                                                 relTransform.Origin, relTransform.BasisZ, relTransform.BasisX);

            IFCAnyHandle ownerHistory        = ExporterCacheManager.OwnerHistoryHandle;
            double       scaledOpeningLength = extrusionCreationData.ScaledLength;
            string       openingObjectType;

            if (!MathUtil.IsAlmostZero(scaledHostWidth) && !MathUtil.IsAlmostZero(scaledOpeningLength))
            {
                openingObjectType = scaledOpeningLength < (scaledHostWidth - MathUtil.Eps()) ? "Recess" : "Opening";
            }
            else
            {
                openingObjectType = isRecess ? "Recess" : "Opening";
            }

            string openingName = NamingUtil.GetNameOverride(insertElement, null);

            if (string.IsNullOrEmpty(openingName))
            {
                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(hostObjHnd))
                {
                    openingName = IFCAnyHandleUtil.GetStringAttribute(hostObjHnd, "Name");
                }
                else
                {
                    openingName = NamingUtil.GetNameOverride(hostElement, NamingUtil.CreateIFCObjectName(exporterIFC, hostElement));
                }
            }

            string       openingDescription = NamingUtil.GetDescriptionOverride(insertElement, null);
            string       openingTag         = NamingUtil.GetTagOverride(insertElement);
            IFCAnyHandle openingHnd         = IFCInstanceExporter.CreateOpeningElement(exporterIFC,
                                                                                       openingGUID, ownerHistory, openingName, openingDescription, openingObjectType,
                                                                                       openingPlacement, prodRep, openingTag);
            IFCExportInfoPair exportInfo = new IFCExportInfoPair(IFCEntityType.IfcOpeningElement, openingObjectType);

            if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities)
            {
                PropertyUtil.CreateOpeningQuantities(exporterIFC, openingHnd, extrusionCreationData);
            }

            if (localWrapper != null)
            {
                Element elementForProperties = GUIDUtil.IsGUIDFor(insertElement, openingGUID) ?
                                               insertElement : null;

                localWrapper.AddElement(elementForProperties, openingHnd, setter, extrusionCreationData,
                                        false, exportInfo);
            }

            string voidGuid = GUIDUtil.GenerateIFCGuidFrom(IFCEntityType.IfcRelVoidsElement,
                                                           hostObjHnd, openingHnd);

            IFCInstanceExporter.CreateRelVoidsElement(file, voidGuid, ownerHistory, null, null,
                                                      hostObjHnd, openingHnd);
            return(openingHnd);
        }