UNPKG

@koopjs/featureserver

Version:

*An open source implementation of the GeoServices specification*

121 lines (99 loc) 4.15 kB
const Winnow = require('@koopjs/winnow'); const { getGeometryTypeFromGeojson } = require('../helpers'); const validateClassificationDefinition = require('./validate-classification-definition'); const { createColorRamp } = require('./color-ramp'); const { createSymbol } = require('./create-symbol'); function buildRenderer(data, requestParams = {}) { const { statistics = {}, features } = data; const { classificationDef } = requestParams; const geometryType = getGeometryTypeFromGeojson(data); if (statistics.classBreaks) { return generateRendererFromPrecalculatedStatistics(statistics, { classificationDef: classificationDef || {}, geometryType, }); } if (!classificationDef || !features) { return {}; } return generateRendererFromFeatures(data, { ...requestParams, geometryType }); } function generateRendererFromPrecalculatedStatistics(statistics, options) { const { classificationDef = {}, geometryType = 'esriGeometryPoint' } = options; const { colorRamp: colorRampConfig = {}, baseSymbol } = classificationDef; const classification = statistics.classBreaks.sort((a, b) => a[0] - b[0]); validateClassificationDefinition(classificationDef, geometryType, classification); const colorRamp = createColorRamp({ classification, ...colorRampConfig }); const symbolCollection = colorRamp.map((color) => { return createSymbol(baseSymbol, color, geometryType); }); return renderClassBreaks(classification, classificationDef, symbolCollection); } function generateRendererFromFeatures(data, params) { const { classificationDef = {}, geometryType } = params; const { colorRamp: colorRampConfig = {}, baseSymbol } = classificationDef; // TODO: this seems weird; the winnow method is "query" but it's really a very // specialized transform (aggregation) consider changes to winnow - this should // maybe be a different method const classification = Winnow.query(data, params); validateClassificationDefinition(classificationDef, geometryType, classification); const colorRamp = createColorRamp({ classification, ...colorRampConfig }); const symbolCollection = colorRamp.map((color) => { return createSymbol(baseSymbol, color, geometryType); }); if (classificationDef.type === 'classBreaksDef') { return renderClassBreaks(classification, classificationDef, symbolCollection); } // if not 'classBreaksDef', then its unique-values return renderUniqueValue(classification, classificationDef, symbolCollection); } function renderClassBreaks(breaks, classificationDef, symbolCollection) { return { type: 'classBreaks', field: classificationDef.classificationField || '', classificationMethod: classificationDef.classificationMethod || '', minValue: breaks[0][0], classBreakInfos: createClassBreakInfos(breaks, symbolCollection), }; } function createClassBreakInfos(breaks, symbolCollection) { return breaks.map((classBreak, index) => { return { classMinValue: classBreak[0], classMaxValue: classBreak[1], label: `${classBreak[0]}-${classBreak[1]}`, description: '', symbol: symbolCollection[index], }; }); } function renderUniqueValue(classification, classificationDef, symbolCollection) { const { uniqueValueFields, fieldDelimiter } = classificationDef; return { type: 'uniqueValue', field1: uniqueValueFields[0], field2: '', field3: '', fieldDelimiter, defaultSymbol: {}, defaultLabel: '', uniqueValueInfos: createUniqueValueInfos(classification, fieldDelimiter, symbolCollection), }; } function createUniqueValueInfos(uniqueValueEntries, fieldDelimiter, symbolCollection) { return uniqueValueEntries.map((uniqueValue, index) => { const value = serializeUniqueValues(uniqueValue, fieldDelimiter); return { value, count: uniqueValue.count, label: value, description: '', symbol: symbolCollection[index], }; }); } function serializeUniqueValues(uniqueValue, delimiter) { const { count, ...rest } = uniqueValue; return Object.values(rest).join(delimiter); } module.exports = { buildRenderer };