Revit求直线与平面的交点

直线与平面的交点有两种情况,交点在平面内或平面外,计算出交点后需确定此交点是否在已知平面内。
代码如下:

/// <summary>
/// 计算直线与平面的交点
/// </summary>
/// <param name="point">直线上某一点</param>
/// <param name="direct">直线的方向</param>
/// <param name="planePoints">平面的顶点(最少需传入平面内三个点)</param>
/// <returns></returns>
private XYZ GetIntersectWithLineAndPlane(XYZ point, XYZ direct, List<XYZ> planePoints)
{
    //根据3点求平面法向量
    XYZ p1 = planePoints[0]; XYZ p2 = planePoints[1]; XYZ p3 = planePoints[2];
    ///v1(n1,n2,n3); 平面方程: na * (x – n1) + nb * (y – n2) + nc * (z – n3) = 0 ;
    double na = (p2.Y - p1.Y) * (p3.Z - p1.Z) - (p2.Z - p1.Z) * (p3.Y - p1.Y);
    double nb = (p2.Z - p1.Z) * (p3.X - p1.X) - (p2.X - p1.X) * (p3.Z - p1.Z);
    double nc = (p2.X - p1.X) * (p3.Y - p1.Y) - (p2.Y - p1.Y) * (p3.X - p1.X);
    XYZ planeNormal = new XYZ(na, nb, nc);
    //平面上任意一点
    XYZ planePoint = planePoints.Last();
    //使用点积计算交点距直线上点point的距离
    double d = (planePoint - point).DotProduct(planeNormal) / direct.Normalize().DotProduct(planeNormal);
    XYZ pointResult = d * direct.Normalize() + point;
    return pointResult;
}

/// <summary>
/// 确定坐标是否在平面内
/// </summary>
/// <param name="points">平面顶点坐标</param>
/// <param name="pos">已知坐标(传入上述方法计算得来的交点)</param>
/// <returns></returns>
private bool IsPosPlane(List<XYZ> points, XYZ pos)
{
    double RadianValue = 0;
    XYZ potOld = XYZ.Zero;
    XYZ potNew = XYZ.Zero;
    for (int i = 0; i < points.Count; i++)
    {
        if (i == 0)
        {
            potOld = points[i] - pos;
        }
        if (i == points.Count - 1)
        {
            potNew = points[0] - pos;
        }
        else
        {
            potNew = points[i + 1] - pos;
        }
        //夹角和
        RadianValue += Math.Acos(potOld.Normalize().DotProduct(potNew.Normalize())) * (180 / Math.PI);
        potOld = potNew;
    }
    //夹角的和等于360度表示在平面内
    if (Math.Abs(RadianValue - 360) < 0.1f)
    {
        return true;
    }
    else
    {
        return false;
    }
}
方法解析

代数方式
我们假设它们的交点为P,既然我们有一个平面,那么平面上面的一个点P0和平面的normal(垂直于平面的向量)我们是肯定知道的。
根据3D数学知识,(P-P₀) · normal = 0(公式一);(既然垂直,那么它们点乘肯定为0)。
对于这条直线,我们肯定知道直线上面的某一点L0和直线的方向L,那么 P = L₀ + dL(公式二),d是距离。
把公式二代入公式一,我们可以得到如下:
(L₀ + dL - P₀)· normal = 0;—> dL · normal + (L₀ - P₀) · normal = 0;
这样我们可以求出d值,然后我们就可以通过公式二求出P!

//point 是直线上面某一点,direct是直线的方向,planeNormal是垂直于平面的向量,planePoint是平面上的任意一点
public XYZ GetIntersectWithLineAndPlane(XYZ point,XYZ direct,XYZ planeNormal,XYZ planePoint)
{
    float d = (planePoint - point).DotProduct(planeNormal)/direct.DotProduct(planeNormal);
    return d * direct.Normalize() + point;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值