123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747 |
- import Point from "../Geometry/Point.js";
- import Road from "../Geometry/Road.js";
- import { dataService } from "./DataService.js";
- import { pointService } from "./PointService.js";
- import { edgeService } from "./EdgeService.js";
- import { mathUtil } from "../Util/MathUtil.js";
- export default class RoadService {
- constructor() {}
- create(startId, endId, vectorId) {
- let road = new Road(startId, endId, vectorId);
- dataService.addRoad(road);
- let startPoint = dataService.getPoint(startId);
- startPoint.setPointParent(road.vectorId, "start");
- let endPoint = dataService.getPoint(endId);
- endPoint.setPointParent(road.vectorId, "end");
- let edgePoints = mathUtil.RectangleVertex(startPoint, endPoint, road.width);
- let leftEdge = edgeService.create(
- edgePoints.leftEdgeStart,
- edgePoints.leftEdgeEnd,
- null,
- vectorId
- );
- dataService.addEdge(leftEdge);
- let rightEdge = edgeService.create(
- edgePoints.rightEdgeStart,
- edgePoints.rightEdgeEnd,
- null,
- vectorId
- );
- dataService.addEdge(rightEdge);
- road.setLeftEdge(leftEdge.vectorId);
- road.setRightEdge(rightEdge.vectorId);
- if (!vectorId) {
- leftEdge.setEdgeParent(road.vectorId);
- rightEdge.setEdgeParent(road.vectorId);
- }
- return road;
- }
- getMidLine(road) {
- let startPoint = dataService.getPoint(road.startId);
- let endPoint = dataService.getPoint(road.endId);
- let line = mathUtil.createLine1(startPoint, endPoint);
- return line;
- }
- // roadId对应墙的两个端点。尽量不要改
- // dir表示:保留start还是保留end(对应端点的parent不用变)
- splitRoad(roadId, pointId, dir) {
- const road = dataService.getRoad(roadId);
- const startPoint = dataService.getPoint(road.startId);
- const endPoint = dataService.getPoint(road.endId);
- const point = dataService.getPoint(pointId);
- if (
- mathUtil.getDistance(startPoint, point) < Constant.minAdsorbPix ||
- mathUtil.getDistance(endPoint, point) < Constant.minAdsorbPix
- ) {
- //console.error('splitRoad********************************************1')
- //return null
- }
- let newRoad = null;
- if (dir == "start") {
- // 第一步先断开链接
- delete endPoint.parent[roadId];
- newRoad = this.create(pointId, road.endId);
- //修改旧公路的end
- point.setPointParent(roadId, "end");
- } else if (dir == "end") {
- delete startPoint.parent[roadId];
- newRoad = this.create(road.start, pointId);
- //修改旧公路的start
- point.setPointParent(roadId, "start");
- }
- return newRoad.vectorId;
- }
- // roadId的两个端点分别是pointId1,pointId2,获取这个roadId
- getRoadId(pointId1, pointId2) {
- const point1 = dataService.getPoint(pointId1);
- const point2 = dataService.getPoint(pointId2);
- // 公路可能删除了。
- if (!point1 || !point2) {
- console.warn("pointId1或者pointId2不存在");
- return null;
- }
- if (pointId1 == pointId2) {
- console.warn("给的是同一个point");
- return null;
- }
- const parent1 = point1.parent;
- const parent2 = point2.parent;
- for (const key in parent1) {
- if (parent2.hasOwnProperty(key)) {
- return key;
- }
- }
- return null;
- }
- getNeighPoints(pointId, exceptPointId) {
- let points = [];
- let point = dataService.getPoint(pointId);
- for (let key in point.parent) {
- let road = dataService.getRoad(key);
- const otherPointId = road.getOtherPointId(pointId);
- if (exceptPointId && exceptPointId == otherPointId) {
- continue;
- }
- const otherPoint = dataService.getPoint(otherPointId);
- points.push(otherPoint);
- }
- return points;
- }
- // id1和id2不相交
- AngleForRoad(id1, id2) {
- const road1 = dataService.getRoad(id1);
- const road2 = dataService.getRoad(id2);
- if (
- road1 == null ||
- road2 == null ||
- typeof road1 === "undefined" ||
- typeof road2 === "undefined"
- ) {
- return null;
- }
- const start1 = dataService.getPoint(road1.startId);
- const end1 = dataService.getPoint(road1.endId);
- const start2 = dataService.getPoint(road2.startId);
- const end2 = dataService.getPoint(road2.endId);
- const distance1 = mathUtil.getDistance(start1, start2);
- const distance2 = mathUtil.getDistance(start1, end2);
- const distance3 = mathUtil.getDistance(end1, start2);
- const distance4 = mathUtil.getDistance(end1, end2);
- const minDistance = Math.min(distance1, distance2, distance3, distance4);
- const join = mathUtil.getIntersectionPoint2(start1, end1, start2, end2);
- if (join == null) {
- return Math.PI;
- }
- // start和start相交
- if (distance1 == minDistance) {
- end1.x += start2.x - start1.x;
- end1.y += start2.y - start1.y;
- return mathUtil.Angle(start2, end1, end2);
- } else if (distance2 == minDistance) {
- end1.x += end2.x - start1.x;
- end1.y += end2.y - start1.y;
- return mathUtil.Angle(end2, end1, start2);
- } else if (distance3 == minDistance) {
- start1.x += start2.x - end1.x;
- start1.y += start2.y - end1.y;
- return mathUtil.Angle(start2, start1, end2);
- } else if (distance4 == minDistance) {
- start1.x += end2.x - end1.x;
- start1.y += end2.y - end1.y;
- return mathUtil.Angle(end2, start1, start2);
- } else {
- console.error("AngleForRoad**************************1");
- return null;
- }
- }
- // 除了返回角度,还返回:id1对应的start,end和id2对应的另外一点组成的三角形,是顺时针还是逆时针
- AngleForRoad2(id1, id2) {
- const road1 = dataService.getRoad(id1);
- const road2 = dataService.getRoad(id2);
- if (
- road1 == null ||
- road2 == null ||
- typeof road1 === "undefined" ||
- typeof road2 === "undefined"
- ) {
- return null;
- }
- const start1 = dataService.getPoint(road1.startId);
- const end1 = dataService.getPoint(road1.endId);
- const start2 = dataService.getPoint(road2.startId);
- const end2 = dataService.getPoint(road2.endId);
- let angle = null;
- const points = [];
- points.push(start1);
- points.push(end1);
- if (road1.startId == road2.startId) {
- angle = mathUtil.Angle(start1, end1, end2);
- points.push(end2);
- } else if (road1.startId == road2.endId) {
- angle = mathUtil.Angle(start1, end1, start2);
- points.push(start2);
- } else if (road1.endId == road2.startId) {
- angle = mathUtil.Angle(end1, start1, end2);
- points[0] = end1;
- points[1] = start1;
- points.push(end2);
- } else if (road1.endId == road2.endId) {
- angle = mathUtil.Angle(end1, start1, start2);
- points[0] = end1;
- points[1] = start1;
- points.push(start2);
- }
- if (angle == null) {
- return null;
- } else {
- const flag = mathUtil.isClockwise(points);
- if (flag) {
- return {
- angle: angle,
- clockwise: 1,
- };
- } else {
- return {
- angle: angle,
- clockwise: 0,
- };
- }
- }
- }
- // id1的端点坐标不变
- AngleForRoad3(id1, id2) {
- const road1 = dataService.getRoad(id1);
- const road2 = dataService.getRoad(id2);
- if (
- road1 == null ||
- road2 == null ||
- typeof road1 === "undefined" ||
- typeof road2 === "undefined"
- ) {
- return null;
- }
- const start1 = dataService.getPoint(road1.startId);
- const end1 = dataService.getPoint(road1.endId);
- const start2 = dataService.getPoint(road2.startId);
- const end2 = dataService.getPoint(road2.endId);
- const distance1 = mathUtil.getDistance(start1, start2);
- const distance2 = mathUtil.getDistance(start1, end2);
- const distance3 = mathUtil.getDistance(end1, start2);
- const distance4 = mathUtil.getDistance(end1, end2);
- const minDistance = Math.min(distance1, distance2, distance3, distance4);
- const _start1 = {};
- const _end1 = {};
- // start和start相交
- if (distance1 == minDistance) {
- _end1.x = end1.x + start2.x - start1.x;
- _end1.y = end1.y + start2.y - start1.y;
- return mathUtil.Angle(start2, _end1, end2);
- } else if (distance2 == minDistance) {
- _end1.x = end1.x + end2.x - start1.x;
- _end1.y = end1.y + end2.y - start1.y;
- return mathUtil.Angle(end2, _end1, start2);
- } else if (distance3 == minDistance) {
- _start1.x = start1.x + start2.x - end1.x;
- _start1.y = start1.y + start2.y - end1.y;
- return mathUtil.Angle(start2, _start1, end2);
- } else if (distance4 == minDistance) {
- _start1.x = start1.x + end2.x - end1.x;
- _start1.y = start1.y + end2.y - end1.y;
- return mathUtil.Angle(end2, _start1, start2);
- } else {
- console.error(
- "RoadService.AngleForRoad3************************************1"
- );
- return null;
- }
- }
- // pointId的parent超过两个
- // 获取最小角度(顺时针和逆时针)
- // 可能缺顺时针或者逆时针,这时候对应的取最大角度的逆时针或者顺时针
- roadIdForMinAngle(pointId, roadId) {
- const point = dataService.getPoint(pointId);
- const parent = point.parent;
- let minAngle0 = null;
- let maxAngle0 = null; // 可能minAngle1不存在,这时候要找逆时针最大的
- let minAngle1 = null;
- let maxAngle1 = null;
- let minInfo0, minInfo1;
- let maxInfo0, maxInfo1;
- if (Object.keys(parent).length > 2) {
- for (const key in parent) {
- if (key == roadId) {
- continue;
- }
- const angleInfo = this.AngleForRoad2(roadId, key);
- if (minAngle1 == null && angleInfo.clockwise == 1) {
- minInfo1 = angleInfo;
- minInfo1.roadId = key;
- minAngle1 = angleInfo.angle;
- maxInfo1 = angleInfo;
- maxInfo1.roadId = key;
- maxAngle1 = angleInfo.angle;
- } else if (minAngle1 > angleInfo.angle && angleInfo.clockwise == 1) {
- minInfo1 = angleInfo;
- minInfo1.roadId = key;
- minAngle1 = angleInfo.angle;
- } else if (maxAngle1 < angleInfo.angle && angleInfo.clockwise == 1) {
- maxInfo1 = angleInfo;
- maxInfo1.roadId = key;
- maxAngle1 = angleInfo.angle;
- } else if (minAngle0 == null && angleInfo.clockwise == 0) {
- minInfo0 = angleInfo;
- minInfo0.roadId = key;
- minAngle0 = angleInfo.angle;
- maxInfo0 = angleInfo;
- maxInfo0.roadId = key;
- maxAngle0 = angleInfo.angle;
- } else if (minAngle0 > angleInfo.angle && angleInfo.clockwise == 0) {
- minInfo0 = angleInfo;
- minInfo0.roadId = key;
- minAngle0 = angleInfo.angle;
- } else if (maxAngle0 < angleInfo.angle && angleInfo.clockwise == 0) {
- maxInfo0 = angleInfo;
- maxInfo0.roadId = key;
- maxAngle0 = angleInfo.angle;
- }
- }
- const result = {
- min0: minInfo0,
- min1: minInfo1,
- };
- if (!result.min0) {
- result.min0 = maxInfo1;
- result.min0.angle = 360 - maxInfo1.angle;
- }
- if (!result.min1) {
- result.min1 = maxInfo0;
- result.min1.angle = 360 - maxInfo0.angle;
- }
- return result;
- } else {
- console.error(
- "roadIdForMinAngle*********************************************************"
- );
- return null;
- }
- }
- isRoadLink(roadId1, roadId2) {
- let road1 = dataService.getRoad(roadId1);
- let road2 = dataService.getRoad(roadId2);
- if (
- road1.startId == road2.startId ||
- road1.startId == road2.endId ||
- road1.endId == road2.startId ||
- road1.endId == road2.endId
- ) {
- return true;
- } else {
- return false;
- }
- }
- //point在road所在的线上,只是不确定是否在线段上
- isContain(road, point) {
- const startPoint = dataService.getPoint(road.startId);
- const endPoint = dataService.getPoint(road.endId);
- const minDis = road.width / 2;
- return mathUtil.isContainForSegment(point, startPoint, endPoint, minDis);
- }
- getDirction(pointId, roadId) {
- const road = dataService.getRoad(roadId);
- if (road.startId == pointId) {
- return "start";
- } else if (road.endId == pointId) {
- return "end";
- } else {
- console.error(
- "RoadService.getDirction*******************************************************************************************"
- );
- return null;
- }
- }
- subtraRoadFromIntersect(pointId, roadId) {
- const point = dataService.getPoint(pointId);
- const parent = point.getParent();
- const dir = this.getDirction(pointId, roadId);
- if (Object.keys(parent).length == 1) {
- return;
- }
- // 第一步先断开链接
- delete parent[roadId];
- // 第二步先新建端点
- const newPoint = pointService.create(point);
- // 第三步建立链接
- newPoint.setPointParent(roadId, dir);
- let road = dataService.getRoad(roadId);
- if (dir == "start") {
- road.startId = newPoint.vectorId;
- } else if (dir == "end") {
- road.endId = newPoint.vectorId;
- }
- }
- // pointId1移动到pointId2
- // 如果有一堵墙(roadId)的两头是pointId1和pointId2,那么这堵墙会被删除
- moveTo(pointId1, pointId2) {
- const roadId = this.getRoadId(pointId1, pointId2);
- // 不能重合
- let point1 = dataService.getPoint(pointId1);
- let point2 = dataService.getPoint(pointId2);
- const dx = point1.x - point2.x;
- const dy = point1.y - point2.y;
- let parent1 = point1.getParent();
- const parent2 = point2.getParent();
- //确保pointId1与pointId2重合后,墙的角度不能太小
- for (const roadId1 in parent1) {
- if (roadId1 == roadId) {
- continue;
- }
- const road1 = dataService.getRoad(roadId1);
- const otherPointId1 = road1.getOtherPointId(pointId1);
- const otherPoint1 = dataService.getPoint(otherPointId1);
- for (const roadId2 in parent2) {
- if (roadId2 == roadId) {
- continue;
- }
- const road2 = dataService.getRoad(roadId2);
- const otherPointId2 = road2.getOtherPointId(pointId2);
- const otherPoint2 = dataService.getPoint(otherPointId2);
- const angle = mathUtil.Angle(point2, otherPoint1, otherPoint2);
- if (Math.abs(angle) < (Constant.minAngle / 180) * Math.PI) {
- return false;
- }
- }
- }
- // pointId1,pointId2属于同一堵墙
- if (roadId != null) {
- dataService.deleteRoad(roadId);
- }
- point1 = dataService.getPoint(pointId1);
- point2 = dataService.getPoint(pointId2);
- if (!point1 || !point2) {
- return false;
- }
- //准备合并
- for (const roadId1 in parent1) {
- const road1 = dataService.getRoad(roadId1);
- const otherPointId = road1.getOtherPointId(pointId1);
- const _roadId = this.getRoadId(otherPointId, pointId2);
- if (_roadId != null) {
- return false;
- }
- // road1上pointId1被pointId2取代
- if (road1.startId == pointId1) {
- dataService.deletePoint(road1.startId, roadId1);
- road1.startId = pointId2;
- point2.setPointParent(roadId1, "start");
- } else if (road1.endId == pointId1) {
- dataService.deletePoint(road1.endId, roadId1);
- road1.endId = pointId2;
- point2.setPointParent(roadId1, "end");
- } else {
- console.error(
- "roadService.moveTo****************************************************"
- );
- }
- }
- return true;
- }
- AngleForRoad2(id1, id2) {
- let road1 = dataService.getRoad(id1);
- let road2 = dataService.getRoad(id2);
- if (
- road1 == null ||
- road2 == null ||
- typeof road1 == "undefined" ||
- typeof road2 == "undefined"
- ) {
- return null;
- }
- let start1 = dataService.getPoint(road1.startId);
- let end1 = dataService.getPoint(road1.endId);
- let start2 = dataService.getPoint(road2.startId);
- let end2 = dataService.getPoint(road2.endId);
- let angle = null;
- let points = [];
- points.push(start1);
- points.push(end1);
- if (road1.startId == road2.startId) {
- angle = mathUtil.Angle(start1, end1, end2);
- points.push(end2);
- } else if (road1.startId == road2.endId) {
- angle = mathUtil.Angle(start1, end1, start2);
- points.push(start2);
- } else if (road1.endId == road2.startId) {
- angle = mathUtil.Angle(end1, start1, end2);
- points[0] = end1;
- points[1] = start1;
- points.push(end2);
- } else if (road1.endId == road2.endId) {
- angle = mathUtil.Angle(end1, start1, start2);
- points[0] = end1;
- points[1] = start1;
- points.push(start2);
- }
- if (angle == null) {
- return null;
- } else {
- let flag = mathUtil.isClockwise(points);
- if (flag) {
- return {
- angle: angle,
- clockwise: 1,
- };
- } else {
- return {
- angle: angle,
- clockwise: 0,
- };
- }
- }
- }
- //pointId的parent超过两个
- //获取最小角度(顺时针和逆时针)
- //可能缺顺时针或者逆时针,这时候对应的取最大角度的逆时针或者顺时针
- roadIdForMinAngle(pointId, roadId) {
- let point = dataService.getPoint(pointId);
- let parent = point.getParent();
- let minAngle0 = null;
- let maxAngle0 = null; //可能minAngle1不存在,这时候要找逆时针最大的
- let minAngle1 = null;
- let maxAngle1 = null;
- let minInfo0, minInfo1;
- let maxInfo0, maxInfo1;
- if (Object.keys(parent).length > 2) {
- for (let key in parent) {
- if (key == roadId) {
- continue;
- }
- let angleInfo = this.AngleForRoad2(roadId, key);
- if (minAngle1 == null && angleInfo.clockwise == 1) {
- minInfo1 = angleInfo;
- minInfo1.roadId = key;
- minAngle1 = angleInfo.angle;
- maxInfo1 = angleInfo;
- maxInfo1.roadId = key;
- maxAngle1 = angleInfo.angle;
- } else if (minAngle1 > angleInfo.angle && angleInfo.clockwise == 1) {
- minInfo1 = angleInfo;
- minInfo1.roadId = key;
- minAngle1 = angleInfo.angle;
- } else if (maxAngle1 < angleInfo.angle && angleInfo.clockwise == 1) {
- maxInfo1 = angleInfo;
- maxInfo1.roadId = key;
- maxAngle1 = angleInfo.angle;
- } else if (minAngle0 == null && angleInfo.clockwise == 0) {
- minInfo0 = angleInfo;
- minInfo0.roadId = key;
- minAngle0 = angleInfo.angle;
- maxInfo0 = angleInfo;
- maxInfo0.roadId = key;
- maxAngle0 = angleInfo.angle;
- } else if (minAngle0 > angleInfo.angle && angleInfo.clockwise == 0) {
- minInfo0 = angleInfo;
- minInfo0.roadId = key;
- minAngle0 = angleInfo.angle;
- } else if (maxAngle0 < angleInfo.angle && angleInfo.clockwise == 0) {
- maxInfo0 = angleInfo;
- maxInfo0.roadId = key;
- maxAngle0 = angleInfo.angle;
- }
- }
- let result = {
- min0: minInfo0,
- min1: minInfo1,
- };
- if (!result.min0) {
- result.min0 = maxInfo1;
- result.min0.angle = 360 - maxInfo1.angle;
- }
- if (!result.min1) {
- result.min1 = maxInfo0;
- result.min1.angle = 360 - maxInfo0.angle;
- }
- return result;
- } else {
- console.error(
- "roadIdForMinAngle*********************************************************"
- );
- return null;
- }
- }
- getDirction(pointId, roadId) {
- let road = dataService.getRoad(roadId);
- if (road.startId == pointId) {
- return "start";
- } else if (road.endId == pointId) {
- return "end";
- } else {
- console.error(
- "getDirction*******************************************************************************************"
- );
- return null;
- }
- }
- //pointId的parent超过两个
- //获取最小角度(顺时针和逆时针)
- //可能缺顺时针或者逆时针,这时候对应的取最大角度的逆时针或者顺时针
- roadIdForMinAngle(pointId, roadId) {
- let point = dataService.getPoint(pointId);
- let parent = point.parent;
- let minAngle0 = null;
- let maxAngle0 = null; //可能minAngle1不存在,这时候要找逆时针最大的
- let minAngle1 = null;
- let maxAngle1 = null;
- let minInfo0, minInfo1;
- let maxInfo0, maxInfo1;
- if (Object.keys(parent).length > 2) {
- for (let key in parent) {
- if (key == roadId) {
- continue;
- }
- let angleInfo = this.AngleForRoad2(roadId, key);
- if (minAngle1 == null && angleInfo.clockwise == 1) {
- minInfo1 = angleInfo;
- minInfo1.roadId = key;
- minAngle1 = angleInfo.angle;
- maxInfo1 = angleInfo;
- maxInfo1.roadId = key;
- maxAngle1 = angleInfo.angle;
- } else if (minAngle1 > angleInfo.angle && angleInfo.clockwise == 1) {
- minInfo1 = angleInfo;
- minInfo1.roadId = key;
- minAngle1 = angleInfo.angle;
- } else if (maxAngle1 < angleInfo.angle && angleInfo.clockwise == 1) {
- maxInfo1 = angleInfo;
- maxInfo1.roadId = key;
- maxAngle1 = angleInfo.angle;
- } else if (minAngle0 == null && angleInfo.clockwise == 0) {
- minInfo0 = angleInfo;
- minInfo0.roadId = key;
- minAngle0 = angleInfo.angle;
- maxInfo0 = angleInfo;
- maxInfo0.roadId = key;
- maxAngle0 = angleInfo.angle;
- } else if (minAngle0 > angleInfo.angle && angleInfo.clockwise == 0) {
- minInfo0 = angleInfo;
- minInfo0.roadId = key;
- minAngle0 = angleInfo.angle;
- } else if (maxAngle0 < angleInfo.angle && angleInfo.clockwise == 0) {
- maxInfo0 = angleInfo;
- maxInfo0.roadId = key;
- maxAngle0 = angleInfo.angle;
- }
- }
- let result = {
- min0: minInfo0,
- min1: minInfo1,
- };
- if (!result.min0) {
- result.min0 = maxInfo1;
- result.min0.angle = 360 - maxInfo1.angle;
- }
- if (!result.min1) {
- result.min1 = maxInfo0;
- result.min1.angle = 360 - maxInfo0.angle;
- }
- return result;
- } else {
- console.error(
- "roadIdForMinAngle*********************************************************"
- );
- return null;
- }
- }
- }
- const roadService = new RoadService();
- export { roadService };
|