UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

169 lines (168 loc) 5.38 kB
"use strict"; 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) ); } }