# Problem beim picken



## Chris82123xyz (6. Dez 2007)

Hi! Ich habe folgendes Problem.
Ich möchte wenn ich Objekte in meiner Szene anklicke mir ihren Namen ausgeben lassen, den ich vorher mit .setName gesetzt habe.
Ich habe das vorher mit ColorCubes ausprobiert und da lief es wunderbar, allerdings wollte ich jetzt auf Kugeln umsteigen und jetzt gibt er mir beim Namen immer ein null. Wenn ich den Namen abfrage nachdem ich ihn gesetzt hab is er da, nur nich mehr über die Pickmethode, also liegt es wohl irgendwie daran.
Ich steh gerade etwas aufm Schlauch.
Hier jetzt dazu der Code

```
void handleObjectSelection(MouseEvent mousee) {
		    Node         PickedObject;
		    PickCanvas   MyPick=new PickCanvas(c3d,objRoot);
		    PickResult[] MyPickResult;
		       int i = 0;
		
		    MyPick.setTolerance(0f);
		    MyPick.setMode(PickTool.GEOMETRY);
		    MyPick.setShapeLocation(mousee);
		    MyPickResult=MyPick.pickAllSorted();
		    PickedObject=MyPickResult[i].getObject();
			
			       
					
			       	name_tf.setText(PickedObject.getName());
			       	System.out.println("Name "+PickedObject.getName());
			       
			       	id_tf.setText(PickedObject.toString());
			       				       
    }
```

Und das PickedObject.toString() läuft auch ganz normal weiter. Aber der blöde Name nicht 
Hoffe ihr könnt mir da weiterhelfen!
Danke schonmal im Vorraus.

Ps.: Wie kann ich aus nem Transform3D das mir von getLocalToVworld(t3d) zurückgegeben wird am besten einen Punkt mit den angegebenen Koordinaten bekommen, oder irgendwie die Werte aus dem Transform3d separieren?!
Das sie also nicht mehr in einer Matrix vorliegen sondern zB in 3 floats oder so.
Hab da inner API irgendwie nix gefunden.

In freudiger Erwartung ....


----------



## Marco13 (6. Dez 2007)

Zum ersten Teil kann ich nicht viel sagen, außer dass es seltsam aussieht, dass da immer ein neuer PickCanvas erstellt wird (hat aber mit dem Problem wohl nicht so viel zu tun)

Wenn man eine Transform3D hat, dann beschreibt die letzte Spalte der Matrix3f in dieser Transform3D "die Position" (d.h. den Ursprung des lokalen Koordinatensystems). Man kann sich also die Matrix3f da rausholen, und da dann getColumn(3, positionVector3f) machen


----------



## Chris82123xyz (6. Dez 2007)

Das PickCanvas hab ich da jetzt der Übersicht wegen reingepackt! Steht da normalerweise auch nicht.  :shock: 

Der Sinn hinter dem Transform3D ist eigentlich der, dass ich mir die Koordinaten des Objektes was ich anklicke auch ausgeben lassen will bzw bekommen will um dann zB zwei Objekte durch eine Linie zu verbinden!
Vielleicht gibts da ja auch eine elegantere Verfahrensweise =)


----------



## Marco13 (6. Dez 2007)

Hämja ... man kann auch einen Point3f(0,0,0) mit dieser Transform transformieren, aber das kommt aufs gleiche raus...


----------



## Florianer (7. Dez 2007)

Mich würde die Sache mit dem Namen noch immer interessieren (mein Topic), denn ich würde zumindest gerne mir oder dem Anwender anzeigen lassen, auf was er geklickt hat, nicht nur wo. Falls es also eine Möglichkeit gibt, den Namen zu setzten und beim Picking Objekt zu erfragen, wäre das sehr hilfreich. 
Danke.


----------



## Marco13 (7. Dez 2007)

Hab' mit Picking in Java3D ehrlich gesagt nie was gemacht   

Heißt
_Und das PickedObject.toString() läuft auch ganz normal weiter. _
dass dort der gewünschte Name ausgegeben wird?


----------



## Chris82123xyz (10. Dez 2007)

Also mit PickedObject.toString() bekommt man die Java Objektbezeichnung also zB sowas! 
[Desease1] com.sun.j3d.utils.geometry.ColorCube@1dfc547

Dieser ColorCube heisst nun Desease1 und der Name wurde ihm mit .setName() gegeben. 
Mit dem PickedObject.getName() lässt man sich nun diesen Namen ausgeben. Und das kann sich ganz simpel per Textfield oder Console ausgeben lassen.
Aber dummerweise funzt das .getName() komischerweise nach dem Code da oben nur mit den Cubes, obwohl die Objekte ihre Namen noch haben. Hinter das Problem bin ich auch noch nich gekommen. Aber ich denke es hat was mit dem Ursprung der Objekte zu tun. 
Das wäre zB die Objektbezeichnung einer Kugel javax.media.j3d.Shape3D@1a28362 und wie man sieht wird hier der Name nicht davor in [Klammern] aufgeführt und man kann ihn auch nicht über .getName() abfragen, obwohl er einen hat.
Kann es unter Umständen daran liegen, dass der Code da oben auf Shape3Ds nicht klar kommt und somit nur den Namen von ColorCubes(Geometrys) auslesen kann?!
Ich hab irgendwie die ganze Zeit das Gefühl, dass es eigentlich was ziemlich simples ist, was man blos nicht entdeckt  :bahnhof: 



```
Sphere c1 = new Sphere();
c1.setName("Desease"+i);
System.out.println("Name "+c1.getName());
```
So geht es wunderbar. Aber eben nicht über die Pickingmethode!  
Also muss es ja irgendwie da verloren gehen ^^


----------



## Marco13 (10. Dez 2007)

ColorCube IST eine Shape3D. Aber Sphere ist KEINE Shape3D. 

http://ls7-www.cs.uni-dortmund.de/s...tml/com/sun/j3d/utils/geometry/ColorCube.html
http://ls7-www.cs.uni-dortmund.de/s...d-html/com/sun/j3d/utils/geometry/Sphere.html

Vermutlich hängt das Problem mit dieser unterschiedlichen Einordnung in die Hierarchie zusammen. 

Hab mal kurz über die PickingResult-Klasse geschaut: Man bekommt dort "irgendeinen" Node - mit  getNode(int flags) kann man sich einen bestimmten Node-Typ holen. Was man vielleicht (!) testweise (!) mal probieren könnte: 
Die zu Pickenden Objekte jeweils als einzige Objekte an eine BranchGroup hängen, und dann mit getNode(PickingResult.BRANCH_GROUP) die BranchGroup aus dem PickingResult holen. Das erste (und einzige) Child dieser BranchGroups müßte dann das gesuchte Objekt sein. 
Ansonsten würde ich mal schauen, was in den Arrays (getGeometryArrays(), getCompressedGeometryShape3Ds()) vom PickingResult so drinsteht, oder ob man mit getSceneGraphPath() irgendwie das gesuchte Objekt finden kann, aber einen konkreten Ansatz hätte ich jetzt nicht - sorry.


----------



## Chris82123xyz (11. Dez 2007)

Soooo......
Ich habs dann mal hinbekommen


```
void handleObjectSelection(MouseEvent mousee) {
	    

	    pickCanvas.setShapeLocation(mousee); 
	    PickResult result = pickCanvas.pickClosest(); 
	    
                    Primitive p = (Primitive)result.getNode(PickResult.PRIMITIVE); 
                    
                    id_tf.setText(p.getClass().toString());
	    name_tf.setText(p.getName());
	         
	       
	    }
```

Somit geht es dann für Spheren, Cylinder, Cones usw...

Wenn man doch wieder zum ColorCube zurück will tauscht man einfach die Primitive p Zeile mit folgender

```
Shape3D p = (Shape3D)result.getNode(PickResult.SHAPE3D);
```


----------



## Marco13 (11. Dez 2007)

Ah OK - ich hatte das jetzt so verstanden, dass BEIDES gehen soll    - dann müßte man aben irgendwie mit instanceof rumwursten, und dem Kommenta bei 'getShape' (in der verlinkten Doku von ColorCube nach) deuete darauf hin, dass so etwas (wie instanceof eben so ist) "gefährlich" sein könnte, wenn die Klassenstruktur sich ändert. Aber wenn's jetzt (für den gewünschten Objekttyp) geht, ists ja gut...


----------



## Chris82123xyz (11. Dez 2007)

Wenns mit beiden gehen soll, kann man die beiden Zeilen auch einfach in if/else Blöcke packen!
Sprich so:

```
public void mouseClicked(MouseEvent e) 

{ 

    pickCanvas.setShapeLocation(e); 

    PickResult result = pickCanvas.pickClosest(); 

    if (result == null) { 

       System.out.println("Nothing picked"); 

    } else { 

       Primitive p = (Primitive)result.getNode(PickResult.PRIMITIVE); 

       Shape3D s = (Shape3D)result.getNode(PickResult.SHAPE3D); 

       if (p != null) { 

          System.out.println(p.getName()); 

       } else if (s != null) { 

             System.out.println(s.getName()); 

       } else{ 

          System.out.println("null"); 
       } 
    } 
}
```

Aber das muss es bei mir ja nicht!


----------

