Revit FindColumns 找柱子-构件相交

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

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

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Revit API中,获取柱子的所有面需要经过以下步骤: 1. 首先,通过Revit API中的过滤器,使用ElementClassFilter或ElementCategoryFilter来获取所有柱子元素的列表。 2. 遍历柱子元素列表,使用IsElementCategorized为真来判断柱子是不是一个实例化的元素。如果柱子是实例化的元素,使用Instance.GetGeometryObjectFromReference方法将其转换成几何对象。 3. 将几何对象转换成Solid类型,通过Solid.Faces属性获取所有的面。使用Solid.Faces.Size方法获取面的数量。 4. 遍历面的集合,使用Face.ComputeNormal方法获取每个面的法线,使用Face.Evaluate方法获取面的顶点坐标。 5. 将每个面的顶点坐标和法线存储在集合中,并依次遍历输出。 以下是一个示例代码来获取柱子的所有面: ```csharp UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Document doc = uidoc.Document; // 定义过滤器获取所有柱子元素 FilteredElementCollector collector = new FilteredElementCollector(doc); collector.OfCategory(BuiltInCategory.OST_Columns); collector.OfClass(typeof(FamilyInstance)); List<Element> columnElements = collector.ToElements().ToList(); foreach (Element element in columnElements) { if (element is FamilyInstance instance) { // 将柱子元素转换为几何对象 Options options = new Options(); options.ComputeReferences = true; options.View = uidoc.ActiveView; GeometryElement geometryElement = instance.get_Geometry(options); foreach (GeometryObject geometryObject in geometryElement) { if (geometryObject is Solid solid) { // 获取所有面 foreach (Face face in solid.Faces) { // 获取面的法线和顶点坐标 XYZ normal = face.ComputeNormal(new UV()); IList<XYZ> vertices = face.Triangulate().Vertices; // 输出顶点坐标和法线 foreach (XYZ vertex in vertices) { // 输出顶点坐标 TaskDialog.Show("Revit", "顶点坐标:" + vertex.ToString()); } // 输出法线 TaskDialog.Show("Revit", "法线:" + normal.ToString()); } } } } } ``` 以上就是使用Revit API获取柱子的所有面的方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值