zoukankan      html  css  js  c++  java
  • 直线投影到三角网曲面上

    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;
    }
    
  • 相关阅读:
    [原]【实例化需求】1.FitNesse工具应用简介
    [原][问题解决]常见问题的5种解决办法(由Jenkins问题解决谈起)
    [原][自动化测试]Robot Framework Selenium基本使用
    [原]好玩的Linux,关于时间cal命令
    [原][问题解决]Romote Control 图形化界面显示问题解决办法
    【SBE】由需求管理谈起
    [Robot]关于robot的几个学习网站
    coolite中在UserControl中使用Coolite.AjaxMethods方法
    javascript实现页面加载进度条(转)
    coolite 在前台更新Window中控件的值
  • 原文地址:https://www.cnblogs.com/myzw/p/13906896.html
Copyright © 2011-2022 走看看