コード例 #1
0
ファイル: LevelInfoCache.cs プロジェクト: zhoyq/revit-ifc
        /// <summary>
        /// Get the IFCLevelInfo corresponding to a level.
        /// </summary>
        /// <param name="exporterIFC">The exporter data object.</param>
        /// <param name="levelId">The level ElementId.</param>
        /// <returns>The IFCLevelInfo.</returns>
        public IFCLevelInfo GetLevelInfo(ExporterIFC exporterIFC, ElementId levelId)
        {
            IFCLevelInfo levelInfo = null;

            if (!exporterIFC.GetLevelInfos().TryGetValue(levelId, out levelInfo))
            {
                return(null);
            }
            return(levelInfo);
        }
コード例 #2
0
        /// <summary>
        ///    Gets the level info related to an offset of the element's local placement.
        /// </summary>
        /// <param name="offset">The vertical offset to the local placement.</param>
        /// <param name="scale">The linear scale.</param>
        /// <param name="pPlacementHnd">The handle to the new local placement.</param>
        /// <param name="pScaledOffsetFromNewLevel">The scaled offset from the new level.</param>
        /// <returns>The level info.</returns>
        public IFCLevelInfo GetOffsetLevelInfoAndHandle(double offset, double scale, Document document, out IFCAnyHandle placementHnd, out double scaledOffsetFromNewLevel)
        {
            placementHnd             = null;
            scaledOffsetFromNewLevel = 0;

            double newHeight = Offset + offset;

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

            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 = document.GetElement(levelInfoPair.Key);
                    if (levelElem == null || !(levelElem is Level))
                    {
                        continue;
                    }
                }

                IFCLevelInfo levelInfo   = levelInfoPair.Value;
                double       startHeight = levelInfo.Elevation;

                if (startHeight > newHeight + MathUtil.Eps())
                {
                    continue;
                }

                double height    = levelInfo.DistanceToNextLevel;
                bool   useHeight = !MathUtil.IsAlmostZero(height);

                if (!useHeight)
                {
                    scaledOffsetFromNewLevel = (newHeight - startHeight) * scale;
                    placementHnd             = levelInfo.GetLocalPlacement();
                    return(levelInfo);
                }

                double endHeight = startHeight + height;
                if (newHeight < endHeight - MathUtil.Eps())
                {
                    scaledOffsetFromNewLevel = (newHeight - startHeight) * scale;
                    placementHnd             = levelInfo.GetLocalPlacement();
                    return(levelInfo);
                }
            }

            return(null);
        }
コード例 #3
0
 /// <summary>
 /// Get the IFCLevelInfo corresponding to a level.
 /// </summary>
 /// <param name="exporterIFC">The exporter data object.</param>
 /// <param name="levelId">The level ElementId.</param>
 /// <returns>The IFCLevelInfo.</returns>
 public IFCLevelInfo GetLevelInfo(ExporterIFC exporterIFC, ElementId levelId)
 {
    return exporterIFC.GetLevelInfos()[levelId];
 }
コード例 #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;
        }
コード例 #5
0
      /// <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;
      }
コード例 #6
0
ファイル: LevelInfoCache.cs プロジェクト: whztt07/RevitIFC
 /// <summary>
 /// Get the IFCLevelInfo corresponding to a level.
 /// </summary>
 /// <param name="exporterIFC">
 /// The exporter data object.
 /// </param>
 /// <param name="levelId">
 /// The level ElementId.
 /// </param>
 /// <returns>
 /// The IFCLevelInfo.
 /// </returns>
 public IFCLevelInfo GetLevelInfo(ExporterIFC exporterIFC, ElementId levelId)
 {
     return(exporterIFC.GetLevelInfos()[levelId]);
 }
コード例 #7
0
        /// <summary>
        /// Gets offset of non-storey level.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="level">
        /// The level.
        /// </param>
        /// <returns>
        /// The offset.
        /// </returns>
        public static double GetNonStoryLevelOffsetIfAny(ExporterIFC exporterIFC, Level level)
        {
            if ((level == null) || !LevelHasViews(level))
                return 0.0;
            Document document = level.Document;

            const double veryNegativeHeight = -1000000000;
            double levelHeight = level.Elevation;
            double prevHeight = veryNegativeHeight;

            IDictionary<ElementId, IFCLevelInfo> storeys = exporterIFC.GetLevelInfos();
            foreach (KeyValuePair<ElementId, IFCLevelInfo> storey in storeys)
            {
                double currentHeight = storey.Value.Elevation;
                if (currentHeight < levelHeight + MathUtil.Eps() && currentHeight > prevHeight)
                    prevHeight = currentHeight;
            }

            if (prevHeight > veryNegativeHeight)
                return levelHeight - prevHeight;
            else
                return 0.0;
        }
コード例 #8
0
        /// <summary>
        /// Creates a list of ranges to split an element.
        /// </summary>
        /// <remarks>
        /// We may need to split an element (e.g. column) into parts by level.
        /// </remarks>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="exportType">
        /// The export type.
        /// </param>
        /// <param name="element">
        /// The element.
        /// </param>
        /// <param name="levels">
        /// The levels to split the element.
        /// </param>
        /// <param name="ranges">
        /// The ranges to split the element.
        /// </param>
        public static void CreateSplitLevelRangesForElement(ExporterIFC exporterIFC, IFCExportType exportType, Element elem,
            out IList<ElementId> levels, out IList<UV> ranges)
        {
            // If we are exporting a column, we may need to split it into parts by level.  Create a list of ranges.
            levels = new List<ElementId>();
            ranges = new List<UV>();
            double extension = GetLevelExtension();

            if ((exportType == IFCExportType.ExportColumnType) && (exporterIFC.WallAndColumnSplitting))
            {
                BoundingBoxXYZ boundingBox = elem.get_BoundingBox(null);
                {
                    UV zSpan = new UV(boundingBox.Min.Z, boundingBox.Max.Z);
                    if (zSpan.U < zSpan.V)
                    {
                        IDictionary<ElementId, IFCLevelInfo> storeys = exporterIFC.GetLevelInfos();
                        foreach (KeyValuePair<ElementId, IFCLevelInfo> storey in storeys)
                        {
                            IFCLevelInfo levelInfo = storey.Value;
                            // endBelowLevel 
                            if (zSpan.V < levelInfo.Elevation + extension)
                                continue;
                            // startAboveLevel
                            if ((!MathUtil.IsAlmostZero(levelInfo.DistanceToNextLevel)) &&
                               (zSpan.U > levelInfo.Elevation + levelInfo.DistanceToNextLevel - extension))
                                continue;

                            bool startBelowLevel = (zSpan.U < levelInfo.Elevation - extension);
                            bool endAboveLevel = ((!MathUtil.IsAlmostZero(levelInfo.DistanceToNextLevel)) &&
                               (zSpan.V > levelInfo.Elevation + levelInfo.DistanceToNextLevel + extension));
                            if (!startBelowLevel && !endAboveLevel)
                                break;

                            UV currentSpan = new UV(
                               startBelowLevel ? levelInfo.Elevation : zSpan.U,
                               endAboveLevel ? (levelInfo.Elevation + levelInfo.DistanceToNextLevel) : zSpan.V);
                            ranges.Add(currentSpan);
                            levels.Add(storey.Key);
                        }
                    }
                }
            }
        }