X
返回顶部
当前位置: 首页> BIM资讯> BIM技术

revit几何信息如何存储?Revit 如何获取梁柱几何信息

发布:中文网小编3号 浏览:1276人 分享
发布于:2021-05-31 10:57

  Author-----Yen

Revit 如何获取梁柱几何信息

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

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

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

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

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

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

  6、判断两个点是否相同

  类GeometrySupport的主要逻辑:

public GeometrySupport(FamilyInstance element){         // get the geometry element of the ed 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 ed element.");         }    // 获取元素的轮廓信息         SweptProfile swProfile = element.GetSweptProfile();      // 判断路径是否是直线         if (swProfile == null || !(swProfile.GetDrivingCurve() is Line))         {            throw new Exception("The ed 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.");         }      }

  如何获取拉伸的轮廓信息:

  主要是根据传入的solid信息来获取拉伸面Face的信息

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

  如何从局部坐标系转换到全局坐标系:

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

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

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

  如何判断线是否垂直于面

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

  判断两个点是否相同

 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技术是未来的趋势,学习、了解掌握更多BIM前言技术是大势所趋,欢迎更多BIMer加入BIM中文网大家庭(http://www.wanbim.com),一起共同探讨学习BIM技术,了解BIM应用!