交叉路口定位算法/两条线要素相交获取交点

在B/S端的矢量地图中,道路都是一条条的线要素,而线要素是由点要素连接而成。这个过程被封装在地图服务器中如arcgis server或supermap iserver,其中连接为线要素的点要素是可以通过请求来获取的。

若要获取两条线要素的交点坐标,需要先将组成线要素的各个相邻的点坐标存储成一个数组var ptt1=[{x1,y1},{x2,y2},{x3,y3},.........],然后计算两个线要素上各自相邻的两个点组成的两个直线的交点,最后判断这个交点在不在这四个点各自组成的两条线段某一个上。(注意线段与直线的区别)

判断方法为:交点坐标是否在以两条线段为对角线的两个矩形区域内,当满足同时在两个矩形区域时,此交点即所求。

具体代码如下:

    //* @param {geometry} geometry_r1 第一条道路的图形
    //* @param {geometry} geometry_r2 第二条道路的图形(列表中的)
    function point(geometry_r1, geometry_r2) {
        //道路 pt1 未排序 点 数组 ptt1 排序点数组 
        var pt1 = new Array(); //先声明一维
      
        for (var i = 0; i < geometry_r1.geometry.components.length; i++) { //一维长度为i,i为变量,可以根据实际情况改变
            pt1[i] = new Array(); //声明二维,每一个一维数组里面的一个元素都是一个数组;
            pt1[i][0] = geometry_r1.geometry.components[i].x; //这里将变量初始化,我这边统一初始化为空,后面在用所需的值覆盖里面的值
            pt1[i][1] = geometry_r1.geometry.components[i].y;
        }
        var mapped = pt1.map(function (ar, i) {
            return {
                value: ar[0],
                index: i
            } //输出一个object对象,value为排序的数字的值,index为数字所在的数组在一维数组中的索引值
        })
        mapped.sort(function (a, b) {
            return a.value - b.value;
        })
        ptt1 = mapped.map(function (ar) {
            return pt1[ar.index];
        })
        //道路 pt2 未排序 点 数组 ptt2 排序点数组 
        var pt2 = new Array(); //先声明一维
        for (var i = 0; i < geometry_r2.geometry.components.length; i++) { //一维长度为i,i为变量,可以根据实际情况改变
            pt2[i] = new Array(); //声明二维,每一个一维数组里面的一个元素都是一个数组;
            pt2[i][0] = geometry_r2.geometry.components[i].x; //这里将变量初始化,我这边统一初始化为空,后面在用所需的值覆盖里面的值
            pt2[i][1] = geometry_r2.geometry.components[i].y;
        }
        console.log(pt2)
        var mapped2 = pt2.map(function (ar, i) {
            return {
                value: ar[0],
                index: i
            } //输出一个object对象,value为排序的数字的值,index为数字所在的数组在一维数组中的索引值
        })
        mapped2.sort(function (a, b) {
            return a.value - b.value;
        })
        ptt2 = mapped2.map(function (ar) {
            return pt2[ar.index];
        })
       
    }
    计算两条线交点
    //参数seg1、seg2{x1,x2,y1,y2}(x1<x2);options{pOrl:Boolean,tolerance:number}
    function pointxy(ptt1, ptt2) {
        for (var i = 0; i < ptt1.length-1; i++) {
            for (var j = 0; j < ptt2.length-1; j++) {
                var a1 = ptt1[i][1] - ptt1[i + 1][1];
                var b1 = ptt1[i + 1][0] - ptt1[i][0];
                var c1 = a1 * ptt1[i + 1][0] + b1 * ptt1[i + 1][1];
                //转换成一般式: Ax+By = C
                var a2 = ptt2[j][1] - ptt2[j + 1][1];
                var b2 = ptt2[j + 1][0] - ptt2[j][0];
                var c2 = a2 * ptt2[j + 1][0] + b2 * ptt2[j + 1][1];
                // 计算交点		
                var d = a1 * b2 - a2 * b1;
                // 当d==0时,两线平行
                if (d == 0) {
                    return false;
                } else {
                    var x = (b2 * c1 - b1 * c2) / d;
                    var y = (a1 * c2 - a2 * c1) / d;
                    // 检测交点是否在两条线段上
                    if ((isInBetween(ptt1[i + 1][0], x, ptt1[i][0]) || isInBetween(ptt1[i + 1][1], y, ptt1[i][1])) &&
                        (isInBetween(ptt2[j + 1][0], x, ptt2[j][0]) || isInBetween(ptt2[j + 1][1], y, ptt2[j][1]))) {

                        map.setCenter(new top.SuperMap.LonLat(x, y), 7)
                    }
                }
            }
            //如果b在a和c之间,返回true
            //当a==b或者b==c时排除结果,返回false
            function isInBetween(a, b, c) {
                // 如果b几乎等于a或c,返回false.为了避免浮点运行时两值几乎相等,但存在相差0.00000...0001的这种情况出现使用下面方式进行避免
                if ((Math.abs(a - b) > 0.000001 || Math.abs(b - c) > 0.000001) && ((b > a && b < c) || (b < a && b > c)) || (a==b||b==c)) {
                    return true;
                } else {
                    return false;
                }
            }
        }
    }

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值