123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- import GeoJSON from 'ol/format/GeoJSON';
- import { Geometry } from 'ol/geom';
- import { ArrayVector, DataFrame, Field, FieldType, getFieldTypeFromValue } from '@grafana/data';
- interface FieldInfo {
- values: any[];
- types: Set<FieldType>;
- count: number;
- }
- // http://geojson.xyz/
- export function frameFromGeoJSON(body: Document | Element | Object | string): DataFrame {
- const data = new GeoJSON().readFeatures(body, { featureProjection: 'EPSG:3857' });
- const length = data.length;
- const geo: Geometry[] = new Array(length).fill(null);
- const fieldOrder: string[] = [];
- const lookup = new Map<string, FieldInfo>();
- const getField = (name: string) => {
- let f = lookup.get(name);
- if (!f) {
- f = {
- types: new Set<FieldType>(),
- values: new Array(length).fill(null),
- count: 0,
- };
- fieldOrder.push(name);
- lookup.set(name, f);
- }
- return f;
- };
- const getBestName = (...names: string[]) => {
- for (const k of names) {
- if (!lookup.has(k)) {
- return k;
- }
- }
- return '___' + names[0];
- };
- const idfield: FieldInfo = {
- types: new Set<FieldType>(),
- values: new Array(length).fill(null),
- count: 0,
- };
- for (let i = 0; i < length; i++) {
- const feature = data[i];
- geo[i] = feature.getGeometry()!;
- const id = feature.getId();
- if (id != null) {
- idfield.values[i] = id;
- idfield.types.add(getFieldTypeFromValue(id));
- idfield.count++;
- }
- for (const key of feature.getKeys()) {
- const val = feature.get(key);
- if (val === geo[i] || val == null) {
- continue;
- }
- const field = getField(key);
- field.values[i] = val;
- field.types.add(getFieldTypeFromValue(val));
- field.count++;
- }
- }
- const fields: Field[] = [];
- if (idfield.count > 0) {
- const type = ensureSingleType(idfield);
- fields.push({
- name: getBestName('id', '_id', '__id'),
- type,
- values: new ArrayVector(idfield.values),
- config: {},
- });
- }
- // Add a geometry field
- fields.push({
- name: getBestName('geo', 'geometry'),
- type: FieldType.geo,
- values: new ArrayVector(geo),
- config: {},
- });
- for (const name of fieldOrder) {
- const info = lookup.get(name);
- if (!info) {
- continue;
- }
- const type = ensureSingleType(info);
- fields.push({
- name,
- type,
- values: new ArrayVector(info.values),
- config: {},
- });
- }
- // Simple frame
- return {
- fields,
- length,
- };
- }
- function ensureSingleType(info: FieldInfo): FieldType {
- if (info.count < 1) {
- return FieldType.other;
- }
- if (info.types.size > 1) {
- info.values = info.values.map((v) => {
- if (v != null) {
- return `${v}`;
- }
- return v;
- });
- return FieldType.string;
- }
- return info.types.values().next().value;
- }
|