001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wpvs/utils/VisADWrapper.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2001-2008 by:
006 EXSE, Department of Geography, University of Bonn
007 http://www.giub.uni-bonn.de/deegree/
008 lat/lon GmbH
009 http://www.lat-lon.de
010
011 This library is free software; you can redistribute it and/or
012 modify it under the terms of the GNU Lesser General Public
013 License as published by the Free Software Foundation; either
014 version 2.1 of the License, or (at your option) any later version.
015
016 This library is distributed in the hope that it will be useful,
017 but WITHOUT ANY WARRANTY; without even the implied warranty of
018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019 Lesser General Public License for more details.
020
021 You should have received a copy of the GNU Lesser General Public
022 License along with this library; if not, write to the Free Software
023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024
025 Contact:
026
027 Andreas Poth
028 lat/lon GmbH
029 Aennchenstraße 19
030 53177 Bonn
031 Germany
032 E-Mail: poth@lat-lon.de
033
034 Prof. Dr. Klaus Greve
035 Department of Geography
036 University of Bonn
037 Meckenheimer Allee 166
038 53115 Bonn
039 Germany
040 E-Mail: greve@giub.uni-bonn.de
041
042 ---------------------------------------------------------------------------*/
043 package org.deegree.ogcwebservices.wpvs.utils;
044
045 import java.rmi.RemoteException;
046 import java.util.ArrayList;
047 import java.util.List;
048
049 import javax.vecmath.Point3d;
050
051 import org.deegree.framework.log.ILogger;
052 import org.deegree.framework.log.LoggerFactory;
053
054 import visad.Delaunay;
055 import visad.FlatField;
056 import visad.FunctionType;
057 import visad.Irregular2DSet;
058 import visad.RealTupleType;
059 import visad.RealType;
060 import visad.VisADException;
061
062 /**
063 * A wrapper for VisAD objects. This class takes care of collecting points to build a TIN, of TIN creation itself and
064 * its output as a geometry collection.
065 *
066 * @author <a href="mailto:taddei@lat-lon.de">Ugo Taddei</a>
067 * @author last edited by: $Author: apoth $
068 *
069 * $Revision: 9345 $, $Date: 2007-12-27 17:22:25 +0100 (Do, 27 Dez 2007) $
070 *
071 *
072 */
073 public class VisADWrapper {
074
075 private static final ILogger LOG = LoggerFactory.getLogger( VisADWrapper.class );
076
077 /**
078 * A list for hold points representing te DEM/TIN.
079 */
080 private List<Point3d> pointsList;
081
082 private double scale;
083
084 /**
085 * Initializes the object by creating a common domain field from the geometrical information (the envelope, the
086 * width and the height) supplied. The envelope cannot the null, nor can the dimensions by < 1.
087 *
088 * @param ptsList
089 * a list of Points
090 * @param scale
091 * to multiply to the z-value
092 */
093 public VisADWrapper( List<Point3d> ptsList, double scale ) {
094 this.pointsList = ptsList;
095 this.scale = scale;
096 }
097
098 /**
099 * Add <code>Point</code>s to the internal list. Lists without any elements (or null lists) are ignored.
100 *
101 * @param points
102 * to be added to the list
103 */
104 public final void addPoints( List<Point3d> points ) {
105
106 if ( points == null || points.size() == 0 ) {
107 return;
108 }
109
110 this.pointsList.addAll( points );
111 }
112
113 /**
114 * Generates a list of tringles containing the triangles representing the TIN. Triangles are represented float[3][3]
115 *
116 * @return a collection of <code>float[3][3]</code>, each of which representing a TIN triangle
117 *
118 */
119 public final List<float[][]> getTriangleCollectionAsList() {
120
121 List<float[][]> list = null;
122 try {
123 FlatField tinField = triangulatePoints();
124 if ( tinField == null )
125 return null;
126 list = toGeoCollectionList( tinField );
127 } catch ( NoClassDefFoundError ncdfe ) {
128 LOG.logError( "WPVS: It seems that the visad library could not be found: " + ncdfe.getLocalizedMessage(),
129 ncdfe );
130 } catch ( VisADException ve ) {
131 LOG.logError( ve.getLocalizedMessage(), ve );
132 }
133 return list;
134 }
135
136 /**
137 * Triangulate <code>GM_Point</code>s contained in <code>gmPointsList</code> using the Clarkson algorithm. This
138 * method returns a <code>FlatField</code> containing all points triangulated and with their elevation values.<br/>
139 *
140 * @author <a href="mailto:taddei@lat-lon.de">Ugo Taddei</a>
141 *
142 * @param gmPointsList
143 * the list of <code>GM_Point</code>s. Cannot be null and must contain at least 3
144 * <code>GM_Point</code>s.
145 * @return a <code>FlatField</code> containg a TIN (with an <code>Irregular2DSet</code> as its domain set and
146 * the elevation values)
147 *
148 */
149 private FlatField triangulatePoints()
150 throws NoClassDefFoundError {
151
152 if ( this.pointsList == null || this.pointsList.size() < 3 ) {
153 throw new IllegalArgumentException( "Points list cannot be null and must contain at least 3 GM_Points." );
154 }
155
156 // removing double points
157 ArrayList<Point3d> remove = new ArrayList<Point3d>();
158 for ( int i = 0; i < pointsList.size(); ++i ) {
159 Point3d p = pointsList.get( i );
160
161 if ( !remove.contains( p ) ) {
162 for ( int j = i + 1; j < pointsList.size(); ++j ) {
163 Point3d tmpP = pointsList.get( j );
164 if ( ( Math.abs( tmpP.x - p.x ) < 0.001 ) && ( Math.abs( tmpP.y - p.y ) < 0.001 ) ) {
165 remove.add( tmpP );
166 }
167 }
168 }
169 }
170 for ( Point3d p : remove ) {
171 pointsList.remove( p );
172 }
173 float[][] triPoints = new float[3][this.pointsList.size()];
174 int cnt = 0;
175
176 for ( Point3d p : this.pointsList ) {
177 triPoints[0][cnt] = (float) p.x;
178 triPoints[1][cnt] = (float) p.y;
179 triPoints[2][cnt++] = (float) ( p.z * scale );
180 }
181
182 try {
183 FunctionType functionType = new FunctionType( new RealTupleType( RealType.XAxis, RealType.YAxis ),
184 RealType.ZAxis );
185 float[][] ptsXY = new float[][] { triPoints[0], triPoints[1] };
186
187 // ptsXY = Delaunay.perturb(ptsXY,0.1f, false);
188 // ptsXY = Delaunay.perturb( ptsXY, 5.5f, false );
189 Delaunay delan = Delaunay.factory( ptsXY, false );
190 // Delaunay delan = new DelaunayClarkson( ptsXY );
191 // Delaunay delan = new DelaunayWatson( ptsXY );
192 // DelaunayFast delan = new DelaunayFast( ptsXY );
193 // delan.setNonConvex();
194 try {
195 // delan.improve( ptsXY, 5 );
196 } catch ( Exception e ) {
197 // just do noting
198 }
199
200 // Delaunay delan = new DelaunayClarkson( ptsXY );
201 // Delaunay delan = new DelaunayFast( ptsXY );
202 Irregular2DSet pointsSet = new Irregular2DSet( functionType.getDomain(), ptsXY, null, null, null, delan );
203
204 FlatField ff = new FlatField( functionType, pointsSet );
205
206 ff.setSamples( new float[][] { triPoints[2] }, true );
207
208 return ff;
209
210 } catch ( VisADException e ) {
211 LOG.logError(e.getMessage(), e );
212 return null;
213 } catch ( RemoteException re ) {
214 LOG.logError(re.getMessage(), re );
215 return null;
216 } catch ( IndexOutOfBoundsException ioobe ) {
217 LOG.logError(ioobe.getMessage(), ioobe );
218 return null;
219 }
220 }
221
222 /**
223 * Generated a list of triangles from the FlatField passed in as tinField
224 *
225 * @param tinField
226 * the FlatField containing triangles
227 * @return a collection of <code>float[3][3]</code>, each of which representing a TIN triangle
228 * @throws VisADException
229 * @throws Exception
230 * in the unlikely event that a VisAD expcetion is thrown
231 */
232 private final List<float[][]> toGeoCollectionList( FlatField tinField )
233 throws NoClassDefFoundError, VisADException {
234 if ( tinField == null ) {
235 throw new RuntimeException( "FlatField cannot be null." );
236 }
237
238 List<float[][]> geoCollec = new ArrayList<float[][]>( 5000 );
239
240 Irregular2DSet domainSet = (Irregular2DSet) tinField.getDomainSet();
241 float[][] xyPositions = domainSet.getSamples();
242 float[][] zValues = tinField.getFloats();
243 int[][] indices = domainSet.Delan.Tri;
244
245 // loop over triangles...
246 for ( int i = 0; i < indices.length; i++ ) {
247
248 // indices[i].length == coords.length == 3
249 // this is float[3][3] -> 3 points per triabngle, each point with 3 coords
250 float[][] myCoords = new float[3][3];
251
252 // ...then over points
253 for ( int j = 0; j < indices[i].length; j++ ) {
254
255 int index = indices[i][j];
256 myCoords[j] = new float[3];
257 myCoords[j][0] = xyPositions[0][index];
258 myCoords[j][1] = xyPositions[1][index];
259 myCoords[j][2] = zValues[0][index];
260 }
261
262 geoCollec.add( myCoords );
263 }
264
265 tinField = null;
266
267 return geoCollec;
268 }
269
270 /**
271 * Clear all points and invalidate list.
272 *
273 */
274 public void clear() {
275 this.pointsList.clear();
276 this.pointsList = null;
277
278 }
279
280 }