Vorab: ich gehe davon aus, dass die Methode findTack() bereits Switches richtig behandelt. D. h. es wird nur der Track zurückgegeben, der auch befahrbar ist.Momentan gebe ich in der findTrack Methode eine Track zurück, aber falls es sich um eine Switch handelt, kann daraus gar nicht geschlossen werden um welche Switch es sich handelt, oder?
Wie soll ich das implementieren? Dann kann der Rückgabewert ja nicht Track sein, oder?ich gehe davon aus, dass die Methode findTack() bereits Switches richtig behandelt. D. h. es wird nur der Track zurückgegeben, der auch befahrbar ist.
private Track findTrack(Point point) {
for (Track track : tracks.values()) {
if (inTrack(point, track)) {
return track;
}
}
return null;
}
Es geht nur um die Prüfung, ob der Punkt auf dem Track liegt. Die gezeigte Implementierung von Dir ist vollkommen ok, nur dass inTrack() eine Methode von Track sein sollte (also stattWie soll ich das implementieren? Dann kann der Rückgabewert ja nicht Track sein, oder?
inTrack(point, track)
einfach track.contains(point)
).public boolean canNavigateTo(Point p) {
if (switchedTo == null) { return false; }
Point p1 = getStartPoint();
Point p2 = switchedTo;
if (p1.equals(p) || p2.equals(p)) { return true; }
return p1.x == p.x && p.x == p2.x && (p.y-p1.y)/(p2.y-p1.y) == 0 && (p2.y-p1.y)/(p.y-p1.y) > 0 ||
p1.y == p.y && p.y == p2.y && (p.x-p1.x)/(p2.x-p1.x) == 0 && (p2.x-p1.x)/(p.x-p1.x) > 0;
}
private Track findTrack(Point point) {
for (Track track : tracks.values()) {
if (track.canNavigateTo(point)) {
return track;
}
}
return null;
}
Das reicht ja.@mihe7 Inwiefern kann das Edge übernehmen? Denn Edge modelliert doch nur die Strecke zwischen zwei Punkten und hat dabei keinerlei Aufschluss auf die nächste verbundene Kante, außer das der Endpunkt der vorherigen Kante der Startpunkt der jetzigen Kante ist
Bei Edge ist das sehr einfach, weil es immer nur zwei Endpunkte gibt.wenn ich an Punkt p bin und in Richtung r fahre, von welchem Endpunkt aus bin ich auf dem Track gestartet?
Auch das kann Edge beantworten. Es ist einfach der Abstand zwischen zwei gegebenen Punkten auf der Kante.wie groß ist die Entfernung auf dem Track zwischen p und diesem Endpunkt?
Danke, so ähnlich habe ich es im Prinzip auch gehabt. Durch ein paar kleine Änderungen funktioniert die Funktion jetzt auch tadellos.Die Methode dürfte in Track etwa so aussehen (Fehler nicht ausgeschlossen):
Java:public boolean canNavigateTo(Point p) { if (switchedTo == null) { return false; } Point p1 = getStartPoint(); Point p2 = switchedTo; if (p1.equals(p) || p2.equals(p)) { return true; } return p1.x == p.x && p.x == p2.x && (p.y-p1.y)/(p2.y-p1.y) == 0 && (p2.y-p1.y)/(p.y-p1.y) > 0 || p1.y == p.y && p.y == p2.y && (p.x-p1.x)/(p2.x-p1.x) == 0 && (p2.x-p1.x)/(p.x-p1.x) > 0; }
public void putTrain(Train train, Point point, Point directionVector) {
...
if (!findTrack(point).isPresent()) {
throw new ...("point " + point + " is not passable");
}
long trainLength = train.getLength();
}
Map<Point, Train>
(?))? Es muss ja geschaut werden, ob auf den Gleisen bereits ein anderer Zug steht.Warum weiß der Track nicht einfach, welcher Zug auf ihm steht?Wie speichere ich die aufgegleisten Züge am besten (Map<Point, Train>
(?))? Es muss ja geschaut werden, ob auf den Gleisen bereits ein anderer Zug steht.
Speichert man im Track, dann das Objekt Zug ab oder wie soll das gemacht werden?Warum weiß der Track nicht einfach, welcher Zug auf ihm steht?
Ja.Speichert man im Track, dann das Objekt Zug ab oder wie soll das gemacht werden?
Ja.Denn es kann durchaus sein, das der Zug auf mehreren Gleisen steht und daher mehrere Gleise dann mit dem gleichen Zug belegt werden
Track track = findTrack(point).get();
if (track.getCurrentTrain() != null) {
// Throw exception
}
track.setCurrentTrain(train);
Weil, Du auch hin und her springst. Wir waren ja noch nicht fertig.Allerdings ist mir unklar, wie ich die Länge jetzt noch einbringen soll.
1. wenn ich an Punkt p bin und in Richtung r fahre, von welchem Endpunkt aus bin ich auf dem Track gestartet?
2. wie groß ist die Entfernung auf dem Track zwischen p und diesem Endpunkt?
Beide Fragen kann der Track beantworten.
public Point toDirection() {
return new Point((int)Math.signum(x), (int)Math.signum(y));
}
Wieso ist das wichtig und warum ist gefragt, von welchem Endpunkt der Zug gestartet ist? Es kann doch auch ein Startpunkt einer Track sein. Oder meinst du mit Endpunkt den Punkt, auf dem der hinterste Teil des Zuges steht?1. wenn ich an Punkt p bin und in Richtung r fahre, von welchem Endpunkt aus bin ich auf dem Track gestartet?
Ja.Oder meinst du mit Endpunkt den Punkt, auf dem der hinterste Teil des Zuges steht?
Die Weiche hat ja eine Stellung. Die kann sich schlecht ändern, wenn der Zug auf ihr steht.Ich habe die Länge, aber es geht ja nicht nur in die entgegengesetzte Richtung des Vektors, sondern es kann durch Weichen auch in ganz andere Richtungen gehen.
Genau damit, dass Dir der Track sagt, welche Haltestelle der Zug zuletzt passiert haben muss. Über diesen Punkt kann das RailNetwork den anliegenden Track ermitteln, der Dir wieder sagen kann, welche Haltestelle der Zug zuletzt passiert haben muss usw. Das machst Du so lange, bis die Länge des Zugs erreicht wurde und schon hast Du alle Tracks, auf denen der Zug stehen muss.Wie soll ich den Verlauf des Zuges zurückverfolgen, um den hintersten Punkt zu bekommen?
Auf welche Weise lässt sich das dann implementieren?Ja.
Ja.
Gespeichert werden ja nicht die Objekte selbst, sondern nur Referenzen darauf. Es ist also nicht so, dass da Kopien des Zugs gespeichert würden, sondern alle Tracks, auf denen der Zug steht, würden dann auf das selbe(!) Objekt verweisen.
Denn hier wird erneut nur auf das Gleis, auf welchem sich der Kopf des Zuges befindet mit der Referenz vom Zug bestückt und nicht die anderen Gleise, auf welchen sich der Zug potentiell befinden kannOK, das ist natürlich sinnvoll!
Allerdings ist mir unklar, wie ich die Länge und den Richtungsvektor jetzt noch einbringen soll.Java:Track track = findTrack(point).get(); if (track.getCurrentTrain() != null) { // Throw exception } track.setCurrentTrain(train);
Ah, jetzt verstehe ich die Frage. Das ist an der Stelle auch noch nicht richtig und kommt daher, weil Dagobert schon beim Aufgleisen war, obwohl der entscheidende Punkt noch nicht gelöst wurdeDenn hier wird erneut nur auf das Gleis, auf welchem sich der Kopf des Zuges befindet mit der Referenz vom Zug bestückt und nicht die anderen Gleise, auf welchen sich der Zug potentiell befinden kann
findTrack()
also eine Liste von Tracks zurückgeben?Nein. die Aufgabe von findTrack besteht einfach nur darin, den Track zu liefern, der den gegebenen Punkt enthält, sofern zu diesem überhaupt gefahren werden kann.Muss die MethodefindTrack()
also eine Liste von Tracks zurückgeben?
/*
TODO:
- Check if there is even a track at the point <point>.
- If it is a switch at point <point> then check if it's switched to this track.
- Check if no other train is already on the required track(s) - note the length of the train
- Check if directionVector fits with direction of track
*/
public void putTrain(Train train, Point point, Point directionVector) throws LogicException {
...
long trainLength = train.getLength();
}
Wobei mir gerade auffällt, dass der zweite Punkt noch eine Extrabehandlung braucht, da andere Weichen so gestellt sein könnten, dass das betreffende Gleis umfahren wird...Konkret die ersten beiden Punkte.
Ja. Aber nicht die Anzahl sondern die Menge der Tracks.required track(s) ist somit der Platzbedarf (gemessen in Tracks, welche benötigt werden um den Zug aufzugleisen) des einzelnen Zugs, welcher auf den Gleisen aufliegt.
Eben. Nehmen wir mal an, der Kopf des Zuges würde genau an einem Gleisende stehen, das betreffende Gleis befindet sich bereits in der Liste und len gäbe die noch auf den Gleisen unterzubringende Länge des Zugs an - anfangs also die komplette Länge des Zugs.Ich kenne die Länge des gesamten Zugs und die Länge jedes Gleises und die genaue Länge von dem Gleis auf, welchem der Zugkopf aufliegt.
Pseudocode:Könntest du den Vorgang beispielsweise durch Pseudo-Code etwas verdeutlichen?
Track currentTrack = startTrack;
Point pos = startPosition;
List<Track> required = new ArrayList<>();
while (len > 0) {
if (currentTrack == null || required.contains(currentTrack)) {
// Zug kann nicht positioniert werden
throw new ...
}
required.add(currentTrack);
Point passed = currentTrack.getPassedPoint(direction);
len -= currentTrack.distance(pos, passed);
pos = passed;
currentTrack = getConnection(passed, currentTrack);
}
Ich weiß jetzt nicht, ob Du #88 gesehen hast, verstehe aber Dein Problem nicht:und somit nur den Zugkopf direkt in Relation mit einem track stellen kann und der Rest des Zuges dabei unberücksichtigt bleibt.
V----------Z-----------------H
| | |
|<-------->|<--------------->|
Länge VZ Länge ZH
Nein Ich meine edges.Danke. Sicher, dass du die Map tracks und nicht edges meinst?
Ja, man hat dann die Restlänge von dem Zug, aber das gibt mir ja trotzdem keine Auskunft darüber auf welchen er letztendlich stehen tut. Es sagt mir die Länge VZ/VH befindet sich momentan auf einem anderen Zug in die entgegengesetzte Richtung vom Richtungsvektor.Ich weiß jetzt nicht, ob Du #88 gesehen hast, verstehe aber Dein Problem nicht:
Code:V----------Z-----------------H | | | |<-------->|<--------------->| Länge VZ Länge ZH
Wenn Zug Z irgendwo steht und du weißt, dass er aus Richtung H gekommen ist, kannst Du doch ZH berechnen und weißt, wie viel vom Zug auf diesem Abschnitt höchstens stehen kann.
private Track getConnection(Point point, Track track) {
return edges.get(point).stream().filter(...);
}
Nein, point ist ein Anschlusspunkt - kann nicht mitten auf dem Gleis liegen.@mihe7 Wenn der Punkt noch mitten auf dem Gleis liegt wird dasselbe Gleis zurückgegeben, oder? (getConnection)
private Track getConnection(Point point, Track track) {
return edges.get(point).stream().filter(x -> x.getSwitchedTo() != null);
}