001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/ogcwebservices/wpvs/utils/VisADWrapper.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 package org.deegree.ogcwebservices.wpvs.utils;
037
038 import java.rmi.RemoteException;
039 import java.util.ArrayList;
040 import java.util.List;
041
042 import javax.vecmath.Point3d;
043
044 import org.deegree.framework.log.ILogger;
045 import org.deegree.framework.log.LoggerFactory;
046
047 import visad.Delaunay;
048 import visad.FlatField;
049 import visad.FunctionType;
050 import visad.Irregular2DSet;
051 import visad.RealTupleType;
052 import visad.RealType;
053 import visad.VisADException;
054
055 /**
056 * A wrapper for VisAD objects. This class takes care of collecting points to build a TIN, of TIN creation itself and
057 * its output as a geometry collection.
058 *
059 * @author <a href="mailto:taddei@lat-lon.de">Ugo Taddei</a>
060 * @author last edited by: $Author: mschneider $
061 *
062 * $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
063 *
064 *
065 */
066 public class VisADWrapper {
067
068 private static final ILogger LOG = LoggerFactory.getLogger( VisADWrapper.class );
069
070 /**
071 * A list for hold points representing te DEM/TIN.
072 */
073 private List<Point3d> pointsList;
074
075 private double scale;
076
077 /**
078 * Initializes the object by creating a common domain field from the geometrical information (the envelope, the
079 * width and the height) supplied. The envelope cannot the null, nor can the dimensions by < 1.
080 *
081 * @param ptsList
082 * a list of Points
083 * @param scale
084 * to multiply to the z-value
085 */
086 public VisADWrapper( List<Point3d> ptsList, double scale ) {
087 this.pointsList = ptsList;
088 this.scale = scale;
089 }
090
091 /**
092 * Add <code>Point</code>s to the internal list. Lists without any elements (or null lists) are ignored.
093 *
094 * @param points
095 * to be added to the list
096 */
097 public final void addPoints( List<Point3d> points ) {
098
099 if ( points == null || points.size() == 0 ) {
100 return;
101 }
102
103 this.pointsList.addAll( points );
104 }
105
106 /**
107 * Generates a list of tringles containing the triangles representing the TIN. Triangles are represented float[3][3]
108 *
109 * @return a collection of <code>float[3][3]</code>, each of which representing a TIN triangle
110 *
111 */
112 public final List<float[][]> getTriangleCollectionAsList() {
113
114 List<float[][]> list = null;
115 try {
116 FlatField tinField = triangulatePoints();
117 if ( tinField == null )
118 return null;
119 list = toGeoCollectionList( tinField );
120 } catch ( NoClassDefFoundError ncdfe ) {
121 LOG.logError( "WPVS: It seems that the visad library could not be found: " + ncdfe.getLocalizedMessage(),
122 ncdfe );
123 } catch ( VisADException ve ) {
124 LOG.logError( ve.getLocalizedMessage(), ve );
125 }
126 return list;
127 }
128
129 /**
130 * Triangulate <code>GM_Point</code>s contained in <code>gmPointsList</code> using the Clarkson algorithm. This
131 * method returns a <code>FlatField</code> containing all points triangulated and with their elevation values.<br/>
132 *
133 * @author <a href="mailto:taddei@lat-lon.de">Ugo Taddei</a>
134 *
135 * @return a <code>FlatField</code> containing a TIN (with an <code>Irregular2DSet</code> as its domain set and
136 * the elevation values)
137 *
138 */
139 private FlatField triangulatePoints()
140 throws NoClassDefFoundError {
141
142 if ( this.pointsList == null || this.pointsList.size() < 3 ) {
143 throw new IllegalArgumentException( "Points list cannot be null and must contain at least 3 GM_Points." );
144 }
145
146 // removing double points
147 ArrayList<Point3d> remove = new ArrayList<Point3d>();
148 for ( int i = 0; i < pointsList.size(); ++i ) {
149 Point3d p = pointsList.get( i );
150
151 if ( !remove.contains( p ) ) {
152 for ( int j = i + 1; j < pointsList.size(); ++j ) {
153 Point3d tmpP = pointsList.get( j );
154 if ( ( Math.abs( tmpP.x - p.x ) < 0.001 ) && ( Math.abs( tmpP.y - p.y ) < 0.001 ) ) {
155 remove.add( tmpP );
156 }
157 }
158 }
159 }
160 for ( Point3d p : remove ) {
161 pointsList.remove( p );
162 }
163 float[][] triPoints = new float[3][this.pointsList.size()];
164 int cnt = 0;
165
166 for ( Point3d p : this.pointsList ) {
167 triPoints[0][cnt] = (float) p.x;
168 triPoints[1][cnt] = (float) p.y;
169 triPoints[2][cnt++] = (float) ( p.z * scale );
170 }
171
172 try {
173 FunctionType functionType = new FunctionType( new RealTupleType( RealType.XAxis, RealType.YAxis ),
174 RealType.ZAxis );
175 float[][] ptsXY = new float[][] { triPoints[0], triPoints[1] };
176
177 // ptsXY = Delaunay.perturb(ptsXY,0.1f, false);
178 // ptsXY = Delaunay.perturb( ptsXY, 5.5f, false );
179 Delaunay delan = Delaunay.factory( ptsXY, false );
180 // Delaunay delan = new DelaunayClarkson( ptsXY );
181 // Delaunay delan = new DelaunayWatson( ptsXY );
182 // DelaunayFast delan = new DelaunayFast( ptsXY );
183 // delan.setNonConvex();
184 try {
185 // delan.improve( ptsXY, 5 );
186 } catch ( Exception e ) {
187 // just do noting
188 }
189
190 // Delaunay delan = new DelaunayClarkson( ptsXY );
191 // Delaunay delan = new DelaunayFast( ptsXY );
192 Irregular2DSet pointsSet = new Irregular2DSet( functionType.getDomain(), ptsXY, null, null, null, delan );
193
194 FlatField ff = new FlatField( functionType, pointsSet );
195
196 ff.setSamples( new float[][] { triPoints[2] }, true );
197
198 return ff;
199
200 } catch ( VisADException e ) {
201 LOG.logError(e.getMessage(), e );
202 return null;
203 } catch ( RemoteException re ) {
204 LOG.logError(re.getMessage(), re );
205 return null;
206 } catch ( IndexOutOfBoundsException ioobe ) {
207 LOG.logError(ioobe.getMessage(), ioobe );
208 return null;
209 }
210 }
211
212 /**
213 * Generated a list of triangles from the FlatField passed in as tinField
214 *
215 * @param tinField
216 * the FlatField containing triangles
217 * @return a collection of <code>float[3][3]</code>, each of which representing a TIN triangle
218 * @throws VisADException
219 * in the unlikely event that a VisAD exception is thrown
220 * @throws NoClassDefFoundError
221 * in the unlikely event that the VisAD library could not be found.
222 */
223 private final List<float[][]> toGeoCollectionList( FlatField tinField )
224 throws NoClassDefFoundError, VisADException {
225 if ( tinField == null ) {
226 throw new RuntimeException( "FlatField cannot be null." );
227 }
228
229 List<float[][]> geoCollec = new ArrayList<float[][]>( 5000 );
230
231 Irregular2DSet domainSet = (Irregular2DSet) tinField.getDomainSet();
232 float[][] xyPositions = domainSet.getSamples();
233 float[][] zValues = tinField.getFloats();
234 int[][] indices = domainSet.Delan.Tri;
235
236 // loop over triangles...
237 for ( int i = 0; i < indices.length; i++ ) {
238
239 // indices[i].length == coords.length == 3
240 // this is float[3][3] -> 3 points per triabngle, each point with 3 coords
241 float[][] myCoords = new float[3][3];
242
243 // ...then over points
244 for ( int j = 0; j < indices[i].length; j++ ) {
245
246 int index = indices[i][j];
247 myCoords[j] = new float[3];
248 myCoords[j][0] = xyPositions[0][index];
249 myCoords[j][1] = xyPositions[1][index];
250 myCoords[j][2] = zValues[0][index];
251 }
252
253 geoCollec.add( myCoords );
254 }
255
256 tinField = null;
257
258 return geoCollec;
259 }
260
261 /**
262 * Clear all points and invalidate list.
263 *
264 */
265 public void clear() {
266 this.pointsList.clear();
267 this.pointsList = null;
268
269 }
270
271 }