@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
169 lines (168 loc) • 5.38 kB
JavaScript
;
import {
FileLoader,
Loader,
BufferGeometry,
Float32BufferAttribute,
Group,
Shape,
Vector2
} from "three";
import { BaseSopOperation } from "../../../../engine/operations/sop/_Base";
import { ObjectType } from "../../../geometry/Constant";
import { createGeometriesFromTypeFlat } from "../../../geometry/text/TextFlat";
import { arrayCompact } from "../../../ArrayUtils";
import { isArray } from "../../../Type";
import { ThreejsCoreObject } from "../../../geometry/modules/three/ThreejsCoreObject";
export class GEOJSONLoader extends Loader {
constructor(manager) {
super(manager);
}
load(url, onLoad, onProgress, onError) {
const scope = this;
const loader = new FileLoader(this.manager);
loader.setPath(scope.path);
loader.setResponseType("json");
loader.setRequestHeader(scope.requestHeader);
loader.setWithCredentials(scope.withCredentials);
loader.load(
url,
(buffer) => {
try {
const json = buffer;
onLoad(this.parse(json));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
scope.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(data) {
const group = new Group();
this._parseGeojson(group, data);
return group;
}
_parseGeojson(group, data) {
const type = data.type;
switch (type) {
case "FeatureCollection": {
return this._parseFeatureCollection(group, data.features);
}
}
console.warn(`_parseGeojson:${type} not implemented`);
}
_parseFeatureCollection(group, features) {
for (const feature of features) {
const objects = this._parseFeature(feature);
if (objects) {
if (isArray(objects)) {
for (const object of objects) {
this._addAttributes(object, feature);
group.add(object);
}
} else {
this._addAttributes(objects, feature);
group.add(objects);
}
}
}
}
_addAttributes(object, feature) {
if (!feature.properties) {
return;
}
const propertyNames = Object.keys(feature.properties);
for (let propertyName of propertyNames) {
const value = feature.properties[propertyName];
ThreejsCoreObject.addAttribute(object, propertyName, value);
}
}
_parseFeature(feature) {
const geometry = feature.geometry;
const type = geometry.type;
switch (type) {
case "Point": {
return this._parseFeaturePoint(feature);
}
case "LineString": {
return this._parseFeatureLineString(feature);
}
case "Polygon": {
return this._parseFeaturePolygon(feature);
}
case "MultiPolygon": {
return this._parseFeatureMultiPolygon(feature);
}
}
console.warn(`_parseFeature:${type} not implemented`);
}
_parseFeaturePoint(feature) {
const coordinates = feature.geometry.coordinates;
const pointsCount = 1;
const positions = new Array(pointsCount * 3);
const indices = new Array(pointsCount);
const i = 0;
positions[i * 3] = coordinates[0];
positions[i * 3 + 1] = 0;
positions[i * 3 + 2] = coordinates[1];
indices[0] = 0;
const geometry = new BufferGeometry();
geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
geometry.setIndex(indices);
return BaseSopOperation.createObject(geometry, ObjectType.POINTS);
}
_parseFeatureLineString(feature) {
const coordinates = feature.geometry.coordinates;
const pointsCount = coordinates.length;
const positions = new Array(pointsCount * 3);
const indices = new Array(pointsCount);
for (let i = 0; i < pointsCount; i++) {
positions[i * 3] = coordinates[i][0];
positions[i * 3 + 1] = 0;
positions[i * 3 + 2] = coordinates[i][1];
if (i > 0) {
indices[(i - 1) * 2] = i - 1;
indices[(i - 1) * 2 + 1] = i;
}
}
const geometry = new BufferGeometry();
geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
geometry.setIndex(indices);
return BaseSopOperation.createObject(geometry, ObjectType.LINE_SEGMENTS);
}
_parseFeaturePolygon(feature) {
const coordinates = feature.geometry.coordinates;
const shapes = coordinates.map((coordinate) => new Shape(coordinate.map((c) => new Vector2(c[0], c[1]))));
const geometries = createGeometriesFromTypeFlat({ shapes: [shapes] });
if (!geometries) {
return;
}
const compactGeometries = [];
arrayCompact(geometries, compactGeometries);
return compactGeometries.map(
(geometry) => BaseSopOperation.createObject(geometry.rotateX(-0.5 * Math.PI), ObjectType.MESH)
);
}
_parseFeatureMultiPolygon(feature) {
const coordinates = feature.geometry.coordinates;
const shapes = coordinates.map(
(coordinate) => coordinate.map((c) => new Shape(c.map((c2) => new Vector2(c2[0], c2[1]))))
);
const geometries = createGeometriesFromTypeFlat({ shapes });
if (!geometries) {
return;
}
const compactGeometries = [];
arrayCompact(geometries, compactGeometries);
return compactGeometries.map(
(geometry) => BaseSopOperation.createObject(geometry.rotateX(-0.5 * Math.PI), ObjectType.MESH)
);
}
}