Skip to content

Commit

Permalink
#278 monitor route analysis - wip
Browse files Browse the repository at this point in the history
  • Loading branch information
vmarc committed Jan 9, 2024
1 parent c259d41 commit 9afbb5e
Show file tree
Hide file tree
Showing 8 changed files with 4,125 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,13 @@ import java.nio.charset.Charset
object DownloadRelationTool {

private val routes = Seq(
"VPSM01" -> 15656714L,
"VPSM02" -> 15656715L,
"VPSM03" -> 15656716L,
"VPSM04" -> 12921288L,
"VPSM05" -> 12921427L,
"VPSM06" -> 13014492L,
"VPSM07" -> 13014677L,
"VPSM08" -> 13014771L,
"VPSM09" -> 12955973L,
"VPSM10" -> 12964641L,
"VPSM11" -> 12966181L,
"VPSM12" -> 12966645L,
"VPSM13" -> 12966812L,
"VPSM14" -> 12867780L,
"VPSM15" -> 12882087L,
"VPSM16" -> 12882250L,
"VPSM17" -> 12887722L,
"VPSM18" -> 12859714L,
"VPSM19" -> 12863114L,
"VPSM20" -> 12864030L,
"VPSM21" -> 12865974L,
"route" -> 4840541,
)

def main(args: Array[String]): Unit = {
val overpassQueryExecutor = new OverpassQueryExecutorRemoteImpl()
new DownloadRelationTool(overpassQueryExecutor).download()
println("down")
println("done")
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
package kpn.server.analyzer.engine.analysis.route

import kpn.api.common.data.Node
import kpn.api.common.data.Way

case class RouteWay(way: Way, reversed: Boolean = false)
case class RouteWay(way: Way, reversed: Boolean = false) {

def startNode: Node = {
if (reversed) {
way.nodes.last
}
else {
way.nodes.head
}
}

def endNode: Node = {
if (reversed) {
way.nodes.head
}
else {
way.nodes.last
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
package kpn.server.analyzer.engine.monitor

import kpn.api.common.data.Way
import kpn.api.common.data.WayMember
import kpn.api.custom.Relation
import kpn.server.analyzer.engine.analysis.route.RouteWay

import scala.collection.mutable

class MonitorRouteStructureAnalyzer {

def analyzeRoute(relation: Relation) {
val mainSegments = analyzeMainSegments(relation)
val forwardSegments = analyzeForwardSegments(relation)

debug(s"main segments.size=${mainSegments.size}")
debug(s"forward segments.size=${forwardSegments.size}")

forwardSegments.zipWithIndex.foreach { case (forwardSegment, forwardSegmentIndex) =>
debug(s"forward segment $forwardSegmentIndex")
val startNodeId = forwardSegment.head.startNode.id
val endNodeId = forwardSegment.last.endNode.id
mainSegments.zipWithIndex.foreach { case (mainSegment, mainSegmentIndex) =>
debug(s" test main segment $mainSegmentIndex")
val mainSegmentNodeIds = mainSegment.flatMap(_.way.nodes).map(_.id)
if (mainSegmentNodeIds.contains(startNodeId) || mainSegmentNodeIds.contains(endNodeId)) {
debug(s"forward segment $forwardSegmentIndex matched $mainSegmentIndex")
}
}
}
}

private def analyzeMainSegments(relation: Relation): Seq[Seq[RouteWay]] = {

val ways = relation
.members
.flatMap(member => member match {
case wayMember: WayMember => Some(wayMember)
case _ => None
})
.filter(wayMember => !wayMember.role.isDefined)
.map(_.way)

debug(s"main segments ways.size=${ways.size}")

val segments = analyzeWaySegments(ways)
debug(s"main segments segments.size=${segments.size}")
segments.toSeq
}

private def analyzeForwardSegments(relation: Relation): Seq[Seq[RouteWay]] = {

val wayMembers = relation
.members
.flatMap(member => member match {
case wayMember: WayMember => Some(wayMember)
case _ => None
})

val segments = mutable.Buffer[Seq[RouteWay]]()
val wayMemberIterator = wayMembers.iterator

if (wayMembers.isEmpty) {
// done
}
else if (wayMembers.size == 1) {
val wayMember = wayMemberIterator.next()
if (wayMember.role.contains("forward")) {
segments.addOne(Seq(RouteWay(wayMember.way)))
}
}
else {
val currentSegment = mutable.Buffer[Way]()
var inForwardWays = false
val wayMember = wayMemberIterator.next()
if (wayMember.role.contains("forward")) {
currentSegment.addOne(wayMember.way)
inForwardWays = true
}

while (wayMemberIterator.hasNext) {
val wayMember = wayMemberIterator.next()
// debug(s"way ${wayMember.way.id} ${wayMember.role}")
if (wayMember.role.contains("forward")) {
if (inForwardWays) {
// debug("add way to existing current segment")
currentSegment.addOne(wayMember.way)
}
else {
// debug("add first way to new current segment")
currentSegment.addOne(wayMember.way)
inForwardWays = true
}
}
else {
if (inForwardWays) {
// debug("first way after forward segment, save to segments, and start new segment")
segments.addAll(analyzeWaySegments(currentSegment.toSeq))
currentSegment.clear()
inForwardWays = false
}
}
}

if (currentSegment.nonEmpty) {
segments.addAll(analyzeWaySegments(currentSegment.toSeq))
}
}
segments.toSeq
}


private def analyzeWaySegments(ways: Seq[Way]): Seq[Seq[RouteWay]] = {

val segments = mutable.Buffer[Seq[RouteWay]]()
val wayIterator = ways.iterator

if (ways.isEmpty) {
// done
}
else if (ways.size == 1) {
segments.addOne(Seq(RouteWay(ways.head)))
}
else {
val way1 = wayIterator.next()
val way2 = wayIterator.next()

val routeWays = firstConnection(way1, way2)
if (routeWays.isEmpty) {
segments.addOne(Seq(RouteWay(way1)))
segments.addOne(Seq(RouteWay(way2)))
}
else {
val currentSegment = mutable.Buffer[RouteWay]()
currentSegment.addAll(routeWays)

// endNodeId: handle way without nodes or only one node
var endNodeId = routeWays.last.endNode.id

while (wayIterator.hasNext) {
val way = wayIterator.next()
if (endNodeId == way.nodes.head.id) {
currentSegment.addOne(RouteWay(way))
endNodeId = way.nodes.last.id
}
else if (endNodeId == way.nodes.last.id) {
currentSegment.addOne(RouteWay(way, reversed = true))
endNodeId = way.nodes.head.id
}
else {
if (currentSegment.nonEmpty) {
segments.addOne(currentSegment.toSeq)
currentSegment.clear()
}
}
}

if (currentSegment.nonEmpty) {
segments.addOne(currentSegment.toSeq)
}
}
}

debug(s"way segments.size=${segments.size}")
segments.toSeq
}

private def firstConnection(way1: Way, way2: Way): Seq[RouteWay] = {
if (way1.nodes.last.id == way2.nodes.head.id) {
Seq(
RouteWay(way1),
RouteWay(way2)
)
}
else if (way1.nodes.last.id == way2.nodes.last.id) {
Seq(
RouteWay(way1),
RouteWay(way2, reversed = true)
)
}
else if (way1.nodes.head.id == way2.nodes.head.id) {
Seq(
RouteWay(way1, reversed = true),
RouteWay(way2)
)
}
else if (way1.nodes.head.id == way2.nodes.last.id) {
Seq(
RouteWay(way1, reversed = true),
RouteWay(way2, reversed = true)
)
}
else {
Seq.empty
}
}

private def debug(message: String): Unit = {
println(message)
}
}

0 comments on commit 9afbb5e

Please sign in to comment.