001    //$HeadURL: $
002    /*----------------    FILE HEADER  ------------------------------------------
003     This file is part of deegree.
004     Copyright (C) 2001-2008 by:
005     Department of Geography, University of Bonn
006     http://www.giub.uni-bonn.de/deegree/
007     lat/lon GmbH
008     http://www.lat-lon.de
009    
010     This library is free software; you can redistribute it and/or
011     modify it under the terms of the GNU Lesser General Public
012     License as published by the Free Software Foundation; either
013     version 2.1 of the License, or (at your option) any later version.
014     This library is distributed in the hope that it will be useful,
015     but WITHOUT ANY WARRANTY; without even the implied warranty of
016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     Lesser General Public License for more details.
018     You should have received a copy of the GNU Lesser General Public
019     License along with this library; if not, write to the Free Software
020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021     Contact:
022    
023     Andreas Poth
024     lat/lon GmbH
025     Aennchenstr. 19
026     53177 Bonn
027     Germany
028     E-Mail: poth@lat-lon.de
029    
030     Prof. Dr. Klaus Greve
031     Department of Geography
032     University of Bonn
033     Meckenheimer Allee 166
034     53115 Bonn
035     Germany
036     E-Mail: greve@giub.uni-bonn.de
037     ---------------------------------------------------------------------------*/
038    
039    package org.deegree.crs.transformations;
040    
041    import java.util.List;
042    
043    import javax.vecmath.Point3d;
044    
045    /**
046     * The <code>ConcatenatedTransform</code> class allows the connection of two transformations.
047     * <p>
048     * Calling inverse on this transformation will invert the whole underlying transformation chain. For example, if A * (B
049     * *C)=D and D is this transformation calling D.inverse() will result in (C.inverse * B.inverse) * A.inverse.
050     * </p>
051     * 
052     * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
053     * 
054     * @author last edited by: $Author:$
055     * 
056     * @version $Revision:$, $Date:$
057     * 
058     */
059    
060    public class ConcatenatedTransform extends CRSTransformation {
061    
062        boolean isIdentitiy = false;
063    
064        private CRSTransformation firstTransform;
065    
066        private CRSTransformation secondTransform;
067    
068        /**
069         * Creates a transform by concatenating two existing transforms. A concatenated transform applies two transforms,
070         * one after the other. The dimension of the output space of the first transform must match the dimension of the
071         * input space in the second transform.
072         * 
073         * @param first
074         *            The first transformation to apply to given points.
075         * @param second
076         *            The second transformation to apply to given points.
077         * @param identifier
078         */
079        public ConcatenatedTransform( CRSTransformation first, CRSTransformation second, String identifier ) {
080            super( first.getSourceCRS(), second.getTargetCRS(), identifier, "Concatenated-Transform", null, null,null );
081            if ( first.isIdentity() && second.isIdentity() ) {
082                isIdentitiy = true;
083            }
084            firstTransform = first;
085            secondTransform = second;
086        }
087    
088        /**
089         * Creates a transformation by concatenating two existing transforms. A concatenated transform applies two
090         * transforms, one after the other. The dimension of the output space of the first transform must match the
091         * dimension of the input space in the second transform. This constructor creates an identifier with following form:
092         * <code>
093         * FROM_id1_TO_id2.</code> The name will be generated the same way (with getName() instead).
094         * 
095         * @param first
096         *            The first transformation to apply to given points.
097         * @param second
098         *            The second transformation to apply to given points.
099         * @param identifier
100         * @param name
101         */
102        public ConcatenatedTransform( CRSTransformation first, CRSTransformation second ) {
103            this( first, second, new StringBuilder( "FROM_" ).append( first.getIdentifier() )
104                                                             .append( "_TO_" )
105                                                             .append( second.getIdentifier() )
106                                                             .toString() );
107        }
108    
109        @Override
110        public List<Point3d> doTransform( List<Point3d> srcPts ) {
111            if ( !isIdentitiy ) {
112                List<Point3d> dest = firstTransform.doTransform( srcPts );
113                return secondTransform.doTransform( dest );
114            }
115            // System.out.println( "The concatenated transform is identity" );
116            return srcPts;
117        }
118    
119        @Override
120        public void inverse() {
121            super.inverse();
122            CRSTransformation tmp = firstTransform;
123            firstTransform = secondTransform;
124            secondTransform = tmp;
125            firstTransform.inverse();
126            secondTransform.inverse();
127        }
128    
129        /*
130         * (non-Javadoc)
131         * 
132         * @see org.deegree.crs.transformations.CRSTransformation#isIdentity()
133         */
134        @Override
135        public boolean isIdentity() {
136            return isIdentitiy;
137        }
138    
139        /**
140         * @return the firstTransform, which is the second transformation if this transform is inverse.
141         */
142        public final CRSTransformation getFirstTransform() {
143            return firstTransform;
144        }
145    
146        /**
147         * @return the secondTransform, which is the first transformation if this transform is inverse.
148         */
149        public final CRSTransformation getSecondTransform() {
150            return secondTransform;
151        }
152    
153    }