Skip to content

Commit

Permalink
fix(geo): inporting vector (igo2 issues #1146)
Browse files Browse the repository at this point in the history
* refactor(geo): move detect epsg to projection utils

* refactor(geo): refactor based on review

* wip

* wip

* wip
  • Loading branch information
pelord authored and alecarn committed Apr 4, 2024
1 parent c5b12db commit 3dc85a1
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import {
import { ConfirmDialogService, DragAndDropDirective } from '@igo2/common';
import { ConfigService, MessageService } from '@igo2/core';

import { BehaviorSubject, Subscription } from 'rxjs';
import { Subscription } from 'rxjs';
import { concatMap, first, skipWhile } from 'rxjs/operators';

import { Feature } from '../../feature/shared/feature.interfaces';
import { LayerService } from '../../layer/shared/layer.service';
import { MapBrowserComponent } from '../../map/map-browser/map-browser.component';
import { IgoMap } from '../../map/shared/map';
import { detectFileEPSG } from '../../map/shared/projection.utils';
import { StyleListService } from '../../style/style-list/style-list.service';
import { StyleService } from '../../style/style-service/style.service';
import {
Expand All @@ -35,7 +36,6 @@ export class DropGeoFileDirective
{
protected filesDropped: EventEmitter<File[]> = new EventEmitter();
protected filesInvalid: EventEmitter<File[]> = new EventEmitter();
private epsgCode$: BehaviorSubject<string> = new BehaviorSubject(undefined);
private epsgCode$$: Subscription[] = [];
private filesDropped$$: Subscription;

Expand Down Expand Up @@ -66,6 +66,7 @@ export class DropGeoFileDirective

ngOnDestroy() {
this.filesDropped$$.unsubscribe();
this.epsgCode$$.map((e) => e.unsubscribe());
}

@HostListener('dragover', ['$event'])
Expand All @@ -85,16 +86,16 @@ export class DropGeoFileDirective

private onFilesDropped(files: File[]) {
for (const file of files) {
this.detectEPSG(file);
this.epsgCode$$.push(
this.epsgCode$
detectFileEPSG({ file })
.pipe(
skipWhile((code) => !code),
first(),
concatMap((epsgCode) => {
const epsg = epsgCode === 'epsgNotDefined' ? undefined : epsgCode;
this.epsgCode$.next(undefined);
return this.importService.import(file, epsg);
return this.importService.import(
file,
epsgCode === 'epsgNotDefined' ? undefined : epsgCode
);
})
)
.subscribe(
Expand All @@ -105,52 +106,6 @@ export class DropGeoFileDirective
}
}

private detectEPSG(file: File, nbLines: number = 500) {
if (
!file.name.toLowerCase().endsWith('.geojson') &&
!file.name.toLowerCase().endsWith('.gml')
) {
this.epsgCode$.next('epsgNotDefined');
return;
}
const reader = new FileReader();
reader.onload = (e) => {
if (file.name.toLowerCase().endsWith('.geojson')) {
const geojson = JSON.parse(reader.result as string);
if (geojson.crs?.properties?.name) {
const epsg = geojson.crs.properties.name.match(/EPSG:{1,2}\d{0,6}/gm);
if (epsg !== null && epsg.length) {
this.epsgCode$.next(epsg[0].replace(/::/g, ':'));
return;
} else {
this.epsgCode$.next('epsgNotDefined');
return;
}
} else {
this.epsgCode$.next('epsgNotDefined');
return;
}
} else if (file.name.toLowerCase().endsWith('.gml')) {
const text = reader.result as string;
const lines = (text as string).split('\n');
for (let line = 0; line <= nbLines; line++) {
const epsg = lines[line].match(/EPSG:\d{0,6}/gm);
if (epsg !== null && epsg.length) {
this.epsgCode$.next(epsg[0]);
break;
} else {
this.epsgCode$.next(undefined);
return;
}
}
} else {
this.epsgCode$.next('epsgNotDefined');
return;
}
};
reader.readAsText(file, 'UTF-8');
}

private onFileImportSuccess(file: File, features: Feature[]) {
const importExportOptions = this.config.getConfig(
'importExport'
Expand Down
67 changes: 67 additions & 0 deletions packages/geo/src/lib/map/shared/projection.utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Observable, from } from 'rxjs';

import { ProjectionsLimitationsOptions } from './projection.interfaces';

/**
Expand Down Expand Up @@ -66,3 +68,68 @@ export function computeProjectionsConstraints(
};
return projectionsConstraints;
}
/**
* Method allowing to read the file and try to detect projection/Coord system
* Only geojson/json/gml could be detected at this moment.
* @param options A file and an optional number of line to read the EPSG Code. Used only for GML files
* @returns Observable string, epsgNotDefined if the EPSG is not detected or a EPSG string ex: EPSG:3857
*/
export function detectFileEPSG(options: {
file: File;
nbLines?: number;
}): Observable<string> {
const file = options.file;
const nbLines = options.nbLines ?? 500;

const reader = new FileReader();
return from(
new Promise<string>((resolve) => {
if (
!file.name.toLowerCase().endsWith('.geojson') &&
!file.name.toLowerCase().endsWith('.json') &&
!file.name.toLowerCase().endsWith('.gml')
) {
resolve('epsgNotDefined');
return;
}

reader.onload = (e) => {
if (
file.name.toLowerCase().endsWith('.geojson') ||
file.name.toLowerCase().endsWith('.json')
) {
const geojson = JSON.parse(reader.result as string);
if (geojson.crs?.properties?.name) {
const epsg =
geojson.crs.properties.name.match(/EPSG:{1,2}\d{0,6}/gm);
if (epsg !== null && epsg.length) {
resolve(epsg[0].replace(/::/g, ':'));
return;
} else {
resolve('epsgNotDefined');
return;
}
} else {
resolve('epsgNotDefined');
return;
}
} else if (file.name.toLowerCase().endsWith('.gml')) {
const text = reader.result as string;
const lines = (text as string).split('\n');
for (let line = 0; line <= nbLines; line++) {
const epsg = lines[line].match(/EPSG:\d{0,6}/gm);
if (epsg !== null && epsg.length) {
resolve(epsg[0]);
break;
} else {
resolve(undefined);
}
}
} else {
resolve('epsgNotDefined');
}
};
reader.readAsText(file, 'UTF-8');
})
);
}

0 comments on commit 3dc85a1

Please sign in to comment.