001 //$HeadURL: svn+ssh://mschneider@svn.wald.intevation.org/deegree/base/trunk/resources/eclipse/svn_classfile_header_template.xml $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 This file is part of deegree. 004 Copyright (C) 2001-2008 by: 005 Department of Geography, University of Bonn 006 http://www.giub.uni-bonn.de/deegree/ 007 lat/lon GmbH 008 http://www.lat-lon.de 009 010 This library is free software; you can redistribute it and/or 011 modify it under the terms of the GNU Lesser General Public 012 License as published by the Free Software Foundation; either 013 version 2.1 of the License, or (at your option) any later version. 014 This library is distributed in the hope that it will be useful, 015 but WITHOUT ANY WARRANTY; without even the implied warranty of 016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 017 Lesser General Public License for more details. 018 You should have received a copy of the GNU Lesser General Public 019 License along with this library; if not, write to the Free Software 020 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 021 Contact: 022 023 Andreas Poth 024 lat/lon GmbH 025 Aennchenstr. 19 026 53177 Bonn 027 Germany 028 E-Mail: poth@lat-lon.de 029 030 Prof. Dr. Klaus Greve 031 Department of Geography 032 University of Bonn 033 Meckenheimer Allee 166 034 53115 Bonn 035 Germany 036 E-Mail: greve@giub.uni-bonn.de 037 ---------------------------------------------------------------------------*/ 038 039 package org.deegree.tools.app3d; 040 041 import java.awt.BorderLayout; 042 import java.awt.Color; 043 import java.awt.Dimension; 044 import java.awt.FlowLayout; 045 import java.awt.GraphicsConfigTemplate; 046 import java.awt.event.ActionEvent; 047 import java.awt.event.ActionListener; 048 import java.awt.event.KeyEvent; 049 import java.awt.event.KeyListener; 050 import java.awt.event.WindowAdapter; 051 import java.awt.event.WindowEvent; 052 import java.io.File; 053 import java.io.IOException; 054 import java.net.MalformedURLException; 055 import java.security.InvalidParameterException; 056 import java.util.ArrayList; 057 import java.util.Enumeration; 058 import java.util.List; 059 import java.util.prefs.Preferences; 060 061 import javax.media.j3d.Appearance; 062 import javax.media.j3d.Background; 063 import javax.media.j3d.BoundingSphere; 064 import javax.media.j3d.Bounds; 065 import javax.media.j3d.BranchGroup; 066 import javax.media.j3d.Canvas3D; 067 import javax.media.j3d.ColoringAttributes; 068 import javax.media.j3d.DirectionalLight; 069 import javax.media.j3d.GeometryArray; 070 import javax.media.j3d.GraphicsConfigTemplate3D; 071 import javax.media.j3d.Group; 072 import javax.media.j3d.Light; 073 import javax.media.j3d.LineArray; 074 import javax.media.j3d.Material; 075 import javax.media.j3d.PointArray; 076 import javax.media.j3d.PolygonAttributes; 077 import javax.media.j3d.RenderingAttributes; 078 import javax.media.j3d.Shape3D; 079 import javax.media.j3d.Transform3D; 080 import javax.media.j3d.TransformGroup; 081 import javax.media.j3d.View; 082 import javax.swing.JButton; 083 import javax.swing.JFileChooser; 084 import javax.swing.JFrame; 085 import javax.swing.JOptionPane; 086 import javax.swing.JPanel; 087 import javax.swing.filechooser.FileFilter; 088 import javax.vecmath.Color3f; 089 import javax.vecmath.Matrix3d; 090 import javax.vecmath.Point3d; 091 import javax.vecmath.Vector3d; 092 import javax.vecmath.Vector3f; 093 import javax.xml.transform.TransformerException; 094 095 import org.deegree.framework.log.ILogger; 096 import org.deegree.framework.log.LoggerFactory; 097 import org.deegree.framework.xml.XMLFragment; 098 import org.deegree.framework.xml.XMLParsingException; 099 import org.deegree.framework.xml.XSLTDocument; 100 import org.deegree.io.dbaseapi.DBaseException; 101 import org.deegree.io.shpapi.shape_new.ShapeFile; 102 import org.deegree.io.shpapi.shape_new.ShapeFileReader; 103 import org.deegree.model.feature.Feature; 104 import org.deegree.model.feature.FeatureCollection; 105 import org.deegree.model.feature.GMLFeatureCollectionDocument; 106 import org.deegree.model.spatialschema.Curve; 107 import org.deegree.model.spatialschema.CurveSegment; 108 import org.deegree.model.spatialschema.Envelope; 109 import org.deegree.model.spatialschema.Geometry; 110 import org.deegree.model.spatialschema.GeometryException; 111 import org.deegree.model.spatialschema.MultiSurface; 112 import org.deegree.model.spatialschema.Point; 113 import org.deegree.model.spatialschema.Position; 114 import org.deegree.model.spatialschema.Ring; 115 import org.deegree.model.spatialschema.Surface; 116 import org.deegree.ogcbase.CommonNamespaces; 117 import org.jdesktop.j3d.loaders.vrml97.VrmlLoader; 118 import org.w3c.dom.Node; 119 import org.w3c.dom.NodeList; 120 import org.xml.sax.SAXException; 121 122 import com.sun.j3d.loaders.IncorrectFormatException; 123 import com.sun.j3d.loaders.ParsingErrorException; 124 import com.sun.j3d.loaders.Scene; 125 import com.sun.j3d.utils.behaviors.mouse.MouseRotate; 126 import com.sun.j3d.utils.geometry.ColorCube; 127 import com.sun.j3d.utils.geometry.GeometryInfo; 128 import com.sun.j3d.utils.geometry.NormalGenerator; 129 import com.sun.j3d.utils.universe.SimpleUniverse; 130 131 /** 132 * The <code>View3DFile</code> class can display shape and gml/citygml file in 3D. 133 * 134 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a> 135 * 136 * @author last edited by: $Author:$ 137 * 138 * @version $Revision:$, $Date:$ 139 * 140 */ 141 142 public class View3DFile extends JFrame implements ActionListener, KeyListener { 143 /** 144 * 145 */ 146 private static final long serialVersionUID = 7698388852544865855L; 147 148 private static ILogger LOG = LoggerFactory.getLogger( View3DFile.class ); 149 150 private SimpleUniverse simpleUniverse; 151 152 // private JCanvas3D canvas; 153 // private TrackBall trackBall; 154 155 private Canvas3D canvas; 156 157 private MouseRotate trackBall; 158 159 private BranchGroup scene; 160 161 private TransformGroup rotationGroup; 162 163 private Light firstLight, secondLight, thirdLight; 164 165 private Point3d centroid; 166 167 private JFileChooser fileChooser; 168 169 private Preferences prefs; 170 171 private final static String PREF_KEY = "lastlocation"; 172 173 private final static String WIN_TITLE = "Deegree 3D Object viewer: "; 174 175 private Background backGround; 176 177 /** 178 * Creates a frame with the menus and the canvas3d set and tries to load the file from given location. 179 * 180 * @param fileName 181 * to be loaded. 182 * @throws DBaseException 183 * @throws IOException 184 */ 185 public View3DFile( String fileName ) { 186 this( false ); 187 readFile( fileName ); 188 } 189 190 /** 191 * Creates a new frame with the menus and the canvas3d set. 192 * 193 * @param testSphere 194 * true if a sphere should be displayed. 195 */ 196 public View3DFile( boolean testSphere ) { 197 super( WIN_TITLE ); 198 199 setupGUI(); 200 201 setupFileChooser(); 202 203 setupJava3D( testSphere ); 204 205 pack(); 206 } 207 208 /** 209 * GUI stuff 210 */ 211 private void setupGUI() { 212 // add listener for closing the frame/application 213 addWindowListener( new WindowAdapter() { 214 @Override 215 public void windowClosing( WindowEvent evt ) { 216 System.exit( 0 ); 217 } 218 } ); 219 setLayout( new BorderLayout() ); 220 setMinimumSize( new Dimension( 400, 400 ) ); 221 setPreferredSize( new Dimension( 400, 400 ) ); 222 setVisible( true ); 223 // Adding the button panel 224 JPanel buttonPanel = new JPanel( new FlowLayout() ); 225 createButtons( buttonPanel ); 226 getContentPane().add( buttonPanel, BorderLayout.SOUTH ); 227 addKeyListener( this ); 228 229 } 230 231 private void setupFileChooser() { 232 // Setting up the fileChooser. 233 prefs = Preferences.userNodeForPackage( View3DFile.class ); 234 String lastLoc = prefs.get( PREF_KEY, System.getProperty( "user.home" ) ); 235 File lastFile = new File( lastLoc ); 236 if ( !lastFile.exists() ) { 237 lastFile = new File( System.getProperty( "user.home" ) ); 238 } 239 fileChooser = new JFileChooser( lastFile ); 240 241 ArrayList<String> extensions = new ArrayList<String>(); 242 extensions.add( "gml" ); 243 extensions.add( "xml" ); 244 CustomFileFilter fileFilter = new CustomFileFilter( extensions, "(*.gml, *.xml) GML or CityGML-Files" ); 245 fileChooser.setFileFilter( fileFilter ); 246 247 extensions.clear(); 248 extensions.add( "shp" ); 249 fileFilter = new CustomFileFilter( extensions, "(*.shp) Esri ShapeFiles" ); 250 fileChooser.setFileFilter( fileFilter ); 251 252 extensions.clear(); 253 extensions.add( "vrml" ); 254 extensions.add( "wrl" ); 255 fileFilter = new CustomFileFilter( extensions, "(*.vrml, *.wrl) VRML97 - Virtual Reality Modelling Language" ); 256 fileChooser.setFileFilter( fileFilter ); 257 258 // The *.* filter is off. 259 fileChooser.setAcceptAllFileFilterUsed( false ); 260 261 fileChooser.setMultiSelectionEnabled( false ); 262 } 263 264 private void setupJava3D( boolean testSphere ) { 265 // setting up Java3D 266 GraphicsConfigTemplate3D configTemplate = new GraphicsConfigTemplate3D(); 267 configTemplate.setSceneAntialiasing( GraphicsConfigTemplate.PREFERRED ); 268 configTemplate.setDoubleBuffer( GraphicsConfigTemplate.REQUIRED ); 269 canvas = new Canvas3D( SimpleUniverse.getPreferredConfiguration() ); 270 simpleUniverse = new SimpleUniverse( canvas ); 271 if ( canvas != null ) { 272 getContentPane().add( canvas, BorderLayout.CENTER ); 273 } 274 275 View view = simpleUniverse.getViewer().getView(); 276 277 // view parameters 278 view.setBackClipDistance( 10000 ); 279 view.setFrontClipDistance( 0.1 ); 280 view.setWindowEyepointPolicy( View.RELATIVE_TO_FIELD_OF_VIEW ); 281 view.setSceneAntialiasingEnable( true ); 282 283 centroid = new Point3d(); 284 scene = new BranchGroup(); 285 firstLight = createDirectionalLight( new Vector3f( 0, 0, 1 ) ); 286 secondLight = createDirectionalLight( new Vector3f( 0, -1, -1 ) ); 287 thirdLight = createDirectionalLight( new Vector3f( -1, 0, 0 ) ); 288 289 scene.addChild( firstLight ); 290 scene.addChild( secondLight ); 291 scene.addChild( thirdLight ); 292 293 // is handled by the mouse rotater, all objects will be added to it. 294 rotationGroup = new TransformGroup(); 295 rotationGroup.setCapability( TransformGroup.ALLOW_TRANSFORM_WRITE ); 296 rotationGroup.setCapability( TransformGroup.ALLOW_TRANSFORM_READ ); 297 rotationGroup.setCapability( BranchGroup.ALLOW_DETACH ); 298 rotationGroup.setCapability( Group.ALLOW_CHILDREN_EXTEND ); 299 rotationGroup.setCapability( Group.ALLOW_CHILDREN_READ ); 300 rotationGroup.setCapability( Group.ALLOW_CHILDREN_WRITE ); 301 scene.addChild( rotationGroup ); 302 303 backGround = new Background ( new Color3f( Color.LIGHT_GRAY ) ); 304 backGround.setCapability( Background.ALLOW_BOUNDS_WRITE ); 305 backGround.setCapability( Background.ALLOW_BOUNDS_READ ); 306 backGround.setCapability( Background.ALLOW_APPLICATION_BOUNDS_READ); 307 backGround.setCapability( Background.ALLOW_APPLICATION_BOUNDS_WRITE); 308 309 scene.addChild( backGround ); 310 311 trackBall = new MouseRotate(); 312 trackBall.setTransformGroup( rotationGroup ); 313 trackBall.setSchedulingBounds( new BoundingSphere() ); 314 scene.addChild( trackBall ); 315 316 simpleUniverse.addBranchGraph( scene ); 317 318 // adding the key listeners 319 canvas.addKeyListener( this ); 320 321 if ( testSphere ) { 322 BranchGroup sphere = createJ3DSphere( new Point3d( 0, 0, 0 ) ); 323 addBranchGroupToScene( sphere ); 324 } 325 } 326 327 /** 328 * Create a directional light, with color.WHITE. 329 */ 330 private DirectionalLight createDirectionalLight( Vector3f lightDir ) { 331 // create the color for the light 332 Color3f color = new Color3f( Color.WHITE ); 333 // create the directional light with the color and direction 334 DirectionalLight light = new DirectionalLight( color, lightDir ); 335 light.setCapability( Light.ALLOW_INFLUENCING_BOUNDS_READ ); 336 light.setCapability( Light.ALLOW_INFLUENCING_BOUNDS_WRITE ); 337 return light; 338 } 339 340 private void addBranchGroupToScene( BranchGroup b ) { 341 LOG.logInfo( "Setting the branchgroup to : " + b.getName() ); 342 rotationGroup.removeAllChildren(); 343 // translationGroup.removeAllChildren(); 344 // System.out.println( b.getBounds() ); 345 Bounds bounds = b.getBounds(); 346 if ( bounds != null ) { 347 348 LOG.logDebug( "Old centroid: " + centroid ); 349 BoundingSphere bs = new BoundingSphere( bounds ); 350 bs.getCenter( centroid ); 351 LOG.logDebug( "New centroid: " + centroid ); 352 353 double radius = bs.getRadius(); 354 355 View view = simpleUniverse.getViewer().getView(); 356 // view parameters 357 view.setBackClipDistance( radius * 10 ); 358 // the near clippingplane is one hundereth of the far. 359 view.setFrontClipDistance( ( radius * 4 ) * 0.001 ); 360 361 TransformGroup viewToWorld = simpleUniverse.getViewingPlatform().getViewPlatformTransform(); 362 Transform3D trans = new Transform3D(); 363 trans.lookAt( new Point3d( centroid.x,centroid.y, centroid.z -(radius*2) ), centroid, new Vector3d( 0, 1, 0 ) ); 364 LOG.logDebug( "Trans Matrix after lookat:\n" + trans ); 365 viewToWorld.setTransform( trans ); 366 367 LOG.logDebug( "Center: " + centroid ); 368 LOG.logDebug( "radius: " + bs.getRadius() ); 369 370 firstLight.setInfluencingBounds( new BoundingSphere( centroid, radius * 100 ) ); 371 secondLight.setInfluencingBounds( new BoundingSphere( centroid, radius * 100 ) ); 372 thirdLight.setInfluencingBounds( new BoundingSphere( centroid, radius * 100 ) ); 373 trackBall.setSchedulingBounds( new BoundingSphere( centroid, radius * 60 ) ); 374 backGround.setApplicationBounds( new BoundingSphere( centroid, radius * 100 ) ); 375 } 376 rotationGroup.addChild( b ); 377 } 378 379 /** 380 * @return a brand new sphere 381 */ 382 private BranchGroup createJ3DSphere( Point3d translation ) { 383 Appearance app = new Appearance(); 384 RenderingAttributes ra = new RenderingAttributes(); 385 ra.setDepthBufferEnable( true ); 386 ra.setDepthBufferWriteEnable( true ); 387 app.setRenderingAttributes( ra ); 388 389 ColoringAttributes ca = new ColoringAttributes(); 390 ca.setShadeModel( ColoringAttributes.SHADE_GOURAUD ); 391 ca.setCapability( ColoringAttributes.NICEST ); 392 app.setColoringAttributes( ca ); 393 394 Material material = new Material(); 395 material.setAmbientColor( new Color3f( Color.WHITE ) ); 396 material.setDiffuseColor( new Color3f( Color.RED ) ); 397 material.setSpecularColor( new Color3f( Color.BLUE ) ); 398 app.setMaterial( material ); 399 TransformGroup tg = new TransformGroup(); 400 Transform3D trans = new Transform3D(); 401 if ( translation != null ) { 402 trans.setTranslation( new Vector3d( translation ) ); 403 tg.setTransform( trans ); 404 } 405 406 BranchGroup b = new BranchGroup(); 407 b.setCapability( BranchGroup.ALLOW_DETACH ); 408 b.addChild( tg ); 409 410 // tg.addChild( new Sphere( 0.2f, app ) ); 411 tg.addChild( new ColorCube( 0.2f ) ); 412 return b; 413 } 414 415 private void createButtons( JPanel buttonPanel ) { 416 JButton button = new JButton( "Open File" ); 417 button.setMnemonic( KeyEvent.VK_O ); 418 button.addActionListener( this ); 419 buttonPanel.add( button, FlowLayout.LEFT ); 420 } 421 422 private void readFile( String fileName ) { 423 424 if ( fileName == null || "".equals( fileName.trim() ) ) { 425 throw new InvalidParameterException( "the file name may not be null or empty" ); 426 } 427 fileName = fileName.trim(); 428 429 FeatureCollection fc = null; 430 if ( fileName.toUpperCase().endsWith( ".SHP" ) ) { 431 // File f = new File( fileName ); 432 try { 433 ShapeFile file = new ShapeFileReader( fileName ).read(); 434 fc = file.getFeatureCollection(); 435 } catch ( IOException e ) { 436 LOG.logError( "Could not open shape file: " + fileName + " because: " + e.getMessage() ); 437 return; 438 } catch ( DBaseException e ) { 439 LOG.logError( "Could not open shape file: " + fileName + " because: " + e.getMessage() ); 440 return; 441 } 442 } else if ( fileName.toUpperCase().endsWith( ".XML" ) || fileName.toUpperCase().endsWith( ".GML" ) ) { 443 try { 444 XMLFragment doc = new XMLFragment( new File( fileName ) ); 445 boolean isCityGML = ( doc.getRootElement() 446 .getOwnerDocument() 447 .lookupPrefix( CommonNamespaces.CITYGMLNS.toASCIIString() ) != null ) || CommonNamespaces.CITYGMLNS.toASCIIString() 448 .equals( doc.getRootElement() 449 .getOwnerDocument() 450 .lookupNamespaceURI( "" ) ); 451 452 if ( !isCityGML ) { 453 isCityGML = isCityGMLDefined( doc.getRootElement() ); 454 } 455 LOG.logInfo( "The xmlfile " + ( ( isCityGML ) ? "contains" : "does not contain" ) + " Citygml" ); 456 if ( isCityGML ) { 457 // convert to gml 458 XSLTDocument transformer = new XSLTDocument( View3DFile.class.getResource( "toShape.xsl" ) ); 459 doc = transformer.transform( doc ); 460 System.out.println( "outgoingdoc: \n " + doc.getAsPrettyString() ); 461 } 462 GMLFeatureCollectionDocument gmlDoc = new GMLFeatureCollectionDocument(); 463 gmlDoc.setRootElement( doc.getRootElement() ); 464 fc = gmlDoc.parse(); 465 } catch ( SAXException e ) { 466 LOG.logError( "Could not open gml file: " + fileName + " because: " + e.getMessage() ); 467 return; 468 } catch ( TransformerException e ) { 469 LOG.logError( "Could not open gml file: " + fileName + " because: " + e.getMessage() ); 470 return; 471 } catch ( XMLParsingException e ) { 472 LOG.logError( "Could not open gml file: " + fileName + " because: " + e.getMessage() ); 473 return; 474 } catch ( MalformedURLException e ) { 475 LOG.logError( "Could not open gml file: " + fileName + " because: " + e.getMessage() ); 476 return; 477 } catch ( IOException e ) { 478 LOG.logError( "Could not open gml file: " + fileName + " because: " + e.getMessage() ); 479 return; 480 } 481 } else if ( fileName.toUpperCase().endsWith( ".WRL" ) || fileName.toUpperCase().endsWith( ".VRML" ) ) { 482 VrmlLoader loader = new VrmlLoader(); 483 try { 484 Scene scene = loader.load( fileName ); 485 if ( scene != null ) { 486 BranchGroup bg = scene.getSceneGroup(); 487 BranchGroup result = new BranchGroup(); 488 result.setCapability( BranchGroup.ALLOW_DETACH ); 489 for( int i = 0; i< bg.numChildren(); ++i ){ 490 removeTransformGroup( bg.getChild( i ), result ); 491 } 492 LOG.logDebug( "Loaded branchgroup: " + bg.getName() ); 493 addBranchGroupToScene( result ); 494 } else { 495 JOptionPane.showMessageDialog( this, "Could not create scene from file: " + fileName ); 496 } 497 // } catch ( FileNotFoundException e ) { 498 // LOG.logError( "Error while loading vrml from file: " + fileName, e ); 499 // JOptionPane.showMessageDialog( this, "Could not create scene from file: " + fileName 500 // + " because: " 501 // + e.getMessage() ); 502 } catch ( IncorrectFormatException e ) { 503 LOG.logError( "Error while loading vrml from file: " + fileName, e ); 504 JOptionPane.showMessageDialog( this, "Could not create scene from file: " + fileName 505 + " because: " 506 + e.getMessage() ); 507 } catch ( ParsingErrorException e ) { 508 LOG.logError( "Error while loading vrml from file: " + fileName, e ); 509 JOptionPane.showMessageDialog( this, "Could not create scene from file: " + fileName 510 + " because: " 511 + e.getMessage() ); 512 } catch ( Exception e ) { 513 LOG.logError( "Error while loading vrml from file: " + fileName, e ); 514 JOptionPane.showMessageDialog( this, "Could not create scene from file: " + fileName 515 + " because: " 516 + e.getMessage() ); 517 } catch ( Throwable e ) { 518 LOG.logError( "Error while loading vrml from file: " + fileName, e ); 519 JOptionPane.showMessageDialog( this, "Could not create scene from file: " + fileName 520 + " because: " 521 + e.getMessage() ); 522 } 523 } 524 if ( fc != null ) { 525 BranchGroup bg = new BranchGroup(); 526 bg.setCapability( BranchGroup.ALLOW_DETACH ); 527 528 Appearance app = new Appearance(); 529 RenderingAttributes ra = new RenderingAttributes(); 530 ra.setDepthBufferEnable( true ); 531 app.setRenderingAttributes( ra ); 532 Material material = new Material(); 533 material.setAmbientColor( new Color3f( Color.WHITE ) ); 534 material.setDiffuseColor( new Color3f( Color.RED ) ); 535 material.setSpecularColor( new Color3f( Color.BLUE ) ); 536 PolygonAttributes pa = new PolygonAttributes(); 537 pa.setCullFace( PolygonAttributes.CULL_NONE); 538 pa.setBackFaceNormalFlip( true ); 539 pa.setPolygonMode( PolygonAttributes.POLYGON_FILL ); 540 app.setPolygonAttributes( pa ); 541 app.setMaterial( material ); 542 Envelope bbox = null; 543 for ( int i = 0; i < fc.size(); ++i ) { 544 Feature f = fc.getFeature( i ); 545 Geometry geom = f.getDefaultGeometryPropertyValue(); 546 if ( bbox == null ) { 547 bbox = geom.getEnvelope(); 548 } else { 549 try { 550 bbox = bbox.merge( geom.getEnvelope() ); 551 LOG.logDebug( "merging the bboxes resulted in: " + bbox ); 552 } catch ( GeometryException e ) { 553 LOG.logError( "Couldn't merge the bboxes" ); 554 e.printStackTrace(); 555 } 556 } 557 } 558 Point3d centroid = new Point3d( 0, 0, 0 ); 559 if ( bbox != null ) { 560 Point p = bbox.getCentroid(); 561 double zValue = p.getZ(); 562 if ( Double.isInfinite( zValue ) || Double.isNaN( zValue ) ) { 563 zValue = 0; 564 } 565 centroid.set( -p.getX(), -p.getY(), -zValue ); 566 } 567 for ( int i = 0; i < fc.size(); ++i ) { 568 Feature f = fc.getFeature( i ); 569 Geometry geom = f.getDefaultGeometryPropertyValue(); 570 Shape3D shape = mapGeometryToShape3D( geom, centroid ); 571 if ( shape != null ) { 572 shape.setAppearance( app ); 573 bg.addChild( shape ); 574 } else { 575 System.out.println( "ERRORORORORORORO" ); 576 } 577 } 578 Enumeration en = bg.getAllChildren(); 579 if ( en.hasMoreElements() ) { 580 addBranchGroupToScene( bg ); 581 } else { 582 LOG.logError( "Could not read any 3D-Info from the location: " + fileName ); 583 } 584 } 585 File f = new File( fileName ); 586 setTitle( WIN_TITLE + f.getName() ); 587 } 588 589 private void removeTransformGroup( javax.media.j3d.Node trans, BranchGroup result ){ 590 if( trans instanceof Group ){ 591 for( int i = 0; i< ((Group)trans).numChildren(); ++i ){ 592 javax.media.j3d.Node n = ((Group)trans).getChild( i ); 593 if( n instanceof TransformGroup ){ 594 Transform3D t = new Transform3D( ); 595 ((TransformGroup)n).getTransform( t ); 596 LOG.logDebug( "Setting old transform: " + t ); 597 Matrix3d id = new Matrix3d(); 598 id.setIdentity(); 599 t.setRotation( id ); 600 ((TransformGroup)n).setTransform( t ); 601 LOG.logDebug( "To new transform: " + t ); 602 } 603 removeTransformGroup( n, result ); 604 } 605 } else { 606 result.addChild( trans.cloneNode( true ) ); 607 } 608 } 609 610 611 /** 612 * @param contextNode 613 * @return true if the namespace "http://www.citygml.org/citygml/1/0/0" was found in one of the nodes of the 614 * dom-tree. 615 */ 616 private boolean isCityGMLDefined( Node contextNode ) { 617 618 boolean isCityGML = ( contextNode.lookupPrefix( CommonNamespaces.CITYGMLNS.toASCIIString() ) != null ) || CommonNamespaces.CITYGMLNS.toASCIIString() 619 .equals( contextNode.lookupNamespaceURI( null ) ); 620 if ( !isCityGML ) { 621 NodeList nl = contextNode.getChildNodes(); 622 for ( int i = 0; i < nl.getLength(); ++i ) { 623 isCityGML = isCityGMLDefined( nl.item( i ) ); 624 if ( isCityGML ) { 625 return true; 626 } 627 } 628 } 629 return isCityGML; 630 } 631 632 private Shape3D mapGeometryToShape3D( Geometry geom, Point3d translation ) { 633 if ( geom instanceof Point ) { 634 return createShape3D( (Point) geom, translation ); 635 } else if ( geom instanceof Curve ) { 636 return createShape3D( (Curve) geom, translation ); 637 } else if ( geom instanceof Surface ) { 638 return createShape3D( (Surface) geom, translation ); 639 } else if ( geom instanceof MultiSurface ) { 640 return createShape3D( (MultiSurface) geom, translation ); 641 } else { 642 if ( geom == null ) { 643 LOG.logError( "Could not map the geometry which was not instantiated" ); 644 } else { 645 LOG.logError( "Could not map the geometry: " + geom.getClass().getName() ); 646 } 647 return null; 648 } 649 650 // if ( geom instanceof MultiPoint ) { 651 // return new ShapeMultiPoint( (MultiPoint) g ); 652 // } 653 // 654 // if ( geom instanceof MultiCurve ) { 655 // List<Curve> cs = Arrays.asList( ( (MultiCurve) g ).getAllCurves() ); 656 // return new ShapePolyline( cs ); 657 // } 658 // 659 660 } 661 662 private Shape3D createShape3D( Point p, Point3d translation ) { 663 GeometryArray geomArray = new PointArray( 1, GeometryArray.COORDINATES ); 664 double z = p.getZ(); 665 if ( Double.isInfinite( z ) || Double.isNaN( z ) ) { 666 z = 0; 667 } 668 geomArray.setCoordinate( 0, new Point3d( p.getX() + translation.x, p.getY() + translation.y, z + translation.z ) ); 669 Shape3D result = new Shape3D( geomArray ); 670 result.setAppearanceOverrideEnable( true ); 671 return result; 672 } 673 674 private Shape3D createShape3D( Curve c, Point3d translation ) { 675 int totalPoints = 0; 676 List<Integer> failSegments = new ArrayList<Integer>(); 677 for ( int i = 0; i < c.getNumberOfCurveSegments(); ++i ) { 678 try { 679 totalPoints += c.getCurveSegmentAt( i ).getNumberOfPoints(); 680 } catch ( GeometryException e ) { 681 LOG.logError( "Could not get CurveSegment at position: " + i ); 682 failSegments.add( new Integer( i ) ); 683 } 684 } 685 686 LineArray geomArray = new LineArray( totalPoints, GeometryArray.COORDINATES ); 687 for ( int i = 0, pointCounter = 0; i < c.getNumberOfCurveSegments(); ++i ) { 688 if ( !failSegments.contains( new Integer( i ) ) ) { 689 CurveSegment segment = null; 690 try { 691 segment = c.getCurveSegmentAt( i ); 692 } catch ( GeometryException e ) { 693 // cannot happen. 694 } 695 for ( int k = 0; k < segment.getNumberOfPoints(); ++k ) { 696 Position p = segment.getPositionAt( k ); 697 double z = p.getZ(); 698 if ( Double.isInfinite( z ) || Double.isNaN( z ) ) { 699 z = 0; 700 } 701 geomArray.setCoordinate( pointCounter++, new Point3d( p.getX() + translation.x, 702 p.getY() + translation.y, 703 z + translation.z ) ); 704 } 705 } 706 } 707 Shape3D result = new Shape3D( geomArray ); 708 result.setAppearanceOverrideEnable( true ); 709 return result; 710 } 711 712 /** 713 * 714 * @param surface 715 * to be created 716 * @param translation 717 * to origin of the scene 718 * @return a Shape3D created from the surface. 719 */ 720 private Shape3D createShape3D( Surface surface, Point3d translation ) { 721 GeometryInfo geometryInfo = new GeometryInfo( GeometryInfo.POLYGON_ARRAY ); 722 723 Position[] pos = surface.getSurfaceBoundary().getExteriorRing().getPositions(); 724 Ring[] innerRings = surface.getSurfaceBoundary().getInteriorRings(); 725 int numberOfRings = 1; 726 int numberOfCoordinates = 3 * ( pos.length ); 727 if ( innerRings != null ) { 728 for ( int i = 0; i < innerRings.length; i++ ) { 729 numberOfRings++; 730 numberOfCoordinates += ( 3 * innerRings[i].getPositions().length ); 731 } 732 } 733 734 float[] coords = new float[numberOfCoordinates]; 735 int contourCounts[] = { numberOfRings }; 736 int[] stripCounts = new int[numberOfRings]; 737 numberOfRings = 0; 738 stripCounts[numberOfRings++] = pos.length; 739 740 int z = 0; 741 for ( int i = 0; i < pos.length; i++ ) { 742 double zValue = pos[i].getZ(); 743 if ( Double.isInfinite( zValue ) || Double.isNaN( zValue ) ) { 744 zValue = 0; 745 } 746 // LOG.logDebug( "Found a point in a surface: " + pos[i] ); 747 coords[z++] = (float) ( pos[i].getX() + translation.x ); 748 coords[z++] = (float) ( pos[i].getY() + translation.y ); 749 coords[z++] = (float) ( zValue + translation.z ); 750 } 751 752 if ( innerRings != null ) { 753 for ( int j = 0; j < innerRings.length; j++ ) { 754 pos = innerRings[j].getPositions(); 755 stripCounts[numberOfRings++] = pos.length; 756 for ( int i = 0; i < pos.length; i++ ) { 757 double zValue = pos[i].getZ(); 758 if ( Double.isInfinite( zValue ) || Double.isNaN( zValue ) ) { 759 zValue = 0; 760 } 761 coords[z++] = (float) ( pos[i].getX() + translation.x ); 762 coords[z++] = (float) ( pos[i].getY() + translation.y ); 763 coords[z++] = (float) ( zValue + translation.z ); 764 } 765 } 766 } 767 768 geometryInfo.setCoordinates( coords ); 769 geometryInfo.setStripCounts( stripCounts ); 770 geometryInfo.setContourCounts( contourCounts ); 771 geometryInfo.recomputeIndices(); 772 773 NormalGenerator ng = new NormalGenerator(); 774 ng.generateNormals( geometryInfo ); 775 Shape3D result = new Shape3D( geometryInfo.getGeometryArray() ); 776 result.setCapability( Shape3D.ALLOW_GEOMETRY_READ ); 777 result.setCapability( Shape3D.ALLOW_GEOMETRY_WRITE ); 778 result.setAppearanceOverrideEnable( true ); 779 return result; 780 } 781 782 /** 783 * @param surface 784 * @return a Shape3D created from the multisurfaces. 785 */ 786 private Shape3D createShape3D( MultiSurface multiSurface, Point3d translation ) { 787 Shape3D result = new Shape3D(); 788 result.setCapability( Shape3D.ALLOW_GEOMETRY_READ ); 789 result.setCapability( Shape3D.ALLOW_GEOMETRY_WRITE ); 790 Surface[] allSurfaces = multiSurface.getAllSurfaces(); 791 for ( int surfaceCount = 0; surfaceCount < allSurfaces.length; ++surfaceCount ) { 792 Surface surface = multiSurface.getSurfaceAt( surfaceCount ); 793 Shape3D s3D = createShape3D( surface, translation ); 794 result.addGeometry( s3D.getGeometry() ); 795 } 796 result.setAppearanceOverrideEnable( true ); 797 return result; 798 } 799 800 /* 801 * (non-Javadoc) 802 * 803 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 804 */ 805 public void actionPerformed( ActionEvent e ) { 806 Object source = e.getSource(); 807 if ( source instanceof JButton ) { 808 // JFileChooser filechooser = new JFileChooser(); 809 // filechooser.setVisible( true ); 810 int result = fileChooser.showOpenDialog( this ); 811 if ( JFileChooser.APPROVE_OPTION == result ) { 812 File f = fileChooser.getSelectedFile(); 813 if ( f != null ) { 814 String path = f.getAbsolutePath(); 815 String dirpath = f.getParent(); 816 System.out.println( "absolute Path: " + dirpath ); 817 prefs.put( PREF_KEY, dirpath ); 818 readFile( path ); 819 } 820 821 } 822 } 823 } 824 825 /* 826 * (non-Javadoc) 827 * 828 * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent) 829 */ 830 public void keyPressed( KeyEvent arg0 ) { 831 // nottin 832 } 833 834 /* 835 * (non-Javadoc) 836 * 837 * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent) 838 */ 839 public void keyReleased( KeyEvent arg0 ) { 840 // nottin 841 } 842 843 /* 844 * (non-Javadoc) 845 * 846 * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent) 847 */ 848 public void keyTyped( KeyEvent e ) { 849 double x = 0; 850 double y = 0; 851 double z = 0; 852 if ( e.getKeyChar() == 'q' ) { 853 System.exit( 0 ); 854 } else if ( e.getKeyChar() == 'x' ) { 855 x = 1; 856 } else if ( e.getKeyChar() == 'X' ) { 857 x = -1; 858 } else if ( e.getKeyChar() == 'y' ) { 859 y = 1; 860 } else if ( e.getKeyChar() == 'Y' ) { 861 y = -1; 862 } else if ( e.getKeyChar() == 'z' ) { 863 z = 1; 864 } else if ( e.getKeyChar() == 'Z' ) { 865 z = -1; 866 } 867 868 TransformGroup viewToWorld = simpleUniverse.getViewingPlatform().getViewPlatformTransform(); 869 Transform3D trans = new Transform3D(); 870 viewToWorld.getTransform( trans ); 871 trans.invert(); 872 Vector3d translation = new Vector3d(); 873 trans.get( translation ); 874 875 x += translation.x; 876 y += translation.y; 877 z += translation.z; 878 Point3d eye = new Point3d( x, y, z ); 879 trans.lookAt( eye, centroid, new Vector3d( 0, 1, 0 ) ); 880 LOG.logDebug( "Trans after:\n" + trans + "\ncentroid: " + centroid ); 881 Vector3d dist = new Vector3d( centroid ); 882 dist.sub( eye ); 883 trackBall.setSchedulingBounds( new BoundingSphere( centroid, dist.length() ) ); 884 viewToWorld.setTransform( trans ); 885 886 } 887 888 /** 889 * @param args 890 */ 891 public static void main( String[] args ) { 892 893 View3DFile viewer = new View3DFile( "/tmp/test.xml" ); 894 viewer.toFront(); 895 //View3DFile viewer = new View3DFile( true ); 896 // viewer.toFront(); 897 898 } 899 900 /** 901 * 902 * The <code>CustomFileFilter</code> class adds functionality to the filefilter mechanism of the JFileChooser. 903 * 904 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a> 905 * 906 * @author last edited by: $Author:$ 907 * 908 * @version $Revision:$, $Date:$ 909 * 910 */ 911 private class CustomFileFilter extends FileFilter { 912 913 private List<String> acceptedExtensions; 914 915 private String desc; 916 917 /** 918 * @param acceptedExtensions 919 * list of extensions this filter accepts. 920 */ 921 CustomFileFilter( List<String> acceptedExtensions, String description ) { 922 this.acceptedExtensions = new ArrayList<String>( acceptedExtensions.size() ); 923 for ( String s : acceptedExtensions ) { 924 if ( s.startsWith( "." ) ) { 925 s = s.substring( 1 ); 926 } 927 this.acceptedExtensions.add( s.trim().toUpperCase() ); 928 } 929 desc = description; 930 } 931 932 @Override 933 public boolean accept( File pathname ) { 934 if ( pathname.isDirectory() ) { 935 return true; 936 } 937 938 String extension = getExtension( pathname ); 939 if ( extension != null ) { 940 if ( acceptedExtensions.contains( extension.trim().toUpperCase() ) ) { 941 return true; 942 } 943 } 944 return false; 945 } 946 947 private String getExtension( File f ) { 948 String ext = null; 949 String s = f.getName(); 950 int i = s.lastIndexOf( '.' ); 951 952 if ( i > 0 && i < s.length() - 1 ) { 953 ext = s.substring( i + 1 ).toLowerCase(); 954 } 955 return ext; 956 } 957 958 @Override 959 public String getDescription() { 960 return desc; 961 } 962 } 963 }