/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2006 by:
University of Bonn
http://www.giub.uni-bonn.de/deegree/
lat/lon GmbH
http://www.lat-lon.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstr. 19
53115 Bonn
Germany
E-Mail: poth@lat-lon.de
Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: klaus.greve@uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.tools.raster;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.deegree.datatypes.CodeList;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.framework.xml.XMLFragment;
import org.deegree.framework.xml.XSLTDocument;
import org.deegree.io.shpapi.ShapeFile;
import org.deegree.model.crs.CRSFactory;
import org.deegree.model.crs.CoordinateSystem;
import org.deegree.model.crs.GeoTransformer;
import org.deegree.model.crs.IGeoTransformer;
import org.deegree.model.crs.UnknownCRSException;
import org.deegree.model.feature.Feature;
import org.deegree.model.feature.FeatureCollection;
import org.deegree.model.feature.FeatureFactory;
import org.deegree.model.spatialschema.Envelope;
import org.deegree.model.spatialschema.GeometryFactory;
import org.deegree.ogcwebservices.wcs.configuration.Resolution;
import org.deegree.ogcwebservices.wcs.describecoverage.CoverageDescription;
import org.deegree.ogcwebservices.wcs.describecoverage.CoverageOffering;
/**
* utility program to group several independ groups of images tiles
* into one WCS coverage
*
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
* @author last edited by: $Author: poth $
*
* @version 1.1, $Revision: 1.15 $, $Date: 2006/11/27 09:07:53 $
*
* @since 1.1
*
* @deprecated use @see org.deegree.tools.raster.RasterTreeBuilder instead; this class
* will be removed from deegree at the end of 2007
*/
public class GroupTiles {
private static final ILogger LOG = LoggerFactory.getLogger( GroupTiles.class );
private String outDir = null;
private int count = 0;
public static String CONFIG_TEMPLATE = "template_wcs_configuration.xml";
public static String CONFIG_XSL = "updateConfig.xsl";
/**
*
*
* @param rootDir directory containing the image tiles
* @param outDir directory where to store the result
* @param name desired name of the covrage
* @param label desired label of the covrage
* @throws Exception
*/
public GroupTiles( String rootDir, String outDir ) throws Exception {
LOG.logInfo( "output directory: " + outDir );
this.outDir = outDir;
count = 0;
List confFiles = getFiles( rootDir, "XML" );
count = 0;
List shpFiles = getFiles( rootDir, "SHP" );
String tmp = (String) confFiles.get( 0 );
if ( tmp.startsWith( "/" ) ) {
tmp = tmp.substring( 1, tmp.length() );
}
CoverageDescription desc = CoverageDescription.createCoverageDescription( new URL(
"file:///"
+ tmp ) );
String nativeCRS = getNativeCRS( desc );
Envelope bbox = calcNewBBOX( shpFiles, nativeCRS );
Envelope llBbox = calcLLBBOX( nativeCRS, bbox );
String resolutions = getResolutions( confFiles );
mergeShapes( shpFiles );
CoverageOffering co = desc.getCoverageOfferings()[0];
createConfigurationFile( co.getName(), co.getDescription(), resolutions,
co.getSupportedFormats().getFormats()[0].getCodes()[0], nativeCRS,
llBbox, bbox );
LOG.logInfo( "finished!" );
}
/**
* walk in a recursion through all directories under the passed one
* and returns the names/pathes of all contained XML-files
*
* @param dir directory to start from
* @return
*/
private List getFiles( String dir, String extension ) {
List list = new ArrayList( 200 );
File file = new File( dir );
String[] lst = file.list( new DFileFilter( extension ) );
for ( int i = 0; i < lst.length; i++ ) {
File fl = new File( dir + '/' + lst[i] );
if ( fl.isDirectory() ) {
List l = getFiles( dir + '/' + lst[i], extension );
list.addAll( l );
} else {
count++;
if ( count % 100 == 0 ) {
System.out.println( "tiles processed: " + count );
}
list.add( dir + '/' + lst[i] );
}
}
return list;
}
/**
* calculates the bounding box of the grouped tiles by evaluating the
* MBRs of all involved shape files.
*
* @param shpFiles
* @param crs
* @return
* @throws IOException
* @throws UnknownCRSException
*/
private Envelope calcNewBBOX( List shpFiles, String crs )
throws IOException, UnknownCRSException {
double minx = 9E9;
double miny = 9E9;
double maxx = -9E9;
double maxy = -9E9;
for ( int i = 0; i < shpFiles.size(); i++ ) {
String tmp = (String) shpFiles.get( i );
int pos = tmp.lastIndexOf( '.' );
tmp = tmp.substring( 0, pos );
ShapeFile shp = new ShapeFile( tmp );
Envelope env = shp.getFileMBR();
if ( env.getMin().getX() < minx ) {
minx = env.getMin().getX();
}
if ( env.getMin().getY() < miny ) {
miny = env.getMin().getY();
}
if ( env.getMax().getX() > maxx ) {
maxx = env.getMax().getX();
}
if ( env.getMax().getY() > maxy ) {
maxy = env.getMax().getY();
}
shp.close();
}
CoordinateSystem cs = CRSFactory.create( crs );
return GeometryFactory.createEnvelope( minx, miny, maxx, maxy, cs );
}
/**
* transforms the all over bbox of the tiles to a latlon bounding box
*
* @param nativeCRS
* @param bbox
* @return
* @throws Exception
*/
private Envelope calcLLBBOX( String nativeCRS, Envelope bbox )
throws Exception {
IGeoTransformer trans = new GeoTransformer("EPSG:4326" );
return trans.transform( bbox, nativeCRS);
}
/**
* returns the name of the native CRS of the coverage
* @param desc
* @return
*/
private String getNativeCRS( CoverageDescription desc ) {
CoverageOffering co = desc.getCoverageOfferings()[0];
CodeList[] cl = co.getSupportedCRSs().getNativeSRSs();
if ( cl != null && cl.length > 0 ) {
LOG.logInfo( "CRS: " + cl[0].getCodes()[0] );
return cl[0].getCodes()[0];
}
Envelope env = co.getDomainSet().getSpatialDomain().getEnvelops()[0];
return env.getCoordinateSystem().getName();
}
/**
* returns a comma seperated list of all available coverage source
* resolutions
*
* @param desc
* @return
*/
private String getResolutions( List confFiles )
throws Exception {
List reso = new ArrayList();
for ( int i = 0; i < confFiles.size(); i++ ) {
String tmp = (String) confFiles.get( i );
if ( tmp.startsWith( "/" ) ) {
tmp = tmp.substring( 1, tmp.length() );
}
CoverageDescription desc = CoverageDescription.createCoverageDescription( new URL(
"file:///"
+ tmp ) );
CoverageOffering co = desc.getCoverageOfferings()[0];
Resolution[] res = co.getExtension().getResolutions();
for ( int j = 0; j < res.length; j++ ) {
Double d = new Double( res[res.length - j - 1].getMinScale() );
if ( !reso.contains( d ) ) {
reso.add( d );
}
}
}
Double[] doubs = (Double[]) reso.toArray( new Double[reso.size()] );
Arrays.sort( doubs );
String rs = "";
for ( int i = 0; i < doubs.length; i++ ) {
rs += String.valueOf( doubs[doubs.length - i - 1] );
if ( i < ( doubs.length - 1 ) ) {
rs += ",";
}
}
return rs;
}
/**
* mergers the shape files for each resolution level into a new one
* @param shpFiles
*/
private void mergeShapes( List shpFiles )
throws Exception {
LOG.logInfo( "mergin shapes ..." );
String fs = "/";
while ( shpFiles.size() > 0 ) {
String tmp = (String) shpFiles.get( 0 );
int pos = tmp.lastIndexOf( "." );
tmp = tmp.substring( 0, pos );
pos = tmp.lastIndexOf( fs );
String res = tmp.substring( pos + 1, tmp.length() );
LOG.logInfo( "processing resolution level: " + res );
FeatureCollection fc = FeatureFactory.createFeatureCollection( "fc" + res, 1000 );
String[] shapes = (String[]) shpFiles.toArray( new String[shpFiles.size()] );
for ( int i = shapes.length; i > 0; i-- ) {
tmp = (String) shpFiles.get( i - 1 );
if ( tmp.indexOf( res ) > 0 ) {
shpFiles.remove( i - 1 );
pos = tmp.lastIndexOf( '.' );
tmp = tmp.substring( 0, pos );
ShapeFile shp = new ShapeFile( tmp );
int cnt = shp.getRecordNum();
for ( int j = 0; j < cnt; j++ ) {
Feature feat = shp.getFeatureByRecNo( j + 1 );
fc.add( feat );
}
shp.close();
}
}
if ( fc.size() > 0 ) {
ShapeFile shp = new ShapeFile( outDir + "/" + res, "rw" );
shp.writeShape( fc );
shp.close();
}
}
}
/**
*
* @param name
* @param description
* @param resolutions
* @param format
* @param crs
* @param llBbox
* @param bbox
*/
private void createConfigurationFile( String name, String description, String resolutions,
String format, String crs, Envelope llBbox, Envelope bbox ) {
URL configURL = AutoTiler.class.getResource( GroupTiles.CONFIG_TEMPLATE );
URL configXSL = AutoTiler.class.getResource( GroupTiles.CONFIG_XSL );
if ( configURL == null || configXSL == null ) {
LOG.logError( "Unable to make configuration file" );
System.exit( 1 );
} else {
XSLTDocument xslt = new XSLTDocument();
try {
if ( description == null ) {
description = "";
}
xslt.load( configXSL );
Map map = new HashMap();
map.put( "upperleftll", llBbox.getMin().getX() + " " + llBbox.getMin().getY() );
map.put( "lowerrightll", llBbox.getMax().getX() + " " + llBbox.getMax().getY() );
map.put( "upperleft", bbox.getMin().getX() + " " + bbox.getMin().getY() );
map.put( "lowerright", bbox.getMax().getX() + " " + bbox.getMax().getY() );
map.put( "dataDir", outDir );
map.put( "label", name );
map.put( "name", name );
map.put( "description", description );
map.put( "keywords", "deegree" );
map.put( "resolutions", resolutions );
map.put( "mimeType", format );
map.put( "srs", crs );
XMLFragment xml = new XMLFragment();
xml.load( configURL );
xml = xslt.transform( xml, XMLFragment.DEFAULT_URL, null, map );
// write the result
String out = outDir + "/wcs_configuration.xm";
FileOutputStream fos = new FileOutputStream( out );
xml.write( fos );
fos.close();
} catch ( Exception e1 ) {
e1.printStackTrace();
}
}
}
public static void printHelp() {
System.out.println( "-i root directory" );
System.out.println( "-o output directory (optional)" );
System.out.println( "-h print this help" );
}
/**
* @version $Revision: 1.15 $
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
*/
private class DFileFilter implements FilenameFilter {
private String extend = null;
public DFileFilter( String extend ) {
this.extend = extend;
}
/**
* @return
*/
public boolean accept( File f, String name ) {
int pos = name.lastIndexOf( "." );
String ext = name.substring( pos + 1 );
System.out.println( name );
return ext.toUpperCase().equals( extend ) || name.indexOf( '.' ) < 0;
}
}
public static void main( String[] args ) {
// if ( args == null || args.length < 2) {
// GroupTiles.printHelp();
// System.exit(1);
// }
//
HashMap map = new HashMap();
for ( int i = 0; i < args.length; i += 2 ) {
if ( args[i].trim().equals( "-h" ) ) {
GroupTiles.printHelp();
System.exit( 1 );
}
map.put( args[i], args[i + 1] );
}
String rootDir = (String) map.get( "-i" );
//rootDir = "D:/java/projekte/ostwuerttemberg/resources/tk25/tiles";
String outDir = (String) map.get( "-o" );
if ( outDir == null ) {
outDir = rootDir;
}
try {
new GroupTiles( rootDir, outDir );
} catch ( Exception e ) {
e.printStackTrace();
}
}
}
/* ********************************************************************
Changes to this class. What the people have been up to:
$Log: GroupTiles.java,v $
Revision 1.15 2006/11/27 09:07:53 poth
JNI integration of proj4 has been removed. The CRS functionality now will be done by native deegree code.
Revision 1.14 2006/09/27 16:46:41 poth
transformation method signature changed
Revision 1.13 2006/07/12 14:46:18 poth
comment footer added
********************************************************************** */