001    /*----------------------------------------------------------------------------
002     This file is part of deegree, http://deegree.org/
003     Copyright (C) 2001-2009 by:
004       Department of Geography, University of Bonn
005     and
006       lat/lon GmbH
007    
008     This library is free software; you can redistribute it and/or modify it under
009     the terms of the GNU Lesser General Public License as published by the Free
010     Software Foundation; either version 2.1 of the License, or (at your option)
011     any later version.
012     This library is distributed in the hope that it will be useful, but WITHOUT
013     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
014     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
015     details.
016     You should have received a copy of the GNU Lesser General Public License
017     along with this library; if not, write to the Free Software Foundation, Inc.,
018     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019    
020     Contact information:
021    
022     lat/lon GmbH
023     Aennchenstr. 19, 53177 Bonn
024     Germany
025     http://lat-lon.de/
026    
027     Department of Geography, University of Bonn
028     Prof. Dr. Klaus Greve
029     Postfach 1147, 53001 Bonn
030     Germany
031     http://www.geographie.uni-bonn.de/deegree/
032    
033     e-mail: info@deegree.org
034    ----------------------------------------------------------------------------*/
035    
036    package org.deegree.tools.srs;
037    
038    import java.io.BufferedReader;
039    import java.io.FileReader;
040    import java.io.IOException;
041    import java.util.HashMap;
042    import java.util.LinkedList;
043    import java.util.List;
044    import java.util.Map;
045    
046    import javax.vecmath.Point3d;
047    
048    import org.deegree.crs.components.Unit;
049    import org.deegree.framework.log.ILogger;
050    import org.deegree.framework.log.LoggerFactory;
051    import org.deegree.model.crs.CRSFactory;
052    import org.deegree.model.crs.CRSTransformationException;
053    import org.deegree.model.crs.CoordinateSystem;
054    import org.deegree.model.crs.GeoTransformer;
055    import org.deegree.model.crs.UnknownCRSException;
056    import org.deegree.model.spatialschema.GeometryFactory;
057    import org.deegree.model.spatialschema.Point;
058    
059    /**
060     * The <code>DemoCRSTransform</code> is a sa(i)mple application for using deegree coordinate systems and their
061     * transformations.
062     *
063     *
064     * @version $Revision: 18195 $
065     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
066     * @author last edited by: $Author: mschneider $
067     *
068     * @version 1.0. $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
069     */
070    public class DemoCRSTransform {
071    
072        private static ILogger LOG = LoggerFactory.getLogger( DemoCRSTransform.class );
073    
074        private CoordinateSystem sourceCRS;
075    
076        private CoordinateSystem targetCRS;
077    
078        /**
079         * Construct a demo crs with following coordinate systems.
080         *
081         * @param sourceCRS
082         * @param targetCRS
083         */
084        public DemoCRSTransform( CoordinateSystem sourceCRS, CoordinateSystem targetCRS ) {
085            this.sourceCRS = sourceCRS;
086            this.targetCRS = targetCRS;
087        }
088    
089        /**
090         * This method transforms the given coordinate (in the sourceCRS) into a coordinate of the targetCRS and back.
091         *
092         * @param coordinate
093         *            to be transformed.
094         * @param withInverse
095         *            true if the inverse has to be calculated.
096         */
097        public void doTransform( Point3d coordinate, boolean withInverse ) {
098            GeoTransformer gt = new GeoTransformer( targetCRS );
099    
100            // point to transform
101            Point point = GeometryFactory.createPoint( coordinate.x, coordinate.y, coordinate.z, sourceCRS );
102    
103            outputPoint( "The original point in crs: " + sourceCRS.getIdentifier() + ": ", point, sourceCRS );
104            Point pp = null;
105            try {
106                pp = (Point) gt.transform( point );
107            } catch ( IllegalArgumentException e ) {
108                LOG.logError( e.getMessage(), e );
109            } catch ( CRSTransformationException e ) {
110                LOG.logError( e.getMessage(), e );
111            }
112            outputPoint( "The transformed point in crs: " + targetCRS.getIdentifier() + ": ", pp, targetCRS );
113            if ( withInverse ) {
114    
115                // transform back to source CRS
116                gt = new GeoTransformer( sourceCRS );
117                try {
118                    point = (Point) gt.transform( pp );
119                } catch ( IllegalArgumentException e ) {
120                    LOG.logError( e.getMessage(), e );
121                } catch ( CRSTransformationException e ) {
122                    LOG.logError( e.getMessage(), e );
123                }
124                outputPoint( "The inversed transformed point in crs: " + sourceCRS.getIdentifier() + ": ", point, sourceCRS );
125            }
126    
127        }
128    
129        private void outputPoint( String outputString, Point coord, CoordinateSystem currentCRS ) {
130            double resultX = coord.getX();
131            double resultY = coord.getY();
132            double resultZ = coord.getZ();
133            Unit[] allUnits = currentCRS.getAxisUnits();
134            System.out.println( outputString + resultX + allUnits[0] + ", " + resultY + allUnits[1]
135                                + ( ( currentCRS.getDimension() == 3 ) ? ", " + resultZ + allUnits[2] : "" ) );
136    
137        }
138    
139        /**
140         * a starter method to transform a given point or a serie of points read from a file.
141         *
142         * @param args
143         * @throws UnknownCRSException
144         * @throws IOException
145         *             if the buffered reader could not read from the file
146         */
147        public static void main( String[] args )
148                                throws UnknownCRSException, IOException {
149            Map<String, String> params = new HashMap<String, String>( 5 );
150            for ( int i = 0; i < args.length; i++ ) {
151                String arg = args[i];
152                if ( arg != null && !"".equals( arg.trim() ) ) {
153                    arg = arg.trim().toLowerCase();
154                    if ( arg.equalsIgnoreCase( "-?" ) || arg.equalsIgnoreCase( "-h" ) ) {
155                        outputHelp();
156                    } else {
157                        if ( i + 1 < args.length ) {
158                            String val = args[++i];
159                            if ( val != null ) {
160                                params.put( arg, val.trim() );
161                            } else {
162                                LOG.logInfo( "Invalid value for parameter: " + arg );
163                            }
164                        } else {
165                            LOG.logInfo( "No value for parameter: " + arg );
166                        }
167                    }
168                }
169            }
170    
171            /**
172             * add crs and point here if using eclipse to start.
173             */
174            // String sourceCRS = "EPSG:25832";
175            // String targetCRS = "EPSG:31466";
176            // String coord = "370766.738,5685588.661";
177    
178            String sourceCRS = "";
179            String targetCRS = "";
180            String coord = "";
181    
182            if ( "".equals( sourceCRS ) ) {
183                sourceCRS = params.get( "-sourcecrs" );
184                if ( sourceCRS == null || "".equals( sourceCRS.trim() ) ) {
185                    LOG.logError( "No source CRS given (-sourceCRS parameter)" );
186                    System.exit( 1 );
187                }
188            }
189            if ( "".equals( targetCRS ) ) {
190                targetCRS = params.get( "-targetcrs" );
191                if ( targetCRS == null || "".equals( targetCRS.trim() ) ) {
192                    LOG.logError( "No target CRS given (-targetCRS parameter)" );
193                    System.exit( 1 );
194                }
195            }
196    
197            CoordinateSystem source = CRSFactory.create( sourceCRS );
198            CoordinateSystem target = CRSFactory.create( targetCRS );
199    
200            DemoCRSTransform demo = new DemoCRSTransform( source, target );
201    
202            String sourceFile = params.get( "-sourcefile" );
203            if ( "".equals( coord ) && sourceFile != null && !"".equals( sourceFile.trim() ) ) {
204                String coordSep = params.get( "-coordsep" );
205                if ( coordSep == null || "".equals( coordSep ) ) {
206                    LOG.logInfo( "No coordinates separator given (-coordSep parameter), therefore using ' ' (a space) as separator" );
207                    coordSep = " ";
208                }
209                BufferedReader br = new BufferedReader( new FileReader( sourceFile ) );
210                String coords = br.readLine();
211    
212                int lineCount = 1;
213                final int sourceDim = source.getDimension();
214                List<Point3d> coordinateList = new LinkedList<Point3d>();
215                while ( coords != null ) {
216                    if ( !coords.startsWith( "#" ) ) {
217                        String[] coordinates = coords.split( coordSep );
218                        if ( coordinates.length != sourceDim ) {
219                            LOG.logError( lineCount
220                                          + ") Each line must contain the number of coordinates fitting the dimension of the source crs ("
221                                          + sourceDim + ") seperated by a '" + coordSep + "'." );
222                        } else {
223                            Point3d from = new Point3d();
224                            from.x = Double.parseDouble( coordinates[0].replace( ",", "." ) );
225                            from.y = Double.parseDouble( coordinates[1].replace( ",", "." ) );
226                            if ( sourceDim == 3 ) {
227                                from.z = Double.parseDouble( coordinates[2].replace( ",", "." ) );
228                            }
229                            coordinateList.add( from );
230                        }
231                    }
232                    coords = br.readLine();
233                    lineCount++;
234                }
235                if ( coordinateList.size() == 0 ) {
236                    LOG.logError( "No valid points found in file: " + sourceFile );
237                } else {
238                    long time = System.currentTimeMillis();
239                    for ( Point3d c : coordinateList ) {
240                        demo.doTransform( c, false );
241                    }
242                    System.out.println( "Transformation took: " + ( ( System.currentTimeMillis() - time ) / 1000. )
243                                        + " seconds" );
244                }
245            } else {
246                if ( "".equals( coord ) ) {
247                    coord = params.get( "-coord" );
248                    if ( coord == null || "".equals( coord.trim() ) ) {
249                        LOG.logError( "No coordinate(s) to transform, use the -coord or the -sourceFile parameter to define a coordinate (list)." );
250                        System.exit( 1 );
251                    }
252                }
253                String[] splitter = coord.split( "," );
254                if ( splitter == null || splitter.length == 1 || splitter.length > 3 ) {
255                    LOG.logError( "A coordinate must be comma separated and may only have two or three ordinates e.g. -coord \"3.1415 , 2.7182\"" );
256                    System.exit( 1 );
257                }
258                double x = Double.parseDouble( splitter[0] );
259                double y = Double.parseDouble( splitter[1] );
260                double z = ( splitter.length == 3 ) ? Double.parseDouble( splitter[2] ) : 0;
261                demo.doTransform( new Point3d( x, y, z ), true );
262            }
263        }
264    
265        private static void outputHelp() {
266            StringBuilder sb = new StringBuilder();
267            sb.append( "The DemoCRSTransform program can be used to transform a single given coordinate or a set of coordinates read from a file.\n" );
268            sb.append( "Following parameters are supported:\n" );
269            sb.append( "-sourceCRS (required) the name of the source crs, e.g. EPSG:4326.\n" );
270            sb.append( "-targetCRS (required) the name of the target crs, e.g. EPSG:31467.\n" );
271            sb.append( "[-coord] parameter defining a coordinate (comma separated) in the source crs, e.g. '3.1415 , 2.7182' \n" );
272            sb.append( "[-sourceFile] a /path/of/a_list_of_coordinates.txt containing a list of coordinate pairs/triples. If supplied the -coordSep (the separator between the ordinates will also be evalutated)..\n" );
273            sb.append( "[-coordSep] (only valid with -sourceFile) defining a separator between the coords in the file e.g. a ';' or ',' if omitted a space is assumed.\n" );
274            sb.append( "-?|-h output this text\n" );
275            System.out.println( sb.toString() );
276            System.exit( 1 );
277        }
278    
279    }