001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/ogcwebservices/wpvs/j3d/TriangleTerrain.java $
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.ogcwebservices.wpvs.j3d;
038
039 import java.awt.image.BufferedImage;
040 import java.util.ArrayList;
041 import java.util.List;
042
043 import javax.vecmath.Point3d;
044 import javax.vecmath.Point3f;
045 import javax.vecmath.TexCoord2f;
046
047 import org.deegree.framework.log.ILogger;
048 import org.deegree.framework.log.LoggerFactory;
049 import org.deegree.model.spatialschema.Envelope;
050 import org.deegree.model.spatialschema.Position;
051 import org.deegree.ogcwebservices.wpvs.utils.VisADWrapper;
052
053 import com.sun.j3d.utils.geometry.GeometryInfo;
054 import com.sun.j3d.utils.geometry.NormalGenerator;
055
056 /**
057 * The <code>TriangleTerrain</code> class respresents the Java3D shape of a set of measurepoints. Before this Terrrain
058 * can be drawn the createTerrain method must be invoked, it will create triangles of the given measurepoints and will
059 * add the optional texture to the apearance of the Shap3D.
060 *
061 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
062 *
063 * @author last edited by: $Author: mschneider $
064 *
065 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $
066 *
067 */
068
069 public class TriangleTerrain extends TerrainModel {
070
071 private static ILogger LOG = LoggerFactory.getLogger( TriangleTerrain.class );
072
073 private Envelope boundingBox;
074
075 private double terrainWidth;
076
077 private double terrainHeight;
078
079 private List<Point3d> measurePoints = null;
080
081 private double minimalHeightlevel;
082
083
084 private double scale;
085
086 /**
087 * @param measurePoints
088 * indicating height values inside this terrain. They will be triangulated in the createTerrain method.
089 * @param env the bbox of this triangle terrain.
090 * @param minimalHeightlevel
091 * which will be used if the measurepoints have no height set.
092 * @param scale
093 * to multiply onto the z-value of the measurepoints
094 */
095 public TriangleTerrain( List<Point3d> measurePoints, Envelope env, double minimalHeightlevel, double scale ) {
096 super();
097 this.measurePoints = measurePoints;
098 this.minimalHeightlevel = minimalHeightlevel;
099 this.scale = scale;
100
101 boundingBox = env;
102
103 this.terrainWidth = boundingBox.getWidth();
104 this.terrainHeight = boundingBox.getHeight();
105 }
106
107 /**
108 * @return the boundingBox of this TriangleTerrain
109 */
110 public Envelope getBoundingBox() {
111 return boundingBox;
112 }
113
114 @Override
115 public void createTerrain() {
116 List<float[][]> triangles = new ArrayList<float[][]>();
117 if ( measurePoints == null || measurePoints.size() == 0 ) { // just a square, asssuming a simple plane,
118 triangles = createFlatTerrain( );
119 } else {
120 LOG.logDebug( "Trying to create triangles with the visad library" );
121 long time = System.currentTimeMillis();
122 VisADWrapper vw = new VisADWrapper( measurePoints, scale );
123 triangles = vw.getTriangleCollectionAsList();
124 if( triangles != null ){
125 LOG.logDebug( new StringBuilder("Creation of ").append( triangles.size()).append( " triangles with the visad library was successfull. (took: ").append( (System.currentTimeMillis() - time) / 1000d).append(" seconds).").toString() );
126 } else{
127 LOG.logDebug( new StringBuilder("Creation of triangles with the visad library was NOT successfull. Creating a flat terrain.").toString() );
128 triangles = createFlatTerrain( );
129 }
130
131 }
132
133 double widthInv = 1d / terrainWidth;
134 double heightInv = 1d / terrainHeight;
135 Position originalLowerLeft = boundingBox.getMin();
136
137 GeometryInfo geometryInfo = new GeometryInfo( GeometryInfo.TRIANGLE_ARRAY );
138
139 BufferedImage texture = getTexture();
140 if ( texture != null ){
141 geometryInfo.setTextureCoordinateParams( 1, 2 );
142 }
143
144 Point3f[] coordinates = new Point3f[triangles.size() * 3];
145 TexCoord2f[] texCoords = new TexCoord2f[triangles.size() * 3];
146
147 int coordNr = 0;
148 for ( float[][] triangleCoords : triangles ) {
149 for ( int k = 0; k < 3; k++ ) {
150 // System.out.println( Thread.currentThread() + "-> coordNR: " + coordNr );
151 Point3f modelCoordinate = new Point3f( triangleCoords[k][0], triangleCoords[k][1], triangleCoords[k][2] );
152 coordinates[coordNr] = modelCoordinate;
153
154 if ( texture != null ) {
155 double texCoordX = ( modelCoordinate.x - originalLowerLeft.getX() ) * widthInv;
156 double texCoordY = ( modelCoordinate.y - originalLowerLeft.getY() ) * heightInv;
157 texCoordX = ( texCoordX > 1 ) ? 1 : ( ( texCoordX < 0 ) ? 0 : texCoordX );
158 texCoordY = ( texCoordY > 1 ) ? 1 : ( ( texCoordY < 0 ) ? 0 : texCoordY );
159 texCoords[coordNr] = new TexCoord2f( (float)texCoordX ,(float) texCoordY );
160 }
161 coordNr++;
162 }
163
164 }
165 geometryInfo.setCoordinates( coordinates );
166 if ( texture != null ) {
167 geometryInfo.setTextureCoordinates( 0, texCoords );
168 }
169 geometryInfo.recomputeIndices();
170 NormalGenerator ng = new NormalGenerator();
171 ng.generateNormals( geometryInfo );
172
173 setGeometry( geometryInfo.getGeometryArray() );
174 }
175
176 private List<float[][]> createFlatTerrain( ){
177 LOG.logDebug( "Creating a flat square at minimalTerrain height, which will represent the terrain." );
178 List<float[][]> triangles = new ArrayList<float[][]>();
179 Position min = boundingBox.getMin();
180 Position max = boundingBox.getMax();
181 float[][] triangle = new float[3][3];
182 triangle[0][0] = (float) min.getX();
183 triangle[0][1] = (float) min.getY();
184 triangle[0][2] = (float) minimalHeightlevel;
185
186 triangle[1][0] = (float) max.getX();
187 triangle[1][1] = (float) min.getY();
188 triangle[1][2] = (float) minimalHeightlevel;
189
190 triangle[2][0] = (float) min.getX();
191 triangle[2][1] = (float) max.getY();
192 triangle[2][2] = (float) minimalHeightlevel;
193
194 triangles.add( triangle );
195
196 triangle = new float[3][3];
197 triangle[0][0] = (float) max.getX();
198 triangle[0][1] = (float) min.getY();
199 triangle[0][2] = (float) minimalHeightlevel;
200
201 triangle[1][0] = (float) max.getX();
202 triangle[1][1] = (float) max.getY();
203 triangle[1][2] = (float) minimalHeightlevel;
204
205 triangle[2][0] = (float) min.getX();
206 triangle[2][1] = (float) max.getY();
207 triangle[2][2] = (float) minimalHeightlevel;
208 triangles.add( triangle );
209 return triangles;
210 }
211
212 }