Ejemplo n.º 1
0
 void Initialize(ExporterIFC exporterIFC, XYZ origin, XYZ xDir, XYZ yDir)
 {
     if (!m_Initialized)
     {
         m_ExporterIFC = exporterIFC;
         Transform trf = Transform.Identity;
         trf.Origin = origin;
         trf.BasisX = xDir;
         trf.BasisY = yDir;
         m_ExporterIFC.PushTransform(trf);
         m_Initialized = true;
     }
 }
Ejemplo n.º 2
0
 void Initialize(ExporterIFC exporterIFC, XYZ origin, XYZ xDir, XYZ yDir)
 {
     if (!m_Initialized)
     {
         m_ExporterIFC = exporterIFC;
         Transform trf = Transform.Identity;
         trf.Origin = origin;
         trf.BasisX = xDir;
         trf.BasisY = yDir;
         m_ExporterIFC.PushTransform(trf);
         m_Initialized = true;
     }
 }
Ejemplo n.º 3
0
        /// <summary>
        /// A special PlacementSetter constructor for element to be placed to the Site or Building
        /// </summary>
        /// <param name="exporterIFC">the exporterIFC</param>
        /// <param name="elem">the element</param>
        /// <param name="familyTrf">The optional family transform.</param>
        /// <param name="orientationTrf">The optional orientation of the element based on IFC standards or agreements.</param>
        /// <param name="siteOrBuilding">IfcSite or IfcBuilding</param>
        public PlacementSetter(ExporterIFC exporterIFC, Element elem, Transform familyTrf, Transform orientationTrf, IFCAnyHandle siteOrBuilding)
        {
            if (!IFCAnyHandleUtil.IsTypeOf(siteOrBuilding, Common.Enums.IFCEntityType.IfcSite) && !IFCAnyHandleUtil.IsTypeOf(siteOrBuilding, Common.Enums.IFCEntityType.IfcBuilding))
            {
                throw new ArgumentException("Argument siteOrBuilding (" + IFCAnyHandleUtil.GetEntityType(siteOrBuilding).ToString() + ") must be either IfcSite or IfcBuilding!");
            }

            ExporterIFC = exporterIFC;
            Transform trf = Transform.Identity;

            if (familyTrf != null)
            {
                XYZ origin, xDir, yDir, zDir;

                xDir = familyTrf.BasisX; yDir = familyTrf.BasisY; zDir = familyTrf.BasisZ; origin = familyTrf.Origin;

                trf = trf.Inverse;

                origin         = UnitUtil.ScaleLength(origin);
                LocalPlacement = ExporterUtil.CreateLocalPlacement(exporterIFC.GetFile(), null, origin, zDir, xDir);
            }
            else if (orientationTrf != null)
            {
                XYZ origin, xDir, yDir, zDir;

                xDir = orientationTrf.BasisX; yDir = orientationTrf.BasisY; zDir = orientationTrf.BasisZ; origin = orientationTrf.Origin;

                trf = orientationTrf.Inverse;

                origin         = UnitUtil.ScaleLength(origin);
                LocalPlacement = ExporterUtil.CreateLocalPlacement(exporterIFC.GetFile(), null, origin, zDir, xDir);
            }
            else
            {
                LocalPlacement = ExporterUtil.CreateLocalPlacement(exporterIFC.GetFile(), null, null, null, null);
            }

            ExporterIFC.PushTransform(trf);
            Offset    = 0.0;
            LevelId   = ElementId.InvalidElementId;
            LevelInfo = null;
        }
Ejemplo n.º 4
0
        void commonInit(ExporterIFC exporterIFC, Element elem, Transform familyTrf, Transform orientationTrf, ElementId overrideLevelId)
        {
            m_ExporterIFC = exporterIFC;

            overrideLevelId = overrideLevelId != null ? overrideLevelId : ElementId.InvalidElementId;

            Document  doc        = elem.Document;
            Element   hostElem   = elem;
            ElementId elemId     = elem.Id;
            ElementId newLevelId = overrideLevelId;

            bool useOverrideOrigin = false;
            XYZ  overrideOrigin    = XYZ.Zero;

            IDictionary <ElementId, IFCLevelInfo> levelInfos = exporterIFC.GetLevelInfos();

            if (overrideLevelId == ElementId.InvalidElementId)
            {
                if (familyTrf == null)
                {
                    // Override for CurveElems -- base level calculation on origin of sketch Plane.
                    if (elem is CurveElement)
                    {
                        SketchPlane sketchPlane = (elem as CurveElement).SketchPlane;
                        if (sketchPlane != null)
                        {
                            useOverrideOrigin = true;
                            overrideOrigin    = sketchPlane.GetPlane().Origin;
                        }
                    }
                    else
                    {
                        ElementId hostElemId = ElementId.InvalidElementId;
                        // a bit of a hack.  If we have a railing, we want it to have the same level base as its host Stair (because of
                        // the way the stairs place railings and stair flights together).
                        if (elem is Railing)
                        {
                            hostElemId = (elem as Railing).HostId;
                        }
                        else if (elem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Assemblies)
                        {
                            hostElemId = elem.AssemblyInstanceId;
                        }

                        if (hostElemId != ElementId.InvalidElementId)
                        {
                            hostElem = doc.GetElement(hostElemId);
                        }

                        newLevelId = hostElem != null ? hostElem.LevelId : ElementId.InvalidElementId;

                        if (newLevelId == ElementId.InvalidElementId)
                        {
                            ExporterIFCUtils.GetLevelIdByHeight(exporterIFC, hostElem);
                        }
                    }
                }

                // todo: store.
                double    bottomHeight  = double.MaxValue;
                ElementId bottomLevelId = ElementId.InvalidElementId;
                if ((newLevelId == ElementId.InvalidElementId) || orientationTrf != null)
                {
                    // if we have a trf, it might geometrically push the instance to a new level.  Check that case.
                    // actually, we should ALWAYS check the bbox vs the settings
                    newLevelId = ElementId.InvalidElementId;
                    XYZ  originToUse   = XYZ.Zero;
                    bool originIsValid = useOverrideOrigin;

                    if (useOverrideOrigin)
                    {
                        originToUse = overrideOrigin;
                    }
                    else
                    {
                        BoundingBoxXYZ bbox = elem.get_BoundingBox(null);
                        if (bbox != null)
                        {
                            originToUse   = bbox.Min;
                            originIsValid = true;
                        }
                        else if (hostElem.Id != elemId)
                        {
                            bbox = hostElem.get_BoundingBox(null);
                            if (bbox != null)
                            {
                                originToUse   = bbox.Min;
                                originIsValid = true;
                            }
                        }
                    }


                    // The original heuristic here was that the origin determined the level containment based on exact location:
                    // if the Z of the origin was higher than the current level but lower than the next level, it was contained
                    // on that level.
                    // However, in some places (e.g. Germany), the containment is thought to start just below the level, because floors
                    // are placed before the level, not above.  So we have made a small modification so that anything within
                    // 10cm of the 'next' level is on that level.

                    double leveExtension = 10.0 / (12.0 * 2.54);
                    foreach (KeyValuePair <ElementId, IFCLevelInfo> levelInfoPair in levelInfos)
                    {
                        // the cache contains levels from all the exported documents
                        // if the export is performed for a linked document, filter the levels that are not from this document
                        if (ExporterCacheManager.ExportOptionsCache.ExportingLink)
                        {
                            Element levelElem = doc.GetElement(levelInfoPair.Key);
                            if (levelElem == null || !(levelElem is Level))
                            {
                                continue;
                            }
                        }

                        IFCLevelInfo levelInfo   = levelInfoPair.Value;
                        double       startHeight = levelInfo.Elevation - leveExtension;
                        double       height      = levelInfo.DistanceToNextLevel;
                        bool         useHeight   = !MathUtil.IsAlmostZero(height);
                        double       endHeight   = startHeight + height;

                        if (originIsValid && ((originToUse[2] > (startHeight - MathUtil.Eps())) && (!useHeight || originToUse[2] < (endHeight - MathUtil.Eps()))))
                        {
                            newLevelId = levelInfoPair.Key;
                        }

                        if (startHeight < (bottomHeight + MathUtil.Eps()))
                        {
                            bottomLevelId = levelInfoPair.Key;
                            bottomHeight  = startHeight;
                        }
                    }
                }

                if (newLevelId == ElementId.InvalidElementId)
                {
                    newLevelId = bottomLevelId;
                }
            }

            m_LevelInfo = exporterIFC.GetLevelInfo(newLevelId);
            if (m_LevelInfo == null)
            {
                foreach (KeyValuePair <ElementId, IFCLevelInfo> levelInfoPair in levelInfos)
                {
                    // the cache contains levels from all the exported documents
                    // if the export is performed for a linked document, filter the levels that are not from this document
                    if (ExporterCacheManager.ExportOptionsCache.ExportingLink)
                    {
                        Element levelElem = doc.GetElement(levelInfoPair.Key);
                        if (levelElem == null || !(levelElem is Level))
                        {
                            continue;
                        }
                    }
                    m_LevelInfo = levelInfoPair.Value;
                    break;
                }
                //m_LevelInfo = levelInfos.Values.First<IFCLevelInfo>();
            }

            double       elevation      = m_LevelInfo.Elevation;
            IFCAnyHandle levelPlacement = m_LevelInfo.GetLocalPlacement();

            IFCFile file = exporterIFC.GetFile();

            Transform trf = Transform.Identity;

            if (familyTrf != null)
            {
                XYZ origin, xDir, yDir, zDir;

                xDir = familyTrf.BasisX; yDir = familyTrf.BasisY; zDir = familyTrf.BasisZ;

                Transform origOffsetTrf  = Transform.Identity;
                XYZ       negLevelOrigin = new XYZ(0, 0, -elevation);
                origOffsetTrf.Origin = negLevelOrigin;

                Transform newTrf = origOffsetTrf * familyTrf;

                origin = newTrf.Origin;

                trf.BasisX = xDir; trf.BasisY = yDir; trf.BasisZ = zDir;
                trf        = trf.Inverse;

                origin           = UnitUtil.ScaleLength(origin);
                m_LocalPlacement = ExporterUtil.CreateLocalPlacement(file, levelPlacement, origin, zDir, xDir);
            }
            else if (orientationTrf != null)
            {
                XYZ origin, xDir, yDir, zDir;

                xDir = orientationTrf.BasisX; yDir = orientationTrf.BasisY; zDir = orientationTrf.BasisZ; origin = orientationTrf.Origin;

                XYZ levelOrigin = new XYZ(0, 0, elevation);
                origin = origin - levelOrigin;

                trf.BasisX = xDir; trf.BasisY = yDir; trf.BasisZ = zDir; trf.Origin = origin;
                trf        = trf.Inverse;

                origin           = UnitUtil.ScaleLength(origin);
                m_LocalPlacement = ExporterUtil.CreateLocalPlacement(file, levelPlacement, origin, zDir, xDir);
            }
            else
            {
                m_LocalPlacement = ExporterUtil.CreateLocalPlacement(file, levelPlacement, null, null, null);
            }

            Transform origOffsetTrf2  = Transform.Identity;
            XYZ       negLevelOrigin2 = new XYZ(0, 0, -elevation);

            origOffsetTrf2.Origin = negLevelOrigin2;
            Transform newTrf2 = trf * origOffsetTrf2;

            m_ExporterIFC.PushTransform(newTrf2);
            m_Offset  = elevation;
            m_LevelId = newLevelId;
        }
      /// <summary>
      /// Attempt to determine the local placement of the element based on the element type and initial input.
      /// </summary>
      /// <param name="exporterIFC">The ExporterIFC class.</param>
      /// <param name="elem">The element being exported.</param>
      /// <param name="familyTrf">The optional family transform.</param>
      /// <param name="orientationTrf">The optional orientation of the element based on IFC standards or agreements.</param>
      /// <param name="overrideLevelId">The optional level to place the element, to be used instead of heuristics.</param>
      private void commonInit(ExporterIFC exporterIFC, Element elem, Transform familyTrf, Transform orientationTrf, ElementId overrideLevelId)
      {
         ExporterIFC = exporterIFC;

         // Convert null value to InvalidElementId.
         if (overrideLevelId == null)
            overrideLevelId = ElementId.InvalidElementId;

         Document doc = elem.Document;
         Element hostElem = elem;
         ElementId elemId = elem.Id;
         ElementId newLevelId = overrideLevelId;

         bool useOverrideOrigin = false;
         XYZ overrideOrigin = XYZ.Zero;

         IDictionary<ElementId, IFCLevelInfo> levelInfos = exporterIFC.GetLevelInfos();

         if (overrideLevelId == ElementId.InvalidElementId)
         {
            if (familyTrf == null)
            {
               // Override for CurveElems -- base level calculation on origin of sketch Plane.
               if (elem is CurveElement)
               {
                  SketchPlane sketchPlane = (elem as CurveElement).SketchPlane;
                  if (sketchPlane != null)
                  {
                     useOverrideOrigin = true;
                     overrideOrigin = sketchPlane.GetPlane().Origin;
                  }
               }
               else
               {
                  ElementId hostElemId = ElementId.InvalidElementId;
                  // a bit of a hack.  If we have a railing, we want it to have the same level base as its host Stair (because of
                  // the way the stairs place railings and stair flights together).
                  if (elem is Railing)
                  {
                     hostElemId = (elem as Railing).HostId;
                  }
                  else if (elem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Assemblies)
                  {
                     hostElemId = elem.AssemblyInstanceId;
                  }

                  if (hostElemId != ElementId.InvalidElementId)
                  {
                     hostElem = doc.GetElement(hostElemId);
                  }

                  newLevelId = hostElem != null ? hostElem.LevelId : ElementId.InvalidElementId;

                  if (newLevelId == ElementId.InvalidElementId)
                  {
                     ExporterIFCUtils.GetLevelIdByHeight(exporterIFC, hostElem);
                  }
               }
            }

            // todo: store.
            double bottomHeight = double.MaxValue;
            ElementId bottomLevelId = ElementId.InvalidElementId;
            if ((newLevelId == ElementId.InvalidElementId) || orientationTrf != null)
            {
               // if we have a trf, it might geometrically push the instance to a new level.  Check that case.
               // actually, we should ALWAYS check the bbox vs the settings
               newLevelId = ElementId.InvalidElementId;
               XYZ originToUse = XYZ.Zero;
               bool originIsValid = useOverrideOrigin;

               if (useOverrideOrigin)
               {
                  originToUse = overrideOrigin;
               }
               else
               {
                  BoundingBoxXYZ bbox = elem.get_BoundingBox(null);
                  if (bbox != null)
                  {
                     originToUse = bbox.Min;
                     originIsValid = true;
                  }
                  else if (hostElem.Id != elemId)
                  {
                     bbox = hostElem.get_BoundingBox(null);
                     if (bbox != null)
                     {
                        originToUse = bbox.Min;
                        originIsValid = true;
                     }
                  }
               }


               // The original heuristic here was that the origin determined the level containment based on exact location:
               // if the Z of the origin was higher than the current level but lower than the next level, it was contained
               // on that level.
               // However, in some places (e.g. Germany), the containment is thought to start just below the level, because floors
               // are placed before the level, not above.  So we have made a small modification so that anything within
               // 10cm of the 'next' level is on that level.

               double leveExtension = 10.0 / (12.0 * 2.54);
               foreach (KeyValuePair<ElementId, IFCLevelInfo> levelInfoPair in levelInfos)
               {
                  // the cache contains levels from all the exported documents
                  // if the export is performed for a linked document, filter the levels that are not from this document
                  if (ExporterCacheManager.ExportOptionsCache.ExportingLink)
                  {
                     Element levelElem = doc.GetElement(levelInfoPair.Key);
                     if (levelElem == null || !(levelElem is Level))
                        continue;
                  }

                  IFCLevelInfo levelInfo = levelInfoPair.Value;
                  double startHeight = levelInfo.Elevation - leveExtension;
                  double height = levelInfo.DistanceToNextLevel;
                  bool useHeight = !MathUtil.IsAlmostZero(height);
                  double endHeight = startHeight + height;

                  if (originIsValid && ((originToUse[2] > (startHeight - MathUtil.Eps())) && (!useHeight || originToUse[2] < (endHeight - MathUtil.Eps()))))
                  {
                     newLevelId = levelInfoPair.Key;
                  }

                  if (startHeight < (bottomHeight + MathUtil.Eps()))
                  {
                     bottomLevelId = levelInfoPair.Key;
                     bottomHeight = startHeight;
                  }
               }
            }

            if (newLevelId == ElementId.InvalidElementId)
               newLevelId = bottomLevelId;
         }

         LevelInfo = exporterIFC.GetLevelInfo(newLevelId);
         if (LevelInfo == null)
         {
            foreach (KeyValuePair<ElementId, IFCLevelInfo> levelInfoPair in levelInfos)
            {
               // the cache contains levels from all the exported documents
               // if the export is performed for a linked document, filter the levels that are not from this document
               if (ExporterCacheManager.ExportOptionsCache.ExportingLink)
               {
                  Element levelElem = doc.GetElement(levelInfoPair.Key);
                  if (levelElem == null || !(levelElem is Level))
                     continue;
               }
               LevelInfo = levelInfoPair.Value;
               break;
            }
            //LevelInfo = levelInfos.Values.First<IFCLevelInfo>();
         }

         double elevation = (LevelInfo != null) ? LevelInfo.Elevation : 0.0;
         IFCAnyHandle levelPlacement = (LevelInfo != null) ? LevelInfo.GetLocalPlacement() : null;

         IFCFile file = exporterIFC.GetFile();

         Transform trf = Transform.Identity;

         if (familyTrf != null)
         {
            XYZ origin, xDir, yDir, zDir;

            xDir = familyTrf.BasisX; yDir = familyTrf.BasisY; zDir = familyTrf.BasisZ;

            Transform origOffsetTrf = Transform.Identity;
            XYZ negLevelOrigin = new XYZ(0, 0, -elevation);
            origOffsetTrf.Origin = negLevelOrigin;

            Transform newTrf = origOffsetTrf * familyTrf;

            origin = newTrf.Origin;

            trf.BasisX = xDir; trf.BasisY = yDir; trf.BasisZ = zDir;
            trf = trf.Inverse;

            origin = UnitUtil.ScaleLength(origin);
            LocalPlacement = ExporterUtil.CreateLocalPlacement(file, levelPlacement, origin, zDir, xDir);
         }
         else if (orientationTrf != null)
         {
            XYZ origin, xDir, yDir, zDir;

            xDir = orientationTrf.BasisX; yDir = orientationTrf.BasisY; zDir = orientationTrf.BasisZ; origin = orientationTrf.Origin;

            XYZ levelOrigin = new XYZ(0, 0, elevation);
            origin = origin - levelOrigin;

            trf.BasisX = xDir; trf.BasisY = yDir; trf.BasisZ = zDir; trf.Origin = origin;
            trf = trf.Inverse;

            origin = UnitUtil.ScaleLength(origin);
            LocalPlacement = ExporterUtil.CreateLocalPlacement(file, levelPlacement, origin, zDir, xDir);
         }
         else
         {
            LocalPlacement = ExporterUtil.CreateLocalPlacement(file, levelPlacement, null, null, null);
         }

         Transform origOffsetTrf2 = Transform.Identity;
         XYZ negLevelOrigin2 = new XYZ(0, 0, -elevation);
         origOffsetTrf2.Origin = negLevelOrigin2;
         Transform newTrf2 = trf * origOffsetTrf2;

         ExporterIFC.PushTransform(newTrf2);
         Offset = elevation;
         LevelId = newLevelId;
      }