Methoden Methoden anpassen und fehlende Funktionen hinzufügen

Diskutiere Methoden anpassen und fehlende Funktionen hinzufügen im Allgemeine Java-Themen Bereich.
D

DagobertDuck

Guten Abend,

das Projekt neigt sich langsam dem Ende zu und ich habe noch Schwierigkeiten mit zwei essentiellen Funktionen.

Die erste Funktion ist es, einen Zug auf ein Gleis zu setzen. Dabei wird immer der ganze Zug komplett auf das Gleis gesetzt. Beim Aufsetzen muss ein Richtungsvektor angegeben werden. Dieser gibt die initiale Fahrrichtung des Zuges an. Der Richtungsvektor entspricht dem Richtungsvektor des Gleises oder ist genau der entgegensetze Vektor. Beim Aufgleisen muss beachtet werden, dass die benutzten Gleise noch frei sind, d.h. kein anderer Zug dort steht und es dort überhaupt ein Gleis gibt. Dabei spielt natürlich auch die Länge eines Zuges eine Rolle. Falls der Zug auf eine Weiche gesetzt werden soll, muss zuerst geprüft werden, ob die Gleisweichenstellung dementsprechend eingestellt ist. Falls dies nicht der Fall ist, soll eine Fehlermeldung ausgegeben werden. Falls Gleisweichen auf denen ein Zug bereits steht, geschaltet werden, entgleist der daraufstehende Zug.

Hier ist meine bisherige Methode:
Java:
    /*
    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();

    }
Wie sollte ich am besten alle Züge, die aufgegleist sind, speichern? Für den step <speed> Befehl, der alle Züge um n-Einheiten fahren lässt, ist es wichtig zu wissen, in welche Richtung der Zug fahren soll (Richtungsvektor) und auf welchem Punkt sich der Zugkopf (vorderster Wagen) gerade befindet. Meine ursprüngliche Idee war es, die aufgegleisten Züge in einer Map<Point, Train> zu speichern, aber woher weiß man dann beim step Befehl in welche Richtung er fahren soll? Des Weiteren weiß ich noch nicht so richtig wie ich den angegeben Richtungsvektor, der durch eine x- und y-Koordinate angegeben wird, auszuwerten habe. Macht es Sinn ihn zu normieren?
Ich hoffe, dass mir hierbei jemand helfen könnte.

Viele Grüße
 
mihe7

mihe7

Also besteht das erste Problem schon einmal darin, das betreffende Gleis zu finden. Schreib mal eine Methode dafür.
 
M

Mika34

Eine Möglichkeit ist es über das Kreuzprodukt zu berechnen, zumindest klappt es bei mir auf die Weise, wenn ich über die Edges gehe
Java:
    public boolean isPointOnEdge(int xCoordinateToCheck, int yCoordinateToCheck, int lengthOfTrain,
            int xDirectionVector, int yDirectionVector) {
        for (int i = 0; i < allTracks.size(); i++) {
            if (allTracks.get(i) instanceof NormalTrack) {
                int xCoordStart = allTracks.get(i).getStartXCoordiante();
                int yCoordStart = allTracks.get(i).getStartYCoordiante();
                int xCoordEnd = allTracks.get(i).getEndXCoordiante();
                int yCoordEnd = allTracks.get(i).getEndYCoordiante();

                int dxc = xCoordinateToCheck - xCoordStart;
                int dyc = yCoordinateToCheck - yCoordStart;

                int dxl = xCoordEnd - xCoordStart;
                int dyl = yCoordEnd - yCoordStart;

                int cross = dxc * dyl - dyc * dxl;
                if (cross == 0) {
                    if (Math.abs(dxl) >= Math.abs(dyl)) {
                        if (dxl > 0) {
                            ...
                           
                            }
                        }
 
mihe7

mihe7

Das hilft hier nicht weiter, da wir hier ein anderes Modell haben. Konkret brauchen wir eine Methode der Form
Java:
/** findet den Track, der ein Gleis enthält, auf dem Punkt p liegt. 
  * @returns Track oder null, falls kein Track gefunden wurde.
  */
public Track findTrack(Point p) {
}
Ist jetzt nicht sooo schwer.
 
D

DagobertDuck

@mihe7 Ich habe folgende Idee:
Jede Track durchgehen und überprüfen, ob die Distanz vom Startpunkt zum angegebenen Punkt + die Distanz vom Endpunkt zum angegeben Punkt gleich die Distanz vom Startpunkt zum Endpunkt ist. Sobald eine Track mit dieser Eigenschaft gefunden wird, wird sie returned.

Also irgendwie so:
Java:
if (getStartPoint().distanceTo(point) + getEndPoints.get(0).distanceTo(point) == getStartPoint.distanceTo(getEndPoint.get(0))) {
    // Der Punkt liegt auf dem Gleis
    return track;
}
// Der Punkt liegt auf keinem Gleis
return false;
Das ganze dann in einer for-Schleife und beide Endpunkte beachten. Ist dieser Ansatz sinnvoll, oder geht es besser?
 
D

DagobertDuck

Einer weitere Idee wäre: Für jede Track wird geschaut, ob die x-Koordinate mit der x-Koordinate von dem angegebenen Punkt übereinstimmt. Falls ja, dann: prüfen, ob die y-Koordinate des Punktes zwischen den beiden y-Punkten des Gleises liegt; und umgekehrt. Die Laufzeit des Algorithmus wäre O(n) für die Anzahl der Tracks.
 
mihe7

mihe7

Du kannst dabei ausnutzen, dass Du Track-Objekte hast, die Methoden anbieten können... ;)

EDIT: macht den Umgang mit Weichen einfacher.
 
D

DagobertDuck

Nur wann weiß ich, ob die Track horizontal oder vertikal ist, damit ich entweder die x- oder die y-Koordinate prüfen kann? Muss ich vorher prüfen, ob die x- bzw y-Koordinaten gleich sind -> horizontal / vertikal? Sollte ich mir dafür am besten eine Methode in der Klasse Track schreiben (nur mit welchem Rückgabetyp)?
 
mihe7

mihe7

Frage: liegt Punkt C auf der Strecke AB?

Annahme: C != A und C != B.

Vektoren: a = OA (Ortsvektor von A), v = AB (Vektor), c = OC.

Dann gilt a+r*v = c für ein Skalar r. Also a.x+r*v.x = c.x und a.y+r*v.y = c.y

Falls v.x = 0: r = (c.y-a.y)/v.x; es muss gelten: 0 <= r < 1 und a.x = c.x
Falls v.y = 0: r = (c.x-a.x)/v.x; es muss gelten: 0 <= r < 1 und a.y = c.y

Da wir ganzzahlig unterwegs sind:
Falls a.x == b.x und a.x == c.x und (c.y-a.y)/(b.y-a.y) == 0
oder a.y == b.y und a.y == c.y und (c.x-a.x)/(b.x-a.x) == 0

EDIT: Ende stimmt nicht ganz, hier fehlt noch die Prüfung auf das Vorzeichen.
 
D

DagobertDuck

OK, ich habe jetzt die Methode fertig und sie funktioniert auch. Wenn ich allerdings den Zug auf einen Knoten setze, wird null ausgegeben, da noch nicht klar ist auf welchem Track der Zug steht. Hier muss jetzt irgendwie noch die Länge berücksichtigt werden. Jeder Zug hat Länge >= 1 und es kann daher eindeutig gesagt werden, auf welchem Track / Tracks er sich befindet. Ist der Zug länger als das Gleis auf dem der Zugkopf steht, kann er natürlich auch auf zwei oder mehr Gleisen stehen. 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?
 
M

Mika34

Die größere Frage ist hier doch eigentlich wie man bewerkstelligt, dass mittels der Zuglänge herausgefunden wird, ob sich der Zug auf mehreren Gleisen befindet. Denn vor dem gleichen Problem stehe ich auch, weil ich nur an die Kante rankomme auf dem sich der Zugkopf befindet...
 
mihe7

mihe7

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?
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.

Zur Frage: mach es Dir nicht so kompliziert und lass den Track die Arbeit machen. Es braucht Dich nicht zu interessieren, ob es ein Switch ist oder nicht. Es gibt doch letztlich zwei Fragen:
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.

Bei @Mika34 kann das Edge übernehmen.
 
D

DagobertDuck

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.
Wie soll ich das implementieren? Dann kann der Rückgabewert ja nicht Track sein, oder?
Java:
    private Track findTrack(Point point) {
        for (Track track : tracks.values()) {
            if (inTrack(point, track)) {
                return track;
            }
        }
        return null;
    }
Außerdem ist mir noch nicht ganz klar wie das mit dem Richtungsvektor funktionieren soll. Dieser muss wahrscheinlich erst normiert werden, oder?
 
M

Mika34

@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
 
D

DagobertDuck

@Mika34 Am besten erstellst du dafür noch mal einen eigenen Thread, da sich unsere Modelle unterscheiden. Sonst kommen wir hier durcheinander.
 
Thema: 

Methoden anpassen und fehlende Funktionen hinzufügen

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben