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) })