Revit 如何获取梁柱几何信息
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