openlayers根据经纬度折线求出平行线
**思路:**现根据现有的经纬度数组在地图上画线,再根据折线求出对应的平行线;
需要解决的问题:
1:角度小的时候两条线段会产生交点,需要单独算出来,作为平行线的连接点
2:角度过大不会有交点,需要求出延长线的交点,作为平行线的连接点
前期准备
1:下载需要的组件
2:按需引入组件
import “ol/ol.css”;
import Map from ‘ol/Map’;
import LineString from ‘ol/geom/LineString’;
import * as olProj from ‘ol/proj’;
import View from ‘ol/View’;
import VectorSource from ‘ol/source/Vector’;
import VectorLayer from ‘ol/layer/Vector’;
import Feature from ‘ol/Feature’;
import { Style, Icon, Stroke } from ‘ol/style’;
import TileLayer from ‘ol/layer/Tile’;
import XYZ from ‘ol/source/XYZ’;
import Point from ‘ol/geom/Point’;
import { defaults as defaultControls, FullScreen, ScaleLine } from “ol/control”;
关键代码封装
方法一
// 折线平行线生成
createParallelLineString(lineString, offset, distance) {
// 创建空的平行线坐标数组
const parallelLineString = [];
const lastList = [];
// 遍历每一段线,创建平行线和相交点--整合所有点
for (let i = 0; i < lineString.length - 1; i++) {
const point1 = lineString[i];
const point2 = lineString[i + 1];
const bearing = turf.bearing(point1, point2);
// 创建平行线的两个点
const parallel1 = turf.destination(point1, offset, bearing - distance);
const parallel2 = turf.destination(point2, offset, bearing - distance);
parallelLineString.push(parallel1.geometry.coordinates);
parallelLineString.push(parallel2.geometry.coordinates);
}
// 根据平行后的所有点做线段两两相交的处理
if (parallelLineString.length > 4) {
// 第一个点不存在相交情况
lastList.push(parallelLineString[0]);
for (let i = 0; i < parallelLineString.length - 3; i++) {
// 只在线段起点做判断
if (i % 2 == 0) {
const point1_1 = parallelLineString[i];
const point1_2 = parallelLineString[i + 1];
const point2_1 = parallelLineString[i + 2];
const point2_2 = parallelLineString[i + 3];
const line1 = turf.lineString([point1_1, point1_2]);
const line2 = turf.lineString([point2_1, point2_2]);
const intersection = turf.lineIntersect(line1, line2);
//null 为没有相交点
if (intersection && intersection.features.length > 0) {
lastList.push(intersection.features[0].geometry.coordinates);
} else {
// 线段角度过大没有相交点,需要无限延长再求出相交点,两条线段的起点和终点作为输入参数(第二条线段起点和终点需要互换,否则没有交点)
let point = this.getIntersectionPoint([point1_1, point1_2], [point2_2, point2_1]);
lastList.push(point);
}
if (i == (parallelLineString.length - 4)) {
lastList.push(point2_2);
}
}
}
} else if (parallelLineString.length == 4) { //两条线
const point1_1 = parallelLineString[0];
const point1_2 = parallelLineString[1];
const point2_1 = parallelLineString[2];
const point2_2 = parallelLineString[3];
const line1 = turf.lineString([point1_1, point1_2]);
const line2 = turf.lineString([point2_1, point2_2]);
const intersection = turf.lineIntersect(line1, line2);
// 第一个点不存在相交情况
lastList.push(point1_1);
//null 为没有相交点
if (intersection && intersection.features.length > 0) {
lastList.push(intersection.features[0].geometry.coordinates);
} else {
// 线段角度过大没有相交点,需要无限延长再求出相交点,两条线段的起点和终点作为输入参数(第二条线段起点和终点需要互换,否则没有交点)
let point = this.getIntersectionPoint([point1_1, point1_2], [point2_2, point2_1]);
lastList.push(point);
}
lastList.push(point2_2);
} else if (parallelLineString.length == 2) { //一条线
lastList.push(parallelLineString[0]);
lastList.push(parallelLineString[1]);
}
return lastList;
},
方法二
// 延长线的相交点
getIntersectionPoint(line1, line2) {
// 计算两条线段的斜率和截距
const slope1 = (line1[1][1] - line1[0][1]) / (line1[1][0] - line1[0][0]);
const slope2 = (line2[1][1] - line2[0][1]) / (line2[1][0] - line2[0][0]);
const intercept1 = line1[0][1] - slope1 * line1[0][0];
const intercept2 = line2[0][1] - slope2 * line2[0][0];
// 如果两条线段斜率相等,则它们平行或者重合,无法计算交点
if (slope1 === slope2) {
return null;
}
// 计算两条线段在无限延长后的直线方程
const a = slope1 - slope2;
const b = intercept2 - intercept1;
const x = b / a;
const y = slope1 * x + intercept1;
// 返回交点的经纬度坐标
const lng = x;
const lat = y;
return [lng, lat];
},
第三调用
// arr为经纬度坐标数组,第二第三参数自定义数值,都是必传
list = this.createParallelLineString(arr, 0.02, -90);
此时list为平行后的直线坐标