UNPKG

gisviewer-vue3-arcgis

Version:

在应用中引入私服的包, 项目根目录下 新建文件 .npmrc 在 .npmrc 中对包源进行配置:

300 lines (299 loc) 10.2 kB
import P from "axios"; import w from "ol/Feature"; import M from "ol/geom/LineString"; import C from "ol/geom/Point"; import F from "ol/geom/Polygon"; import y from "ol/layer/Vector"; import p from "ol/source/Vector"; import v from "ol/style/Circle"; import L from "ol/style/Fill"; import x from "ol/style/Icon"; import S from "ol/style/Stroke"; import d from "ol/style/Style"; import u from "./sumo-utils.mjs"; class E { constructor(o) { this.arrowCanvasCache = /* @__PURE__ */ new Map(), this.nodeStyleCache = /* @__PURE__ */ new Map(), this.trafficLightStyleCache = /* @__PURE__ */ new Map(), this.stopLineStyleCache = /* @__PURE__ */ new Map(), this.map = o, this.trafficLightImage = u.createTrafficLightImage(), this.setupLayers(); } setupLayers() { this.nodePolygonSource = new p(), this.nodePolygonLayer = new y({ source: this.nodePolygonSource }), this.nodePolygonLayer.set("id", "sumo-node-polygon-layer"), this.nodePolygonLayer.setStyle( new d({ fill: new L({ color: "#8B0000" }) }) ), this.map.addLayer(this.nodePolygonLayer), this.polygonLaneSource = new p(); const o = new y({ source: this.polygonLaneSource }); o.set("id", "sumo-polygon-lane-layer"); const t = new d({ fill: new L({ color: "#1a1a1a" }) }), r = new d({ fill: new L({ color: "#1a1a1a" }), stroke: new S({ color: "#ffffff", width: 1, lineDash: [5, 3] }) }); o.setStyle(() => (this.map.getView().getZoom() ?? 0) <= 16 ? t : r), this.map.addLayer(o), this.connectorLaneSource = new p(); const e = new y({ source: this.connectorLaneSource, style: [ // 底层:白色描边,宽度4,透明度0.6 new d({ stroke: new S({ color: [255, 255, 255, 0.6], width: 4, lineCap: "round", lineJoin: "round" }) }), // 上层:灰色中心线,宽度2 new d({ stroke: new S({ color: "#666666", width: 2, lineCap: "round", lineJoin: "round" }) }) ] }); e.set("id", "sumo-connector-lane-layer"), this.map.addLayer(e), this.stopLineSource = new p(); const c = new y({ source: this.stopLineSource }); c.setStyle((s) => { const l = s.get("color") || "#52C41A"; let n = this.stopLineStyleCache.get(l); return n || (n = new d({ stroke: new S({ color: l, width: 4, lineCap: "butt", lineJoin: "round" }) }), this.stopLineStyleCache.set(l, n)), n; }), c.set("id", "sumo-stop-line-layer"), this.map.addLayer(c), this.laneArrowSource = new p(); const a = new y({ source: this.laneArrowSource }); a.set("id", "sumo-lane-arrow-layer"), a.setStyle((s) => { if ((this.map.getView().getZoom() ?? 0) <= 17) return; const l = s.get("arrowType"), n = s.get("angle"); return new d({ image: new x({ img: this.getArrowCanvas(l), scale: this.getArrowScale(), // 图标朝上绘制,按方位角顺时针旋转对齐车道方向 rotation: n * Math.PI / 180, anchor: [0.5, 0.5] }) }); }), this.map.addLayer(a), this.nodePointSource = new p(), this.nodePointLayer = new y({ source: this.nodePointSource }), this.nodePointLayer.set("id", "sumo-node-point-layer"), this.nodePointLayer.setStyle((s) => this.getNodeStyle(s)), this.map.addLayer(this.nodePointLayer); } getNodeStyle(o) { const t = this.getNodeScale(), r = o.get("type"); if ((this.map.getView().getZoom() ?? 0) <= 15 && r === "traffic_light") return; const e = Math.round(t * 100) / 100, c = r === "traffic_light" ? this.trafficLightStyleCache : this.nodeStyleCache; let a = c.get(e); return a || (a = r === "traffic_light" ? new d({ image: new x({ img: this.trafficLightImage, scale: e }) }) : new d({ image: new v({ radius: 6, scale: e, fill: new L({ color: "#FF6B6B" }), stroke: new S({ color: "#ffffff", width: 1.5 }) }) }), c.set(e, a)), a; } /** * 显示 SUMO 路网数据 * @param params 显示 SUMO 路网数据的参数 * @param params.server 解析 SUMO 文件的后端服务地址 * @param params.file 待解析的 SUMO 文件 URL * @param params.options 可选,显示选项配置 * @param params.options.showJunctionPolygon 是否显示路口多边形 * @param params.options.showJunctionPoint 可选,是否显示路口点 * @param params.options.showJunctionLane 是否显示路口车道 * @param params.options.showRoadName 是否显示道路名称 * @param params.options.needZoom 可选,是否将地图缩放到显示所有车道,默认 true * @param params.selectedCallback 可选,要素选中时的回调函数 * @returns 显示结果,包含状态码和消息 */ async showSumoFromFile(o) { var h, f, m; let t; try { const i = await P.get(o.file, { responseType: "blob" }), g = new URL(o.file).pathname.split("/").pop() || "sumo"; t = new File([i.data], g, { type: i.data.type }); } catch (i) { return console.error("下载 SUMO 文件失败:", o.file, i), { status: -1, message: `下载 SUMO 文件失败:${(i == null ? void 0 : i.message) || "未知错误"}` }; } const r = new FormData(); r.append("file", t); let e; try { e = await P.post(o.server, r); } catch (i) { return console.error("解析 SUMO 文件失败:", o.server, i), { status: -1, message: `解析 SUMO 文件失败:${(i == null ? void 0 : i.message) || "未知错误"}` }; } if (e.status !== 200) return { status: -1, message: e.statusText || "error" }; this.nodePolygonLayer.setVisible( ((h = o.options) == null ? void 0 : h.showJunctionPolygon) !== !1 ), this.nodePointLayer.setVisible(((f = o.options) == null ? void 0 : f.showJunctionPoint) !== !1); const { nodes: c, edges: a, connections: s, trafficLights: l } = e.data; console.log(l), this.showNodes(c); const n = this.showEdges(a, s); if (((m = o.options) == null ? void 0 : m.needZoom) !== !1) { const i = u.getFeaturesExtent(n); i && this.map.getView().fit(i, { padding: [10, 10, 10, 10] }); } return { status: 0, message: "success" }; } /** * 显示 SUMO 节点 * @param nodes */ showNodes(o) { this.nodePointSource.clear(), this.nodePolygonSource.clear(); const t = [], r = []; for (const e of o) t.push( new w({ geometry: new C([e.x, e.y]), ...e }) ), !(e.type === "internal" || !e.shape || e.shape.length < 3) && r.push( new w({ geometry: new F([[...e.shape, e.shape[0]]]), ...e }) ); this.nodePointSource.addFeatures(t), this.nodePolygonSource.addFeatures(r); } /** * 显示 SUMO 边(车道、连接段、转向箭头) * @param edges * @returns */ showEdges(o, t) { const r = [], e = [], c = [], a = /* @__PURE__ */ new Map(); for (const s of t) { if (s.fromLane === void 0) continue; const l = `${s.from}_${s.fromLane}`, n = a.get(l) ?? []; if (s.dir) { const h = s.dir.toUpperCase(); n.includes(h) || n.push(h); } a.set(l, n); } for (const s of o) { if (!s.lanes || s.lanes.length === 0) continue; const l = s.isInternal ?? !1; for (const n of s.lanes) if (!(!n.shape || n.shape.length < 2)) if (l) { const h = `${s.id}_${n.index}`, i = !(a.get(h) ?? []).some((g) => g !== "S") ? n.shape : u.smoothShape(n.shape); r.push( new w({ geometry: new M(i), id: s.id, laneIndex: n.index }) ); } else { const h = u.laneToPolygon(n.shape, n.width); h.length > 0 && e.push( new w({ geometry: new F([h]), id: s.id, laneIndex: n.index }) ); const { point: f, angle: m } = u.getLaneArrowPosition(n.shape), i = `${s.id}_${n.index}`, g = a.get(i) ?? []; if (g.length > 0) { const A = u.determineArrowType(g); c.push( new w({ geometry: new C(f), id: i, angle: m, arrowType: A }) ); } } } return this.connectorLaneSource.addFeatures(r), this.polygonLaneSource.addFeatures(e), this.laneArrowSource.addFeatures(c), [...r, ...e]; } showStopLines(o, t) { } /** * 计算当前缩放级别下的箭头图标 scale: * zoom<=18 时为 0.035,zoom>=21 时为 0.6,中间线性插值 */ getArrowScale() { const o = this.map.getView().getZoom() ?? 14, t = 18, r = 21, e = 0.035, c = 0.6; if (o <= t) return e; if (o >= r) return c; const a = (o - t) / (r - t); return e + a * (c - e); } getNodeScale() { const o = this.map.getView().getZoom() ?? 14, t = 18, r = 21, e = 0.6, c = 1.2; if (o <= t) return e; if (o >= r) return c; const a = (o - t) / (r - t); return e + a * (c - e); } /** 获取(并按箭头类型缓存)箭头图标 canvas */ getArrowCanvas(o) { let t = this.arrowCanvasCache.get(o); return t || (t = u.createArrowIcon(o, 64), this.arrowCanvasCache.set(o, t)), t; } /** * 清空 SUMO 渲染结果 * 清空路口点、路口面、连接段车道、车道面图层的所有要素 * 但不清除图层本身,也不清除地图上其他图层的要素 */ clearSumo() { this.nodePointSource.clear(), this.nodePolygonSource.clear(), this.connectorLaneSource.clear(), this.polygonLaneSource.clear(), this.laneArrowSource.clear(); } } export { E as default };