Skip to content

Commit

Permalink
Generate AOI
Browse files Browse the repository at this point in the history
  • Loading branch information
MohamedHamouGisaia committed Nov 10, 2023
1 parent c163f73 commit a498706
Show file tree
Hide file tree
Showing 10 changed files with 464 additions and 33 deletions.
11 changes: 10 additions & 1 deletion projects/arlas-components/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,14 @@
"None": "None",
"Fit the whole thumbnail to the tile": "Fit the whole thumbnail to the tile",
"Fit the thumbnail's width to the tile": "Fit the thumbnail's width to the tile",
"Fit the thumbnail's height to the tile": "Fit the thumbnail's height to the tile"
"Fit the thumbnail's height to the tile": "Fit the thumbnail's height to the tile",
"Enter coordinates in decimal or sexagesimal degrees": "Enter coordinates in decimal or sexagesimal degrees.",
"BBox generator": "Generate a bbox",
"First corner": "First corner",
"Second corner": "Second corner",
"You must enter a coordinate": "Enter a coordinate",
"Enter a coordinate in decimal (1.1) or sexagesimal (1° 6' 3\")": "Enter a coordinate in decimal (1.1) or sexagesimal (1° 6' 3\")",
"Decimal: 1.1 or Sexagesimal 1°6'3\" coordinate": "Decimal: 1.1 or Sexagesimal: 1°6'3\" coordinate",
"Both corners have the same latitudes, change one of them.": "Both corners have the same latitudes, modify one of them.",
"Generate AOI": "Generate the bbox"
}
11 changes: 10 additions & 1 deletion projects/arlas-components/assets/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,14 @@
"None": "Aucune",
"Fit the whole thumbnail to the tile": "Ajuster la taille de la vignette à la tuile",
"Fit the thumbnail's width to the tile": "Ajuster la largeur de la vignette à la tuile",
"Fit the thumbnail's height to the tile": "Ajuster la hauteur de la vignette à la tuile"
"Fit the thumbnail's height to the tile": "Ajuster la hauteur de la vignette à la tuile",
"Enter coordinates in decimal or sexagesimal degrees": "Saisir les coordonnées en degrés décimaux ou sexagésimaux.",
"BBox generator": "Générer une bbox",
"First corner": "Premier coin",
"Second corner": "Deuxième coin",
"You must enter a coordinate": "Saisir une coordonnée",
"Enter a coordinate in decimal (1.1) or sexagesimal (1° 6' 3\")": "Saisir une coordonnée en décimal (1.1) ou en sexagésimal (1° 6' 3\")",
"Decimal: 1.1 or Sexagesimal 1°6'3\" coordinate": "Coordonnée en décimal: 1.1 or sexagésimal: 1°6'3\"",
"Both corners have the same latitudes, modify one of them.": "Les deux coins ont les mêmes latitudes, modifiez l'un d'entre eux.",
"Generate AOI": "Générer la bbox"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<div class="wrapper">
<div class="title-wrapper">
<span>{{'BBox generator' | translate}}</span>
<mat-icon>clear</mat-icon>
</div>
<div class="content">
<div class="description">
<mat-icon>info</mat-icon>
<span>{{DESCRIPTION | translate}}</span>
</div>
<div class="section" *ngIf="bboxForm?.firstCorner" [formGroup]="bboxForm?.firstCorner">
<div class="title">{{'First corner' | translate}}</div>
<div class="coordinate">
<mat-form-field appearance="outline" >
<mat-label>{{'Latitude'}}</mat-label>
<input class="input" matInput [formControl]="bboxForm.firstCorner.latitude" [placeholder]="placeHolder | translate">
<mat-error *ngIf="bboxForm.firstCorner.latitude.invalid">{{getErrorMessage(bboxForm.firstCorner.latitude) | translate}}</mat-error>
</mat-form-field>
</div>
<div class="coordinate">
<mat-form-field appearance="outline">
<mat-label>{{'Longitude'}}</mat-label>
<input class="input" matInput [formControl]="bboxForm.firstCorner.longitude" [placeholder]="placeHolder | translate">
<mat-error *ngIf="bboxForm.firstCorner.longitude.invalid">{{getErrorMessage(bboxForm.firstCorner.longitude) | translate}}</mat-error>
</mat-form-field>
</div>
</div>
<div class="section" *ngIf="bboxForm?.secondCorner" [formGroup]="bboxForm?.secondCorner">
<div class="title">{{'Second corner' | translate}}</div>
<div class="coordinate">
<mat-form-field appearance="outline" >
<mat-label>{{'Latitude'}}</mat-label>
<input class="input" matInput [formControl]="bboxForm.secondCorner.latitude" [placeholder]="placeHolder | translate">
<mat-error *ngIf="bboxForm.secondCorner.latitude.invalid">{{getErrorMessage(bboxForm.secondCorner.latitude) | translate}} </mat-error>
</mat-form-field>
</div>
<div class="coordinate">
<mat-form-field appearance="outline">
<mat-label>{{'Longitude'}}</mat-label>
<input class="input" matInput [formControl]="bboxForm.secondCorner.longitude" [placeholder]="placeHolder | translate">
<mat-error *ngIf="bboxForm.secondCorner.longitude.invalid">{{getErrorMessage(bboxForm.secondCorner.longitude) | translate}}</mat-error>
</mat-form-field>
</div>


</div>
<div class="errors" *ngIf="bboxForm.latitudeErrors">
<mat-icon>report</mat-icon>
<mat-error>{{getErrorMessage(bboxForm) | translate}}</mat-error>
</div>
</div>
<div class="actions">
<button mat-button [mat-dialog-close]="null">{{'Close' | translate}}
</button>
<button class="create-action" mat-stroked-button (click)="generateBbox()"
[disabled]="bboxForm.invalid || bboxForm.latitudeErrors">
<span class="label">{{'Generate AOI' | translate}}</span>
</button>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
.wrapper {
padding: 5px;
border-radius: 3px;
background-color: white;
font-size: 16px;
min-width: 365px;
.title-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
font-weight: 600;
}
.content {
display: flex;
flex-direction: column;
.description {
margin: 5px 0;
display: flex;
align-items: center;
font-size: 14px;
color: rgb(146, 146, 146);
mat-icon {
font-size: 18px;
height: 18px;
width: 18px;
margin-right: 5px;
}
}
.section {
.title {
margin-bottom: 5px;
}
display: flex;
flex-direction: column;
.coordinate {
width: 100%;
mat-form-field {
width: 100%;
}
.input {
font-size: 14px;
}
}
}

.errors {
mat-icon {
font-size: 16px;
height: 16px;
width: 16px;
margin-right: 5px;
color: #f44336;
}
margin-bottom: 10px;
display: flex;
align-items: center;
font-size: 12px;
}
}

.actions {
display: flex;
justify-content: end;
.create-action {
margin-left: 5px;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/*
* Licensed to Gisaïa under one or more contributor
* license agreements. See the NOTICE.txt file distributed with
* this work for additional information regarding copyright
* ownership. Gisaïa licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { AfterViewInit, ChangeDetectorRef, Component, Inject, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Observable, merge, mergeMap, of } from 'rxjs';
import { MapboxAoiDrawService } from '../mapgl/draw/draw.service';
import { Corner } from '../mapgl/draw/draw.models';

@Component({
selector: 'arlas-bbox-generator',
templateUrl: './bbox-generator.component.html',
styleUrls: ['./bbox-generator.component.scss']
})
export class BboxGeneratorComponent implements OnInit, AfterViewInit {
public DESCRIPTION = 'Enter coordinates in decimal or sexagesimal degrees';
public bboxForm: BboxFormGroup;
public placeHolder = 'Decimal: 1.1 or Sexagesimal 1°6\'3" coordinate';
public constructor(
private drawService: MapboxAoiDrawService,
private cdr: ChangeDetectorRef,
@Inject(MAT_DIALOG_DATA) public data: {
initCorner: Corner;
},
public dialogRef: MatDialogRef<BboxGeneratorComponent>,) {
}

public ngOnInit(): void {
if (!!this.data && !this.data.initCorner) {
this.data.initCorner = {
lat: 32,
lng: -8
};
}
this.bboxForm = new BboxFormGroup(this.data.initCorner);
}
public ngAfterViewInit(): void {
this.cdr.detectChanges();
}

public getErrorMessage(formControl: FormControl | FormGroup) {
if (formControl.hasError('required')) {
return 'You must enter a coordinate';
} else if ((formControl as BboxFormGroup).latitudeErrors) {
return 'Both corners have the same latitudes, change one of them.';
}
return formControl.hasError('pattern') ? 'Enter a coordinate in decimal (1.1) or sexagesimal (1° 6\' 3")' : '';
}

public generateBbox() {
this.drawService.drawBbox(this.bboxForm.getFirstCorner(), this.bboxForm.getSecondCorner());
this.dialogRef.close();
}

}

export class BboxFormGroup extends FormGroup {

private firstCornerLatitude;
private secondCornerLatitude;
public firstCorner: PointFormGroup;
public secondCorner: PointFormGroup;
public latitudeErrors = false;
public constructor(corner: Corner) {
const firstCorner = new PointFormGroup(corner.lat - 0.5, corner.lng - 0.5);
const secondCorner = new PointFormGroup(corner.lat + 0.5, corner.lng + 0.5);
super({
firstCorner,
secondCorner
});
this.firstCorner = firstCorner;
this.secondCorner = secondCorner;

this.firstCorner.latitude.valueChanges.subscribe(v => {
this.firstCornerLatitude = v;
this.secondCornerLatitude = this.secondCorner.latitude.value;
if (this.secondCornerLatitude !== undefined) {
if (this.parse(this.firstCornerLatitude) === this.parse(this.secondCornerLatitude)) {
this.latitudeErrors = true;
} else {
this.latitudeErrors = false;
}
}
});

this.secondCorner.latitude.valueChanges.subscribe(v => {
this.secondCornerLatitude = v;
this.firstCornerLatitude = this.firstCorner.latitude.value;
if (this.firstCornerLatitude !== undefined) {
if (this.parse(this.firstCornerLatitude) === this.parse(this.secondCornerLatitude)) {
this.latitudeErrors = true;
} else {
this.latitudeErrors = false;
}
}
});
}

public getFirstCorner(): Corner {
this.parse(this.firstCorner.latitude.value);
this.parse(this.firstCorner.longitude.value);
return {
lat: this.parse(this.firstCorner.latitude.value),
lng: this.parse(this.firstCorner.longitude.value)
};
}

public getSecondCorner(): Corner {
return {
lat: this.parse(this.secondCorner.latitude.value),
lng: this.parse(this.secondCorner.longitude.value)
};
}

private parse(value: string) {
// eslint-disable-next-line max-len
const coordinatesRegex = '^(?<decimal>[+-]?([0-9]*[.])?[0-9]+)$|^(?<degrees>(-?)[0-9]+)°[ ]*((?<minutes>[0-9]+)\'[ ]*((?<seconds>[0-9]+)\")?)?$';
const parsedCoordinates = (String(value)).match(coordinatesRegex);
if (parsedCoordinates && parsedCoordinates.groups) {
const groups = parsedCoordinates.groups;
if (groups.decimal) {
return +groups.decimal;
} else {
const degrees = +groups.degrees;
const minutes = +groups.minutes;
const seconds = +groups.seconds;
return this.dmsToDd(degrees, minutes, seconds);
}
}
}

private dmsToDd(degrees: number, minutes: number, seconds: number) {
const isNegative = (degrees < 0);
if (!minutes) {
minutes = 0;
}
if (!seconds) {
seconds = 0;
}
const dd = Math.abs(degrees) + minutes / 60 + seconds / 3600;
return isNegative ? -dd : dd;
}
}

export class PointFormGroup extends FormGroup {

public latitude: FormControl;
public longitude: FormControl;

public latitudeChanges$: Observable<any>;
public longitudesChanges$: Observable<any>;

public constructor(initLat: number, initLng: number) {
// eslint-disable-next-line max-len
const coordinatesRegex = '^(?<decimal>[+-]?([0-9]*[.])?[0-9]+)$|^(?<degrees>(-?)[0-9]+)°[ ]*((?<minutes>[0-9]+)\'[ ]*((?<seconds>[0-9]+)\")?)?$';
const latitude = new FormControl(String(initLat), [
Validators.required,
Validators.pattern(coordinatesRegex)
]);
const longitude = new FormControl(String(initLng), [
Validators.required,
Validators.pattern(coordinatesRegex),
]);
super({
latitude,
longitude
});
this.latitude = latitude;
this.longitude = longitude;
}

}


Loading

0 comments on commit a498706

Please sign in to comment.