Skip to content

Commit

Permalink
Merge pull request #143 from ndsev/quadtree-clustering
Browse files Browse the repository at this point in the history
Version 2024.3.2
  • Loading branch information
josephbirkner authored Jul 18, 2024
2 parents 4561284 + 2c35821 commit fdec735
Show file tree
Hide file tree
Showing 16 changed files with 615 additions and 105 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

`erdblick` is a dynamic mapviewer built on the `mapget` feature service.

> **Warning ⚠️**: Erdblick is still under active development and hasn't reached its final form. However, we'd love to hear your feedback during this phase.
**Capabilities:** 🛠️

* 🗺️ View map layers from a specific [`mapget`](https://github.com/klebert-engineering/mapget) server.
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2024.3.1
2024.3.2
9 changes: 6 additions & 3 deletions erdblick_app/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {ToastModule} from "primeng/toast";
import {MessageService} from "primeng/api";
import {InputNumberModule} from "primeng/inputnumber";
import {FieldsetModule} from "primeng/fieldset";
import {InfoMessageService} from "./info.service";
import {AlertDialogComponent, InfoMessageService} from "./info.service";
import {SearchPanelComponent} from "./search.panel.component";
import {JumpTargetService} from "./jump.service";
import {MapService} from "./map.service";
Expand Down Expand Up @@ -49,6 +49,7 @@ import {ListboxModule} from "primeng/listbox";
import {FeatureSearchService} from "./feature.search.service";
import {ClipboardService} from "./clipboard.service";
import {MultiSelectModule} from "primeng/multiselect";
import {InputTextareaModule} from "primeng/inputtextarea";

export function initializeServices(styleService: StyleService, mapService: MapService, coordService: CoordinatesService) {
return async () => {
Expand All @@ -69,7 +70,8 @@ export function initializeServices(styleService: StyleService, mapService: MapSe
EditorComponent,
ErdblickViewComponent,
CoordinatesPanelComponent,
FeatureSearchComponent
FeatureSearchComponent,
AlertDialogComponent
],
imports: [
BrowserModule,
Expand Down Expand Up @@ -99,7 +101,8 @@ export function initializeServices(styleService: StyleService, mapService: MapSe
CardModule,
ColorPickerModule,
ListboxModule,
MultiSelectModule
MultiSelectModule,
InputTextareaModule
],
providers: [
{
Expand Down
5 changes: 3 additions & 2 deletions erdblick_app/app/cesium.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ export type PrimitiveCollection = Cesium.PrimitiveCollection;
export const PrimitiveCollection = Cesium.PrimitiveCollection;
export type BillboardCollection = Cesium.BillboardCollection;
export const BillboardCollection = Cesium.BillboardCollection;
export type PointPrimitiveCollection = Cesium.PointPrimitiveCollection;
export const PointPrimitiveCollection = Cesium.PointPrimitiveCollection;
export type PinBuilder = Cesium.PinBuilder;
export const PinBuilder = Cesium.PinBuilder;
export const SceneTransforms = Cesium.SceneTransforms;
export type Entity = Cesium.Entity;
export const Entity = Cesium.Entity;
export type Camera = Cesium.Camera;
Expand Down
99 changes: 83 additions & 16 deletions erdblick_app/app/feature.search.component.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
import {ChangeDetectorRef, Component, Input} from "@angular/core";
import {Component, ViewChild, ViewContainerRef} from "@angular/core";
import {FeatureSearchService} from "./feature.search.service";
import {JumpTargetService} from "./jump.service";
import {InspectionService} from "./inspection.service";
import {MapService} from "./map.service";
import {SidePanelService, SidePanelState} from "./sidepanel.service";
import {Listbox} from "primeng/listbox";
import {InfoMessageService} from "./info.service";

@Component({
selector: "feature-search",
template: `
<p-dialog class="search-menu-dialog" header="Search Loaded Features" [(visible)]="isPanelVisible"
<p-dialog class="search-menu-dialog" header="Search Loaded Features" [(visible)]="isPanelVisible" style="padding: 0 0.5em 0.5em 0.5em"
[position]="'topleft'" [draggable]="false" [resizable]="false" (onHide)="searchService.clear()">
<p-progressBar [value]="percentDone">
<ng-template pTemplate="content" let-percentDone>
<span>{{ searchService.doneTiles }} / {{ searchService.totalTiles }} tiles</span>
</ng-template>
</p-progressBar>
<div class="feature-search-controls">
<div class="progress-bar-container">
<p-progressBar [value]="percentDone">
<ng-template pTemplate="content" let-percentDone>
<span>{{ searchService.doneTiles }} / {{ searchService.totalTiles }} tiles</span>
</ng-template>
</p-progressBar>
</div>
<p-button (click)="pauseSearch()" [icon]="isSearchPaused ? 'pi pi-play-circle' : 'pi pi-pause-circle'" label=""
[disabled]="!canPauseStopSearch" tooltipPosition="bottom"
[pTooltip]="isSearchPaused ? 'Resume search' : 'Pause search'"></p-button>
<p-button (click)="stopSearch()" icon="pi pi-stop-circle" label="" [disabled]="!canPauseStopSearch"
pTooltip="Stop search" tooltipPosition="bottom"></p-button>
</div>
<div style="display: flex; flex-direction: row; justify-content: space-between; margin: 0.5em 0; font-size: 0.9em; align-items: center;">
<span>Elapsed time:</span><span>{{ searchService.timeElapsed }}</span>
</div>
Expand All @@ -34,49 +45,105 @@ import {SidePanelService, SidePanelState} from "./sidepanel.service";
<span>{{ trace.content }}</span>
</p-accordionTab>
</p-accordion>
<p-listbox class="results-listbox" [options]="results" [(ngModel)]="selectedResult"
optionLabel="label" [virtualScroll]="false" [virtualScrollItemSize]="38"
<p-listbox class="results-listbox" [options]="placeholder" [(ngModel)]="selectedResult"
optionLabel="label" [virtualScroll]="true" [virtualScrollItemSize]="35"
[multiple]="false" [metaKeySelection]="false" (onChange)="selectResult($event)"
emptyMessage="No features matched." [scrollHeight]="'calc(100vh - 22em)'"
emptyMessage="No features matched." [scrollHeight]="'calc(100vh - 23em)'"
#listbox
/>
</p-dialog>
<div #alert></div>
`,
styles: [``]
})
export class FeatureSearchComponent {
isPanelVisible: boolean = false;
results: Array<any> = [];
placeholder: Array<any> = [];
traceResults: Array<any> = [];
selectedResult: any;
percentDone: number = 0;
isSearchPaused: boolean = false;
canPauseStopSearch: boolean = false;

@ViewChild('listbox') listbox!: Listbox;
@ViewChild('alert', { read: ViewContainerRef, static: true }) alertContainer!: ViewContainerRef;

constructor(public searchService: FeatureSearchService,
public jumpService: JumpTargetService,
public mapService: MapService,
public inspectionService: InspectionService,
public sidePanelService: SidePanelService) {
public sidePanelService: SidePanelService,
private infoMessageService: InfoMessageService) {
this.sidePanelService.observable().subscribe(panel=> {
this.isPanelVisible = panel == SidePanelState.FEATURESEARCH || this.isPanelVisible;
});
this.searchService.isFeatureSearchActive.subscribe(value => {
this.results = [];
this.searchService.isFeatureSearchActive.subscribe(isActive => {
if (isActive) {
this.results = [];
this.placeholder = [{label: "Loading..."}];
this.canPauseStopSearch = isActive;
} else {
this.listbox.options = this.results;
}
});
this.searchService.searchUpdates.subscribe(tileResult => {
for (const [mapTileKey, featureId, _] of tileResult.matches) {
// TODO: Also show info from the mapTileKey
const mapId = mapTileKey.split(':')[1]
this.results = [...this.results, {label: `${featureId}`, mapId: mapId, featureId: featureId}]
this.results.push({label: `${featureId}`, mapId: mapId, featureId: featureId});
}
});
this.searchService.progress.subscribe(value => {
this.percentDone = value;
if (value >= 100) {
this.listbox.options = this.results;
this.canPauseStopSearch = false;
if (this.searchService.errors.size) {
this.infoMessageService.showAlertDialog(
this.alertContainer,
'Feature Search Errors',
Array.from(searchService.errors).join('\n'))
}
}
});
}

selectResult(event: any) {
if (event.value.mapId && event.value.featureId) {
this.jumpService.highlightFeature(event.value.mapId, event.value.featureId).then();
this.mapService.focusOnFeature(this.inspectionService.selectedFeature!)
this.jumpService.highlightFeature(event.value.mapId, event.value.featureId).then(() => {
if (this.inspectionService.selectedFeature) {
this.mapService.focusOnFeature(this.inspectionService.selectedFeature);
}
});
}
}

pauseSearch() {
if (this.canPauseStopSearch) {
if (this.isSearchPaused) {
this.isSearchPaused = false;
this.searchService.run(this.searchService.currentQuery, true);
return;
}
this.searchService.pause();
this.listbox.options = this.results;
this.isSearchPaused = true;
}
}

stopSearch() {
if (this.canPauseStopSearch) {
this.listbox.options = this.results;
this.searchService.stop();
this.canPauseStopSearch = false;

if (this.searchService.errors.size) {
this.infoMessageService.showAlertDialog(
this.alertContainer,
'Feature Search Errors',
Array.from(this.searchService.errors).join('\n'))
}
}
}
}
Loading

0 comments on commit fdec735

Please sign in to comment.