Skip to content

Commit

Permalink
Modify Ssld examplar and Free reporting section (#1198)
Browse files Browse the repository at this point in the history
* Modify Ssld examplar and Free reporting section

* Improve after review

* Ssld: Update calculation for dissolution section

* Improve after review

* Improve after review

* Modify examplar
  • Loading branch information
TruongQuangSB authored Dec 20, 2024
1 parent 9cb6e2e commit 8604ece
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 183 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,8 @@ public Optional<TopPath> findShortestPath(final TopPoint from,
return Optional.ofNullable( //
DijkstraShortestPath.findPathBetween(graphView, fromNode,
toNode))
.map(p -> new TopPath(
p.getEdgeList().stream().map(Edge::edge).distinct()
.toList(),
getPathWeight(p),
p.getEdgeList().getFirst().getWeight()));
.map(p -> new TopPath(p.getEdgeList().stream().map(Edge::edge)
.distinct().toList(), getPathWeight(p), from));
}

private static BigDecimal getPathWeight(final GraphPath<Node, Edge> path) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class TopPath {
private final List<TOP_Kante> edges;
private final BigDecimal length;
private final BigDecimal firstEdgeLength;
private final TopPoint startNode;

/**
* @param edges
Expand All @@ -40,6 +41,46 @@ public TopPath(final List<TOP_Kante> edges, final BigDecimal length,
this.edges = edges;
this.length = length;
this.firstEdgeLength = firstEdgeLength;
this.startNode = determineStartNode();
}

/**
* @param edges
* ordered list of edges for this path
* @param length
* the total length of the path. may be less than the total
* length of the edges if the path does not cover the full extent
* of the edges
* @param startNode
* the start point of this path
*/
public TopPath(final List<TOP_Kante> edges, final BigDecimal length,
final TopPoint startNode) {
this.edges = edges;
this.length = length;
this.startNode = startNode;
this.firstEdgeLength = determintFirstEdgeLength();
}

private TopPoint determineStartNode() {
try {
final TOP_Kante firstEdge = edges.getFirst();
return new TopPoint(firstEdge, firstEdge.getTOPKanteAllg()
.getTOPLaenge().getWert().subtract(firstEdgeLength));
} catch (final Exception e) {
throw new IllegalArgumentException(
"Can\'t find start node of TopPath"); //$NON-NLS-1$
}
}

private BigDecimal determintFirstEdgeLength() {
try {
return edges.getFirst().getTOPKanteAllg().getTOPLaenge().getWert()
.subtract(startNode.distance());
} catch (final Exception e) {
throw new IllegalArgumentException(
"Can\'t find first edge length of TopPath"); //$NON-NLS-1$
}
}

/**
Expand Down Expand Up @@ -72,49 +113,76 @@ public BigDecimal firstEdgeLength() {
* on the path
*/
public Optional<BigDecimal> getDistance(final TopPoint point) {
BigDecimal pathOffset = this.firstEdgeLength;

BigDecimal pathOffset = firstEdgeLength;
TOP_Kante previousEdge = null;
for (final TOP_Kante edge : edges()) {
final BigDecimal edgeLength = edge.getTOPKanteAllg().getTOPLaenge()
.getWert();

// If the point is on the current edge, check which direction to add
if (point.edge().equals(edge)) {
// In top direction
if (previousEdge == null
|| previousEdge.getIDTOPKnotenB().getValue() == edge
.getIDTOPKnotenA().getValue()
|| previousEdge.getIDTOPKnotenA().getValue() == edge
.getIDTOPKnotenA().getValue()) {
final BigDecimal pointDistance = pathOffset
.add(point.distance());
if (pointDistance.compareTo(BigDecimal.ZERO) < 0
|| pointDistance.compareTo(length) > 0) {
return Optional.empty();
}

return Optional.of(pointDistance);
}

// against top direction
final BigDecimal pointDistance = pathOffset.add(edgeLength)
.subtract(point.distance());
if (pointDistance.compareTo(BigDecimal.ZERO) < 0
|| pointDistance.compareTo(length) > 0) {
return Optional.empty();
}

return Optional.of(pointDistance);
return getDistance(point, pathOffset, previousEdge, edge);
}

// Point not on this edge, check next edge
if (previousEdge != null) {
pathOffset = pathOffset.add(edgeLength);
}
previousEdge = edge;

}
return Optional.empty();
}

// If the point is on the current edge, check which direction to add
private Optional<BigDecimal> getDistance(final TopPoint point,
final BigDecimal pathOffset, final TOP_Kante previousEdge,
final TOP_Kante edge) {
final BigDecimal edgeLength = edge.getTOPKanteAllg().getTOPLaenge()
.getWert();
// Point in first Edge
if (previousEdge == null) {
return getDistanceOnFirstEdge(point, edgeLength);
}
// In top direction
if (previousEdge.getIDTOPKnotenB().getValue() == edge.getIDTOPKnotenA()
.getValue()
|| previousEdge.getIDTOPKnotenA().getValue() == edge
.getIDTOPKnotenA().getValue()) {

final BigDecimal pointDistance = pathOffset.add(point.distance());
if (pointDistance.compareTo(BigDecimal.ZERO) < 0
|| pointDistance.compareTo(length) > 0) {
return Optional.empty();
}

return Optional.of(pointDistance);
}

// against top direction
final BigDecimal pointDistance = pathOffset.add(edgeLength)
.subtract(point.distance());
if (pointDistance.compareTo(BigDecimal.ZERO) < 0
|| pointDistance.compareTo(length) > 0) {
return Optional.empty();
}

return Optional.of(pointDistance);
}

private Optional<BigDecimal> getDistanceOnFirstEdge(final TopPoint point,
final BigDecimal edgeLength) {
if (point.distance().compareTo(startNode.distance()) == 0) {
return Optional.of(BigDecimal.ZERO);
}

final boolean inTopDirection = edgeLength.subtract(startNode.distance())
.compareTo(firstEdgeLength) == 0;
// Point lie before path start
if (inTopDirection == point.distance()
.compareTo(startNode.distance()) < 0) {
return Optional.empty();
}
return Optional
.of(point.distance().subtract(startNode.distance()).abs());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,8 @@ private static double getOpposideDistance(
new Coordinate(transformX, transformY) });
final List<LineString> relevantGeometries = Streams
.stream(getContainer(potk).getGEOKante())
.filter(geoKante -> GeoKanteExtensions
.topKante(geoKante) != null)
.filter(geoKante -> GeoKanteExtensions
.topKante(geoKante) != potk.getIDTOPKante().getValue())
.map(GEOKanteGeometryExtensions::getGeometry)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,14 @@ public class SsldColumns {
public static final String Manuell = "P";

/**
* Ssld.Aufloesung.Zielgleisabschnitt.Bezeichnung
* Ssld.Aufloesung.Aufloeseabschnitt.Bezeichnung
*/
public static final String Zielgleisabschnitt_Bezeichnung = "Q";
public static final String Aufloeseabschnitt_Bezeichnung = "Q";

/**
* Ssld.Aufloesung.Zielgleisabschnitt.Laenge
* Ssld.Aufloesung.Aufloeseabschnitt.Laenge
*/
public static final String Zielgleisabschnitt_Laenge = "R";
public static final String Aufloeseabschnitt_Laenge = "R";

/**
* Ssld.Aufloesung.Verzoegerung
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,22 @@
*/
package org.eclipse.set.feature.table.pt1.ssld

import java.math.BigDecimal
import java.math.RoundingMode
import java.util.Set
import org.eclipse.set.basis.graph.TopPath
import org.eclipse.set.basis.graph.TopPoint
import org.eclipse.set.core.services.enumtranslation.EnumTranslationService
import org.eclipse.set.core.services.graph.TopologicalGraphService
import org.eclipse.set.feature.table.pt1.AbstractPlanPro2TableModelTransformator
import org.eclipse.set.model.planpro.Ansteuerung_Element.Stell_Bereich
import org.eclipse.set.model.planpro.Basisobjekte.Punkt_Objekt
import org.eclipse.set.model.planpro.Fahrstrasse.Fstr_DWeg
import org.eclipse.set.model.planpro.Fahrstrasse.Fstr_Zug_Rangier
import org.eclipse.set.model.planpro.Signale.Signal
import org.eclipse.set.model.tablemodel.ColumnDescriptor
import org.eclipse.set.ppmodel.extensions.container.MultiContainer_AttributeGroup
import org.eclipse.set.ppmodel.extensions.utils.Case
import org.eclipse.set.utils.math.AgateRounding
import org.eclipse.set.ppmodel.extensions.utils.TopGraph
import org.eclipse.set.utils.table.TMFactory

import static org.eclipse.set.feature.table.pt1.ssld.SsldColumns.*
Expand All @@ -38,8 +39,6 @@ import static extension org.eclipse.set.ppmodel.extensions.PunktObjektExtensions
import static extension org.eclipse.set.ppmodel.extensions.SignalExtensions.*
import static extension org.eclipse.set.ppmodel.extensions.UrObjectExtensions.*
import static extension org.eclipse.set.utils.math.BigDecimalExtensions.*
import org.eclipse.set.ppmodel.extensions.utils.TopGraph
import java.math.BigDecimal

/**
* Table transformation for a Durchrutschwegtabelle (SSLD).
Expand All @@ -57,45 +56,53 @@ class SsldTransformator extends AbstractPlanPro2TableModelTransformator {
this.topGraphService = topGraphService
}

def BigDecimal getShortestPathLength(Signal signal, Punkt_Objekt p) {
def TopPath getShortestPath(Signal signal, Punkt_Objekt p) {
val points1 = signal.singlePoints.map[new TopPoint(it)]
val points2 = p.singlePoints.map[new TopPoint(it)]

return points1.flatMap [ pa |
points2.map [ pb |
topGraphService.findShortestDistance(pa, pb)
topGraphService.findShortestPath(pa, pb)
]
].filter[present].map[get].min
].filter[present].map[get].minBy[length]
}

def String getFreigemeldetLaenge(Fstr_DWeg dweg, TopGraph topGraph,
BigDecimal maxLength) {
val startSignal = dweg?.fstrFahrweg?.start
var fmas = dweg?.FMAs.toList.filter [
topGraph.isInWirkrichtungOfSignal(startSignal, it)
].toList
// When not exists relevant FMA_Komponent/Gleis_Abschluss on the Fstr_Fahrweg of this DWeg,
// then take the FMA_Komponent/Gleis_Abschluss of this FMA_Anlage_Freimeldung,
// which in direction of the start Signal
if (fmas.empty) {
fmas = dweg?.fmaAnlageFreimeldung?.map[fmaGrenzen]?.flatten.toSet.
filter[topGraph.isInWirkrichtungOfSignal(startSignal, it)].
toList
}

val relevantDistances = fmas?.map [
getShortestPathLength(dweg?.fstrFahrweg?.start, it)
val fmas = dweg?.fmaAnlageFreimeldung?.map[fmaGrenzen]?.flatten.toSet.
filter[topGraph.isInWirkrichtungOfSignal(startSignal, it)].toList
val pathFromSignalToFMA = fmas?.map [
it -> getShortestPath(dweg?.fstrFahrweg?.start, it)
]
if (relevantDistances.isEmpty) {
if (pathFromSignalToFMA.isEmpty) {
return ""
}
val roundedDistance = AgateRounding.roundDown(
relevantDistances.max.doubleValue)
if (roundedDistance == 0.0)
throw new IllegalArgumentException("no path found")
else
return roundedDistance > maxLength.doubleValue
? '''> «maxLength.toTableIntegerAgateDown»''' : roundedDistance.toString

val relevantFmas = pathFromSignalToFMA.filter [
dweg.isRelevantFma(key, value)
].toList

// When the free reporting section ending before the Dweg end,
// then take the FMA am nearst of the end of Dweg
if (relevantFmas.isEmpty) {
val fstrTOPKante = dweg.fstrFahrweg.bereichObjektTeilbereich.map [
topKante
]
val relevantPaths = pathFromSignalToFMA.filter [
value.edges.forall[fstrTOPKante.contains(it)]
]
if (relevantPaths.empty) {
throw new IllegalArgumentException("no path found")
}
return relevantPaths.maxBy[value.length].value.length.
toTableIntegerAgateDown
}

val distance = relevantFmas.map[value.length].max
return distance > maxLength
? '''> «maxLength.toTableIntegerAgateDown»'''
: distance.toTableIntegerAgateDown
}

override transformTableContent(
Expand Down Expand Up @@ -309,10 +316,10 @@ class SsldTransformator extends AbstractPlanPro2TableModelTransformator {
]
)

// Q: Ssld.Aufloesung.Zielgleisabschnitt.Bezeichnung
// Q: Ssld.Aufloesung.Aufloeseabschnitt.Bezeichnung
fillConditional(
instance,
cols.getColumn(Zielgleisabschnitt_Bezeichnung),
cols.getColumn(Aufloeseabschnitt_Bezeichnung),
dweg,
[dweg.fstrDWegSpezifisch !== null],
[
Expand All @@ -321,29 +328,14 @@ class SsldTransformator extends AbstractPlanPro2TableModelTransformator {
]
)

// R: Ssld.Aufloesung.Zielgleisabschnitt.Laenge
// R: Ssld.Aufloesung.Aufloeseabschnitt.Laenge
fillConditional(
instance,
cols.getColumn(Zielgleisabschnitt_Laenge),
cols.getColumn(Aufloeseabschnitt_Laenge),
dweg,
[dweg.fstrDWegSpezifisch !== null],
[
val fstrs = fstrZugRangier
if (fstrs.empty) {
return ""
}

val distance = fstrs?.fold(
Double.valueOf(0.0),
[ Double current, Fstr_Zug_Rangier fstr |
Math.max(current,
fstrDWegSpezifisch?.IDFMAAnlageZielgleis?.
value?.IDGleisAbschnitt?.value?.
getOverlappingLength(
fstr.IDFstrFahrweg?.value).doubleValue)
]
)
return AgateRounding.roundDown(distance).toString
getZielGleisAbschnittLength(topGraph)
]
)

Expand All @@ -365,4 +357,34 @@ class SsldTransformator extends AbstractPlanPro2TableModelTransformator {

return factory.table
}

private def String getZielGleisAbschnittLength(Fstr_DWeg dweg,
TopGraph topGraph) {
val fstrs = dweg.fstrZugRangier
if (fstrs.empty) {
return ""
}
val startSignal = dweg?.fstrFahrweg?.start
val fmaAnlage = dweg.fstrDWegSpezifisch?.IDFMAAnlageZielgleis?.value
// The relevant FMA shouldn't lie on direction of start signal
val fmaKomponent = fmaAnlage.fmaGrenzen.filter [
!topGraph.isInWirkrichtungOfSignal(startSignal, it)
].toList
val pathFromSignalToFMA = fmaKomponent.map [
startSignal.getShortestPath(it)
]

// Determine which path overlapping with Fstr and take the longest path
val overlappingPaths = fstrs.map [ fstr |
val fstrTOPKanten = fstr.IDFstrFahrweg?.value.
bereichObjektTeilbereich.map[IDTOPKante.value]
val relevantPath = pathFromSignalToFMA.filter [ path |
path.edges.forall[fstrTOPKanten.contains(it)]
]
return relevantPath.map[it -> length].maxBy[value]
].toList
// Take the longest overlapping path
val maxDistance = overlappingPaths.maxBy[value]
return maxDistance.value.toTableIntegerAgateDown
}
}
Binary file not shown.
Loading

0 comments on commit 8604ece

Please sign in to comment.