# Volumen von Quader berechnen



## Blamaster (6. Nov 2012)

Hi,

wie lässt sich das Volumen eines Quaders berechnen, wenn einem nur die Eckpunkte zur Verfügung stehen.

Konkret sind als Beispiel folgende Eckpunkte gegeben:

P1(6.7, 3.9, 1.3)
P2(-8.3, 4.9, 5.3)
P3(-6.3, -1.1, 14.3)
P4(2.7, 4.9, 16.3)
P5(-0.3, -8.1, 8.3)
P6(0.7, 10.9, 7.3)
P7(-2.3, -2.1, -0.7)
P8(8.7, -2.1, 10.3)

Es soll zuerst überprüft werden, ob es sich bei den Koordinaten um einen gültigen Quader handelt und anschließend das Volumen berechnet werden.

Der richtige Ansatz ist wohl über Vektoren auf Parallelität und Orthogonalität zu prüfen. Allerdings weiß ich nicht wie ich die Vektoren dazu aufstellen soll. 

Zuerst müsste man doch auch wissen, welcher der obigen Punkte an welcher Ecke des Quader sitzt oder ?


----------



## Landei (6. Nov 2012)

Der zu einem gegebenen Punkt am weitesten entfernte Punkt ist schon mal die "gegenüberliegende" Ecke (die Verbindung also die Raumdiagonale). Der zu einem gegebenen Punkt am nächsten liegende Punkt hat mit diesem eine gemeinsame Kante.

Einfach mal alle Kombinationen von Abständen ausrechnen...


----------



## SlaterB (6. Nov 2012)

also 'vektor aus zwei punkten' ist in Suchmaschinen schnell getippt und hier so grundlegend,
dass alles weitere wirklich in Frage steht, wenn dieser Schritt bereits unbekannt ist..

was ist ein Vektor überhaupt? was bedeutet ein Vektor (1,1) in 2D? 
die grundsätzliche Defintion ist doch schon mit Punkten verbunden,
ein Vektor (1,1) zeigt von Punkt 0,0 auf Punkt 1,1..


ganz spontane Überlegung noch:
bilde mit je zwei Vektoren eine Ebene, also ziemlich viele Ebenen, über Normalenvektor vergleichen, 
was wie gesagt schon etwas Wissen voraussetzt, evtl. alles nachschlagen

wie man an einem Beispiel-Quader sieht gibt es nicht nur die gewünschten Außenseiten sondern auch in Diagonalen Ebenen als mehreren Vektoren und dazu paar nicht ganz so wichtige,
ob es hilft kann ich nicht sagen


----------



## Blamaster (6. Nov 2012)

Ich glaube ich muss doch erstmal sicher gehen, dass ich die Mathematik dahinter verstehe. 

Jeder meiner 8 Punkte ist ein Vektor mit den Koordinaten x,y,z.

Nun nehme ich als Beispiel P1 und P2 zum betrachten. 

P1(6.7, 3.9, 1.3)
P2(-8.3, 4.9, 5.3)

Mit der Rechnung P1->P2:
(-8.3 - 6.7) x
( 4.9 - 3.9) y
( 5.3 - 1.3) y

= (-15, 1, 4)

bilde ich P1 auf P2 ab. Sprich ich erhalte mit (-15, 1, 4) die x,y und z Werte um die P1 verschoben werden muss um auf P2 zu liegen. 

Berechne ich nun die Länge des Vektor (-15, 1, 4):

sqrt(15² + 1² + 4²) = 15,56

so sagt mir die 15,56, dass wenn ich P1 und P2 mit einer Linie auf direktem Weg verbinde, so hat diese Linie eine Länge von 15,56. 

So weit alles richtig ?


----------



## pappawinni (6. Nov 2012)

bah.. das wird wohl nicht ganz einfach.
Hm, ein Würfel hätte z.B. ja auch 8 Ecken, also sowas ähnliches ist das dann wohl. 
D.h. es dürfte 6 Seitenflächen geben, die es zu identifzieren gilt.
Für eine Seitenfläche gilt dann wohl, dass 4 Punkte darauf liegen und die jeweils anderen auf nur einer Seite dieser Ebene liegen.
kennt man dann die Anordnung der Seitenflächen bzw. der Kanten, sollte es möglich sein, mit Hilfe des Spatproduktes das Volumen des Körpers schrittweise zu berechnen. 
Da muss selbst ich länger drüber nachdenken... und dabei weiss ich immerhin schon, was ein Differenzvektor ist.


----------



## Blamaster (6. Nov 2012)

Ich habe noch eine neue Idee (hoffe ich zumindest)

Wenn man jetzt erstmal davon ausgeht, dass es sich um einen Würfel handelt. 

Ich habe jetzt mal folgendes angewendet. 

Ich nehme mir einfach P1 und bilde P1 auf alle anderen 7 Punkte ab. 
Dann verwende ich die obige Berechnung um auf die Länge des Vektors zu kommen. 


```
public static void main(String[] args) {
        double[][] testArray = {{6.7, 3.9, 1.3},{-8.3, 4.9, 5.3},{-6.3, -1.1, 14.3},{2.7, 4.9, 16.3},
                {-0.3, -8.1, 8.3},{0.7, 10.9, 7.3},{-2.3, -2.1, -0.7},{8.7, -2.1, 10.3}};
        double tmp;
        double[] tmpVec = new double[3];
        double length = 0;
        
        for(int i = 0 ; i< 8; i++) {
            for(int x = 0; x < 8; x++) {
                if (i != x) {
                    tmp = 0;
                    tmpVec[0] = testArray[i][0] - testArray[x][0];
                    tmpVec[1] = testArray[i][1] - testArray[x][1];
                    tmpVec[2] = testArray[i][2] - testArray[x][2];
            
                    length = Math.sqrt(Math.abs((Math.pow(tmpVec[0], 2) + Math.pow(tmpVec[1], 2) + Math.pow(tmpVec[2], 2))));
                    System.out.printf("Punkt %d zu Punkt %d : %.3f \n", i+1, x+1, length);
                }
            }
        }

    }
```

In der Ausgabe lässt sich erkennen, dass immer nur 3 Werte herauskommen:
19,053
15,556
11,000

19,053 sprich den größten Wert kann man ja schnell identifizieren. Das ist die Diagonale. Liege ich jetzt komplett daneben, wenn ich sagen würde, dass 15,556 und 11,000 die Höhe und Breite jeder Seitenfläche sind ?


----------



## Blamaster (6. Nov 2012)

Hi,

mir kam gerade noch ein Ansatz. Um zu prüfen, ob es sich um einen Würfel handelt, sollte es doch reichen, wenn ich Mir einen der 8 Punkte aussuche. Am einfachsten P1 den auf P2-P7 abbilde und jeweils die Länge des Vektors bestimme. Wenn alle 7 Ergebnisse = sind, dann handelt es sich um einen Würfel und ich kann das Volumen bequem mit der Formel a^3 sprich (Länge des Vektors)^3 bestimmen. 

Damit wäre zumindest schonmal Teil 1 der Aufgabe unter Kontrolle. 

Kann jemand bestätigen ob das so passt ?


----------



## SlaterB (6. Nov 2012)

reicht für sich nicht, kann ja sein dass alle anderen Punkte gemeinerweise in einer Ebene kreisförmig drumherum angeordnet sind, so dass es für diesen einen Punkt mit dem Abständen gut aussieht,
wenn die Bedingung für zwei oder gleich alle Punkte gilt, insbesondere mit gleichen drei Abständen, dann schon etwas verläßlicher

also
19,053
15,556
11,000

7x derselbe Wert wäre ja wohl nicht gut

die drei Werte
19,053
15,556
11,000
kann man auch untereinander prüfen, wurzel(11*11*2) ~ 15,556, 
das stimmt nach Pythagoras, für die komplette Diagonale im Wüfel gibts sicher auch ne Formel


deine Aufgabe betrifft aber noch einen Quader, nicht nur Würfel, das gibt paar mehr relevante Entfernungen,
male dir Beispiele auf,

dürfte aber alles ein günstiger Weg sein, ja,
von mir Zustimmung, was du aber nicht mit Sicherheit verwechseln solltest 

bei Bedarf wie gesagt noch Ebenen anschauen, zumindest ob paar rechte Winkel drin sind usw.,
muss auch erstmal geschafft werden, Ebene mit Normalvector kommt doch nochmal ins Spiel


----------



## Helgon (6. Nov 2012)

Ist ein Quader nicht auch ein Spat und dann Spatprodukt einfach, wenns doch 3 Vektoren sind?

Spatprodukt ? Wikipedia


----------



## pappawinni (6. Nov 2012)

ach.. ja.. bin ja doof... Quader.. freilich, das müsste ja dann tatsächlich was rechtwinkliges sein, also nicht wirklich weit vom Würfel entfernt.
Wenn man da den mittleren Wert der X, Y und Z Koordinaten berechnet, dürfte das dann den Mittelpunkt des Quaders ergeben.
Von diesem müssten alle Punkte den gleichen Abstand haben. 
Damit wüsste man dann auch schon mal die Diagonale, denk ich.
Bringt uns das jetzt weiter ?

[EDIT]
Hm.. und du hast nur drei verschiedene Abstände ... sieht nach Würfel mit Kantenlänge 11 aus.
[/EDIT]


----------



## Blamaster (6. Nov 2012)

Die Idee mit dem Mittelpunkt gefällt mir  

Allerdings will das noch nicht so ganz klappen:


```
public static void main(String[] args) {
        //double[][] testArray = {{6.7, 3.9, 1.3},{-8.3, 4.9, 5.3},{-6.3, -1.1, 14.3},{2.7, 4.9, 16.3},
        //        {-0.3, -8.1, 8.3},{0.7, 10.9, 7.3},{-2.3, -2.1, -0.7},{8.7, -2.1, 10.3}};
        
        double[][] testArray = {{0.0, 0.0, 0.0},{0.0, 0.0, 5.0},{5.0, 0.0, 0.0},{5.0, 0.0, 5.0},
                {0.0, 5.0, 0.0},{0.0, 5.0, 5.0},{5.0, 5.0, 0.0},{5.0, 5.0, 5.0}};
        
        //double[][] testArray = {{0.0, 0.0, 0.0},{0.0, 5.0, 0.0},{0.0, 3.0, 4.0},{0.0, 8.0, 4.0},
        //        {5.0, 0.0, 0.0},{5.0, 5.0, 0.0},{5.0, 3.0, 4.0},{5.0, 8.0, 4.0}};
        
        double[] tmpVec = new double[3];
        double[] vecLength = new double[8];
        double tmpx = 0;
        double tmpy = 0;
        double tmpz = 0;
        
        for (int i = 0; i<7; i++) {
            tmpx += testArray[i][0];
            tmpy += testArray[i][1];
            tmpz += testArray[i][2];
        }
        
        tmpx = tmpx / 8.0;
        tmpy = tmpy / 8.0;
        tmpz = tmpz / 8.0;
        
        for (int i = 0 ; i < 7; i++) {
            tmpVec[0] = tmpx - testArray[i][0];
            tmpVec[1] = tmpy - testArray[i][1];
            tmpVec[2] = tmpz - testArray[i][2];
            
            vecLength[i] = Math.sqrt(Math.abs((Math.pow(tmpVec[0], 2) + Math.pow(tmpVec[1], 2) + Math.pow(tmpVec[2], 2))));
            System.out.printf("%f\n", vecLength[i]);
        }
        
    }
```

Ausgabe:
3,247595
4,098399
4,098399
4,800716
4,098399
4,800716
4,800716

Sieht da jemand den Fehler. Nach meinem Verständnis müssten da gemessen vom Mittelpunkt die gleichen Abstände bei rauskommen.


----------



## pappawinni (7. Nov 2012)

Ja, der Fehler ..
der zeigt sich dann auch darin, dass am Ende nur 7 Ergebnisse ausgespuckt werden, statt der erwarteten 8.
Würdest du deine Schleifen mit 
	
	
	
	





```
for (int i = 0; i<8; i++)
```
 machen, statt 
	
	
	
	





```
for (int i = 0; i<7; i++)
```
 wär ich doch zuversichtlich, dass da das richtige heraus kommt.


----------



## Blamaster (7. Nov 2012)

ja irgendwann war gestern scheinbar die Konzentration weg. 

Nach dem anpassen der Schleife wird der Mittelpunkt jetzt korrekt berechnet. 

Damit lässt sich jetzt auf gültigen Quader bzw. Würfel prüfen richtig ?
Sprich wenn vom Mittelpunkt die Abstände zu allen anderen Punkten gleich sind, dann ist es ein gültiger Quader. Wenn nicht dann irgendetwas anderes. 

Gleichzeitig dürfte ich über den Mittelpunkt auch den Schwerpunkt haben. 

Jetzt muss ich nur noch irgendwie auf die Länge x Breite x Höhe kommen, dann war es das hoffentlich  

Aber über den Mittelpunkt kommt man auch nicht leichter zu den fehlenden Werten oder ? Der ist scheinbar nur wirklich gut um bestimmen zu können ob gültiger Körper oder nicht. 

Achso und erstmal vielen Dank für die Hilfe


----------



## Trolllllll (7. Nov 2012)

Länge*Breite*Höhe=Volumen eines Quader ;-)

also musst tu nun 3 Strecken ausrechnen, nämlich die Strecke von einem Punkt zu den 3 dazu gehörigen punkten

```
x
    |
    | h
  b |
x---x
     \ l
      x
```

b=Breite, h=Höhe, l=Länge


----------



## SlaterB (7. Nov 2012)

dass ein Mittelpunkt mit gleichen Abständen reichen soll ist doch wie zuvor erstmal skeptisch zu sehen,
allzu leicht zu belegen bzw. eher wiederlegen allerdings auch wieder nicht

grundsätzlich müssen alle Punkte auf einer Kugel um den Mittelkreis liegen, das ist zunächst nicht schlecht, gilt für Quader ja auch

vereinfacht zunächt nur eine Seite betrachtet, 2D, ein Rechteck in einem Kreis,
den Mittelpunkt zu verschieben soll hier mal nicht zielführend sein, der bleibt fest,
bewegt man dann einen Punkt auf der Kreisbahn, muss glaube der gegenüberliegende zum Ausgleich auch bewegt werden,
möge man sich auf Papier anschauen,
es bleibt bei einem Rechteck, aber etwas verschoben

und sehe man den Quader als zwei sich gegenüberstehende Rechtecke in zwei 2D-Ebenen,
wenn man die gegeneinander verdreht, wie eine Eieruhr, eine Schraube, eine Feder, einen Zauberwürfel  ,







dürfte das meiner Ansicht nach auf Mittelpunkt und Abstände keine Auswirkung haben, aber kein Quader mehr

reicht also nicht, da fande ich die Abstände besser


----

> also musst tu nun 3 Strecken ausrechnen, nämlich die Strecke von einem Punkt zu den 3 dazu gehörigen punkten

welche die drei zugehörigen sind, das wäre gerade die Frage..


----------



## Trolllllll (7. Nov 2012)

Zum Einen der dichteste Punkt


```
x
    |
    | h
  b |
x---x
     \ l
      x
```

_zum Besipiel die den an der Strecke l_ 

Wenn er der dichteste ist, kann es keine Diagonale sein laut Pythagoras, da in einem rechtwinkligen Dreieck die Hypotenuse nie die kürzeste Strecke ist ;-)
die anderen punkte müssen nun nur rechtwinklig auf dieser Graden liegen, da ein Quader ja nur aus rechtwinkligen Winkeln besteht ;-)


----------



## Guest2 (7. Nov 2012)

Moin,

ich würde es so machen, wie es der TO oben schon angedeutet hat, über die Vektoren, Parallelität und die Orthogonalität. Welcher der Punkte wo sitzt, ist imho dabei unwichtig. Konkret:

1. Alle Vektoren zwischen allen Punkten bestimmen.
2. Alle Vektoren paarweise auf Parallelität und Orthogonalität prüfen.

Imho gibt es bei diesem paarweisen Vergleich, bei einem Quader, immer genau 12 Kanten, die jeweils genau 4 parallele und genau 12 orthogonale Vektoren haben (bzw. 3 parallele, wenn man die eigene Kante nicht mitzählt). Alle übrigen Vektoren können ignoriert werden (das sind z.B. die Diagonalen)

3. Von den 12 Kanten sind jeweils 4 parallel. Die 12 Kanten können also in 3 Gruppen aufgeteilt werden. Die Länge der Vektoren in dieser Gruppe entspricht dann der Größe des Quaders in einer Dimension.

Mit den Zahlen oben komme ich auf 1331 Kubikeinheiten.



Spoiler: Lösung (muss nicht stimmen ;)





```
public final class Point3D {

    private final double x;
    private final double y;
    private final double z;


    public Point3D(final double x, final double y, final double z) {

        this.x = x;
        this.y = y;
        this.z = z;

    }


    public double getX() {

        return x;

    }


    public double getY() {

        return y;

    }


    public double getZ() {

        return z;

    }


}
```


```
public final class Vector3D {

    private static final double EPSILON = 0.000001;

    private final double        x;
    private final double        y;
    private final double        z;

    private final double        length;


    public Vector3D(final Point3D p1, final Point3D p2) {

        this.x = p2.getX() - p1.getX();
        this.y = p2.getY() - p1.getY();
        this.z = p2.getZ() - p1.getZ();

        this.length = calculateLength();

    }


    public boolean isParallel(final Vector3D other) {

        final double dot = dotProduct(other);
        final double len = this.length * other.getLength();
        final double angle = dot / (len);

        return (1 - Math.abs(angle)) < EPSILON;

    }


    public boolean isOrthogonal(final Vector3D other) {

        final double dot = dotProduct(other);
        final double len = this.length * other.getLength();
        final double angle = dot / (len);

        return Math.abs(angle) < EPSILON;

    }


    private double dotProduct(final Vector3D other) {

        final double xProduct = this.x * other.getX();
        final double yProduct = this.y * other.getY();
        final double zProduct = this.z * other.getZ();

        return xProduct + yProduct + zProduct;

    }


    private double calculateLength() {

        final double xSquare = x * x;
        final double ySquare = y * y;
        final double zSquare = z * z;

        return Math.sqrt(xSquare + ySquare + zSquare);

    }


    public double getX() {

        return x;

    }


    public double getY() {

        return y;

    }


    public double getZ() {

        return z;

    }


    public double getLength() {

        return length;

    }


}
```


```
public final class Cuboid {

    private static final List<Point3D> SAMPLE                = Arrays.asList(
            new Point3D(6.7, 3.9, 1.3),
            new Point3D(-8.3, 4.9, 5.3),
            new Point3D(-6.3, -1.1, 14.3),
            new Point3D(2.7, 4.9, 16.3),
            new Point3D(-0.3, -8.1, 8.3),
            new Point3D(0.7, 10.9, 7.3),
            new Point3D(-2.3, -2.1, -0.7),
            new Point3D(8.7, -2.1, 10.3)
            );


    private static final int           DIMENSION_PER_CUBOID  = 3;
    private static final int           EDGES_PER_CUBOID      = 12;
    private static final int           PARALLES_PER_EDGE     = 4;
    private static final int           ORTHOGONALES_PER_EDGE = 12;


    private final List<Vector3D>       edges;
    private final List<Vector3D>       dimensions;


    public Cuboid(final List<Point3D> points) {

        edges = buildAllEdges(buildAllVectors(points));

        if (edges.size() != EDGES_PER_CUBOID)
            throw new IllegalArgumentException("This is not a Cuboid!");


        dimensions = buildDimensions(edges);

        if (dimensions.size() != DIMENSION_PER_CUBOID)
            throw new IllegalArgumentException("This is not a Cuboid!");

    }


    private List<Vector3D> buildAllVectors(final List<Point3D> points) {

        final List<Vector3D> result = new ArrayList<Vector3D>();

        for (int i = 0; i < points.size(); i++)
            for (int j = i + 1; j < points.size(); j++)
                result.add(new Vector3D(points.get(i), points.get(j)));

        return result;

    }


    private List<Vector3D> buildAllEdges(final List<Vector3D> vectors) {

        final List<Vector3D> result = new ArrayList<Vector3D>();

        for (int i = 0; i < vectors.size(); i++) {

            int parallel = 0;
            int orthogonal = 0;

            for (int j = 0; j < vectors.size(); j++) {

                if (vectors.get(i).isParallel(vectors.get(j)))
                    parallel++;

                if (vectors.get(i).isOrthogonal(vectors.get(j)))
                    orthogonal++;

            }

            if (parallel == PARALLES_PER_EDGE && orthogonal == ORTHOGONALES_PER_EDGE)
                result.add(vectors.get(i));

        }

        return result;

    }


    private List<Vector3D> buildDimensions(final List<Vector3D> vectors) {

        final List<Vector3D> result = new ArrayList<Vector3D>();

        for (final Vector3D v : vectors)
            if (!containsParallelVector(result, v))
                result.add(v);

        return result;

    }


    private boolean containsParallelVector(final List<Vector3D> vectors, final Vector3D vector) {

        for (final Vector3D v : vectors)
            if (vector.isParallel(v))
                return true;

        return false;

    }


    public double getVolume() {

        return dimensions.get(0).getLength() * dimensions.get(1).getLength() * dimensions.get(2).getLength();

    }


    public static void main(final String[] args) {

        final Cuboid cube = new Cuboid(SAMPLE);
        final double volume = cube.getVolume();

        System.out.println(volume);

    }
}
```




Viele Grüße,
Fancy


----------



## pappawinni (7. Nov 2012)

Naja.. dass das Volumen im gegebenen Beispiel einem Würfel mit der Kantenlänge 11 entspricht hatte ich ja schon angedeutet.
Ebenfalls hatte ich angedeutet, wie meine Vorgehensweise etwa wäre. Der TO soll sich ja selbst auch ein paar Gedanken machen.
1. 
Mittelpunkt aller Punkte bestimmen und prüfen, ob alle Punkte den gleichen Abstand zu diesem Mittelpunkt haben.
Abstände variant => kein Quader, ansonsten
erwartete Raumdiagonale = doppelter Abstand der Punkte vom Mittelpunkt.
2.
Von einem der Punkte die Abstände zu allen anderen Punkten bestimmen.
Abstände sortieren.
Grösster gefundenen Abstand ungleich erwarteter Raumdiagonale => kein Quader, sonst...

die beiden kürzesten der 7 Abstände sind die Kanten a und b.
Kante c = wurzel( Raumdiagonale^2 - a^2 - b ^2)
Volumen = a * b *  wurzel( Raumdiagonale^2 - a^2 - b ^2)


----------

