Revit FindColumns 找柱子-构件相交
FindColumns 找柱子-构件相交
级别:Advanced
This sample shows how to find columns that are embedded in walls with the Revit API method FindReferencesWithContextByDirection.
——如何通过Revit API的FindReferencesWithContextByDirection方法来找到嵌入到墙体的柱子
效果:
运行之前,例子里面可以看到各种墙体,有幕墙,复合墙体,一般墙体,弧形墙体
运行之后,这些与墙相交的柱子都被找出来了
核心判断的流程
取到wall的 LocationCurve 转换为 Curve,分为两种情况
|------------Line linear -> 一般是centerline中心线
CheckLinearWallForEmbeddedColumns(wall, locationCurve, (Line)wallCurve);主要的思路是根据墙的中心线,在两侧做两条ReferenceIntersector,这能返回所有与之相交的构件,其中有墙的话就是我们需要的。
// 核心函数
private void FindColumnsOnEitherSideOfWall(Wall wall, LocationCurve locationCurve, Curve wallCurve, double parameter, double elevation, double within)
{
// 求取ray射线的方向,其实就是线的切线
XYZ rayDirection = GetTangentAt(wallCurve, parameter);
// 获取墙的一个位置点,parameter取值为0的时候就是起始点的位置
XYZ wallLocation = wallCurve.Evaluate(parameter, true);
// 求取墙体两边偏移的向量
XYZ wallDelta = GetWallDeltaAt(wall, locationCurve, parameter);
// 一侧的起始点
XYZ rayStart = new XYZ(wallLocation.X + wallDelta.X, wallLocation.Y + wallDelta.Y, elevation);
FindColumnsByDirection(rayStart, rayDirection, within, wall);
// 另一侧的起始点
rayStart = new XYZ(wallLocation.X - wallDelta.X, wallLocation.Y - wallDelta.Y, elevation);
FindColumnsByDirection(rayStart, rayDirection, within, wall);
}
1)计算切线向量
private XYZ GetTangentAt(Curve curve, double parameter)
{
Transform t = curve.ComputeDerivatives(parameter, true);
// BasisX is the tangent vector of the curve.
// 返回的Transform中对应的BasisX是切线方向向量,并归一化
return t.BasisX.Normalize();
}
其他的返回值:
Origin 曲线的原点,前提是参数取0
BasisX:切线的向量
BasisY:二阶向量,加速度
参考:https://blog.csdn.net/niaxiapia/article/details/109127893
2)取得直线的原点位置坐标信息
// 此处parameter取0 就是起始点
XYZ wallLocation = wallCurve.Evaluate(parameter, true);
3)获取墙的delta插值段
求出墙的法线方向,并乘以墙厚和一小段扰动,等到偏移量
private XYZ GetWallDeltaAt(Wall wall, LocationCurve locationCurve, double parameter)
{
XYZ wallNormal = GetNormalToWallAt(wall, locationCurve, parameter);
double wallWidth = wall.Width;
// The LocationCurve is always the wall centerline, regardless of the setting for the wall Location Line.
// So the delta to place the ray just outside the wall extents is always 1/2 the wall width + a little extra.
// 根据向量偏移墙厚
XYZ wallDelta = new XYZ(wallNormal.X * wallWidth / 2 + WALL_EPSILON, wallNormal.Y * wallWidth / 2 + WALL_EPSILON, 0);
return wallDelta;
}
private XYZ GetNormalToWallAt(Wall wall, LocationCurve curve, double parameter)
{
Curve wallCurve = curve.Curve;
// There is no normal at a given point for a line. We need to get the normal based on the tangent of the wall location curve.
// 对一个直线上的点来说没有法线的说法,根据切线来求得法线
if (wallCurve is Line)
{
XYZ wallDirection = GetTangentAt(wallCurve, 0);
// modified yen 这部分有问题 之前SDK中只能判断坐标轴上情况,没考虑斜向的墙体
var ANGLE = Math.PI / 2;
XYZ wallNormal = new XYZ(
wallDirection.X * Math.Cos(ANGLE) - wallDirection.Y * Math.Sin(ANGLE),
wallDirection.X * Math.Sin(ANGLE) - wallDirection.Y * Math.Cos(ANGLE),
0);
// 之前SDK中的样例代码
//XYZ wallNormal = new XYZ(wallDirection.Y, wallDirection.X, 0);
return wallNormal;
}
else
{
Transform t = wallCurve.ComputeDerivatives(parameter, true);
// For non-linear curves, BasisY is the normal vector to the curve.
// 针对于非线性曲线来说,BasisY方向就是法线方向
return t.BasisY.Normalize();
}
}
4)构造碰撞线
private void FindColumnsByDirection(XYZ rayStart, XYZ rayDirection, double within, Wall wall)
{
ReferenceIntersector referenceIntersector = new ReferenceIntersector(m_view3D);
//指定起点及方向,返回的是直线上所有碰撞的构件
IList<ReferenceWithContext> intersectedReferences = referenceIntersector.Find(rayStart, rayDirection);
//再根据下面函数中的reference.Proximity判断距离,来取对应的柱
FindColumnsWithin(intersectedReferences, within, wall);
}
|------------------non-linear 以折线代弧的思想
CheckProfiledWallForEmbeddedColumns
private void CheckProfiledWallForEmbeddedColumns(Wall wall, LocationCurve locationCurve, Curve wallCurve)
{
double bottomHeight = GetElevationForRay(wall);
// Figure out the increment for the normalized parameter based on how long the wall is.
// 根据墙长来确定取得增量的步子
double parameterIncrement = WallIncrement / wallCurve.Length;
// Find columns within 2' of the start of the ray. Any smaller, and you run the risk of not finding a boundary
// face of the column within the target range.
// 射线的长度
double findColumnWithin = 2;
// check for columns along every WallIncrement fraction of the wall
// 将弧线转换为直线来判断,思路类似
for (double parameter = 0; parameter < 1.0; parameter += parameterIncrement)
{
FindColumnsOnEitherSideOfWall(wall, locationCurve, wallCurve, parameter, bottomHeight, findColumnWithin);
}
}
适用场景:
1、检测构件碰撞;
2、一定区域范围内的构件;
BIM树洞
做一个静谧的树洞君
用建筑的语言描述IT事物;
用IT的思维解决建筑问题;
共建BIM桥梁,聚合团队。
本学习分享资料不得用于商业用途,仅做学习交流!!如有侵权立即删除!!
-
微信公众号: BIM树洞
-
知乎专栏:BIM树洞
-
气氛组博客:http://www.31bim.com
-
BIM应用及咨询,CAD,Revit, OpenGL,图形开发交流,加Q群1083064224