UNPKG

@orca-fe/x-map

Version:
187 lines (179 loc) 7.64 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const three_1 = require("three"); const LineMaterial_1 = require("three/examples/jsm/lines/LineMaterial"); const LineGeometry_1 = require("three/examples/jsm/lines/LineGeometry"); const Line2_1 = require("three/examples/jsm/lines/Line2"); const turf_1 = require("@turf/turf"); const coord_1 = require("../../utils/coord"); const ThreeObject_1 = tslib_1.__importDefault(require("./ThreeObject")); // Polygon | MultiPolygon -> MultiPolygon const geoJson2multiPolygon = (geoJson) => { const multiPolygon = { type: 'MultiPolygon', coordinates: [], }; if (geoJson.type === 'Polygon') { multiPolygon.coordinates = [geoJson.coordinates]; } else { multiPolygon.coordinates = geoJson.coordinates; } return multiPolygon; }; // 合成多个holes,并返回在范围内部分 const formatPolygonJson = (polygonJson) => { var _a; const { coordinates } = polygonJson; const shapePoint = [...coordinates]; const holes = shapePoint.splice(1).map(i => (0, turf_1.polygon)([i])); if (holes.length === 0) { return polygonJson; } let [unionHoles] = holes; if (holes.length > 1) { unionHoles = holes.reduce((prev, next) => { const res = (0, turf_1.union)(prev, next); if (res) return res; return prev; }); } return (_a = (0, turf_1.difference)((0, turf_1.polygon)(shapePoint), unionHoles)) === null || _a === void 0 ? void 0 : _a.geometry; }; class PolygonObject extends ThreeObject_1.default { constructor(options = {}) { var _a; super(options); this.object3D = new three_1.Mesh(); const { polygonGeoJson, fill = { color: 0x33ccff, opacity: 0.1 }, border = false, polygonMaterialParameters, } = options; this.polygonGeoJson = polygonGeoJson; const color = new three_1.Color(fill.color); this.polygonMaterial = new three_1.RawShaderMaterial(Object.assign({ uniforms: { baseColor: { value: [color.r, color.g, color.b, (_a = fill.opacity) !== null && _a !== void 0 ? _a : 1] }, }, vertexShader: ` precision mediump float; precision mediump int; uniform mat4 modelViewMatrix; // optional uniform mat4 projectionMatrix; // optional attribute vec3 position; attribute vec4 color; varying vec3 vPosition; void main() { vPosition = position; gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); } `, fragmentShader: ` precision mediump float; precision mediump int; uniform vec4 baseColor; varying vec3 vPosition; void main() { gl_FragColor = baseColor; } `, side: three_1.DoubleSide, depthWrite: false, depthTest: false, transparent: true }, polygonMaterialParameters)); if (border) { this.lineMaterial = new LineMaterial_1.LineMaterial(Object.assign({ transparent: true }, border)); } this.object3D.position.set(0, 0, this.z); } // 创建一个常规(不带孔)的shape及line createNormalPolygonShape(polygonJson) { var _a; const shape = new three_1.Shape(); const positions = []; if (!((_a = this.layer) === null || _a === void 0 ? void 0 : _a.map)) return { shape }; const { threeCenter } = this.layer.map; const { coordinates } = polygonJson; const [shapePoint = []] = coordinates; for (let i = 0; i < shapePoint.length; i++) { const [x, y] = (0, coord_1.lonLat2Mercator)(shapePoint[i]).map((value, index) => value - threeCenter[index]); if (i === 0) { shape.moveTo(x, y); } shape.lineTo(x, y); positions.push(x, y, 0); } let line; if (this.lineMaterial && positions.length > 0) { const linGeometry = new LineGeometry_1.LineGeometry(); linGeometry.setPositions(positions); line = new Line2_1.Line2(linGeometry, this.lineMaterial); line.computeLineDistances(); line.scale.set(1, 1, 1); } return { shape, line }; } createObject() { var _a; if (!((_a = this.layer) === null || _a === void 0 ? void 0 : _a.map)) return; if (!this.polygonGeoJson) return; // 统一格式化为MultiPolygon const multiPolygon = geoJson2multiPolygon(this.polygonGeoJson); const shapeList = []; const lineList = []; multiPolygon.coordinates.forEach((polygonCoordinates) => { // 合成holes const polygonJson = formatPolygonJson({ type: 'Polygon', coordinates: polygonCoordinates }); if (polygonJson) { // 再次格式化为MultiPolygon const normalizeMultiPolygon = geoJson2multiPolygon(polygonJson); normalizeMultiPolygon.coordinates.forEach((normalizeMultiPolygonCoordinates) => { const mainShapePoint = [...normalizeMultiPolygonCoordinates]; const holes = mainShapePoint.splice(1); // 主体 const { shape, line } = this.createNormalPolygonShape({ type: 'Polygon', coordinates: mainShapePoint }); if (line) { lineList.push(line); } // 孔 holes.forEach((hole) => { const { shape: holeShape, line: holeLine } = this.createNormalPolygonShape({ type: 'Polygon', coordinates: [hole], }); shape.holes.push(holeShape); if (holeLine) { lineList.push(holeLine); } }); shapeList.push(shape); }); } }); const polygonGeometry = new three_1.ShapeGeometry(shapeList); this.object3D.geometry = polygonGeometry; this.object3D.material = this.polygonMaterial; this.object3D.clear(); this.object3D.renderOrder = Math.round(this.z); lineList.forEach((line) => { this.object3D.add(line); }); } setPolygon(polygon) { this.polygonGeoJson = polygon; this.createObject(); } updatePosition() { if (this.layer && this.lineMaterial) { const [width, height] = this.layer.getSize(); this.lineMaterial.resolution.set(width, height); } } updateBorder(border) { var _a, _b; (_a = this.lineMaterial) === null || _a === void 0 ? void 0 : _a.setValues(border); (_b = this.layer) === null || _b === void 0 ? void 0 : _b.updatePosition(); } updateFill(fill) { var _a, _b; const color = new three_1.Color(fill.color); this.polygonMaterial.uniforms.baseColor.value = [color.r, color.g, color.b, fill.opacity]; (_b = (_a = this.layer) === null || _a === void 0 ? void 0 : _a.updatePositionDebounce) === null || _b === void 0 ? void 0 : _b.call(_a); } } exports.default = PolygonObject;