001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_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 }