001 //$HeadURL: svn+ssh://mschneider@svn.wald.intevation.org/deegree/base/trunk/resources/eclipse/svn_classfile_header_template.xml $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 037 package org.deegree.tools.app3d; 038 039 import java.awt.BorderLayout; 040 import java.awt.Color; 041 import java.awt.Dimension; 042 import java.awt.GraphicsConfigTemplate; 043 import java.awt.GridBagConstraints; 044 import java.awt.GridBagLayout; 045 import java.awt.Insets; 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.FileWriter; 054 import java.io.IOException; 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.BoundingBox; 064 import javax.media.j3d.BoundingSphere; 065 import javax.media.j3d.Bounds; 066 import javax.media.j3d.BranchGroup; 067 import javax.media.j3d.Canvas3D; 068 import javax.media.j3d.ColoringAttributes; 069 import javax.media.j3d.DirectionalLight; 070 import javax.media.j3d.GraphicsConfigTemplate3D; 071 import javax.media.j3d.Group; 072 import javax.media.j3d.Light; 073 import javax.media.j3d.Material; 074 import javax.media.j3d.RenderingAttributes; 075 import javax.media.j3d.Texture; 076 import javax.media.j3d.Transform3D; 077 import javax.media.j3d.TransformGroup; 078 import javax.media.j3d.View; 079 import javax.swing.BorderFactory; 080 import javax.swing.JButton; 081 import javax.swing.JDialog; 082 import javax.swing.JFileChooser; 083 import javax.swing.JFrame; 084 import javax.swing.JLabel; 085 import javax.swing.JOptionPane; 086 import javax.swing.JPanel; 087 import javax.swing.JProgressBar; 088 import javax.swing.JRadioButton; 089 import javax.swing.SwingConstants; 090 import javax.swing.WindowConstants; 091 import javax.swing.border.BevelBorder; 092 import javax.swing.border.Border; 093 import javax.swing.filechooser.FileFilter; 094 import javax.vecmath.Color3f; 095 import javax.vecmath.Point3d; 096 import javax.vecmath.Vector3d; 097 import javax.vecmath.Vector3f; 098 099 import org.deegree.framework.log.ILogger; 100 import org.deegree.framework.log.LoggerFactory; 101 import org.j3d.renderer.java3d.geom.Sphere; 102 import org.w3c.dom.Node; 103 104 import com.sun.j3d.utils.behaviors.mouse.MouseRotate; 105 import com.sun.j3d.utils.geometry.ColorCube; 106 import com.sun.j3d.utils.universe.SimpleUniverse; 107 108 /** 109 * The <code>View3DFile</code> class can display shape and gml/citygml file in 3D. 110 * 111 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a> 112 * 113 * @author last edited by: $Author:$ 114 * 115 * @version $Revision:$, $Date:$ 116 * 117 */ 118 119 public class View3DFile extends JFrame implements ActionListener, KeyListener { 120 /** 121 * 122 */ 123 private static final long serialVersionUID = 7698388852544865855L; 124 125 private static ILogger LOG = LoggerFactory.getLogger( View3DFile.class ); 126 127 private SimpleUniverse simpleUniverse; 128 129 private Canvas3D canvas; 130 131 private MouseRotate trackBall; 132 133 private BranchGroup scene; 134 135 private TransformGroup rotationGroup; 136 137 private Light firstLight, secondLight, thirdLight; 138 139 private Point3d centroid; 140 141 private Preferences prefs; 142 143 private final static String OPEN_KEY = "lastOpenLocation"; 144 145 private final static String LAST_EXTENSION = "lastFileExtension"; 146 147 private final static String WIN_TITLE = "Deegree 3D Object viewer: "; 148 149 private Background backGround; 150 151 private double zoomX = 1; 152 153 private double zoomY = 1; 154 155 private double zoomZ = 1; 156 157 private final Vector3d upVector = new Vector3d( 0, 1, 0 ); 158 159 private List<CustomFileFilter> supportedOpenFilter = new ArrayList<CustomFileFilter>(); 160 161 /** 162 * A panel showing some key stroke helps 163 */ 164 JPanel helpLister; 165 166 /** 167 * Creates a frame with the menus and the canvas3d set and tries to load the file from given location. 168 * 169 * @param fileName 170 * to be loaded. 171 */ 172 public View3DFile( String fileName ) { 173 this( false ); 174 readFile( fileName ); 175 } 176 177 /** 178 * Creates a new frame with the menus and the canvas3d set. 179 * 180 * @param testSphere 181 * true if a sphere should be displayed. 182 */ 183 public View3DFile( boolean testSphere ) { 184 super( WIN_TITLE ); 185 prefs = Preferences.userNodeForPackage( View3DFile.class ); 186 setupGUI(); 187 188 // openFileChooser(); 189 190 setupJava3D( testSphere ); 191 ArrayList<String> extensions = new ArrayList<String>(); 192 193 extensions.add( "gml" ); 194 extensions.add( "xml" ); 195 supportedOpenFilter.add( new CustomFileFilter( extensions, "(*.gml, *.xml) GML or CityGML-Files" ) ); 196 197 extensions.clear(); 198 extensions.add( "shp" ); 199 supportedOpenFilter.add( new CustomFileFilter( extensions, "(*.shp) Esri ShapeFiles" ) ); 200 201 extensions.clear(); 202 extensions.add( "vrml" ); 203 extensions.add( "wrl" ); 204 supportedOpenFilter.add( new CustomFileFilter( extensions, 205 "(*.vrml, *.wrl) VRML97 - Virtual Reality Modelling Language" ) ); 206 207 pack(); 208 } 209 210 /** 211 * GUI stuff 212 */ 213 private void setupGUI() { 214 // add listener for closing the frame/application 215 addWindowListener( new WindowAdapter() { 216 @Override 217 public void windowClosing( WindowEvent evt ) { 218 System.exit( 0 ); 219 } 220 } ); 221 setLayout( new BorderLayout() ); 222 setMinimumSize( new Dimension( 600, 600 ) ); 223 setPreferredSize( new Dimension( 600, 600 ) ); 224 setVisible( true ); 225 // Adding the button panel 226 JPanel totalPanel = new JPanel( new BorderLayout() ); 227 // JPanel buttonPanel = new JPanel( new FlowLayout() ); 228 // createButtons( buttonPanel ); 229 totalPanel.add( createButtons(), BorderLayout.NORTH ); 230 addKeyListener( this ); 231 helpLister = new JPanel( new GridBagLayout() ); 232 Border border = BorderFactory.createTitledBorder( BorderFactory.createBevelBorder( BevelBorder.LOWERED ), 233 "Instant help" ); 234 helpLister.setBorder( border ); 235 GridBagConstraints gb = new GridBagConstraints(); 236 gb.ipadx = 10; 237 gb.gridx = 0; 238 gb.gridy = 0; 239 JLabel tmp = new JLabel( "x: move postive X-axis" ); 240 helpLister.add( tmp, gb ); 241 242 gb.gridx++; 243 tmp = new JLabel( "X: move negative X-axis" ); 244 helpLister.add( tmp, gb ); 245 246 gb.gridx = 0; 247 gb.gridy++; 248 tmp = new JLabel( "y: move positve Y-axis" ); 249 helpLister.add( tmp, gb ); 250 251 gb.gridx++; 252 tmp = new JLabel( "Y: move negative Y-axis" ); 253 helpLister.add( tmp, gb ); 254 255 gb.gridy++; 256 gb.gridx = 0; 257 tmp = new JLabel( "z: move positve Z-axis" ); 258 helpLister.add( tmp, gb ); 259 gb.gridx++; 260 261 tmp = new JLabel( "Z: move negative Z-axis" ); 262 helpLister.add( tmp, gb ); 263 helpLister.setVisible( false ); 264 265 totalPanel.add( helpLister, BorderLayout.SOUTH ); 266 getContentPane().add( totalPanel, BorderLayout.SOUTH ); 267 268 } 269 270 private JFileChooser createFileChooser( List<CustomFileFilter> fileFilter ) { 271 // Setting up the fileChooser. 272 273 String lastLoc = prefs.get( OPEN_KEY, System.getProperty( "user.home" ) ); 274 275 File lastFile = new File( lastLoc ); 276 if ( !lastFile.exists() ) { 277 lastFile = new File( System.getProperty( "user.home" ) ); 278 } 279 JFileChooser fileChooser = new JFileChooser( lastFile ); 280 fileChooser.setMultiSelectionEnabled( false ); 281 if ( fileFilter != null && fileFilter.size() > 0 ) { 282 // the *.* file fileter is off 283 fileChooser.setAcceptAllFileFilterUsed( false ); 284 String lastExtension = prefs.get( LAST_EXTENSION, "*" ); 285 FileFilter selected = fileFilter.get( 0 ); 286 for ( CustomFileFilter filter : fileFilter ) { 287 fileChooser.setFileFilter( filter ); 288 if ( filter.accepts( lastExtension ) ) { 289 selected = filter; 290 } 291 } 292 293 fileChooser.setFileFilter( selected ); 294 } 295 296 return fileChooser; 297 } 298 299 private void setupJava3D( boolean testSphere ) { 300 // setting up Java3D 301 GraphicsConfigTemplate3D configTemplate = new GraphicsConfigTemplate3D(); 302 configTemplate.setSceneAntialiasing( GraphicsConfigTemplate.PREFERRED ); 303 configTemplate.setDoubleBuffer( GraphicsConfigTemplate.REQUIRED ); 304 canvas = new Canvas3D( SimpleUniverse.getPreferredConfiguration() ); 305 canvas.setDoubleBufferEnable( true ); 306 simpleUniverse = new SimpleUniverse( canvas ); 307 if ( canvas != null ) { 308 getContentPane().add( canvas, BorderLayout.CENTER ); 309 } 310 311 View view = simpleUniverse.getViewer().getView(); 312 313 // view parameters 314 view.setSceneAntialiasingEnable( true ); 315 view.setUserHeadToVworldEnable( true ); 316 317 centroid = new Point3d( 0.3, 0.3, 0.3 ); 318 scene = new BranchGroup(); 319 firstLight = createDirectionalLight( new Vector3f( 0, 0, 1 ) ); 320 secondLight = createDirectionalLight( new Vector3f( 0, -1, -1 ) ); 321 thirdLight = createDirectionalLight( new Vector3f( -1, 0, 0 ) ); 322 323 scene.addChild( firstLight ); 324 scene.addChild( secondLight ); 325 scene.addChild( thirdLight ); 326 327 // is handled by the mouse rotater, all objects will be added to it. 328 rotationGroup = new TransformGroup(); 329 rotationGroup.setCapability( TransformGroup.ALLOW_TRANSFORM_WRITE ); 330 rotationGroup.setCapability( TransformGroup.ALLOW_TRANSFORM_READ ); 331 rotationGroup.setCapability( BranchGroup.ALLOW_DETACH ); 332 rotationGroup.setCapability( Group.ALLOW_CHILDREN_EXTEND ); 333 rotationGroup.setCapability( Group.ALLOW_CHILDREN_READ ); 334 rotationGroup.setCapability( Group.ALLOW_CHILDREN_WRITE ); 335 scene.addChild( rotationGroup ); 336 337 backGround = new Background( new Color3f( Color.LIGHT_GRAY ) ); 338 backGround.setCapability( javax.media.j3d.Node.ALLOW_BOUNDS_WRITE ); 339 backGround.setCapability( javax.media.j3d.Node.ALLOW_BOUNDS_READ ); 340 backGround.setCapability( Background.ALLOW_APPLICATION_BOUNDS_READ ); 341 backGround.setCapability( Background.ALLOW_APPLICATION_BOUNDS_WRITE ); 342 343 scene.addChild( backGround ); 344 345 trackBall = new MouseRotate( rotationGroup ); 346 scene.addChild( trackBall ); 347 348 simpleUniverse.addBranchGraph( scene ); 349 350 // adding the key listeners 351 canvas.addKeyListener( this ); 352 353 if ( testSphere ) { 354 BranchGroup sphere = createStartScene( null ); 355 addBranchGroupToScene( sphere ); 356 } 357 } 358 359 /** 360 * Create a directional light, with color.WHITE. 361 */ 362 private DirectionalLight createDirectionalLight( Vector3f lightDir ) { 363 // create the color for the light 364 Color3f color = new Color3f( Color.WHITE ); 365 // create the directional light with the color and direction 366 DirectionalLight light = new DirectionalLight( color, lightDir ); 367 light.setCapability( Light.ALLOW_INFLUENCING_BOUNDS_READ ); 368 light.setCapability( Light.ALLOW_INFLUENCING_BOUNDS_WRITE ); 369 return light; 370 } 371 372 /** 373 * Add the given branch group to the scene and set the appropriate distance etc. After adding the branch group to 374 * the rotation group which is controlled by the mouse rotator. 375 * 376 * @param b 377 */ 378 private void addBranchGroupToScene( BranchGroup b ) { 379 rotationGroup.removeAllChildren(); 380 // translationGroup.removeAllChildren(); 381 // System.out.println( b.getBounds() ); 382 Bounds bounds = b.getBounds(); 383 BranchGroup wrapper = new BranchGroup(); 384 wrapper.setCapability( BranchGroup.ALLOW_DETACH ); 385 wrapper.setCapability( Group.ALLOW_CHILDREN_READ ); 386 wrapper.setCapability( Texture.ALLOW_ENABLE_READ ); 387 wrapper.setCapability( Texture.ALLOW_IMAGE_READ ); 388 if ( bounds != null ) { 389 LOG.logDebug( "Old centroid: " + centroid ); 390 BoundingSphere bs = new BoundingSphere( bounds ); 391 bs.getCenter( centroid ); 392 LOG.logDebug( "New centroid: " + centroid ); 393 394 TransformGroup viewToWorld = simpleUniverse.getViewingPlatform().getViewPlatformTransform(); 395 Transform3D trans = new Transform3D(); 396 397 BoundingBox bbox = new BoundingBox( bounds ); 398 Point3d lower = new Point3d(); 399 bbox.getLower( lower ); 400 Point3d upper = new Point3d(); 401 bbox.getUpper( upper ); 402 double lengthX = Math.abs( upper.x - lower.x ); 403 double lengthY = Math.abs( upper.y - lower.y ); 404 double lengthZ = Math.abs( upper.z - lower.z ); 405 406 zoomX = lengthX * 0.1; 407 zoomY = lengthY * 0.1; 408 zoomZ = lengthZ * 0.1; 409 410 double radius = ( lengthX > lengthY ) ? ( ( lengthX > lengthZ ) ? lengthX 411 : ( ( lengthY > lengthZ ) ? lengthY 412 : lengthZ ) ) 413 : ( ( lengthY > lengthZ ) ? lengthY : lengthZ ); 414 Point3d eye = new Point3d(); 415 eye.z += ( ( lower.z - upper.z < 0 ) ? -1 : 1 ) * ( radius * 1.5 ); 416 if ( Math.abs( eye.z ) < 0.00001 && Math.abs( centroid.z ) < 0.00001 ) { 417 eye.z = 1; 418 } 419 trans.lookAt( eye, centroid, upVector ); 420 421 LOG.logDebug( "Trans Matrix after lookat:\n" + trans ); 422 LOG.logDebug( "BBox lower: " + lower ); 423 LOG.logDebug( "BBox upper: " + upper ); 424 LOG.logDebug( "Center: " + centroid ); 425 LOG.logDebug( "eye: " + eye ); 426 LOG.logDebug( "up: " + upVector ); 427 LOG.logDebug( "radius: " + bs.getRadius() ); 428 LOG.logDebug( "used radius (of largest axis): " + radius ); 429 LOG.logDebug( "zoomX: " + zoomX ); 430 LOG.logDebug( "zoomY: " + zoomY ); 431 LOG.logDebug( "zoomZ: " + zoomZ ); 432 viewToWorld.setTransform( trans ); 433 View view = simpleUniverse.getViewer().getView(); 434 435 // view parameters 436 view.setBackClipDistance( radius * 100 ); 437 // the near clippingplane is one hundereth of the far. 438 view.setFrontClipDistance( radius * 0.001 ); 439 440 BoundingSphere influence = new BoundingSphere( eye, radius * 4 ); 441 442 firstLight.setInfluencingBounds( influence ); 443 secondLight.setInfluencingBounds( influence ); 444 thirdLight.setInfluencingBounds( influence ); 445 trackBall.setSchedulingBounds( influence ); 446 backGround.setApplicationBounds( influence ); 447 448 // add the negativ translation for the mouse tracker to work. 449 TransformGroup resultTrans = new TransformGroup(); 450 Transform3D negativTranslation = new Transform3D(); 451 negativTranslation.setTranslation( new Vector3d( -centroid.x, -centroid.y, -centroid.z ) ); 452 resultTrans.setTransform( negativTranslation ); 453 resultTrans.addChild( b ); 454 wrapper.addChild( resultTrans ); 455 } else { 456 wrapper.addChild( b ); 457 } 458 rotationGroup.addChild( wrapper ); 459 } 460 461 /** 462 * @return a shere and a cube 463 */ 464 private BranchGroup createStartScene( Point3d translation ) { 465 Appearance app = new Appearance(); 466 RenderingAttributes ra = new RenderingAttributes(); 467 ra.setDepthBufferEnable( true ); 468 ra.setDepthBufferWriteEnable( true ); 469 app.setRenderingAttributes( ra ); 470 471 ColoringAttributes ca = new ColoringAttributes(); 472 ca.setShadeModel( ColoringAttributes.SHADE_GOURAUD ); 473 ca.setCapability( ColoringAttributes.NICEST ); 474 app.setColoringAttributes( ca ); 475 476 Material material = new Material(); 477 material.setAmbientColor( new Color3f( Color.WHITE ) ); 478 material.setDiffuseColor( new Color3f( Color.RED ) ); 479 material.setSpecularColor( new Color3f( Color.ORANGE ) ); 480 app.setMaterial( material ); 481 TransformGroup tg = new TransformGroup(); 482 Transform3D trans = new Transform3D(); 483 if ( translation != null ) { 484 trans.setTranslation( new Vector3d( translation ) ); 485 tg.setTransform( trans ); 486 } 487 tg.setCapability( BranchGroup.ALLOW_DETACH ); 488 tg.setCapability( Group.ALLOW_CHILDREN_READ ); 489 tg.addChild( new ColorCube( 0.2f ) ); 490 BranchGroup b = new BranchGroup(); 491 b.setCapability( BranchGroup.ALLOW_DETACH ); 492 b.addChild( tg ); 493 494 tg.addChild( new Sphere( 0.3f, app ) ); 495 496 return b; 497 } 498 499 private JPanel createButtons() { 500 JPanel buttonPanel = new JPanel( new GridBagLayout() ); 501 GridBagConstraints gb = new GridBagConstraints(); 502 gb.gridx = 0; 503 gb.gridy = 0; 504 505 JRadioButton help = new JRadioButton( "Activate help" ); 506 help.addActionListener( new ActionListener() { 507 public void actionPerformed( ActionEvent e ) { 508 if ( helpLister.isVisible() ) { 509 helpLister.setVisible( false ); 510 ( (JRadioButton) e.getSource() ).setText( "Activate help" ); 511 } else { 512 helpLister.setVisible( true ); 513 ( (JRadioButton) e.getSource() ).setText( "De-Activate help" ); 514 515 } 516 } 517 } ); 518 buttonPanel.add( help, gb ); 519 520 gb.insets = new Insets( 10, 10, 10, 10 ); 521 gb.gridx++; 522 JButton button = new JButton( "Open File" ); 523 button.setMnemonic( KeyEvent.VK_O ); 524 button.addActionListener( this ); 525 buttonPanel.add( button, gb ); 526 527 gb.gridx++; 528 button = new JButton( "Export File" ); 529 button.setMnemonic( KeyEvent.VK_O ); 530 button.addActionListener( this ); 531 buttonPanel.add( button, gb ); 532 533 return buttonPanel; 534 } 535 536 private void readFile( String fileName ) { 537 538 if ( fileName == null || "".equals( fileName.trim() ) ) { 539 throw new InvalidParameterException( "the file name may not be null or empty" ); 540 } 541 fileName = fileName.trim(); 542 543 final Open3DFile openFile = new Open3DFile( fileName, this ); 544 545 final JDialog dialog = new JDialog( this, "Loading", true ); 546 547 dialog.getContentPane().setLayout( new BorderLayout() ); 548 dialog.getContentPane().add( 549 new JLabel( "<HTML>Loading file:<br>" + fileName + "<br>Please wait!</HTML>", 550 SwingConstants.CENTER ), BorderLayout.NORTH ); 551 final JProgressBar progressBar = new JProgressBar(); 552 progressBar.setStringPainted( true ); 553 progressBar.setIndeterminate( false ); 554 dialog.getContentPane().add( progressBar, BorderLayout.CENTER ); 555 556 dialog.pack(); 557 dialog.setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE ); 558 dialog.setResizable( false ); 559 dialog.setLocationRelativeTo( this ); 560 561 final Thread openThread = new Thread() { 562 /** 563 * Opens the file in a separate thread. 564 */ 565 @Override 566 public void run() { 567 openFile.openFile( progressBar ); 568 if ( dialog.isDisplayable() ) { 569 dialog.setVisible( false ); 570 dialog.dispose(); 571 } 572 } 573 }; 574 openThread.start(); 575 576 dialog.setVisible( true ); 577 BranchGroup result = openFile.getOpenedFile(); 578 // 579 if ( result != null ) { 580 addBranchGroupToScene( result ); 581 File f = new File( fileName ); 582 setTitle( WIN_TITLE + f.getName() ); 583 } else { 584 showExceptionDialog( "The file: " + fileName 585 + " could not be read,\nSee error log for detailed information." ); 586 } 587 588 } 589 590 /** 591 * Shows an export dialog to the user. 592 */ 593 @SuppressWarnings("unchecked") 594 private void doExport() { 595 596 Export3DFile exportEvaluater = new Export3DFile( this ); 597 // find the scene graph to export 598 Enumeration<Node> en = rotationGroup.getAllChildren(); 599 BranchGroup toExport = null; 600 if ( en.hasMoreElements() ) { 601 toExport = (BranchGroup) en.nextElement(); 602 } 603 if ( toExport == null ) { 604 showExceptionDialog( "Could not get the scene to export." ); 605 return; 606 } 607 StringBuilder sb = exportEvaluater.exportBranchgroup( toExport ); 608 if ( sb.length() == 0 ) { 609 showExceptionDialog( "Exporting failed, see error log for details." ); 610 return; 611 } 612 addBranchGroupToScene( toExport ); 613 JFileChooser chooser = createFileChooser( null ); 614 int result = chooser.showSaveDialog( this ); 615 if ( JFileChooser.APPROVE_OPTION == result ) { 616 File f = chooser.getSelectedFile(); 617 FileFilter ff = chooser.getFileFilter(); 618 if ( ff instanceof CustomFileFilter ) { 619 prefs.put( LAST_EXTENSION, ( (CustomFileFilter) ff ).getExtension( f ) ); 620 prefs.put( OPEN_KEY, f.getParent() ); 621 } 622 try { 623 FileWriter output = new FileWriter( f ); 624 output.write( sb.toString() ); 625 output.flush(); 626 output.close(); 627 } catch ( IOException e ) { 628 LOG.logError( e.getMessage(), e ); 629 showExceptionDialog( "Exporting failed, see error log for details." ); 630 } 631 632 } 633 } 634 635 /** 636 * @param errorMessage 637 * to display 638 */ 639 public void showExceptionDialog( String errorMessage ) { 640 JOptionPane.showMessageDialog( this, errorMessage ); 641 } 642 643 /* 644 * (non-Javadoc) 645 * 646 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 647 */ 648 public void actionPerformed( ActionEvent e ) { 649 Object source = e.getSource(); 650 if ( source instanceof JButton ) { 651 JButton clicked = (JButton) source; 652 if ( clicked.getText().startsWith( "Export" ) ) { 653 doExport(); 654 } else { 655 JFileChooser fileChooser = createFileChooser( supportedOpenFilter ); 656 int result = fileChooser.showOpenDialog( this ); 657 if ( JFileChooser.APPROVE_OPTION == result ) { 658 File f = fileChooser.getSelectedFile(); 659 if ( f != null ) { 660 String path = f.getAbsolutePath(); 661 prefs.put( LAST_EXTENSION, ( (CustomFileFilter) fileChooser.getFileFilter() ).getExtension( f ) ); 662 prefs.put( OPEN_KEY, f.getParent() ); 663 readFile( path ); 664 } 665 666 } 667 } 668 } 669 } 670 671 /* 672 * (non-Javadoc) 673 * 674 * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent) 675 */ 676 public void keyPressed( KeyEvent arg0 ) { 677 // nottin 678 } 679 680 /* 681 * (non-Javadoc) 682 * 683 * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent) 684 */ 685 public void keyReleased( KeyEvent arg0 ) { 686 // nottin 687 } 688 689 /* 690 * (non-Javadoc) 691 * 692 * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent) 693 */ 694 public void keyTyped( KeyEvent e ) { 695 double x = 0; 696 double y = 0; 697 double z = 0; 698 if ( e.getKeyChar() == 'q' ) { 699 System.exit( 0 ); 700 } else if ( e.getKeyChar() == 'x' ) { 701 x = zoomX; 702 } else if ( e.getKeyChar() == 'X' ) { 703 x = -zoomX; 704 } else if ( e.getKeyChar() == 'y' ) { 705 y = zoomY; 706 } else if ( e.getKeyChar() == 'Y' ) { 707 y = -zoomY; 708 } else if ( e.getKeyChar() == 'z' ) { 709 z = zoomZ; 710 } else if ( e.getKeyChar() == 'Z' ) { 711 z = -zoomZ; 712 } 713 714 TransformGroup viewToWorld = simpleUniverse.getViewingPlatform().getViewPlatformTransform(); 715 Transform3D trans = new Transform3D(); 716 viewToWorld.getTransform( trans ); 717 trans.invert(); 718 Vector3d translation = new Vector3d(); 719 trans.get( translation ); 720 721 x += translation.x; 722 y += translation.y; 723 z += translation.z; 724 725 Point3d eye = new Point3d( x, y, z ); 726 trans.lookAt( eye, centroid, upVector ); 727 LOG.logDebug( "Trans after:\n" + trans + "\ncentroid: " + centroid ); 728 LOG.logDebug( "Center: " + centroid ); 729 LOG.logDebug( "eye: " + eye ); 730 731 Vector3d dist = new Vector3d( centroid ); 732 dist.sub( eye ); 733 // trackBall.setSchedulingBounds( new BoundingSphere( centroid, dist.length() ) ); 734 viewToWorld.setTransform( trans ); 735 736 } 737 738 /** 739 * @param args 740 */ 741 public static void main( String[] args ) { 742 View3DFile viewer = new View3DFile( true ); 743 viewer.toFront(); 744 745 } 746 747 /** 748 * 749 * The <code>CustomFileFilter</code> class adds functionality to the filefilter mechanism of the JFileChooser. 750 * 751 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a> 752 * 753 * @author last edited by: $Author:$ 754 * 755 * @version $Revision:$, $Date:$ 756 * 757 */ 758 private class CustomFileFilter extends FileFilter { 759 760 private List<String> acceptedExtensions; 761 762 private String desc; 763 764 /** 765 * @param acceptedExtensions 766 * list of extensions this filter accepts. 767 * @param description 768 * to show 769 */ 770 CustomFileFilter( List<String> acceptedExtensions, String description ) { 771 this.acceptedExtensions = new ArrayList<String>( acceptedExtensions.size() ); 772 StringBuilder sb = new StringBuilder(); 773 if ( acceptedExtensions.size() > 0 ) { 774 775 sb.append( "(" ); 776 int i = 0; 777 for ( String ext : acceptedExtensions ) { 778 if ( ext.startsWith( "." ) ) { 779 ext = ext.substring( 1 ); 780 } else if ( ext.startsWith( "*." ) ) { 781 ext = ext.substring( 2 ); 782 } else if ( ext.startsWith( "*" ) ) { 783 ext = ext.substring( 1 ); 784 } 785 786 this.acceptedExtensions.add( ext.trim().toUpperCase() ); 787 sb.append( "*." ); 788 sb.append( ext ); 789 if ( ++i < acceptedExtensions.size() ) { 790 sb.append( ", " ); 791 } 792 } 793 sb.append( ")" ); 794 } 795 sb.append( description ); 796 desc = sb.toString(); 797 } 798 799 /** 800 * @param extension 801 * @return true if the extension is accepted 802 */ 803 public boolean accepts( String extension ) { 804 return extension != null && acceptedExtensions.contains( extension.toUpperCase() ); 805 } 806 807 @Override 808 public boolean accept( File pathname ) { 809 if ( pathname.isDirectory() ) { 810 return true; 811 } 812 813 String extension = getExtension( pathname ); 814 if ( extension != null ) { 815 if ( acceptedExtensions.contains( extension.trim().toUpperCase() ) ) { 816 return true; 817 } 818 } 819 return false; 820 } 821 822 /** 823 * @param f 824 * @return the file extension (e.g. gml/shp/xml etc.) 825 */ 826 String getExtension( File f ) { 827 String ext = null; 828 String s = f.getName(); 829 int i = s.lastIndexOf( '.' ); 830 831 if ( i > 0 && i < s.length() - 1 ) { 832 ext = s.substring( i + 1 ).toLowerCase(); 833 } 834 return ext; 835 } 836 837 @Override 838 public String getDescription() { 839 return desc; 840 } 841 } 842 843 }