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-2007 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.BoundingSphere; 063 import javax.media.j3d.Bounds; 064 import javax.media.j3d.BranchGroup; 065 import javax.media.j3d.Canvas3D; 066 import javax.media.j3d.ColoringAttributes; 067 import javax.media.j3d.DirectionalLight; 068 import javax.media.j3d.GeometryArray; 069 import javax.media.j3d.GraphicsConfigTemplate3D; 070 import javax.media.j3d.Group; 071 import javax.media.j3d.Light; 072 import javax.media.j3d.LineArray; 073 import javax.media.j3d.Material; 074 import javax.media.j3d.PointArray; 075 import javax.media.j3d.PolygonAttributes; 076 import javax.media.j3d.RenderingAttributes; 077 import javax.media.j3d.Shape3D; 078 import javax.media.j3d.Transform3D; 079 import javax.media.j3d.TransformGroup; 080 import javax.media.j3d.View; 081 import javax.swing.JButton; 082 import javax.swing.JFileChooser; 083 import javax.swing.JFrame; 084 import javax.swing.JPanel; 085 import javax.swing.filechooser.FileFilter; 086 import javax.vecmath.Color3f; 087 import javax.vecmath.Point3d; 088 import javax.vecmath.Vector3d; 089 import javax.vecmath.Vector3f; 090 import javax.xml.transform.TransformerException; 091 092 import org.deegree.framework.log.ILogger; 093 import org.deegree.framework.log.LoggerFactory; 094 import org.deegree.framework.xml.XMLFragment; 095 import org.deegree.framework.xml.XMLParsingException; 096 import org.deegree.framework.xml.XSLTDocument; 097 import org.deegree.io.dbaseapi.DBaseException; 098 import org.deegree.io.shpapi.shape_new.ShapeFile; 099 import org.deegree.io.shpapi.shape_new.ShapeFileReader; 100 import org.deegree.model.feature.Feature; 101 import org.deegree.model.feature.FeatureCollection; 102 import org.deegree.model.feature.GMLFeatureCollectionDocument; 103 import org.deegree.model.spatialschema.Curve; 104 import org.deegree.model.spatialschema.CurveSegment; 105 import org.deegree.model.spatialschema.Envelope; 106 import org.deegree.model.spatialschema.Geometry; 107 import org.deegree.model.spatialschema.GeometryException; 108 import org.deegree.model.spatialschema.MultiSurface; 109 import org.deegree.model.spatialschema.Point; 110 import org.deegree.model.spatialschema.Position; 111 import org.deegree.model.spatialschema.Ring; 112 import org.deegree.model.spatialschema.Surface; 113 import org.deegree.ogcbase.CommonNamespaces; 114 import org.w3c.dom.Node; 115 import org.w3c.dom.NodeList; 116 import org.xml.sax.SAXException; 117 118 import com.sun.j3d.utils.behaviors.mouse.MouseRotate; 119 import com.sun.j3d.utils.geometry.ColorCube; 120 import com.sun.j3d.utils.geometry.GeometryInfo; 121 import com.sun.j3d.utils.geometry.NormalGenerator; 122 import com.sun.j3d.utils.universe.SimpleUniverse; 123 124 /** 125 * The <code>View3DFile</code> class can display shape and gml/citygml file in 3D. 126 * 127 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a> 128 * 129 * @author last edited by: $Author:$ 130 * 131 * @version $Revision:$, $Date:$ 132 * 133 */ 134 135 public class View3DFile extends JFrame implements ActionListener, KeyListener { 136 /** 137 * 138 */ 139 private static final long serialVersionUID = 7698388852544865855L; 140 141 private static ILogger LOG = LoggerFactory.getLogger( View3DFile.class ); 142 143 private SimpleUniverse simpleUniverse; 144 145 // private JCanvas3D canvas; 146 // private TrackBall trackBall; 147 148 private Canvas3D canvas; 149 150 private MouseRotate trackBall; 151 152 private BranchGroup scene; 153 154 private TransformGroup rotationGroup; 155 156 private Light firstLight, secondLight, thirdLight; 157 158 private Point3d centroid; 159 160 private JFileChooser fileChooser; 161 162 private Preferences prefs; 163 private final static String PREF_KEY = "lastlocation"; 164 private final static String WIN_TITLE = "Deegree 3D Object viewer: "; 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 * @throws DBaseException 172 * @throws IOException 173 */ 174 public View3DFile( String fileName ){ 175 this( false ); 176 readFile( fileName ); 177 } 178 179 /** 180 * Creates a new frame with the menus and the canvas3d set. 181 * @param testSphere true if a sphere should be displayed. 182 */ 183 public View3DFile( boolean testSphere ) { 184 super( WIN_TITLE ); 185 186 // add listener for closing the frame/application 187 addWindowListener( new WindowAdapter() { 188 @Override 189 public void windowClosing( WindowEvent evt ) { 190 System.exit( 0 ); 191 } 192 } ); 193 setLayout( new BorderLayout() ); 194 setMinimumSize( new Dimension( 400, 400 ) ); 195 setPreferredSize( new Dimension( 400, 400 ) ); 196 setVisible( true ); 197 198 //Setting up the fileChooser. 199 prefs = Preferences.userNodeForPackage( View3DFile.class ); 200 String lastLoc = prefs.get( PREF_KEY, System.getProperty( "user.home" ) ); 201 File lastFile = new File( lastLoc ); 202 if( !lastFile.exists() ){ 203 lastFile = new File( System.getProperty( "user.home" ) ); 204 } 205 fileChooser = new JFileChooser( lastFile ); 206 207 ArrayList<String> extensions = new ArrayList<String>(); 208 extensions.add( "gml" ); 209 extensions.add( "xml" ); 210 CustomFileFilter fileFilter = new CustomFileFilter( extensions, "(*.gml *.xml)GML or CityGML-Files" ); 211 fileChooser.setFileFilter( fileFilter ); 212 213 extensions.clear(); 214 extensions.add( "shp" ); 215 fileFilter = new CustomFileFilter( extensions, "Esri ShapeFiles" ); 216 fileChooser.setFileFilter( fileFilter ); 217 fileChooser.setAcceptAllFileFilterUsed( false ); 218 fileChooser.setMultiSelectionEnabled( false ); 219 220 //Adding the button panel 221 JPanel buttonPanel = new JPanel( new FlowLayout() ); 222 createButtons( buttonPanel ); 223 getContentPane().add( buttonPanel, BorderLayout.SOUTH ); 224 225 226 227 //setting up Java3D 228 GraphicsConfigTemplate3D configTemplate = new GraphicsConfigTemplate3D(); 229 configTemplate.setSceneAntialiasing( GraphicsConfigTemplate.PREFERRED ); 230 configTemplate.setDoubleBuffer( GraphicsConfigTemplate.REQUIRED ); 231 canvas = new Canvas3D( SimpleUniverse.getPreferredConfiguration() ); 232 simpleUniverse = new SimpleUniverse( canvas ); 233 if ( canvas != null ) { 234 getContentPane().add( canvas, BorderLayout.CENTER ); 235 } 236 237 View view = simpleUniverse.getViewer().getView(); 238 239 // view parameters 240 view.setBackClipDistance( 10000 ); 241 view.setFrontClipDistance( 0.1 ); 242 view.setWindowEyepointPolicy( View.RELATIVE_TO_FIELD_OF_VIEW ); 243 view.setSceneAntialiasingEnable( true ); 244 245 centroid = new Point3d(); 246 scene = new BranchGroup(); 247 firstLight = createDirectionalLight( new Vector3f( 0, 0, 1 ) ); 248 secondLight = createDirectionalLight( new Vector3f( 0, -1, 0 ) ); 249 thirdLight = createDirectionalLight( new Vector3f( -1, 0, 0 ) ); 250 251 scene.addChild( firstLight ); 252 scene.addChild( secondLight ); 253 scene.addChild( thirdLight ); 254 255 //is handled by the mouse rotater, all objects will be added to it. 256 rotationGroup = new TransformGroup(); 257 rotationGroup.setCapability( TransformGroup.ALLOW_TRANSFORM_WRITE ); 258 rotationGroup.setCapability( TransformGroup.ALLOW_TRANSFORM_READ ); 259 rotationGroup.setCapability( BranchGroup.ALLOW_DETACH ); 260 rotationGroup.setCapability( Group.ALLOW_CHILDREN_EXTEND ); 261 rotationGroup.setCapability( Group.ALLOW_CHILDREN_READ ); 262 rotationGroup.setCapability( Group.ALLOW_CHILDREN_WRITE ); 263 scene.addChild( rotationGroup ); 264 265 trackBall = new MouseRotate(); 266 trackBall.setTransformGroup( rotationGroup ); 267 trackBall.setSchedulingBounds( new BoundingSphere() ); 268 scene.addChild( trackBall ); 269 270 simpleUniverse.addBranchGraph( scene ); 271 272 //adding the key listeners 273 addKeyListener( this ); 274 canvas.addKeyListener( this ); 275 276 if ( testSphere ) { 277 BranchGroup sphere = createJ3DSphere( new Point3d( 0, 0, 0 ) ); 278 addBranchGroupToScene( sphere ); 279 } 280 281 pack(); 282 } 283 284 /** 285 * Create a directional light, with color.WHITE. 286 */ 287 private DirectionalLight createDirectionalLight( Vector3f lightDir ) { 288 // create the color for the light 289 Color3f color = new Color3f( Color.WHITE ); 290 // create the directional light with the color and direction 291 DirectionalLight light = new DirectionalLight( color, lightDir ); 292 light.setCapability( Light.ALLOW_INFLUENCING_BOUNDS_READ ); 293 light.setCapability( Light.ALLOW_INFLUENCING_BOUNDS_WRITE ); 294 return light; 295 } 296 297 private void addBranchGroupToScene( BranchGroup b ) { 298 rotationGroup.removeAllChildren(); 299 // translationGroup.removeAllChildren(); 300 // System.out.println( b.getBounds() ); 301 Bounds bounds = b.getBounds(); 302 if ( bounds != null ) { 303 304 BoundingSphere bs = new BoundingSphere( bounds ); 305 bs.getCenter( centroid ); 306 307 double radius = bs.getRadius(); 308 309 View view = simpleUniverse.getViewer().getView(); 310 // view parameters 311 view.setBackClipDistance( radius*4 ); 312 //the near clippingplane is one hundereth of the far. 313 view.setFrontClipDistance( (radius*4)*0.001 ); 314 315 316 TransformGroup viewToWorld = simpleUniverse.getViewingPlatform().getViewPlatformTransform(); 317 Transform3D trans = new Transform3D(); 318 trans.lookAt( new Point3d( 0, 0, -radius*2 ), centroid, new Vector3d( 0, 1, 0 ) ); 319 LOG.logDebug( "Trans Matrix after lookat:\n" + trans ); 320 viewToWorld.setTransform( trans ); 321 322 LOG.logDebug( "Center: " + centroid ); 323 LOG.logDebug( "radius: " + bs.getRadius() ); 324 325 firstLight.setInfluencingBounds( new BoundingSphere( centroid, radius * 3 ) ); 326 secondLight.setInfluencingBounds( new BoundingSphere( centroid, radius * 3 ) ); 327 thirdLight.setInfluencingBounds( new BoundingSphere( centroid, radius * 3 ) ); 328 trackBall.setSchedulingBounds( new BoundingSphere( centroid, radius*4 ) ); 329 } 330 rotationGroup.addChild( b ); 331 } 332 333 /** 334 * @return a brand new sphere 335 */ 336 private BranchGroup createJ3DSphere( Point3d translation ) { 337 Appearance app = new Appearance(); 338 RenderingAttributes ra = new RenderingAttributes(); 339 ra.setDepthBufferEnable( true ); 340 ra.setDepthBufferWriteEnable( true ); 341 app.setRenderingAttributes( ra ); 342 343 ColoringAttributes ca = new ColoringAttributes(); 344 ca.setShadeModel( ColoringAttributes.SHADE_GOURAUD ); 345 ca.setCapability( ColoringAttributes.NICEST ); 346 app.setColoringAttributes( ca ); 347 348 Material material = new Material(); 349 material.setAmbientColor( new Color3f( Color.WHITE ) ); 350 material.setDiffuseColor( new Color3f( Color.RED ) ); 351 material.setSpecularColor( new Color3f( Color.BLUE ) ); 352 app.setMaterial( material ); 353 TransformGroup tg = new TransformGroup(); 354 Transform3D trans = new Transform3D(); 355 if ( translation != null ) { 356 trans.setTranslation( new Vector3d( translation ) ); 357 tg.setTransform( trans ); 358 } 359 360 BranchGroup b = new BranchGroup(); 361 b.setCapability( BranchGroup.ALLOW_DETACH ); 362 b.addChild( tg ); 363 364 // tg.addChild( new Sphere( 0.2f, app ) ); 365 tg.addChild( new ColorCube( 0.2f ) ); 366 return b; 367 } 368 369 private void createButtons( JPanel buttonPanel ) { 370 JButton button = new JButton( "Open File" ); 371 button.setMnemonic( KeyEvent.VK_O ); 372 button.addActionListener( this ); 373 buttonPanel.add( button, FlowLayout.LEFT ); 374 } 375 376 private void readFile( String fileName ) { 377 378 if ( fileName == null || "".equals( fileName.trim() ) ) { 379 throw new InvalidParameterException( "the file name may not be null or empty" ); 380 } 381 FeatureCollection fc = null; 382 if ( fileName.endsWith( ".shp" ) ) { 383 // File f = new File( fileName ); 384 try { 385 ShapeFile file = new ShapeFileReader( fileName ).read(); 386 fc = file.getFeatureCollection(); 387 } catch ( IOException e ) { 388 LOG.logError( "Could not open shape file: " + fileName + " because: " + e.getMessage() ); 389 return; 390 } catch ( DBaseException e ) { 391 LOG.logError( "Could not open shape file: " + fileName + " because: " + e.getMessage() ); 392 return; 393 } 394 } else if ( fileName.endsWith( ".xml" ) || fileName.endsWith( ".gml" ) ) { 395 try { 396 XMLFragment doc = new XMLFragment( new File( fileName ) ); 397 boolean isCityGML = ( doc.getRootElement().getOwnerDocument().lookupPrefix( 398 CommonNamespaces.CITYGMLNS.toASCIIString() ) != null ) 399 || CommonNamespaces.CITYGMLNS.toASCIIString().equals( 400 doc.getRootElement().getOwnerDocument().lookupNamespaceURI( 401 "" ) ); 402 if ( !isCityGML ) { 403 isCityGML = isCityGMLDefined( doc.getRootElement() ); 404 } 405 System.out.println( "is Citygml: " + isCityGML ); 406 if ( isCityGML ) { 407 // convert to gml 408 File f = new File( "src/org/deegree/tools/app3d/toShape.xsl" ); 409 XSLTDocument transformer = new XSLTDocument( f.toURL() ); 410 doc = transformer.transform( doc ); 411 // System.out.println( "outgoingdoc: \n " + doc.getAsPrettyString() ); 412 } 413 GMLFeatureCollectionDocument gmlDoc = new GMLFeatureCollectionDocument(); 414 gmlDoc.setRootElement( doc.getRootElement() ); 415 fc = gmlDoc.parse(); 416 } catch ( SAXException e ) { 417 LOG.logError( "Could not open gml file: " + fileName + " because: " + e.getMessage() ); 418 return; 419 } catch ( TransformerException e ) { 420 LOG.logError( "Could not open gml file: " + fileName + " because: " + e.getMessage() ); 421 return; 422 } catch ( XMLParsingException e ) { 423 LOG.logError( "Could not open gml file: " + fileName + " because: " + e.getMessage() ); 424 return; 425 } catch ( MalformedURLException e ) { 426 LOG.logError( "Could not open gml file: " + fileName + " because: " + e.getMessage() ); 427 return; 428 } catch ( IOException e ) { 429 LOG.logError( "Could not open gml file: " + fileName + " because: " + e.getMessage() ); 430 return; 431 } 432 } 433 BranchGroup bg = new BranchGroup(); 434 bg.setCapability( BranchGroup.ALLOW_DETACH ); 435 436 Appearance app = new Appearance(); 437 RenderingAttributes ra = new RenderingAttributes(); 438 ra.setDepthBufferEnable( true ); 439 ra.setDepthBufferEnable( true ); 440 app.setRenderingAttributes( ra ); 441 Material material = new Material(); 442 material.setAmbientColor( new Color3f( Color.WHITE ) ); 443 material.setDiffuseColor( new Color3f( Color.RED ) ); 444 material.setSpecularColor( new Color3f( Color.BLUE ) ); 445 PolygonAttributes pa = new PolygonAttributes(); 446 pa.setCullFace( PolygonAttributes.CULL_NONE ); 447 app.setPolygonAttributes( pa ); 448 app.setMaterial( material ); 449 Envelope bbox = null; 450 for ( int i = 0; i < fc.size(); ++i ) { 451 Feature f = fc.getFeature( i ); 452 Geometry geom = f.getDefaultGeometryPropertyValue(); 453 if ( bbox == null ) { 454 bbox = geom.getEnvelope(); 455 } else { 456 try { 457 bbox = bbox.merge( geom.getEnvelope() ); 458 LOG.logDebug( "merging the bboxes resulted in: " + bbox ); 459 } catch ( GeometryException e ) { 460 LOG.logError( "Couldn't merge the bboxes" ); 461 e.printStackTrace(); 462 } 463 } 464 } 465 Point3d centroid = new Point3d( 0, 0, 0 ); 466 if ( bbox != null ) { 467 Point p = bbox.getCentroid(); 468 double zValue = p.getZ(); 469 if ( Double.isInfinite( zValue ) || Double.isNaN( zValue ) ) { 470 zValue = 0; 471 } 472 centroid.set( -p.getX(), -p.getY(), -zValue ); 473 } 474 for ( int i = 0; i < fc.size(); ++i ) { 475 Feature f = fc.getFeature( i ); 476 Geometry geom = f.getDefaultGeometryPropertyValue(); 477 Shape3D shape = mapGeometryToShape3D( geom, centroid ); 478 if ( shape != null ) { 479 shape.setAppearance( app ); 480 bg.addChild( shape ); 481 } else { 482 System.out.println( "ERRORORORORORORO" ); 483 } 484 } 485 Enumeration en = bg.getAllChildren(); 486 if ( en.hasMoreElements() ) { 487 addBranchGroupToScene( bg ); 488 } else { 489 LOG.logError( "Could read any 3D-Info from the location: " + fileName ); 490 } 491 File f = new File( fileName ); 492 setTitle( WIN_TITLE + f.getName() ); 493 } 494 495 /** 496 * @param contextNode 497 * @return true if the namespace "http://www.citygml.org/citygml/1/0/0" was found in one of the nodes of the 498 * dom-tree. 499 */ 500 private boolean isCityGMLDefined( Node contextNode ) { 501 502 boolean isCityGML = ( contextNode.lookupPrefix( CommonNamespaces.CITYGMLNS.toASCIIString() ) != null ) 503 || CommonNamespaces.CITYGMLNS.toASCIIString().equals( contextNode.lookupNamespaceURI( null ) ); 504 if ( !isCityGML ) { 505 NodeList nl = contextNode.getChildNodes(); 506 for ( int i = 0; i < nl.getLength(); ++i ) { 507 isCityGML = isCityGMLDefined( nl.item( i ) ); 508 if ( isCityGML ) { 509 return true; 510 } 511 } 512 } 513 return isCityGML; 514 } 515 516 private Shape3D mapGeometryToShape3D( Geometry geom, Point3d translation ) { 517 if ( geom instanceof Point ) { 518 return createShape3D( (Point) geom, translation ); 519 } else if ( geom instanceof Curve ) { 520 return createShape3D( (Curve) geom, translation ); 521 } else if ( geom instanceof Surface ) { 522 return createShape3D( (Surface) geom, translation ); 523 } else if ( geom instanceof MultiSurface ) { 524 return createShape3D( (MultiSurface) geom, translation ); 525 } else { 526 if ( geom == null ) { 527 LOG.logError( "Could not map the geometry which was not instantiated" ); 528 } else { 529 LOG.logError( "Could not map the geometry: " + geom.getClass().getName() ); 530 } 531 return null; 532 } 533 534 // if ( geom instanceof MultiPoint ) { 535 // return new ShapeMultiPoint( (MultiPoint) g ); 536 // } 537 // 538 // if ( geom instanceof MultiCurve ) { 539 // List<Curve> cs = Arrays.asList( ( (MultiCurve) g ).getAllCurves() ); 540 // return new ShapePolyline( cs ); 541 // } 542 // 543 544 } 545 546 private Shape3D createShape3D( Point p, Point3d translation ) { 547 GeometryArray geomArray = new PointArray( 1, GeometryArray.COORDINATES ); 548 double z = p.getZ(); 549 if ( Double.isInfinite( z ) || Double.isNaN( z ) ) { 550 z = 0; 551 } 552 geomArray.setCoordinate( 0, new Point3d( p.getX() + translation.x, p.getY() + translation.y, z + translation.z ) ); 553 Shape3D result = new Shape3D( geomArray ); 554 result.setAppearanceOverrideEnable( true ); 555 return result; 556 } 557 558 private Shape3D createShape3D( Curve c, Point3d translation ) { 559 int totalPoints = 0; 560 List<Integer> failSegments = new ArrayList<Integer>(); 561 for ( int i = 0; i < c.getNumberOfCurveSegments(); ++i ) { 562 try { 563 totalPoints += c.getCurveSegmentAt( i ).getNumberOfPoints(); 564 } catch ( GeometryException e ) { 565 LOG.logError( "Could not get CurveSegment at position: " + i ); 566 failSegments.add( new Integer( i ) ); 567 } 568 } 569 570 LineArray geomArray = new LineArray( totalPoints, GeometryArray.COORDINATES ); 571 for ( int i = 0, pointCounter = 0; i < c.getNumberOfCurveSegments(); ++i ) { 572 if ( !failSegments.contains( new Integer( i ) ) ) { 573 CurveSegment segment = null; 574 try { 575 segment = c.getCurveSegmentAt( i ); 576 } catch ( GeometryException e ) { 577 // cannot happen. 578 } 579 for ( int k = 0; k < segment.getNumberOfPoints(); ++k ) { 580 Position p = segment.getPositionAt( k ); 581 double z = p.getZ(); 582 if ( Double.isInfinite( z ) || Double.isNaN( z ) ) { 583 z = 0; 584 } 585 geomArray.setCoordinate( pointCounter++, new Point3d( p.getX() + translation.x, p.getY() 586 + translation.y, 587 z + translation.z ) ); 588 } 589 } 590 } 591 Shape3D result = new Shape3D( geomArray ); 592 result.setAppearanceOverrideEnable( true ); 593 return result; 594 } 595 596 /** 597 * 598 * @param surface to be created 599 * @param translation to origin of the scene 600 * @return a Shape3D created from the surface. 601 */ 602 private Shape3D createShape3D( Surface surface, Point3d translation ) { 603 GeometryInfo geometryInfo = new GeometryInfo( GeometryInfo.POLYGON_ARRAY ); 604 605 Position[] pos = surface.getSurfaceBoundary().getExteriorRing().getPositions(); 606 Ring[] innerRings = surface.getSurfaceBoundary().getInteriorRings(); 607 int k = 1; 608 int l = 3 * ( pos.length ); 609 if ( innerRings != null ) { 610 for ( int i = 0; i < innerRings.length; i++ ) { 611 k++; 612 l += ( 3 * innerRings[i].getPositions().length ); 613 } 614 } 615 616 float[] coords = new float[l]; 617 int contourCounts[] = { k }; 618 int[] stripCounts = new int[k]; 619 k = 0; 620 stripCounts[k++] = pos.length; 621 622 int z = 0; 623 for ( int i = 0; i < pos.length; i++ ) { 624 double zValue = pos[i].getZ(); 625 if ( Double.isInfinite( zValue ) || Double.isNaN( zValue ) ) { 626 zValue = 0; 627 } 628 //LOG.logDebug( "Found a point in a surface: " + pos[i] ); 629 coords[z++] = (float) ( pos[i].getX() + translation.x ); 630 coords[z++] = (float) ( pos[i].getY() + translation.y ); 631 coords[z++] = (float) ( zValue + translation.z ); 632 } 633 634 if ( innerRings != null ) { 635 for ( int j = 0; j < innerRings.length; j++ ) { 636 pos = innerRings[j].getPositions(); 637 stripCounts[k++] = pos.length; 638 for ( int i = 0; i < pos.length; i++ ) { 639 double zValue = pos[i].getZ(); 640 if ( Double.isInfinite( zValue ) || Double.isNaN( zValue ) ) { 641 zValue = 0; 642 } 643 coords[z++] = (float) ( pos[i].getX() + translation.x ); 644 coords[z++] = (float) ( pos[i].getY() + translation.y ); 645 coords[z++] = (float) ( zValue + translation.z ); 646 } 647 } 648 } 649 650 geometryInfo.setCoordinates( coords ); 651 geometryInfo.setStripCounts( stripCounts ); 652 geometryInfo.setContourCounts( contourCounts ); 653 654 NormalGenerator ng = new NormalGenerator(); 655 ng.generateNormals( geometryInfo ); 656 Shape3D result = new Shape3D( geometryInfo.getGeometryArray() ); 657 result.setCapability( Shape3D.ALLOW_GEOMETRY_READ ); 658 result.setCapability( Shape3D.ALLOW_GEOMETRY_WRITE ); 659 result.setAppearanceOverrideEnable( true ); 660 return result; 661 } 662 663 /** 664 * @param surface 665 * @return a Shape3D created from the multisurfaces. 666 */ 667 private Shape3D createShape3D( MultiSurface multiSurface, Point3d translation ) { 668 Shape3D result = new Shape3D(); 669 result.setCapability( Shape3D.ALLOW_GEOMETRY_READ ); 670 result.setCapability( Shape3D.ALLOW_GEOMETRY_WRITE ); 671 Surface[] allSurfaces = multiSurface.getAllSurfaces(); 672 for ( int surfaceCount = 0; surfaceCount < allSurfaces.length; ++surfaceCount ) { 673 Surface surface = multiSurface.getSurfaceAt( surfaceCount ); 674 Shape3D s3D = createShape3D( surface, translation ); 675 result.addGeometry( s3D.getGeometry() ); 676 } 677 result.setAppearanceOverrideEnable( true ); 678 return result; 679 } 680 681 /* 682 * (non-Javadoc) 683 * 684 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 685 */ 686 public void actionPerformed( ActionEvent e ) { 687 Object source = e.getSource(); 688 if ( source instanceof JButton ) { 689 // JFileChooser filechooser = new JFileChooser(); 690 // filechooser.setVisible( true ); 691 int result = fileChooser.showOpenDialog( this ); 692 if( JFileChooser.APPROVE_OPTION == result ){ 693 File f = fileChooser.getSelectedFile(); 694 if( f != null ) { 695 String path = f.getAbsolutePath(); 696 String dirpath = f.getParent(); 697 System.out.println( "absolute Path: " + dirpath ); 698 prefs.put( PREF_KEY, dirpath ); 699 readFile( path ); 700 } 701 702 } 703 } 704 } 705 706 /* 707 * (non-Javadoc) 708 * 709 * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent) 710 */ 711 public void keyPressed( KeyEvent arg0 ) { 712 // nottin 713 } 714 715 /* 716 * (non-Javadoc) 717 * 718 * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent) 719 */ 720 public void keyReleased( KeyEvent arg0 ) { 721 // nottin 722 } 723 724 /* 725 * (non-Javadoc) 726 * 727 * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent) 728 */ 729 public void keyTyped( KeyEvent e ) { 730 double x = 0; 731 double y = 0; 732 double z = 0; 733 if ( e.getKeyChar() == 'q' ) { 734 System.exit( 0 ); 735 } else if ( e.getKeyChar() == 'x' ) { 736 x = 1; 737 } else if ( e.getKeyChar() == 'X' ) { 738 x = -1; 739 } else if ( e.getKeyChar() == 'y' ) { 740 y = 1; 741 } else if ( e.getKeyChar() == 'Y' ) { 742 y = -1; 743 } else if ( e.getKeyChar() == 'z' ) { 744 z = 1; 745 } else if ( e.getKeyChar() == 'Z' ) { 746 z = -1; 747 } 748 749 TransformGroup viewToWorld = simpleUniverse.getViewingPlatform().getViewPlatformTransform(); 750 Transform3D trans = new Transform3D(); 751 viewToWorld.getTransform( trans ); 752 trans.invert(); 753 Vector3d translation = new Vector3d(); 754 trans.get( translation ); 755 756 x += translation.x; 757 y += translation.y; 758 z += translation.z; 759 Point3d eye = new Point3d( x, y, z ); 760 trans.lookAt( eye, centroid, new Vector3d( 0, 1, 0 ) ); 761 LOG.logDebug( "Trans after:\n" + trans ); 762 Vector3d dist = new Vector3d( centroid ); 763 dist.sub( eye ); 764 trackBall.setSchedulingBounds( new BoundingSphere( centroid, dist.length() ) ); 765 viewToWorld.setTransform( trans ); 766 767 } 768 /** 769 * @param args 770 */ 771 public static void main( String[] args ) { 772 773 View3DFile viewer = new View3DFile( "/home/rutger/testViewer/3dtest2.shp" ); 774 viewer.toFront(); 775 // View3DFile viewer = new View3DFile( true ); 776 // viewer.toFront(); 777 778 } 779 780 private class CustomFileFilter extends FileFilter{ 781 782 private List<String> acceptedExtensions; 783 private String desc; 784 /** 785 * @param acceptedExtensions list of extensions this filter accepts. 786 */ 787 CustomFileFilter( List<String> acceptedExtensions, String description) { 788 this.acceptedExtensions = new ArrayList<String>(acceptedExtensions.size() ); 789 for( String s : acceptedExtensions ){ 790 if( s.startsWith( "." ) ){ 791 s = s.substring( 1 ); 792 } 793 this.acceptedExtensions.add( s.trim().toUpperCase() ); 794 } 795 desc = description; 796 } 797 798 @Override 799 public boolean accept( File pathname ) { 800 if (pathname.isDirectory()) { 801 return true; 802 } 803 804 String extension = getExtension(pathname); 805 if (extension != null) { 806 if ( acceptedExtensions.contains( extension.trim().toUpperCase() )) { 807 return true; 808 } 809 } 810 return false; 811 } 812 private String getExtension( File f ){ 813 String ext = null; 814 String s = f.getName(); 815 int i = s.lastIndexOf('.'); 816 817 if (i > 0 && i < s.length() - 1) { 818 ext = s.substring(i+1).toLowerCase(); 819 } 820 return ext; 821 } 822 823 @Override 824 public String getDescription() { 825 return desc; 826 } 827 } 828 } 829