UNPKG

@orca-fe/x-map

Version:
169 lines (168 loc) 7.91 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const three_1 = require("three"); 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 ExtrudePolygonObject extends ThreeObject_1.default { constructor(options = {}) { super(options); this.object3D = new three_1.Mesh(); const { polygonGeoJson, fill = { color: 0x33ccff, opacity: 0.1 }, polygonMaterialParameters, polygonSideMaterialParameters, } = options; this.polygonGeoJson = polygonGeoJson; const color = new three_1.Color(fill.color); this.polygonFaceMaterial = new three_1.MeshStandardMaterial(Object.assign({ side: three_1.FrontSide, depthWrite: true, // depthTest: true, transparent: true, opacity: fill.opacity, color, roughness: 0.6, metalness: 0.5 }, polygonMaterialParameters)); this.polygonSideMaterial = new three_1.MeshBasicMaterial(Object.assign({ // blending: AdditiveBlending, side: three_1.FrontSide, depthWrite: true, depthTest: true, transparent: true, opacity: fill.opacity, color }, polygonSideMaterialParameters)); this.object3D.position.set(0, 0, this.z); } // 创建一个常规(不带孔)的shape createNormalPolygonShape(polygonJson) { var _a; const shape = new three_1.Shape(); const positions = []; const pointPositions = []; 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); pointPositions.push([x, y, 0]); } return { shape, positions: pointPositions }; } createObject() { var _a, _b, _c; 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 extrudeLineList = []; 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, positions } = this.createNormalPolygonShape({ type: 'Polygon', coordinates: mainShapePoint, }); if (this.options.border && positions) { const curve = new three_1.CatmullRomCurve3(positions.map(p => new three_1.Vector3(...p))); const extrudeLine = new three_1.Mesh(new three_1.TubeGeometry(curve, positions.length, 200, 8), new three_1.MeshBasicMaterial(Object.assign({ blending: three_1.AdditiveBlending, side: three_1.FrontSide, color: 0xddeeff, transparent: true }, this.options.border))); extrudeLineList.push(extrudeLine); } // 孔 holes.forEach((hole) => { const { shape: holeShape } = this.createNormalPolygonShape({ type: 'Polygon', coordinates: [hole], }); shape.holes.push(holeShape); }); shapeList.push(shape); }); } }); const polygonGeometry = new three_1.ExtrudeGeometry(shapeList, this.options.extrudeOptions); polygonGeometry.translate(0, 0, -((_c = (_b = this.options.extrudeOptions) === null || _b === void 0 ? void 0 : _b.depth) !== null && _c !== void 0 ? _c : 0)); this.object3D.clear(); this.object3D.add(new three_1.Mesh(polygonGeometry, [this.polygonFaceMaterial, this.polygonSideMaterial])); this.object3D.renderOrder = Math.round(this.z); extrudeLineList.forEach((line) => { line.translateZ(10); this.object3D.add(line); }); // 添加墙体 if (this.options.wall) { const { texture, height, opacity } = this.options.wall; const wallGeometry = new three_1.ExtrudeGeometry(shapeList, Object.assign(Object.assign({}, this.options.extrudeOptions), { depth: height })); const faceMaterial = new three_1.MeshBasicMaterial({ side: three_1.FrontSide, depthTest: false, depthWrite: true, transparent: true, color: 0xffffff, opacity: 0.1, }); const sideMaterial = new three_1.MeshBasicMaterial({ side: three_1.DoubleSide, depthTest: true, depthWrite: false, blending: three_1.AdditiveBlending, transparent: true, opacity, map: texture, }); const wall = new three_1.Mesh(wallGeometry, [faceMaterial, sideMaterial]); this.object3D.add(wall); } } setPolygon(polygon) { this.polygonGeoJson = polygon; this.createObject(); } updatePosition() { } updateFill(fill, sideFill = fill) { var _a; this.polygonFaceMaterial.color = new three_1.Color(fill.color); this.polygonFaceMaterial.opacity = fill.opacity; this.polygonSideMaterial.color = new three_1.Color(sideFill.color); this.polygonSideMaterial.opacity = sideFill.opacity; (_a = this.layer) === null || _a === void 0 ? void 0 : _a.updatePosition(); } } exports.default = ExtrudePolygonObject;