# Position im Raum bestimmen



## kawrom (10. Feb 2006)

Tagchen,
ich habe das folgende Problem, ich möchte, wenn ich im 3D Raum mit der Maus klicke, und dabei ein Objekt treffe, daß mir die genauen Koordinaten (x, y, z) des Treffers zurückgegeben wedren. Hab mich schon durch diverse Tutorials gequält aber keine lösung dieses Problems gefunden. Das einzige was ich erreichen kann das ich das komplette Objekt als rückgabe erhalte, ich möchte aber wie gesagt die Koordinaten des auftreffenden Mausklicks...
Für Antworten bedanke ich mich schon im Voraus.


----------



## MPW (11. Feb 2006)

Aehm, wie soll das gehen? die dreidimensionale Maus ist noch nicht erfunden worden, der Computer weiss also nicht, welche Z Koordinate dein klick hat;-)


----------



## kawrom (11. Feb 2006)

Naja ich hab mir das so gedacht , dass im Raum zb bei ( z= 0) ein Quad-Array-Shape3D mit nur einem Polygon liegt 
die Koordinaten für die einzelnen ecken wären zB. 


```
QuadArray backGlas = new QuadArray(4, QuadArray.COORDINATES);

backGlas.setCoordinate(0, new Point3f(-2.0f, -2.0f, 0.0f));
backGlas.setCoordinate(1, new Point3f( 2.0f, -2.0f, 0.0f));
backGlas.setCoordinate(2, new Point3f( 2.0f,  2.0f, 0.0f));
backGlas.setCoordinate(3, new Point3f(-2.0f,  2.0f, 0.0f));

Shape3D obj = new Shape3D();

obj.setGeometry(backGlas);
```

(das backGlas-Objekt macht man dann Transparent, und der View-Punkt steht z.B. bei (0, 0, 3))

Die z-Koordinate ist hierbei auch garnicht wichtig (die ist eh immer 0), sondern nur die x- und y-Koordinate bei der  mein Click auf mein Shape3D-Objekt auftrifft. 
Das einzige was ich aber abfragen kann ist die Mausposition auf dem Canvas3D.


----------



## MPW (11. Feb 2006)

Hm, kenne mich da jetzt auch nicht so aus, aber theoretisch muesste das mit einer mathematischen Formel zu loesen sein.

Wenn du den Ausschnitt kennst und die groesse der Canvas, muesste man die Pixelkoordinaten in die der 3DWelt umrechnen koennen...sonst koennte man ja auch keine Objekte auswaehlen....


----------



## kawrom (11. Feb 2006)

Genau das habe ich mir auch gedacht, denn um zu bestimmen ob man ein Objekt im 3D-Raum getroffen hat, muss man auch wissen welche koordinaten mein Klick-Strahl durchläuft und schleisslich die des Objektes schneidet.

Der Ansatz deis mit mathematidschen Formeln zu lösen ist aber auch keine schlechte Idee...ich werds mal jetzt auch so versuchen...danke für den Tip, hab bis jetzt nur hartnäckig nach einer Methode gesucht die dieses Problem löst anstatt mir selbst eine zu basteln.


----------



## MPW (11. Feb 2006)

hm, hast du dir denn schon Clipping angeguckt, das ist naemlich eigentlich dafuer gedacht.


----------



## kawrom (12. Feb 2006)

So geschafft, hab es auf die mathematische Art gelöst. War garnicht mal so schwer, da sich das Sichtfeld linear zur Entfernung verändert.
D.h. wenn ich mein View auf "1m" enfernung eingestellt hab seh ich z.B. ca "0.82m" Breite und "0.62m" Höhe (bei z = 0). Wenn ich mein View dann au "2m" rauszoome seh ich dann genau das doppelte also "1.64m X 1.24m". 
Bei "3m" Entfernung "2.64m X 1.86" usw...

Da hierbei eine lineare Abhängikkeit besteht lässt sich jetzt natürlich ohne Probleme eine Urechnung von Pixeln meiner Canvas3D auf die Koordinaten im 3D-Raum umrechnen (voraugesetzt natürlich  z= 0 und der Winkel und die Rotation meines Views bleiben unverändert)

Beispiel:

- Canvas3D Breite: 640  Höhe: 480
- bei 1m (zoom = 1)entf. Sicht wie oben beschrieben 0.82m X 0.62m
- Klick mit der Maus bei 100  X 100

also kann ich jetzt mittels Dreisatz sagen:

Koordinate X = 0.82 / 640 * 100 * zoom= 0.128125
Koordinate Y = 0.62 / 480 * -100 * zoom= -0.129666 (-100 -> da sich der Klick unterhalb des Nullpunktes befindet)

(eigentlich müssten hierbei beide Zahlenwerte (ohne Beachtung des Vorzeichens) gleich sein, doch sind die Werte 0.82m und 0.62m nur eine Schätzung von mir, die ein bieschen abweicht. Bestimmt man die werte genau, dann kriegt man auch exakte Koordinaten)

Was hierbei auch zu beachten ist, ist die Tatsache, daß sich der Koordinaten-Nullpunkt (also x = 0 und y = 0) bei den Pixelwerten 0 X 0 befinden. Verschiebt man den Nullpunkt muss man darauf achten,  links des Ursprungs negative X-Werte  und unterhalb des Ursprungs negative Y-Werte für die Pixelwerte anzugeben
 :cry:  :?:  :###  :!:   

(ach so mir ist durchaus bewust, daß es sich hierbei nicht um "Meter" handelt, hab es aber des besseren Verständnisses wegen so angegeben  )


----------



## DeepBlue (13. Feb 2006)

Ziemlich kompliziert gelöst.

Einfacher wäre es gewesen, am MausClick ein PickCanvas zu erstellen, und dir von diesem die Startpositionen zurückgeben zu lassen. Dabei ist dann die Z-Koordinate zu vernachlässigen.


```
PickCanvas pickcanvas = new PickCanvas(canvas, root);
pickcanvas.setTolerance(0.0f);
pickcanvas.setShapeLocation(loc.x, loc.y);
Point3d point = pickcanvas.getStartPosition();
```

loc entspricht dabei der Position des MouseClicks.


----------



## kawrom (13. Feb 2006)

:?: Ja und in welchem package finde ich die PickCanvas-Klasse? :?:


----------



## DeepBlue (13. Feb 2006)

Seit der 1.4.0 Beta 3 in:
com.sun.j3d.utils.pickfast.PickCanvas

Vorher in:
com.sun.j3d.utils.picking.PickCanvas


----------



## h0b0 (18. Apr 2007)

Ich stand vor dem selben Problem und habe den Schnittpunkt von Fläche und PickRay über ein lineares Gleichungssystem bestimmt.
Ich habe die Vektorgleichungen für Gerade und Fläche gleichgesetzt, in Matrixschreibweise gebracht und das Gleichungssystem dann über die Multiplikation mit der Inversen Matrix gelöst. Klappt einwandfrei.
Sollte jemals jemand an Details interessiert sein, möge er Bescheid sagen und ich werde mir mal die Zeit nehmen, die Details auszubreiten.


----------



## h0b0 (16. Jun 2007)

Es kam jetzt eine Anfrage per PM, wie ich obiges nun genau getan hätte. Inzwischen habe ich aber das bereits erfundene Rad dazu in J3D gefunden:

```
myPickCanvas.setShapeLocation(x, y);
PickResult myPickResult = myPickCanvas.pickCloseset();
PickIntersection myPickIntersection = myPickResult.getIntersection(0);
Point3d result = myPickIntersection.getPointCoordinatesVW();
```
Das ist jetzt sehr gradlinig. Es ist z.B. auch sehr gefährlich, davon auszugehen, dass ein PickResult auch immer mindestens eine PickIntersection liefert. Es lohnt sich, einmal einen Blick in die Dokumentation der verwendeten Klassen zu werfen; sie bieten noch einen Haufen Möglichkeiten mehr.
Habe leider nicht früher gewusst. Immerhin verstehe ich dadurch, dass ich den ganzen Quatsch einmal selbst implementiert habe, warum diese scheinbar überflüssige Klasse PickIntersection eingeführt wurde...


----------

