Formel zur Abgleichung von Positionskoordinaten?

moini

Mitglied
Hello,
in unserem Projekt sollen 3D Objekte (Hochspannungsmaste) konstruiert werden, bei denen ich eine while schleife implementieren wollte, die die Abstände zwischen den eingegebenen Koordinaten prüft und bei Unterschreitung des Mindestabstands von 50 Metern, bzw, Längeneinheiten direkt die erneute Positionseingabe des letzten Objekts auslöst.

Der Abschnitt sieht so aus:

Java:
double[] x = new double[n];
double[] z = new double[n];


                for (int i1 = 0; i1 < n; i1++) {

                    x[i1] = Tastatur.liesDouble("x Koordinate für Position von Mastnummer " + (i1 + 1) + " von " + n + ": ");
                    z[i1] = Tastatur.liesDouble("z Koordinate für Position von Mastnummer " + (i1 + 1) + " von " + n + ": ");

                    //Korrekter Mindestabstand von 50 Metern

                    if (i1>0) {

                        while (Math.sqrt(Math.pow(x[0] - x[i1], 2) + Math.pow(z[0] - z[i1], 2)) < 50) /* &&
                                Math.sqrt(Math.pow(x[i1-2] - x[i1], 2) + Math.pow(z[i1-2] - z[i1], 2)) < 50 &&
                                Math.sqrt(Math.pow(x[i1-3] - x[i1], 2) + Math.pow(z[i1-3] - z[i1], 2)) < 50)
                                */
                        {

                            System.out.println();
                            System.out.println("Whoops... Bitte beachten Sie den nötigen Abstand von 50 Metern zwischen den Masten. ");

                            x[i1] = Tastatur.liesDouble("x Koordinate für Position von Mastnummer " + (i1 + 1) + " von " + n + ": ");
                            z[i1] = Tastatur.liesDouble("z Koordinate für Position von Mastnummer " + (i1 + 1) + " von " + n + ": ");
                        }
                    }

Der kommentierte Abschnitt in der Mitte ist mein work in progress. Ich weiß einfach nicht wie ich das am schlausten lösen kann. Jedes Objekt muss ja immerhin mit jedem anderen schon erfolgreich positionierten Objekt verglichen werden. An sich ist das ja auch lösbar, zumal man insgesamt maximal 10 Objekte konstruieren kann, allerdings wird das mit meiner Methode viel zu viel Code.

Deshalb: hat jemand von euch Ideen und Vorschläge wie ich ohne Redundanz eine Abfrage auf die Beine stelle?

Vielen lieben Dank schon einmal im Voraus!
 
Du schleifst durch alle bisherigen Masten und pruefst den Abstand zum aktuell eingegebenen. Ist einer davon darunter, verlangst du eine neue Eingabe. Idealerweise lagerst du diese Pruefung mit der Schleife in eine eigene Funktion aus, liest sich dann leichter.
 
Also um das in Pseudo-Code auszudruecken:

Code:
funktion istMastInDerNaeheVon(x, z, minimaleDistanz)
    fuer jeden bereits eingegebenen mast
        wenn distanzZwischen(mast, x, z) < minimaleDistanz dann
            return true

    return false
ende

Und die Funktion kannst du dann einfach nach der Eingabe vom neuen Mast aufrufen...etwas Erweiterung wird noch erforderlich sein, aber vom Prinzip her.
 
Java:
for (int i1 = 0; i1 < n; i1++) {

Ich weisz es wird immer unterrichtet i zu verwenden fuer Schleifen, aber wenn man richtige Namen verwendet wird alles so viel besser zu lesen:

Java:
for (int neuerMastIndex = 0; neuerMastIndex < MAXIMALE_ANZAHL_MASTEN; neuerMastIndex++) {
    x[neuerMastIndex] = Tastatur.liesDouble("x Koordinate für Position von Mastnummer " + (neuerMastIndex + 1) + " von " + MAXIMALE_ANZAHL_MASTEN + ": ");
    z[neuerMastIndex] = Tastatur.liesDouble("z Koordinate für Position von Mastnummer " + (neuerMastIndex + 1) + " von " + MAXIMALE_ANZAHL_MASTEN + ": ");
}
 
Ich erlaube mir mal, etwas aufzuräumen:

Java:
public class CoordinateChecker{
    //Zum Thema Record in Java: https://www.baeldung.com/java-record-keyword
    record Coordinate (double X, double Z) {}
  
    private Scanner scanner;
    final double     MINIMUMCLEARANCE = 50.0;
  
    public ArrayList<Coordinate> getUserCoordinates(){
        //Scanner für Tastatureingaben
        scanner = new Scanner(System.input);
        //Kein Array, das macht alles nur umständlich, eine ArrayList macht im Prinzip
        //dasselbe wie ein Array, liefert aber bereits Methoden um z.B. die Länge nicht
        //selber erweitern zu müssen, man muß sich auch nicht vorher auf eine Länge festlegen, usw.
        allCoordinates = new ArrayList<Coordinates>();
      
        nextCoordinate = getNextCoordinateFromUser();
        while(nextCoordinate != Null){
            if(exceedsMinimumClearence(nextCoordinate)){
                System.out.println("Die eingegebene Koordinate verletzt den Mindestabstand.");
            }
            else{
                System.out.println("Koordinate akzeptiert.");
                allCoordinates.add(nextCoordinate);
            }
            nextCoordinate = getNextCoordinateFromUser();
        }
        return allCoordinates;
    }
  
    /*
     * Liest eine Koordinate aus, die der Benutzer eingibt. Liefert Null bei Abbruch.
     */
    private Coordinate getNextCoordinateFromUser(){
        System.out.println("Nächste Koordinate");
      
        System.out.print("X: ");
        if(scanner.hasNextDouble()){
            double x = scanner.nextDouble(); 
        }
        else{
            return null;
        }
      
        System.out.print("Z: ");
        if(scanner.hasNextDouble()){
            double z = scanner.nextDouble(); 
        }
        else{
            return null;
        }
      
        return new Coordinate(x, z);
    }
  
    /*
     * Prüft, ob die übergebene Koordinate den Mindestabstand zu irgendeiner anderen der
     * bereits gesammelten Koordinate unterschreitet. Liefert true bei der ersten
     * Unterschreitung und bricht die Prüfung ab, liefert false wenn keine Unterschreitung
     * gefunden wurde. Die Methode funktioniert nur wenn alle Koordinaten positiv sind,
     * ansonsten braucht es noch eine Fallunterscheidung und Betragsberechnung.
     */
    private boolean exceedsMinimumClearence(Coordinate coordinateA){
        for(Coordinate coordinateB){
            double deltaX, deltaZ;
          
            //Der Abstand zwischen zwei Punkten in einem zweiachsigen Koordinatensystem kann
            //über den Phytagoras der absoluten Abstände auf den jeweiligen Achsen berechent werden.
            deltaX = coordinateA.getX() - coordinateB.getX();
            deltaZ = coordinateA.getZ() - coordinateB.getZ();
          
            double clearance = sqrt(Math.pow(deltaX, 2) + Math.pow(deltaZ));
          
            if(MINIMUMCLEARANCE > clearance){return true};
        }
           return false;
    }
}

Kurz noch zur Erklärung: Ein Record ist im Prinzip eine Klasse, die nur ein paar primitive Variablen und deren Getter/Setter enthält. Das ist einfacher als ständig zwei Arrays zu synchronisieren, du hast dann halt immer die zusammengehörenden X- und Z-Werte beisammen. Und anstelle eines Arrays habe ich eine ArrayList genommen, die erleichtert vieles. Du kannst dann einfach ein Element rausnehmen, am Ende ein neues Element einfügen, usw, ansonsten macht sie dasselbe wie ein Array.

Um deine eigentliche Frage zu beantworten: Den Abstand zwischen zwei Masten kann man über den Phytagoras berechnen, du brauchst lediglich die Abstände auf jeder Achse. Ich gehe jetzt mal nur von positiven Koordinaten aus, wenn ihr negative Koordinaten habt reicht eine einfache Differenzbildung nicht mehr, dann müßt ihr vorher unterscheiden in welchem Quadranten ihr seid. Das Prinzip bleibt aber dasselbe.

Normalerweise kauen wir hier nicht fertigen Code vor, aber ich hab schon relativ lange keinen Javaquelltext mehr geschrieben weil keine Zeit, und hatte Bock dazu. Ich habe es aber nicht getestet, ich habe es nichtmal in der IDE sondern direkt hier im Browser getippt, da wird wahrscheinlich noch der ein oder andere kleine Fehler drin sein. Die darfst du gerne beheben, das sollte mit dem Debugger auch nicht zu schwer sein.

Edit:
Ach siehste, bei den letzten Zeilen in der Abstandsprüfung habe ich nicht aufgepasst, da gehört noch eine If-Abfrage rein.
Jetzt müßte es passen.
 
Zuletzt bearbeitet:
wenn ihr negative Koordinaten habt reicht eine einfache Differenzbildung nicht mehr
Doch doch, die reicht hier auch aus. Der Euclidsche Abstand zwischen zwei Punkten ist immer die Wurzel aus der Summe der Quadrate der Differenzen der einzelnen Koordinaten, egal ob die Koordinaten nun positiv oder negativ sind. (-4 - (-5))^2 wäre als Quadrat der Differenz ja weiterhin richtig.
 
Und da es hier nur um die Frage geht, ob eine bestimmte Distanz eingehalten wird, kann man sich das teure Wurzelziehen auch sparen und quadriert einmal die fragliche Distanz.

Ich bin so frei, und klaue mal den Code von @White_Fox
Java:
    private boolean exceedsMinimumClearence(Coordinate coordinateA){
        double minClearanceSquared = Math.pow(MINIMUMCLEARANCE, 2);

        for(Coordinate coordinateB : allCoordinates) {
            double deltaX = coordinateA.getX() - coordinateB.getX();
            double deltaZ = coordinateA.getZ() - coordinateB.getZ();
          
            double clearance = Math.pow(deltaX, 2) + Math.pow(deltaZ, 2);
          
            if(minClearanceSquared < clearance){return true}; // hier "<", man will ja wissen, ob die MINIMUMCLEARANCE überschritten wurde
        }
        return false;
    }
 
Danke euch allen! Ich glaub damit kann ich auf jeden Fall was anfangen😀
Schön...wie gesagt, wenn du das in dein Programm einbaust, tue dir in jedem Fall den Gefallen und gieße die Koordinaten in einen vernünftigen Datentyp – notfalls machst du eine richtige Klasse mit Zugriffsmethoden, wenn Records dir zuviel Voodoo sind – und verzichte auf den Arrayquatsch, Arbeiten mit Arrays sind schon ziemlich 80er. Auch wenn früher™ nicht alles schlecht war, Collections in jeder Form gehören da nicht dazu, da gibt es heute eigentlich immer was besseres als Arrays.

Wenn dir ArrayLists oder dergleichen noch nicht geläufig sind, die Autovervollständigung einer modernen IDE wird dir da weiterhelfen. Normalerweise wird dir auch noch die Dokumentation dazu angezeigt, aber normalerweise sind die Methoden weitgehend selbsterklärend: add(), remove(), isEmpty(), get(), usw. sollten nur noch wenige Fragen offen lassen.
 

Neue Themen


Zurück
Oben