@orca-fe/x-map
Version:
169 lines (168 loc) • 7.91 kB
JavaScript
"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;