Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion libs/shared/src/lib/models/layer.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FaIconName } from '@oort-front/ui';
import { Gradient } from '../components/controls/gradient-picker/gradient-picker.component';
import { LayerType } from '../components/ui/map/interfaces/layer-settings.type';
import { HeatMapOptions as HeatMapOptionsWithoutOpacity } from 'leaflet';
import { AdminIdentifier } from '../services/map/map-polygons.service';

/**
* Layer types for backend
Expand Down Expand Up @@ -135,7 +136,7 @@ export interface LayerDatasource {
layout?: string;
aggregation?: string;
geoField?: string;
adminField?: string;
adminField?: AdminIdentifier;
latitudeField?: string;
longitudeField?: string;
type?: LayerDatasourceType;
Expand Down
5 changes: 3 additions & 2 deletions libs/shared/src/lib/services/map/map-layers.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -435,9 +435,10 @@ export class MapLayersService {
map((value) => {
// When using adminField mapping, update the feature so geometry is replaced with according polygons
if (layer.datasource?.adminField) {
return this.mapPolygonsService.assignPolygons(
return this.mapPolygonsService.assignGeometry(
value,
layer.datasource.adminField as any
layer.datasource.adminField,
layer.datasource.type
);
} else {
// Else, directly returns the feature layer
Expand Down
55 changes: 42 additions & 13 deletions libs/shared/src/lib/services/map/map-polygons.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,28 @@ import { flattenDeep, get, isArray, isNil, isObject, uniq } from 'lodash';
import * as L from 'leaflet';
import REGIONS from './regions';
import booleanPointInPolygon from '@turf/boolean-point-in-polygon';
import { Feature, MultiPolygon, Polygon } from 'geojson';
import { LayerDatasourceType } from '../../models/layer.model';

/** Available admin identifiers */
type AdminIdentifier = 'admin0.iso2code' | 'admin0.iso3code' | 'admin0.id';
export type AdminIdentifier =
| 'admin0.iso2code'
| 'admin0.iso3code'
| 'admin0.id';

/** Admin 0 available identifiers */
type Admin0Identifier = 'iso2code' | 'iso3code' | 'id';

type Admin0 = {
id: number;
centerlatitude: string;
centerlongitude: string;
iso2code: string;
iso3code: string;
name: string;
polygons: Polygon | MultiPolygon | Feature<Polygon | MultiPolygon>;
};

/**
* Shared map polygons service.
* Allow to use polygons from common services, and assign them to the layer features.
Expand All @@ -23,7 +38,7 @@ type Admin0Identifier = 'iso2code' | 'iso3code' | 'id';
})
export class MapPolygonsService {
/** Admin0 polygons */
public admin0s: any[] = [];
public admin0s: Admin0[] = [];
/** Are admin0 polygons ready */
private admin0sReady = new BehaviorSubject<boolean>(false);
/** Admin0 polygons status as observable */
Expand Down Expand Up @@ -60,28 +75,39 @@ export class MapPolygonsService {
*
* @param data feature layer
* @param identifier admin identifier
* @param layerDatasourceType type of datasource, point or polygon
* @returns feature layer with polygons for geometry
*/
public assignAdmin0Polygons(
public assignAdmin0Geometry(
data: any,
identifier: Admin0Identifier = 'iso3code'
identifier: Admin0Identifier = 'iso3code',
layerDatasourceType: LayerDatasourceType
) {
const polygons = {};
const geometry = {};
for (const admin0 of this.admin0s) {
set(polygons, admin0[identifier].toLowerCase(), admin0.polygons);
set(
geometry,
admin0[identifier].toString().toLowerCase(),
layerDatasourceType === 'Polygon'
? admin0.polygons
: {
type: 'Point',
coordinates: [admin0.centerlongitude, admin0.centerlatitude],
}
);
}
const features: any[] = [];
for (const feature of data.features) {
const adminIds = uniq(flattenDeep([get(feature, 'geometry')])).filter(
(x) => !isObject(x) && !isNil(x)
);
adminIds.forEach((adminId) => {
const adminPolygons = get(polygons, adminId.toString().toLowerCase());
if (adminPolygons) {
const adminGeometry = get(geometry, adminId.toString().toLowerCase());
if (adminGeometry) {
features.push({
...feature,
type: 'Feature',
geometry: adminPolygons,
geometry: adminGeometry,
});
}
});
Expand All @@ -97,16 +123,19 @@ export class MapPolygonsService {
*
* @param data feature layer
* @param identifier admin identifier
* @param layerDatasourceType type of layer datasource, polygon by default
* @returns feature layer with polygons for geometry
*/
public assignPolygons(
public assignGeometry(
data: any,
identifier: AdminIdentifier = 'admin0.iso3code'
identifier: AdminIdentifier = 'admin0.iso3code',
layerDatasourceType: LayerDatasourceType = 'Polygon'
) {
if (identifier.startsWith('admin0.')) {
return this.assignAdmin0Polygons(
return this.assignAdmin0Geometry(
data,
identifier.replace('admin0.', '') as Admin0Identifier
identifier.replace('admin0.', '') as Admin0Identifier,
layerDatasourceType
);
} else {
return EMPTY_FEATURE_COLLECTION;
Expand Down