|
@@ -0,0 +1,234 @@
|
|
|
+import 'babel-core/register'
|
|
|
+import 'babel-polyfill'
|
|
|
+import featuresToPolygon from './featuresToPolygon'
|
|
|
+import { toExtrudeGeometry, reductive } from './PolygonToGeom'
|
|
|
+import geoGrentAttribute from './geoGrentAttribute'
|
|
|
+import config from '../business/config'
|
|
|
+import grentText from './grentText'
|
|
|
+import * as management from './dataManagement'
|
|
|
+
|
|
|
+function mergeBigData(datas) {
|
|
|
+ let index = 0
|
|
|
+ let len = datas.reduce((p, c) => p + c.length, 0)
|
|
|
+ let v3 = new Float32Array(len * 3)
|
|
|
+
|
|
|
+ datas.forEach(data => {
|
|
|
+ let length = data.length
|
|
|
+ for (let i = 0; i < length; i++) {
|
|
|
+ v3[index] = data[i].x
|
|
|
+ v3[index + 1] = data[i].y
|
|
|
+ v3[index + 2] = data[i].z
|
|
|
+ index += 3
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return v3
|
|
|
+}
|
|
|
+
|
|
|
+function getMaxHeight(verticesBuffArrays) {
|
|
|
+ let maxHeight = verticesBuffArrays[2]
|
|
|
+ let len = verticesBuffArrays.length
|
|
|
+
|
|
|
+ for (let i = 3; i < len; i += 3) {
|
|
|
+ if (maxHeight < verticesBuffArrays[i + 2]) {
|
|
|
+ maxHeight = verticesBuffArrays[i + 2]
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return maxHeight
|
|
|
+}
|
|
|
+
|
|
|
+function grentAnimationArray(verticesBuffArrays, stepTotal, maxHeight) {
|
|
|
+ let len = verticesBuffArrays.length
|
|
|
+ let animateBuffArrays = new Float32Array(
|
|
|
+ (len / 3) * stepTotal
|
|
|
+ )
|
|
|
+
|
|
|
+ for (let i = 0, index = 0; i < len; i += 3, index++) {
|
|
|
+ let indexes = index * stepTotal
|
|
|
+ let origin = verticesBuffArrays[i + 2]
|
|
|
+ let average = (maxHeight - origin) / stepTotal
|
|
|
+ for (let j = 1; j < stepTotal + 1; j++) {
|
|
|
+ animateBuffArrays[indexes + j - 1] = maxHeight - (j * average)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return animateBuffArrays
|
|
|
+}
|
|
|
+
|
|
|
+function grentVerticesNormals(map, features) {
|
|
|
+ let polygons = featuresToPolygon(features)
|
|
|
+ let verticesArray = []
|
|
|
+ let normalsArray = []
|
|
|
+ let textVerticesArray = []
|
|
|
+ let textNormalsArray = []
|
|
|
+
|
|
|
+ polygons.forEach((polygon, index) => {
|
|
|
+ let geo = toExtrudeGeometry(
|
|
|
+ polygon,
|
|
|
+ map,
|
|
|
+ features[index].properties.height ||
|
|
|
+ features[index].properties.levels * 5 || 5
|
|
|
+ )
|
|
|
+
|
|
|
+ if (!geo) return;
|
|
|
+
|
|
|
+ let { vertices, normals } = geoGrentAttribute(geo)
|
|
|
+ verticesArray.push(vertices)
|
|
|
+ normalsArray.push(normals)
|
|
|
+
|
|
|
+ if (features[index].properties.name) {
|
|
|
+ let { textVertices, textNormals } = grentText(features[index].properties.name, vertices)
|
|
|
+ textVerticesArray.push(textVertices)
|
|
|
+ textNormalsArray.push(textNormals)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ verticesArray: mergeBigData(verticesArray),
|
|
|
+ normalsArray: mergeBigData(normalsArray),
|
|
|
+ textVerticesArray: mergeBigData(textVerticesArray),
|
|
|
+ textNormalsArray: mergeBigData(textNormalsArray)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function grentAttribute(map, features, stepTotal) {
|
|
|
+ let {verticesArray, normalsArray} = grentVerticesNormals(map, features)
|
|
|
+ let maxHeight = getMaxHeight(verticesArray)
|
|
|
+ let animateBuffArrays = grentAnimationArray(
|
|
|
+ verticesArray,
|
|
|
+ stepTotal,
|
|
|
+ maxHeight
|
|
|
+ )
|
|
|
+
|
|
|
+ return {
|
|
|
+ verticesBuffArrays: verticesArray,
|
|
|
+ normalsBuffArrays: normalsArray,
|
|
|
+ maxHeight,
|
|
|
+ animateBuffArrays
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function extractType(features) {
|
|
|
+ let types = []
|
|
|
+ let typeFeatures = [[]]
|
|
|
+
|
|
|
+ features.forEach(f => {
|
|
|
+ if (f.properties && f.properties.type) {
|
|
|
+ let index = types.indexOf(f.properties.type)
|
|
|
+ // index = 0
|
|
|
+ if (~index) {
|
|
|
+ typeFeatures[index + 1].push(f)
|
|
|
+ } else {
|
|
|
+ types.push(f.properties.type)
|
|
|
+ typeFeatures[types.length] = [f]
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ typeFeatures[0].push(f)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ typeFeatures,
|
|
|
+ types
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function featuresGrentAttribute(map, features) {
|
|
|
+ let { typeFeatures, types } = extractType(features)
|
|
|
+ let geoJsonArray = []
|
|
|
+
|
|
|
+ reductive(map)
|
|
|
+
|
|
|
+ typeFeatures.forEach((features, index) => {
|
|
|
+ if (features.length) {
|
|
|
+ geoJsonArray.push({
|
|
|
+ ...grentAttribute(map, features, config.stepTotal),
|
|
|
+ fids: features.map(f => f.id),
|
|
|
+ type: index === 0 ? 'unknown' : types[index - 1]
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ let transArray = []
|
|
|
+ geoJsonArray.forEach(geo => {
|
|
|
+ transArray.push(
|
|
|
+ geo.verticesBuffArrays.buffer,
|
|
|
+ geo.normalsBuffArrays.buffer,
|
|
|
+ geo.animateBuffArrays.buffer
|
|
|
+ )
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ geoJsonArray,
|
|
|
+ transArray
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+let _interface = {
|
|
|
+ initialAttribute: data => {
|
|
|
+ let map = JSON.parse(data.map)
|
|
|
+ let incident = data.incident || 'grentAttribute'
|
|
|
+ let features = JSON.parse(data.features)
|
|
|
+ let { geoJsonArray, transArray} = featuresGrentAttribute(map, features)
|
|
|
+
|
|
|
+ self.postMessage({
|
|
|
+ incident,
|
|
|
+ geoJsonArray
|
|
|
+ }, transArray)
|
|
|
+ },
|
|
|
+
|
|
|
+ grentAnimationArray: data => {
|
|
|
+ let verticesBuffArrays = data.verticesBuffArrays
|
|
|
+ let maxHeight = getMaxHeight(verticesBuffArrays)
|
|
|
+ let incident = data.incident || 'grentAnimationArray'
|
|
|
+ let animationArray = grentAnimationArray(
|
|
|
+ verticesBuffArrays,
|
|
|
+ config.stepTotal,
|
|
|
+ maxHeight
|
|
|
+ )
|
|
|
+
|
|
|
+ self.postMessage({
|
|
|
+ animationArray,
|
|
|
+ incident
|
|
|
+ }, [animationArray.buffer])
|
|
|
+ },
|
|
|
+
|
|
|
+ getGeo: (function () {
|
|
|
+ let ergodicIndex = 0
|
|
|
+ return async data => {
|
|
|
+ ergodicIndex++
|
|
|
+ let currErgodicIndex = ergodicIndex
|
|
|
+ self.postMessage({
|
|
|
+ incident: 'obsAddGeo'
|
|
|
+ })
|
|
|
+
|
|
|
+ for (let i = 0; i < data.tiles.length; i++) {
|
|
|
+ if (currErgodicIndex !== ergodicIndex) return;
|
|
|
+ let tile = data.tiles[i]
|
|
|
+ let { x, y, z } = tile
|
|
|
+ let features = await management.getFeatures(x, y, z)
|
|
|
+ if (currErgodicIndex !== ergodicIndex) return;
|
|
|
+ let { geoJsonArray, transArray } = featuresGrentAttribute(data.map, features)
|
|
|
+ self.postMessage({
|
|
|
+ incident: 'addGeo',
|
|
|
+ geoJsonArray
|
|
|
+ }, transArray)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })(),
|
|
|
+
|
|
|
+ clearFids: data => {
|
|
|
+ management.clearGeos(data.fids)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+self.addEventListener('message', event => {
|
|
|
+ let data = event.data
|
|
|
+ if (typeof event.data === 'string') {
|
|
|
+ data = JSON.parse(event.data)
|
|
|
+ }
|
|
|
+ _interface[data.thing] && _interface[data.thing](data)
|
|
|
+})
|