@polygonjs/plugin-mapbox
Version:
Mapbox plugin for the 3D engine https://polygonjs.com
105 lines (104 loc) • 4.2 kB
JavaScript
import { Vector2 } from "three";
import { Float32BufferAttribute } from "three";
import { BufferGeometry } from "three";
import { CoreGeometry } from "@polygonjs/polygonjs/dist/src/core/geometry/Geometry";
import { ObjectType } from "@polygonjs/polygonjs/dist/src/core/geometry/Constant";
import { CoordinatesCollection } from "./CoordinatesCollection";
import { ArrayUtils } from "@polygonjs/polygonjs/dist/src/core/ArrayUtils";
import { CoreGeometryBuilderMerge } from "@polygonjs/polygonjs/dist/src/core/geometry/builders/Merge";
import { CoreMapboxString } from "./String";
const MULTILINESTRING = "MultiLineString";
const LINESTRING = "LineString";
export class FeatureConverter {
constructor(node, name, features) {
this.node = node;
this.name = name;
this.features = features;
}
createObject() {
const coordinatesCollections = this._createAllCoordinatesCollections();
const perimeter = ArrayUtils.sum(coordinatesCollections.map((f) => f.perimeter()));
const sortedFeatures = CoordinatesCollection.sort(coordinatesCollections);
const lines = sortedFeatures.map((feature) => {
return this._createLine(feature);
});
lines.forEach((line) => {
const geometry = line.geometry;
const core_geometry2 = new CoreGeometry(geometry);
core_geometry2.addNumericAttrib("perimeter", 1, perimeter);
});
const geometries = lines.map((l) => l.geometry);
const merged_geometry = CoreGeometryBuilderMerge.merge(geometries);
if (!merged_geometry) {
return;
}
const core_geometry = new CoreGeometry(merged_geometry);
core_geometry.addNumericAttrib("pti", 1, 0);
const points = core_geometry.points();
const points_count = points.length;
for (let i = 0; i < points.length; i++) {
const point = points[i];
const pti = i / (points_count - 1);
point.setAttribValue("pti", pti);
}
const mergedObject = this.node.createObject(merged_geometry, ObjectType.LINE_SEGMENTS);
return mergedObject;
}
_createLine(coordinates_collection) {
const points_count = coordinates_collection.coordinates.length;
const positions = [];
const indices = [];
for (let i = 0; i < points_count; i++) {
const coordinates = coordinates_collection.coordinates[i];
positions.push(coordinates.x);
positions.push(0);
positions.push(coordinates.y);
if (i > 0) {
indices.push(i - 1);
indices.push(i);
}
}
const geometry = new BufferGeometry();
geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
geometry.setIndex(indices);
const object = this.node.createObject(geometry, ObjectType.LINE_SEGMENTS);
const core_geometry = new CoreGeometry(geometry);
const id_from_name = CoreMapboxString.toId(this.name) % 1e7;
core_geometry.addNumericAttrib("id", 1, this.id);
core_geometry.addNumericAttrib("name_id", 1, id_from_name);
return object;
}
_createAllCoordinatesCollections() {
const coordinates_collections = [];
this.features.forEach((feature) => {
this.id = this.id || feature["id"];
const feature_geometry = feature.geometry;
if (feature_geometry) {
const type = feature_geometry["type"];
switch (type) {
case MULTILINESTRING:
const multi_coordinates = feature_geometry["coordinates"];
if (multi_coordinates) {
for (let i = 0; i < multi_coordinates.length; i++) {
const coordinates = multi_coordinates[i];
coordinates_collections.push(this._create_coordinates(coordinates));
}
}
break;
case LINESTRING:
coordinates_collections.push(this._create_coordinates(feature_geometry["coordinates"]));
break;
default:
console.warn(`type ${type} not taken into account`);
}
}
});
return coordinates_collections;
}
_create_coordinates(raw_coordinates) {
const vectors = raw_coordinates.map((raw_coordinate) => {
return new Vector2(raw_coordinate[0], raw_coordinate[1]);
});
return new CoordinatesCollection(vectors);
}
}