直線投影到三角網曲面上


civil 3d中要素線及放坡相關的.net api基本沒有開放,

com api也只有要素線有有限的一些功能,

有時需要要素線到曲面的投影線,

這把我卡了很長時間。

 

今天想到了曲面有獲取點到曲面投影的功能,

所以利用這個功能,

實現了求取直線到曲面投影的方法。

基本的思路是:

直線起點投影到曲面,

通過投影點獲取到相應的三角形,

之后直線投影到三角形所在的平面,

再求投影線與三角形的交點,

通過交線找到三角形的邊(有待優化),

通過三角形的邊找到下一個三角形,

循環操作,

找出每一交點,

連成三維多段線。

主要的代碼如下,

還不完善,

有需要的朋友可以借鑒一下,

拿去繼續優化。

/// <summary>
/// 2020年10月31日17:00:18
/// 直線投影到三角網曲面
/// </summary>
/// <param name="l">直線</param>
/// <param name="sur">曲面</param>
/// <param name="direction">投影方向</param>
/// <returns>投影三維多段線</returns>
public static Polyline3d ProjectToTinsurface(this Line l, TinSurface sur, Vector3d direction)
{
    Point3dCollection pts = new Point3dCollection();
    Point3d projectedPt01 = sur.GetIntersectionPoint(l.StartPoint, direction);
    Point3d projectedPt02 = sur.GetIntersectionPoint(l.EndPoint, direction);

    pts.Add(projectedPt01);

    var seedTriangle = sur.FindTriangleAtXY(projectedPt01.X, projectedPt01.Y);
    var projectedLine = l.GetProjectedCurve(seedTriangle.Plane(), direction) as Line;
    var intersectPts = projectedLine.GetIntersectPoints(seedTriangle);
    Point3d seedPt = new Point3d();
    // 如果三角形很大,直線很短,兩個點投影后落到一個三角形內時,
    // 交點數為0,需要直接跳過
    // 交點數大於0時,說明與三角形的邊有交點
    if (intersectPts.Count > 0)
    {
        foreach (Point3d pt in intersectPts)
        {
            if (!pts.Contains(pt))
            {
                seedPt = pt;
                pts.Add(pt);
            }
        }
        // 執行do while循環,依次選擇相鄰的三角形,依次查找交點
        do
        {
            // 交點位置的邊
            // 這個應該有優化的空間,在求交點是記錄邊,
            // 之后傳遞到這里,而不是再用點查找一遍
            var edge = sur.FindEdgeAtXY(seedPt.X, seedPt.Y);
            // 選擇下一個三角形
            if (edge.Triangle1.GetHashCode() != seedTriangle.GetHashCode())
            {
                seedTriangle = edge.Triangle1;
            }
            else
            {
                seedTriangle = edge.Triangle2;
            }
            // 投影直線到三角形上
            projectedLine = l.GetProjectedCurve(seedTriangle.Plane(), direction) as Line;
            // 獲取投影線與三角形的交點
            intersectPts = projectedLine.GetIntersectPoints(seedTriangle);
            // 如果交點不在交點集合中,添加到集合
            foreach (Point3d pt in intersectPts)
            {
                if (!pts.Contains(pt))
                {
                    seedPt = pt;
                    pts.Add(pt);
                }
            }
        } while (intersectPts.Count > 1);
    }
    // 添加終點投影點到集合中
    pts.Add(projectedPt02);
    // 生成三維多段線
    return new Polyline3d(Poly3dType.SimplePoly, pts, false);
}
/// <summary>
/// 2020年10月31日17:07:38
/// 三角形平面
/// 獲取曲面三角形所在的平面
/// </summary>
/// <param name="triangle">三角形</param>
/// <returns>平面</returns>
public static Plane Plane(this TinSurfaceTriangle triangle)
{
    Point3d point1 = triangle.Vertex1.Location;
    Point3d point2 = triangle.Vertex2.Location;
    Point3d point3 = triangle.Vertex3.Location;

    return new Plane(
       point1,
       point1.GetVectorTo(point2),
       point1.GetVectorTo(point3));
}
/// <summary>
/// 2020年10月31日17:08:49
/// 獲取直線與三角形的交點集
/// </summary>
/// <param name="l"></param>
/// <param name="triangle"></param>
/// <returns></returns>
public static Point3dCollection GetIntersectPoints(this Line l, TinSurfaceTriangle triangle)
{
    Point3d point1 = triangle.Vertex1.Location;
    Point3d point2 = triangle.Vertex2.Location;
    Point3d point3 = triangle.Vertex3.Location;

    Point3dCollection result = new Point3dCollection();

    l.IntersectWith(new Line(point1, point2), Intersect.OnBothOperands, result, new IntPtr(0), new IntPtr(0));
    l.IntersectWith(new Line(point1, point3), Intersect.OnBothOperands, result, new IntPtr(0), new IntPtr(0));
    l.IntersectWith(new Line(point3, point2), Intersect.OnBothOperands, result, new IntPtr(0), new IntPtr(0));


    return result;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM