From 216fe4b76b6caedaee2dbd2e1e166c2daecf0049 Mon Sep 17 00:00:00 2001 From: Wagram Airiian Date: Tue, 3 Sep 2024 08:09:47 +0200 Subject: [PATCH] * Add coreLib getGeometryType * Add search result ID * Refactoring --- erdblick_app/app/feature.search.service.ts | 21 ++++++++------ erdblick_app/app/inspection.service.ts | 32 +++++++--------------- erdblick_app/app/view.component.ts | 18 ++++++------ libs/core/include/erdblick/geometry.h | 9 ++++-- libs/core/src/bindings.cpp | 17 ++++++++++-- libs/core/src/geometry.cpp | 8 ++++-- 6 files changed, 61 insertions(+), 44 deletions(-) diff --git a/erdblick_app/app/feature.search.service.ts b/erdblick_app/app/feature.search.service.ts index d976084a..7f000c7d 100644 --- a/erdblick_app/app/feature.search.service.ts +++ b/erdblick_app/app/feature.search.service.ts @@ -8,6 +8,11 @@ import {coreLib, uint8ArrayFromWasm} from "./wasm"; export const MAX_ZOOM_LEVEL = 15; +export interface SearchResultPrimitiveId { + type: string, + index: number +} + function generateChildrenIds(parentTileId: bigint) { if (parentTileId == -1n) { return [0n, 4294967296n]; @@ -33,7 +38,7 @@ class FeatureSearchQuadTreeNode { level: number; children: Array; count: number; - markers: Array<[number, SearchResultPosition]> = []; + markers: Array<[SearchResultPrimitiveId, SearchResultPosition]> = []; rectangle: Rectangle; center: Cartesian3 | null; @@ -42,7 +47,7 @@ class FeatureSearchQuadTreeNode { level: number, count: number, children: Array = [], - markers: Array<[number, SearchResultPosition]> = []) { + markers: Array<[SearchResultPrimitiveId, SearchResultPosition]> = []) { this.tileId = tileId; this.parentId = parentTileId; this.level = level; @@ -59,19 +64,19 @@ class FeatureSearchQuadTreeNode { return Rectangle.contains(this.rectangle, point); } - contains(markers: Array<[number, SearchResultPosition]>) { + contains(markers: Array<[SearchResultPrimitiveId, SearchResultPosition]>) { return markers.some(marker => this.containsPoint(marker[1].cartographicRad as Cartographic) ); } - filterPointsForNode(markers: Array<[number, SearchResultPosition]>) { + filterPointsForNode(markers: Array<[SearchResultPrimitiveId, SearchResultPosition]>) { return markers.filter(marker => this.containsPoint(marker[1].cartographicRad as Cartographic) ); } - addChildren(markers: Array<[number, SearchResultPosition]> | Cartographic) { + addChildren(markers: Array<[SearchResultPrimitiveId, SearchResultPosition]> | Cartographic) { const existingIds = this.children.map(child => child.tileId); const missingIds = generateChildrenIds(this.tileId).filter(id => !existingIds.includes(id)); for (const id of missingIds) { @@ -97,7 +102,7 @@ class FeatureSearchQuadTree { this.root = new FeatureSearchQuadTreeNode(-1n, null, -1, 0); } - private calculateAveragePosition(markers: Array<[number, SearchResultPosition]>): Cartesian3 { + private calculateAveragePosition(markers: Array<[SearchResultPrimitiveId, SearchResultPosition]>): Cartesian3 { const sum = markers.reduce( (acc, marker) => { acc.x += marker[1].cartesian.x; @@ -111,7 +116,7 @@ class FeatureSearchQuadTree { return new Cartesian3(sum.x / markers.length, sum.y / markers.length, sum.z / markers.length); } - insert(tileId: bigint, markers: Array<[number, SearchResultPosition]>) { + insert(tileId: bigint, markers: Array<[SearchResultPrimitiveId, SearchResultPosition]>) { const markersCenter = this.calculateAveragePosition(markers); const markersCenterCartographic = Cartographic.fromCartesian(markersCenter); let currentLevel = 0; @@ -399,7 +404,7 @@ export class FeatureSearchService { } result[2].cartographic = null; const featureId = result[1]; - const id = this.searchResults.length; + const id: SearchResultPrimitiveId = {type: "SearchResult", index: this.searchResults.length}; this.searchResults.push({label: `${featureId}`, mapId: mapId, featureId: featureId}); return [id, result[2]]; })); diff --git a/erdblick_app/app/inspection.service.ts b/erdblick_app/app/inspection.service.ts index 665021d4..1fce019e 100644 --- a/erdblick_app/app/inspection.service.ts +++ b/erdblick_app/app/inspection.service.ts @@ -7,7 +7,7 @@ import {FeatureWrapper} from "./features.model"; import {ParametersService} from "./parameters.service"; import {coreLib} from "./wasm"; import {JumpTargetService} from "./jump.service"; -import {Cartesian3, Cartographic, CesiumMath, Color, Matrix3} from "./cesium"; +import {Cartesian3} from "./cesium"; import {InfoMessageService} from "./info.service"; import {KeyboardService} from "./keyboard.service"; @@ -32,12 +32,12 @@ export class InspectionService { selectedFeatureInspectionModel: Array | null = null; selectedFeatureIdName: string = ""; selectedMapIdName: string = ""; - selectedFeatureGeometryType: string = ""; + selectedFeatureGeometryType: any; selectedFeatureCenter: Cartesian3 | null = null; selectedFeatureOrigin: Cartesian3 | null = null; selectedFeatureBoundingRadius: number = 0; selectedFeature: FeatureWrapper | null = null; - originNormalAndRadiusForFeatureZoom: Subject<[Cartesian3, Cartesian3, number]> = new Subject(); + originAndNormalForFeatureZoom: Subject<[Cartesian3, Cartesian3]> = new Subject(); constructor(private mapService: MapService, private jumpService: JumpTargetService, @@ -63,10 +63,10 @@ export class InspectionService { const center = feature.center() as Cartesian3; this.selectedFeatureCenter = center; this.selectedFeatureOrigin = Cartesian3.fromDegrees(center.x, center.y, center.z); - let radiusPoint = feature.boundingRadiusVector() as Cartesian3; + let radiusPoint = feature.boundingRadiusEndPoint() as Cartesian3; radiusPoint = Cartesian3.fromDegrees(radiusPoint.x, radiusPoint.y, radiusPoint.z); this.selectedFeatureBoundingRadius = Cartesian3.distance(this.selectedFeatureOrigin, radiusPoint); - this.selectedFeatureGeometryType = this.getGeometryType(); + this.selectedFeatureGeometryType = feature.getGeometryType() as any; this.isInspectionPanelVisible = true; this.loadFeatureData(); }); @@ -162,19 +162,6 @@ export class InspectionService { } } - getGeometryType() { - if (this.selectedFeatureInspectionModel) { - for (const section of this.selectedFeatureInspectionModel) { - if (section.key == "Geometry") { - const geometryType = section.children[0].value; - console.log(geometryType) - return geometryType; - } - } - } - return ""; - } - zoomToFeature() { if (!this.selectedFeature) { this.infoMessageService.showError("Could not zoom to feature: no feature is selected!"); @@ -185,7 +172,7 @@ export class InspectionService { return; } - if (this.selectedFeatureGeometryType.toLowerCase() == "mesh") { + if (this.selectedFeatureGeometryType === this.GeometryType.Mesh) { let triangle: Array = []; if (this.selectedFeatureInspectionModel) { for (const section of this.selectedFeatureInspectionModel) { @@ -208,17 +195,18 @@ export class InspectionService { ); Cartesian3.negate(normal, normal); Cartesian3.normalize(normal, normal); - Cartesian3.multiplyByScalar(normal, this.selectedFeatureBoundingRadius, normal); - this.originNormalAndRadiusForFeatureZoom.next([this.selectedFeatureOrigin, normal, this.selectedFeatureBoundingRadius]); + Cartesian3.multiplyByScalar(normal, 3 * this.selectedFeatureBoundingRadius, normal); + this.originAndNormalForFeatureZoom.next([this.selectedFeatureOrigin, normal]); } } else if (this.selectedFeatureCenter) { this.mapService.moveToWgs84PositionTopic.next({ x: this.selectedFeatureCenter.x, y: this.selectedFeatureCenter.y, - z: this.selectedFeatureCenter.z + this.selectedFeatureBoundingRadius + z: this.selectedFeatureCenter.z + 3 * this.selectedFeatureBoundingRadius }); } } protected readonly InspectionValueType = coreLib.ValueType; + protected readonly GeometryType = coreLib.GeomType; } \ No newline at end of file diff --git a/erdblick_app/app/view.component.ts b/erdblick_app/app/view.component.ts index 6b70e0b6..f150f12a 100644 --- a/erdblick_app/app/view.component.ts +++ b/erdblick_app/app/view.component.ts @@ -26,12 +26,13 @@ import {AfterViewInit, Component} from "@angular/core"; import {MapService} from "./map.service"; import {DebugWindow, ErdblickDebugApi} from "./debugapi.component"; import {StyleService} from "./style.service"; -import {FeatureSearchService, MAX_ZOOM_LEVEL} from "./feature.search.service"; +import {FeatureSearchService, MAX_ZOOM_LEVEL, SearchResultPrimitiveId} from "./feature.search.service"; import {CoordinatesService} from "./coordinates.service"; import {JumpTargetService} from "./jump.service"; import {distinctUntilChanged} from "rxjs"; import {SearchResultPosition} from "./featurefilter.worker"; import {InspectionService} from "./inspection.service"; +import {KeyboardService} from "./keyboard.service"; // Redeclare window with extended interface declare let window: DebugWindow; @@ -73,6 +74,7 @@ export class ErdblickViewComponent implements AfterViewInit { public parameterService: ParametersService, public jumpService: JumpTargetService, public inspectionService: InspectionService, + public keyboardService: KeyboardService, public coordinatesService: CoordinatesService) { this.tileVisForPrimitive = new Map(); @@ -147,13 +149,13 @@ export class ErdblickViewComponent implements AfterViewInit { this.coordinatesService.mouseClickCoordinates.next(Cartographic.fromCartesian(coordinates)); } let feature = this.viewer.scene.pick(position); - if (defined(feature) && feature.primitive instanceof Billboard) { + if (defined(feature) && feature.primitive instanceof Billboard && feature.primitive.id.type === "SearchResult") { if (feature.primitive.id) { - const featureInfo = this.featureSearchService.searchResults[feature.primitive.id]; + const featureInfo = this.featureSearchService.searchResults[feature.primitive.id.index]; if (featureInfo.mapId && featureInfo.featureId) { this.jumpService.highlightFeature(featureInfo.mapId, featureInfo.featureId).then(() => { if (this.inspectionService.selectedFeature) { - this.mapService.focusOnFeature(this.inspectionService.selectedFeature); + this.inspectionService.zoomToFeature(); } }); } @@ -243,8 +245,8 @@ export class ErdblickViewComponent implements AfterViewInit { } }); - this.inspectionService.originNormalAndRadiusForFeatureZoom.subscribe(values => { - const [origin, normal, radius] = values; + this.inspectionService.originAndNormalForFeatureZoom.subscribe(values => { + const [origin, normal] = values; // this.viewer.entities.add({ // position: origin, // point: { @@ -470,12 +472,12 @@ export class ErdblickViewComponent implements AfterViewInit { renderFeatureSearchResultTree(level: number) { this.featureSearchService.visualization.removeAll(); const color = Color.fromCssColorString(this.featureSearchService.pointColor); - let markers: Array<[number, SearchResultPosition]> = []; + let markers: Array<[SearchResultPrimitiveId, SearchResultPosition]> = []; const nodes = this.featureSearchService.resultTree.getNodesAtLevel(level); for (const node of nodes) { if (node.markers.length) { markers.push(...node.markers); - } else if (node.count > 0) { + } else if (node.count > 0 && node.center) { this.featureSearchService.visualization.add({ position: node.center, image: this.featureSearchService.getPinGraphics(node.count), diff --git a/libs/core/include/erdblick/geometry.h b/libs/core/include/erdblick/geometry.h index 6ac8d52d..dad47d13 100644 --- a/libs/core/include/erdblick/geometry.h +++ b/libs/core/include/erdblick/geometry.h @@ -33,11 +33,16 @@ bool isPointInsideTriangle(Point const& p, Point const& p0, Point const& p1, Poi Point geometryCenter(model_ptr const& g); /** - * Calculate a reasonable bounding radius for the given geometry + * Calculate a point furthest from the center for the given geometry. * Used to properly scale the camera in the viewer * relative to the feature's bounding sphere. */ -Point boundingRadiusVector(model_ptr const& g); +Point boundingRadiusEndPoint(model_ptr const& g); + +/** + * Get type of the geometry. + */ +GeomType getGeometryType(model_ptr const& g); /** * Calculate a local WGS84 coordinate system for the geometry. diff --git a/libs/core/src/bindings.cpp b/libs/core/src/bindings.cpp index 0aa6d76c..2c040bf3 100644 --- a/libs/core/src/bindings.cpp +++ b/libs/core/src/bindings.cpp @@ -255,12 +255,25 @@ EMSCRIPTEN_BINDINGS(erdblick) return geometryCenter(self->firstGeometry()); })) .function( - "boundingRadiusVector", + "boundingRadiusEndPoint", std::function( [](FeaturePtr& self){ - return boundingRadiusVector(self->firstGeometry()); + return boundingRadiusEndPoint(self->firstGeometry()); + })) + .function( + "getGeometryType", + std::function( + [](FeaturePtr& self){ + return getGeometryType(self->firstGeometry()); })); + ////////// GeomType + em::enum_("GeomType") + .value("Points", mapget::GeomType::Points) + .value("Line", mapget::GeomType::Line) + .value("Polygon", mapget::GeomType::Polygon) + .value("Mesh", mapget::GeomType::Mesh); + ////////// TileFeatureLayer em::class_("TileFeatureLayer") .smart_ptr>( diff --git a/libs/core/src/geometry.cpp b/libs/core/src/geometry.cpp index 66baa4f8..0b6caf29 100644 --- a/libs/core/src/geometry.cpp +++ b/libs/core/src/geometry.cpp @@ -118,11 +118,11 @@ Point erdblick::geometryCenter(const model_ptr& g) return averageVectorPosition(intersectedTrianglePoints); } -Point erdblick::boundingRadiusVector(const model_ptr& g) +Point erdblick::boundingRadiusEndPoint(const model_ptr& g) { const Point center = erdblick::geometryCenter(g); if (!g) { - std::cerr << "Cannot obtain bounding radius of null geometry." << std::endl; + std::cerr << "Cannot obtain bounding radius vector end point of null geometry." << std::endl; return center; } @@ -144,6 +144,10 @@ Point erdblick::boundingRadiusVector(const model_ptr& g) return farPoint; } +GeomType erdblick::getGeometryType(const model_ptr& g) { + return g->geomType(); +} + double erdblick::pointSideOfLine(const Point& lineVector, const Point& lineStart, const Point& p) { return lineVector.x * (p.y - lineStart.y) - lineVector.y * (p.x - lineStart.x);