其他分享
首页 > 其他分享> > Revit Openings 洞口

Revit Openings 洞口

作者:互联网

Revit Openings 洞口

Openings 洞口

级别:High

效果
Shows how to get geometry profile and properties of an opening and how to add x model lines to opening bounding box.

如何获取一个洞口的几何轮廓及属性,以及如何给洞口的包围盒增加若干模型线


提取洞口的轮廓信息:
在这里插入图片描述
添加包围盒信息,其中绿色线就是包围盒大小:
在这里插入图片描述

1、洞口的类型

SDK的sample中共展示了3类洞口类型,对应的宿主元素(host)情况如下:

OST_ShaftOpening Host-null

OST_FloorOpening Host-Floors

OST_SWallRectOpening Host-Walls

2、洞口的常用属性信息

private string m_name = "Opening"; //name of opening名称
private string m_elementId = ""; //Element Id of Opening  id号
private string m_hostElementId = ""; // Element Id of Opening,'s host 宿主元素id号
private string m_hostName = "Null"; //Name of host 宿主元素名称
private bool m_isShaft; //whether Opening is Shaft Opening 是否竖井洞口

3、包围盒信息

//get BoundingBox of Opening
BoundingBoxXYZ boxXYZ = m_opening.get_BoundingBox(m_revit.ActiveUIDocument.Document.ActiveView);

这个包围盒信息很简单,就是boundBoxXYZ.Max和 boundBoxXYZ.Min的信息

4、轮廓信息

获取轮廓信息主要是SDK中的GetProfile() 函数

private void GetProfile()
{
    // 获取轮廓的curves曲线
    CurveArray curveArray = m_opening.BoundaryCurves;
    // 第一种情况是否为空
    if (null != curveArray)
    {
        m_lines.Clear();
        foreach (Curve curve in curveArray)
        {
            // curve.Tessellate离散化成为一小段直线形式,格式为List<XYZ>
            List<XYZ> points = curve.Tessellate() as List<XYZ>;
            AddLine(points);
        }
        WireFrame wireFrameSketch = new WireFrame(new ReadOnlyCollection<Line3D>(m_lines));
        m_sketch = wireFrameSketch;
    }
    //第二种情况 就是方形
    else if (m_opening.IsRectBoundary)
    {
        //if opening profile is RectBoundary, 
        //just can get profile info from BoundaryRect Property
        m_lines.Clear();
        List<XYZ> boundRect = m_opening.BoundaryRect as List<XYZ>;
        // boundRect为两个角点 boundRect[0]/[1]
        List<XYZ> RectPoints = GetPoints(boundRect);
        AddLine(RectPoints);
        WireFrame wireFrameSketch = new WireFrame(new ReadOnlyCollection<Line3D>(m_lines));
        m_sketch = wireFrameSketch;
    }
    else
    {
        m_sketch = null;
    }
}

获取到轮廓之后,就是在二维的图形中根据XY坐标绘制出对应的线,这里不是重点。

5、核心的函数

|————Frame3DTo2D(line3Ds) // transform 3d point to 2d (if all points in the same plane)将三维的点投影到二维平面之上。这个函数的主要步骤是:

1)找到3个点形成2个向量求出面的法向量,对长度和角度的过小值的判断

2)根据法向量形成局部坐标系;UCS ucs = new UCS(origin, xAxis, yAxis);

3)根据坐标系进行line3d的坐标系转换Line3D tmp = ucs.GC2LC(line);

4)局部坐标下X,Y坐标就是投影坐标

|————RectangleF.Union(m_boundingBox, aLineSketch.BoundingBox);

​ 遍历全部包围盒求出最大包围盒

private void Frame3DTo2D(ReadOnlyCollection<Line3D> line3Ds)
{
    const double LengthEpsilon = 0.01;
    const double AngleEpsilon = 0.1;
    // find 3 points to form 2 lines whose length is bigger than LengthEpsilon 
    // and angle between them should be bigger than AngleEpsilon 
    // 找到2条线来构成一个平面
    Line3D line0 = line3Ds[0];
    Vector vector0 = new Vector();
    Vector vector1 = new Vector();
    // to find the first 2 points to form first line
    // 第一条线两个点
    int index = 0;
    for (int i = 1; i < line3Ds.Count; i++)
    {
        vector0 = line3Ds[i].StartPoint - line0.StartPoint;
        if (vector0.GetLength() > LengthEpsilon)
        {
            index = i;
            break;
        }
    }
    if (index == 0)
    {
        return;
    }
    // to find the last points to form the second line
    // 第二条线
    for (int j = index + 1; j < line3Ds.Count; j++)
    {
        vector1 = line3Ds[j].StartPoint - line3Ds[index].StartPoint;
        double angle = Vector.GetAngleOf2Vectors(vector0, vector1, true);
        if (vector1.GetLength() > LengthEpsilon && angle > AngleEpsilon)
        {
            break;
        }
    }

    // find the local coordinate system in which the profile of opening is horizontal
    // 构建局部坐标系,具体见下图
    //先求得vector0 和 vector1的法向量,投影面的法向量
    Vector zAxis = (vector0 & vector1).GetNormal();
    // 上一步求得的法向量再和Y向量求一个法向量 其实就是一个垂直于投影面的法向量
    Vector xAxis = zAxis & (new Vector(0.0, 1.0, 0.0));
    // 根据之前两个向量求第三个向量
    Vector yAxis = zAxis & xAxis;
    Vector origin = new Vector(0.0, 0.0, 0.0);
    // 构建局部坐标系
    UCS ucs = new UCS(origin, xAxis, yAxis);

    // transform all the 3D lines to UCS and create accordingly 2D lines
    bool isFirst = true;
    foreach (Line3D line in line3Ds)
    {
        // 进行坐标系的转换
        Line3D tmp = ucs.GC2LC(line);
        // 起始点
        PointF startPnt = new PointF((float)tmp.StartPoint.X, (float)tmp.StartPoint.Y);
        // 终点
        PointF endPnt = new PointF((float)tmp.EndPoint.X, (float)tmp.EndPoint.Y);
        // 形成二维的线
        Line2D line2D = new Line2D(startPnt, endPnt);
        LineSketch aLineSketch = new LineSketch(line2D);
        if (isFirst)
        {
            m_boundingBox = aLineSketch.BoundingBox;
            isFirst = false;
        }
        else
        {
            // 遍历全部包围盒求出最大包围盒
            m_boundingBox = RectangleF.Union(m_boundingBox, aLineSketch.BoundingBox);
        }
        m_objects.Add(aLineSketch);
    }
}

BIM树洞

做一个静谧的树洞君

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

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

共建BIM桥梁,聚合团队。

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


标签:Openings,opening,line3Ds,Vector,new,洞口,Revit,向量
来源: https://blog.csdn.net/weixin_44204198/article/details/114643052