Skip to content

Commit

Permalink
#369 monitor vector tiles poc - improve line drawing and add interaction
Browse files Browse the repository at this point in the history
  • Loading branch information
vmarc committed Dec 13, 2023
1 parent 4e90a95 commit 5393328
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 49 deletions.
52 changes: 52 additions & 0 deletions frontend/src/app/monitor/route/map/monitor-route-map.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,23 @@ import { Params } from '@angular/router';
import { MonitorRouteMapPage } from '@api/common/monitor';
import { MapPosition } from '@app/ol/domain';
import { ZoomLevel } from '@app/ol/domain';
import { NetworkMarkerLayer } from '@app/ol/layers';
import { BackgroundLayer } from '@app/ol/layers';
import { MapControls } from '@app/ol/layers';
import { MapLayerRegistry } from '@app/ol/layers';
import { OsmLayer } from '@app/ol/layers';
import { OpenlayersMapService } from '@app/ol/services';
import { NavService } from '@app/components/shared';
import { Util } from '@app/components/shared';
import { MapBrowserEvent } from 'ol';
import { Coordinate } from 'ol/coordinate';
import { FeatureLike } from 'ol/Feature';
import { GeoJSON } from 'ol/format';
import { Geometry } from 'ol/geom';
import Interaction from 'ol/interaction/Interaction';
import VectorLayer from 'ol/layer/Vector';
import Map from 'ol/Map';
import MapBrowserEventType from 'ol/MapBrowserEventType';
import VectorSource from 'ol/source/Vector';
import { Stroke } from 'ol/style';
import { Style } from 'ol/style';
Expand Down Expand Up @@ -99,6 +104,9 @@ export class MonitorRouteMapService extends OpenlayersMapService {
} else {
this.map.getView().fit(Util.toExtent(this.stateService.page().bounds, 0.05));
}

this.map.addInteraction(this.buildInteraction());

this.finalizeSetup(true);
}

Expand Down Expand Up @@ -274,4 +282,48 @@ export class MonitorRouteMapService extends OpenlayersMapService {
};
this.setQueryParams(queryParams);
}

private oldRrelationIdString = '';

private buildInteraction(): Interaction {
return new Interaction({
handleEvent: (event: MapBrowserEvent<MouseEvent>) => {
if (MapBrowserEventType.POINTERMOVE === event.type) {
const features: FeatureLike[] = event.map.getFeaturesAtPixel(event.pixel, {
hitTolerance: 10,
});
const relationIds: string[] = [];
if (features && features.length > 0) {
features.forEach((feature) => {
const layer = feature.get('layer');
if (layer === 'xx') {
const id = feature.get('id');
relationIds.push(id);
}
});
}
event.map.getTargetElement().style.cursor =
relationIds.length >= 1 ? 'pointer' : 'default';
if (relationIds.length >= 1) {
const uniqueRelationIds: number[] = [];
relationIds
.map((r) => +r)
.forEach((relationId) => {
if (!uniqueRelationIds.includes(relationId)) {
uniqueRelationIds.push(relationId);
}
});
uniqueRelationIds.sort((a, b) => a - b);
const relationIdString = JSON.stringify(uniqueRelationIds);
if (this.oldRrelationIdString !== relationIdString) {
this.oldRrelationIdString = relationIdString;
console.log('relationIds=' + relationIdString);
}
}
return true; // propagate event
}
return true; // propagate event
},
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@ case class OsmSegments(
osmSegments: Seq[MonitorRouteSegment],
)

case class TileRelationSegment(
lines: Seq[Line]
)

case class TileRelationData(
relationId: Long,
lines: Seq[Line]
segments: Seq[TileRelationSegment]
)

object MonitorTileTool {
Expand All @@ -46,7 +50,7 @@ object MonitorTileTool {
Mongo.executeIn("kpn-monitor") { database =>
val config = new MonitorTileToolConfig(database)
val tool = new MonitorTileTool(config)
tool.run()
tool.generate()
}
}
}
Expand All @@ -69,20 +73,23 @@ class MonitorTileTool(config: MonitorTileToolConfig) {
6691494L,
)

def run(): Unit = {
val allRelationDatas: Map[Long, TileRelationData] = loadTestRelations()
def generate(): Unit = {
val allRelationDatas: Map[Long, TileRelationData] = loadAllRelations()
(2 to 14) foreach { zoomLevel =>
val tileDatas = config.relationRepository.tilesZoomLevel(zoomLevel)
println(s"zoomLevel=$zoomLevel ")
tileDatas.foreach { tileData =>
val Array(z, x, y) = tileData.name.split("-").map(namePart => java.lang.Integer.parseInt(namePart))
val tile = new Tile(z, x, y)
val tileRelationDatas = tileData.relationIds.flatMap { relationId =>
allRelationDatas.get(relationId)
}
if (tileRelationDatas.nonEmpty) {
val tileBytes = build(tile, tileRelationDatas)
writeTile(tile, tileBytes)
Log.context(s"zoom=$zoomLevel") {
val tileDatas = config.relationRepository.tilesZoomLevel(zoomLevel)
tileDatas.zipWithIndex.foreach { case (tileData, index) =>
Log.context(s"${index + 1}/${tileDatas.size}") {
val Array(z, x, y) = tileData.name.split("-").map(namePart => java.lang.Integer.parseInt(namePart))
val tile = new Tile(z, x, y)
val tileRelationDatas = tileData.relationIds.flatMap { relationId =>
allRelationDatas.get(relationId)
}
if (tileRelationDatas.nonEmpty) {
val tileBytes = build(tile, tileRelationDatas)
writeTile(tile, tileBytes)
}
}
}
}
}
Expand All @@ -95,21 +102,22 @@ class MonitorTileTool(config: MonitorTileToolConfig) {
val encoder = new VectorTileEncoder()

tileRelationDatas.foreach { tileRelationData =>

val coordinates = tileRelationData.lines.flatMap { line =>
Seq(
new Coordinate(tile.scaleLon(line.p1.x), tile.scaleLat(line.p1.y)),
new Coordinate(tile.scaleLon(line.p2.x), tile.scaleLat(line.p2.y))
)
tileRelationData.segments.foreach { segment =>
val coordinates = segment.lines.flatMap { line =>
Seq(
new Coordinate(tile.scaleLon(line.p1.x), tile.scaleLat(line.p1.y)),
new Coordinate(tile.scaleLon(line.p2.x), tile.scaleLat(line.p2.y))
)
}
val lineString = geometryFactory.createLineString(coordinates.toArray)
val userData = Seq(
Some("id" -> tileRelationData.relationId.toString),
// Some("name" -> tileRoute.routeName),
// Some("oneway" -> segment.oneWay.toString),
// Some("surface" -> segment.surface),
).flatten.toMap
encoder.addLineStringFeature("xx", userData, lineString)
}
val lineString = geometryFactory.createLineString(coordinates.toArray)
val userData = Seq(
Some("id" -> tileRelationData.relationId.toString),
// Some("name" -> tileRoute.routeName),
// Some("oneway" -> segment.oneWay.toString),
// Some("surface" -> segment.surface),
).flatten.toMap
encoder.addLineStringFeature("xx", userData, lineString)
}

encoder.encode
Expand Down Expand Up @@ -145,32 +153,35 @@ class MonitorTileTool(config: MonitorTileToolConfig) {
)
)
)
val relationIds = config.database.monitorRelations.aggregate[Id](pipeline).map(_._id)
val relationIds = config.database.monitorRelations.aggregate[Id](pipeline).map(_._id).sorted
log.info(s"loading ${relationIds.size} relations")
loadRelations(relationIds)
}

private def loadRelations(relationIds: Seq[Long]): Map[Long, TileRelationData] = {
log.infoElapsed {
val result = relationIds.zipWithIndex.map { case (relationId, index) =>
log.info(s"${index + 1}/${relationIds.size}")
val geoJsons = readOsmSegments(relationId).flatMap(_.osmSegments).map(_.geoJson)
val lines = geoJsons.flatMap { geoJson =>
val geometry = GeoJSONReader.parseGeometry(geoJson)
geometry match {
case lineString: LineString =>
val points = (0 until lineString.getNumPoints).map { index =>
lineString.getPointN(index)
}
points.sliding(2).map { case Seq(p1, p2) =>
Line(p1.getX, p1.getY, p2.getX, p2.getY)
}
case _ => Seq.empty
Log.context("load-relations") {
log.infoElapsed {
val result = relationIds.zipWithIndex.map { case (relationId, index) =>
log.info(s"${index + 1}/${relationIds.size} $relationId")
val geoJsons = readOsmSegments(relationId).flatMap(_.osmSegments).map(_.geoJson)
val segments = geoJsons.flatMap { geoJson =>
val geometry = GeoJSONReader.parseGeometry(geoJson)
geometry match {
case lineString: LineString =>
val points = (0 until lineString.getNumPoints).map { index =>
lineString.getPointN(index)
}
val lines = points.sliding(2).toSeq.map { case Seq(p1, p2) =>
Line(p1.getX, p1.getY, p2.getX, p2.getY)
}
Some(TileRelationSegment(lines))
case _ => None
}
}
}
(relationId -> TileRelationData(relationId, lines))
}.toMap
(s"loaded ${testRelationIds.size} relations", result)
(relationId -> TileRelationData(relationId, segments))
}.toMap
(s"loaded ${testRelationIds.size} relations", result)
}
}
}

Expand Down

0 comments on commit 5393328

Please sign in to comment.