Skip to content

Commit

Permalink
#368 migrate structure tests
Browse files Browse the repository at this point in the history
  • Loading branch information
vmarc committed Jul 11, 2024
1 parent eb3e0e4 commit 285d5fd
Show file tree
Hide file tree
Showing 10 changed files with 223 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ case class RouteNodeAnalysis(
) {
def nodes: Seq[RouteNodeData] = freeNodes ++ startNodes ++ endNodes ++ redundantNodes

def nodeIds: Seq[Long] = nodes.map(_.node.id)
def nodeIds: Seq[Long] = (startNodes ++ endNodes).map(_.node.id)
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,44 +28,43 @@ class RouteSegmentAnalyzer(context: RouteDetailAnalysisContext) {

def analyze(): Seq[NewRouteSegment] = {
Triplet.slide(context.links.routeLinkWays).foreach { case Triplet(previousRouteLinkWayOption, currentRouteLinkWay, nextRouteLinkWayOption) =>
// val change = isDirectionChange(currentLink, nextLinkOption)
// if (change || fragmentEndContainsNetworkNode(currentLink)) {
// elements += buildSegmentElement(currentElementFragments.toSeq)
// currentElementFragments.clear()
// }

if (currentRouteLinkWay.link.direction == LinkDirection.RoundaboutRight && currentRouteLinkWay.isClosedLoop && currentRouteLinkWay.link.hasNext) {
handleRoundabout(previousRouteLinkWayOption, currentRouteLinkWay, nextRouteLinkWayOption)
}
else {
// if (currentRouteLinkWay.link.direction == LinkDirection.RoundaboutRight) { // roundabout that is not a closed loop
// // finalize current element, if any
// if (fragments.nonEmpty) {
// elements += buildSegmentElement(fragments.toSeq)
// fragments.clear()
// }
// }

val fragment = NewRouteSegmentElementFragment(
fragmentIds.next(),
currentRouteLinkWay.way.id,
currentRouteLinkWay.link,
currentRouteLinkWay.role,
currentRouteLinkWay.nodeIds,
Seq.empty // filled in later during path analysis
)
fragments += fragment
val linkFragments = StructureUtil.split(currentRouteLinkWay.nodeIds, context.routeNodeAnalysis.nodeIds).map { nodeIds =>
toFragment(currentRouteLinkWay, nodeIds)
}

if (context.routeNodeAnalysis.nodeIds.contains(linkFragments.head.fromNodeId)) {
if (fragments.nonEmpty) {
elements += buildSegmentElement(fragments.toSeq)
fragments.clear()
}
}

linkFragments.foreach { fragment =>
if (context.routeNodeAnalysis.nodeIds.contains(fragment.nodeIds.last)) {
fragments += fragment
elements += buildSegmentElement(fragments.toSeq)
fragments.clear()
}
else {
fragments += fragment
}
}

if (!currentRouteLinkWay.link.hasNext) {
elements += buildSegmentElement(fragments.toSeq)
fragments.clear()
if (fragments.nonEmpty) {
elements += buildSegmentElement(fragments.toSeq)
fragments.clear()
}
segments += buildSegment(segments.size + 1, elements.toSeq)
elements.clear()
}
else {

val change = isDirectionChange(currentRouteLinkWay, nextRouteLinkWayOption)
if (change || fragmentEndContainsNetworkNode(fragment)) {
if (change) {
elements += buildSegmentElement(fragments.toSeq)
fragments.clear()
}
Expand Down Expand Up @@ -186,35 +185,6 @@ class RouteSegmentAnalyzer(context: RouteDetailAnalysisContext) {
}
}
}


/*
val toConnectingNodeId = if (lastBackwardElement.direction == RoutePathDirection.Backward) {
lastBackwardElement.toNodeId
} else {
lastBackwardElement.fromNodeId
}
val fromConnectingNodeId = 0 // TODO look ahead to element going backward to this roundabout (not simply the next routeLinkWay)
StructureUtil.closedLoopNodeIds(fromConnectingNodeId, toConnectingNodeId, currentRouteLinkWay.way.nodeIds) match {
case Some(nodeIds) =>
elements += buildFragmentElement(currentRouteLinkWay, RoutePathDirection.Backward, nodeIds)
case None => ???
}
case None =>
StructureUtil.closedLoopNodeIds(currentRouteLinkWay.fromNodeId, nextRouteLinkWay.fromNodeId, currentRouteLinkWay.way.nodeIds) match {
case Some(nodeIds) =>
elements += buildFragmentElement(currentRouteLinkWay, RoutePathDirection.Backward, nodeIds)
case None => ???
}
}
*/
}

private def buildSegment(id: Long, elements: Seq[NewRouteSegmentElement]): NewRouteSegment = {
Expand All @@ -228,28 +198,6 @@ class RouteSegmentAnalyzer(context: RouteDetailAnalysisContext) {
)
}

// private def buildSegmentElements(fragments: Seq[NewRouteSegmentElementFragment]): Seq[NewRouteSegmentElement] = {
// // TODO redesign - for now assuming that network nodes are at way start or end node (later allow way splitting, and roundabout handling)
// val elements = ListBuffer[NewRouteSegmentElement]()
// val currentElementFragments = ListBuffer[NewRouteSegmentElementFragment]()
//
// Triplet.slide(fragments).foreach { case Triplet(_, currentLink, nextLinkOption) =>
// currentElementFragments += currentLink
// val change = isDirectionChange(currentLink, nextLinkOption)
// if (change || fragmentEndContainsNetworkNode(currentLink)) {
// elements += buildSegmentElement(currentElementFragments.toSeq)
// currentElementFragments.clear()
// }
// }
//
// if (currentElementFragments.nonEmpty) {
// elements += buildSegmentElement(currentElementFragments.toSeq)
// currentElementFragments.clear()
// }
//
// elements.toSeq
// }

private def fragmentEndContainsNetworkNode(fragment: NewRouteSegmentElementFragment): Boolean = {
context.routeNodeAnalysis.nodeIds.contains(fragment.nodeIds.last) // TODO redesign - not sure if this is ok
}
Expand Down Expand Up @@ -315,4 +263,15 @@ class RouteSegmentAnalyzer(context: RouteDetailAnalysisContext) {
Seq(fragment)
)
}

private def toFragment(routeLinkWay: RouteLinkWay, nodeIds: Seq[Long]): NewRouteSegmentElementFragment = {
NewRouteSegmentElementFragment(
fragmentIds.next(),
routeLinkWay.way.id,
routeLinkWay.link,
routeLinkWay.role,
nodeIds,
Seq.empty // filled in later during path analysis
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ package kpn.server.analyzer.engine.analysis.route.structure
case class Structure(
forwardPath: Option[StructurePath],
backwardPath: Option[StructurePath],
startTentaclePaths: Seq[StructurePath],
endTentaclePaths: Seq[StructurePath],
otherPaths: Seq[StructurePath]
)
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ class StructureAnalyzer(traceEnabled: Boolean = false) {
Structure(
forwardPath = None,
backwardPath = None,
otherPaths = Seq.empty
startTentaclePaths = Seq.empty,
endTentaclePaths = Seq.empty,
otherPaths = Seq.empty,
)
}
else {
Expand Down Expand Up @@ -108,11 +110,74 @@ class StructureAnalyzer(traceEnabled: Boolean = false) {
}
}

val usedPathIds = forwardPath.toSeq.flatMap(_.pathIds) ++ backwardPath.toSeq.flatMap(_.pathIds)
val remainingPaths = paths.filterNot(path => usedPathIds.contains(path.id))

val startTentacleFromNodes = routeNodeAnalysis.startNodes.dropRight(1)
val startTentaclePaths = startTentacleFromNodes.flatMap { fromNode =>
remainingPaths.find(_.fromNodeId == fromNode.node.id) match {
case None => None
case Some(firstPath) =>
Some(
StructurePath(
firstPath.fromNodeId,
firstPath.toNodeId,
Seq(
StructurePathElement(
firstPath,
reversed = false
)
)
)
)
}
}

val endTentacleToNodes = routeNodeAnalysis.endNodes.drop(1)
val endTentaclePaths = endTentacleToNodes.flatMap { toNode =>
remainingPaths.find(_.toNodeId == toNode.node.id) match {
case None => None
case Some(firstPath) =>
Some(
StructurePath(
firstPath.fromNodeId,
firstPath.toNodeId,
Seq(
StructurePathElement(
firstPath,
reversed = false
)
)
)
)
}
}

val otherPaths = {
val usedPathIds = forwardPath.toSeq.flatMap(_.pathIds) ++ backwardPath.toSeq.flatMap(_.pathIds) ++
startTentaclePaths.flatMap(_.pathIds) ++ endTentaclePaths.flatMap(_.pathIds)
val remainingPaths = paths.filterNot(path => usedPathIds.contains(path.id))
remainingPaths.map { path =>
StructurePath(
path.fromNodeId,
path.toNodeId,
Seq(
StructurePathElement(
path,
reversed = false
)
)
)
}
}

Some(
Structure(
forwardPath,
backwardPath,
otherPaths = Seq.empty
startTentaclePaths,
endTentaclePaths,
otherPaths
)
)
}
Expand All @@ -130,6 +195,8 @@ class StructureAnalyzer(traceEnabled: Boolean = false) {
Structure(
None,
None,
Seq.empty,
Seq.empty,
otherPaths
)
}
Expand Down Expand Up @@ -173,6 +240,8 @@ class StructureAnalyzer(traceEnabled: Boolean = false) {
Structure(
forwardPath,
backwardPath,
Seq.empty,
Seq.empty,
otherPaths
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,29 @@ object StructureUtil {
None
}
}

def split(nodeIds: Seq[Long], nodeNetworkNodeIds: Seq[Long]): Seq[Seq[Long]] = {
val splitNodeIdIndexes = {
if (nodeIds.size > 2) {
(1 until nodeIds.size - 1).filter { index =>
val nodeId = nodeIds(index)
nodeNetworkNodeIds.contains(nodeId)
}
}
else {
Seq.empty
}
}
if (splitNodeIdIndexes.nonEmpty) {
val splits = 0 +: splitNodeIdIndexes :+ nodeIds.size
splits.sliding(2).map { case Seq(from, to) =>
nodeIds.slice(from, to + 1)
}.toSeq
}
else {
Seq(
nodeIds
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,63 +31,6 @@ class RouteAnalysisTest extends UnitTest {
*
*/

test("04 tentacle at start with network node at start and end of first way (similar to 3095938)") {

val d = new RouteTestData("01-02") {
node(1, "01")
node(4, "01")
node(6, "02")

memberWay(10, "", 1, 2, 3, 4)
memberWay(11, "", 4, 5)
memberWay(12, "", 5, 6)
}

new RouteAnalysisInspector() {

startTentacleNode(1)
startNode(4)
endNode(6)

tentacle(4, 3, 2, 1)
forward(4, 5, 6)
backward(6, 5, 4)

structure("forward=(01.a-02 via +<01.a- 11>+<-02 12>)")
structure("backward=(02-01.a via -<-02 12>-<01.a- 11>)")
structure("startTentacles=(01.a-01.b via -<01.b-01.a 10>)")
}.analyze(d)
}

test("05 tentacle at start") {

val d = new RouteTestData("01-02") {
node(1, "01")
node(4, "01")
node(6, "02")

memberWay(10, "", 1, 2, 3)
memberWay(11, "", 3, 4)
memberWay(12, "", 4, 5)
memberWay(13, "", 5, 6)
}

new RouteAnalysisInspector() {

startTentacleNode(1)
startNode(4)
endNode(6)

tentacle(4, 3, 2, 1)
forward(4, 5, 6)
backward(6, 5, 4)

structure("forward=(01.a-02 via +<01.a- 12>+<-02 13>)")
structure("backward=(02-01.a via -<-02 13>-<01.a- 12>)")
structure("startTentacles=(01.a-01.b via -<-01.a 11>-<01.b- 10>)")
}.analyze(d)
}

test("06 tentacle at end") {

val d = new RouteTestData("01-02") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ case class RouteDetailAnalysisTestContext(context: RouteDetailAnalysisContext) {
Seq(
context.newStructure.forwardPath.map(path => "forward=" + pathToString(path)).toSeq,
context.newStructure.backwardPath.map(path => "backward=" + pathToString(path)).toSeq,
context.newStructure.startTentaclePaths.map(path => "startTentacle=" + pathToString(path)).toSeq,
context.newStructure.endTentaclePaths.map(path => "endTentacle=" + pathToString(path)).toSeq,
context.newStructure.otherPaths.map(path => "other=" + pathToString(path)),
).flatten
}
Expand Down
Loading

0 comments on commit 285d5fd

Please sign in to comment.