Revit 如何获取梁柱几何信息

19 篇文章 0 订阅
16 篇文章 0 订阅

Revit 如何获取梁柱几何信息

这个例子来源于Revit SDK samples中的NewRebar例子,例子中有一个GeometrySupport类,用于判断你选择的梁或者柱是否是正方形,这个类涉及到的知识点非常多,非常有趣,主要可以概况为:

类GeometrySupport的主要逻辑:

public GeometrySupport(FamilyInstance element)
{
         // get the geometry element of the selected element
      // 获取元素的几何,判断是否存在几何元素
         Autodesk.Revit.DB.GeometryElement geoElement = element.get_Geometry(new Options());
         IEnumerator<GeometryObject> Objects = geoElement.GetEnumerator();
         if (null == geoElement || !Objects.MoveNext())
         {
            throw new Exception("Can't get the geometry of selected element.");
         }
    // 获取元素的轮廓信息
         SweptProfile swProfile = element.GetSweptProfile();
      // 判断路径是否是直线
         if (swProfile == null || !(swProfile.GetDrivingCurve() is Line))
         {
            throw new Exception("The selected element driving curve is not a line.");
         }

         // get the driving path and vector of the beam or column
         Line line = swProfile.GetDrivingCurve() as Line;
         if (null != line)
         {
            m_drivingLine = line;   // driving path 路径
             // 根据两个点求一个方向向量,末尾点减去初始点
            m_drivingVector = GeomUtil.SubXYZ(line.GetEndPoint(1), line.GetEndPoint(0));
            m_drivingLength = m_drivingVector.GetLength();
         }

         //get the geometry object
         //foreach (GeometryObject geoObject in geoElement.Objects)
         Objects.Reset();
         while (Objects.MoveNext())
         {
            GeometryObject geoObject = Objects.Current;

            //get the geometry instance which contains the geometry information
            GeoInstance instance = geoObject as GeoInstance;
            if (null != instance)
            {
               //foreach (GeometryObject o in instance.SymbolGeometry.Objects)
                // 都是从SymbolGeometry这个属性拿到具体的几何对象
               IEnumerator<GeometryObject> Objects1 = instance.SymbolGeometry.GetEnumerator();
               while (Objects1.MoveNext())
               {
                  GeometryObject o = Objects1.Current;

                  // get the solid of beam of column
                  Solid solid = o as Solid;

                  // do some checks.
                  if (null == solid)
                  {
                     continue;
                  }
                  if (0 == solid.Faces.Size || 0 == solid.Edges.Size)
                  {
                     continue;
                  }

                  m_solid = solid;
                  //get the transform value of instance
                   // 这个是GeometryObject的局部坐标系的转换矩阵
                  m_transform = instance.Transform;

                  // Get the swept profile curves information
                   // 获取轮廓信息
                  if (!GetSweptProfile(solid))
                  {
                     throw new Exception("Can't get the swept profile curves.");
                  }
                  break;
               }
            }

         }

         // do some checks about profile curves information
         if (null == m_edges)
         {
            throw new Exception("Can't get the geometry edge information.");
         }
      // 通过四个点个数来判断是否是方形
         if (4 != m_points.Count)
         {
            throw new Exception("The sample only works for rectangle beam or column.");
         }
      }

1、获取梁柱的轮廓面Face信息

主要是根据传入的solid信息来获取拉伸面Face的信息
Face sweptFace = GetSweptProfileFace(solid);


private Face GetSweptProfileFace(Solid solid)
{
         // Get a point on the swept profile from all points in solid
         Autodesk.Revit.DB.XYZ refPoint = new Autodesk.Revit.DB.XYZ();   // the point on swept profile
       // 遍历solid的每一条边edge
         foreach (Edge edge in solid.Edges)
         {
            // 如果判断edge是一条线,先离散,再判断点个数是否是2个
            List<XYZ> points = edge.Tessellate() as List<XYZ>;    //get end points of the edge
            if (2 != points.Count)                   // make sure all edges are lines
            {
               throw new Exception("Each edge should be a line.");
            }

            // get two points of the edge. All points in solid should be transformed first
            Autodesk.Revit.DB.XYZ first = Transform(points[0]);  // start point of edge
            Autodesk.Revit.DB.XYZ second = Transform(points[1]); // end point of edge

            // some edges should be paralleled with the driving line,
            // and the start point of that edge should be the wanted point
            Autodesk.Revit.DB.XYZ edgeVector = GeomUtil.SubXYZ(second, first);
            // 判断是否与路径的方向一致,进而取到轮廓面上的点
            if (GeomUtil.IsSameDirection(edgeVector, m_drivingVector))
            {
               refPoint = first;
               break;
            }
            if (GeomUtil.IsOppositeDirection(edgeVector, m_drivingVector))
            {
               refPoint = second;
               break;
            }
         }

         // Find swept profile(face)
         Face sweptFace = null;  // define the swept face
         foreach (Face face in solid.Faces)
         {
            if (null != sweptFace)
            {
               break;
            }
            // the swept face should be perpendicular with the driving line
             // 面是否垂直于路径线
            if (!GeomUtil.IsVertical(face, m_drivingLine, m_transform, null))
            {
               continue;
            }
            // use the point to get the swept face
            // 获取面的三角化后的顶点数据
            foreach (Autodesk.Revit.DB.XYZ point in face.Triangulate().Vertices)
            {
               Autodesk.Revit.DB.XYZ pnt = Transform(point); // all points in solid should be transformed
               // 判断点是否相同
                if (GeomUtil.IsEqual(refPoint, pnt))
               {
                  sweptFace = face;
                  break;
               }
            }
         }

         return sweptFace;
      }

2、如何判断一个edge是否是一条线

 // 如果判断edge是一条线,先离散,再判断点个数是否是2个
    List<XYZ> points = edge.Tessellate() as List<XYZ>;    //get end points of the edge
      if (2 != points.Count)                   // make sure all edges are lines
      {
         throw new Exception("Each edge should be a line.");
      }

3、如何进行局部全局的坐标变换

public static Autodesk.Revit.DB.XYZ TransformPoint(Autodesk.Revit.DB.XYZ point, Transform transform)
{
    //get the coordinate value in X, Y, Z axis
    // 要转换点的XYZ坐标值
    double x = point.X;
    double y = point.Y;
    double z = point.Z;

    //transform basis of the old coordinate system in the new coordinate system
    // API中没有具体说明get_Basis,猜想对应的是BasisX,BasisY,BasisZ,也就是矩阵的第1,2,3列元素
    Autodesk.Revit.DB.XYZ b0 = transform.get_Basis(0);
    Autodesk.Revit.DB.XYZ b1 = transform.get_Basis(1);
    Autodesk.Revit.DB.XYZ b2 = transform.get_Basis(2);
    Autodesk.Revit.DB.XYZ origin = transform.Origin;

    //transform the origin of the old coordinate system in the new coordinate system
    // 矩阵相乘,并考虑原点的偏移
    double xTemp = x * b0.X + y * b1.X + z * b2.X + origin.X;
    double yTemp = x * b0.Y + y * b1.Y + z * b2.Y + origin.Y;
    double zTemp = x * b0.Z + y * b1.Z + z * b2.Z + origin.Z;

    return new Autodesk.Revit.DB.XYZ (xTemp, yTemp, zTemp);
}

4、如何判断两个向量方向同向或者异向


public static bool IsSameDirection(Autodesk.Revit.DB.XYZ firstVec, Autodesk.Revit.DB.XYZ secondVec)
{
    // get the unit vector for two vectors
    // 获取单位向量
    Autodesk.Revit.DB.XYZ first = UnitVector(firstVec);
    Autodesk.Revit.DB.XYZ second = UnitVector(secondVec);

    // if the dot product of two unit vectors is equal to 1, return true
    // 点乘后是否等于1,等于1就是同向
    double dot = DotMatrix(first, second);
    return (IsEqual(dot, 1));
}

public static bool IsOppositeDirection(Autodesk.Revit.DB.XYZ firstVec, Autodesk.Revit.DB.XYZ secondVec)
{
    // get the unit vector for two vectors
    Autodesk.Revit.DB.XYZ first = UnitVector(firstVec);
    Autodesk.Revit.DB.XYZ second = UnitVector(secondVec);

    // if the dot product of two unit vectors is equal to -1, return true
    // 点乘后是否等于-1,等于-1就是异向
    double dot = DotMatrix(first, second);
    return (IsEqual(dot, -1));
}

5、如何判断一条线与面是否垂直

public static bool IsVertical(Face face, Line line, Transform faceTrans, Transform lineTrans)
{
         //get points which the face contains
      // 获取面的三角化的顶点坐标
          List<XYZ> points = face.Triangulate().Vertices as List<XYZ>;
         if (3 > points.Count)    // face's point number should be above 2
         {
            return false;
         }

         // get three points from the face points
         Autodesk.Revit.DB.XYZ first = points[0];
         Autodesk.Revit.DB.XYZ second = points[1];
         Autodesk.Revit.DB.XYZ third = points[2];

         // get start and end point of line
         Autodesk.Revit.DB.XYZ lineStart = line.GetEndPoint(0);
         Autodesk.Revit.DB.XYZ lineEnd = line.GetEndPoint(1);

         // transForm the three points if necessary
      // 坐标转换
         if (null != faceTrans)
         {
            first = TransformPoint(first, faceTrans);
            second = TransformPoint(second, faceTrans);
            third = TransformPoint(third, faceTrans);
         }

         // transform the start and end points if necessary
         if (null != lineTrans)
         {
            lineStart = TransformPoint(lineStart, lineTrans);
            lineEnd = TransformPoint(lineEnd, lineTrans);
         }

         // form two vectors from the face and a vector stand for the line
         // Use SubXYZ() method to get the vectors
         Autodesk.Revit.DB.XYZ vector1 = SubXYZ(first, second);    // first vector of face
         Autodesk.Revit.DB.XYZ vector2 = SubXYZ(first, third);     // second vector of face
         Autodesk.Revit.DB.XYZ vector3 = SubXYZ(lineStart, lineEnd);   // line vector

         // get two dot products of the face vectors and line vector
      // 计算面的两个向量和线的向量的点积
         double result1 = DotMatrix(vector1, vector3);
         double result2 = DotMatrix(vector2, vector3);

         // if two dot products are all zero, the line is perpendicular to the face
      // 如果两个点积是0的话,线就是垂直于面
         return (IsEqual(result1, 0) && IsEqual(result2, 0));
      }

6、判断两个点是否相同

 public static bool IsEqual(Autodesk.Revit.DB.XYZ first, Autodesk.Revit.DB.XYZ second)
{
     bool flag = true;
     // 每一个点都相同就是相等
     flag = flag && IsEqual(first.X, second.X);
     flag = flag && IsEqual(first.Y, second.Y);
     flag = flag && IsEqual(first.Z, second.Z);
     return flag;
 }

// 相等用减法,差值小于一个非常小的数
 public static bool IsEqual(double d1, double d2)
{
     //get the absolute value;
     double diff = Math.Abs(d1 - d2);
     //  const double Precision = 0.00001; 
     // precision when judge whether two doubles are equal
     return diff < Precision;
 }

BIM树洞

做一个静谧的树洞君

用建筑的语言描述IT事物;

用IT的思维解决建筑问题;

共建BIM桥梁,聚合团队。

本学习分享资料不得用于商业用途,仅做学习交流!!如有侵权立即删除!!


  • 微信公众号: BIM树洞
    在这里插入图片描述

  • 知乎专栏:BIM树洞

  • 气氛组博客:http://www.31bim.com

  • BIM应用及咨询,CAD,Revit, OpenGL,图形开发交流,加Q群1083064224

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值