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 }