Statistics
| Revision:

root / org.gvsig.projection.jcrs / trunk / org.gvsig.projection.jcrs / org.gvsig.projection.jcrs.lib / src / main / java / org / gvsig / crs / COperation.java @ 436

History | View | Annotate | Download (9.99 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 Instituto de Desarrollo Regional and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   Instituto de Desarrollo Regional (Universidad de Castilla La-Mancha)
34
 *   Campus Universitario s/n
35
 *   02071 Alabacete
36
 *   Spain
37
 *
38
 *   +34 967 599 200
39
 */
40

    
41
package org.gvsig.crs;
42

    
43
import java.awt.geom.Point2D;
44
import java.awt.geom.Rectangle2D;
45

    
46
import org.cresques.cts.CoordTransRuntimeException;
47
import org.cresques.cts.ICoordTrans;
48
import org.cresques.cts.IProjection;
49
import org.gdal.gdal.gdal;
50
import org.gdal.osr.CoordinateTransformation;
51
import org.slf4j.Logger;
52
import org.slf4j.LoggerFactory;
53

    
54
import org.gvsig.crs.proj.CrsProj;
55
import org.gvsig.crs.proj.OperationCrsException;
56

    
57
/**
58
 * Clase que implementa las operaciones de tranformacion de coordenadas entre
59
 * dos CRSs.
60
 *
61
 * @author Miguel Garc?a Jim?nez (garciajimenez.miguel@gmail.com)
62
 * @author Diego Guerrero Sevilla (diego.guerrero@uclm.es)
63
 *
64
 */
65

    
66
// public class COperation implements ICOperation {
67
public class COperation implements ICoordTrans {
68

    
69
    private static final Logger logger = LoggerFactory.getLogger(COperation.class);
70
    /**
71
     * CRS Fuente
72
     */
73
    private ICrs sourceCrs;
74
    /**
75
     * CRS Destino
76
     */
77
    private ICrs targetCrs;
78
    /**
79
     * CRS con los par?metros de transformaci?n (puede representar el CRS fuente
80
     * o destino, dependiendo de <code>paramsInTarget</code>).
81
     */
82
    private CrsProj paramsCrsProj = null;
83
    /**
84
     * Indica si los par?metros de transformaci?n van asociados al CRS fuente (
85
     * <code>false</code>) o al destino (<code>true</code>)
86
     */
87
    private boolean paramsInTarget;
88

    
89
    /**
90
     * par?metros de transformaci?n para el CRS fuente en el formato proj4
91
     */
92
    private String sourceParams = null;
93

    
94
    /**
95
     * par?metros de transformaci?n para el CRS destino en el formato proj4
96
     */
97
    private String targetParams = null;
98

    
99
    private CrsProj source = null;
100

    
101
    private CrsProj target = null;
102

    
103
    private CoordinateTransformation coordinateTransformation = null;
104

    
105
    /**
106
     * Constructor.
107
     *
108
     * @param from
109
     *            CRS fuente.
110
     * @param to
111
     *            CRS destino.
112
     * @throws CrsException
113
     */
114
    public COperation(ICrs from, ICrs to) throws CrsException {
115
        sourceCrs = from;
116
        targetCrs = to;
117
        source = sourceCrs.getCrsProj();
118
        target = targetCrs.getCrsProj();
119
    }
120

    
121
    /**
122
     * Construcctor.
123
     *
124
     * @param sourceCrs
125
     *            CRS fuente.
126
     * @param targetCrs
127
     *            CRS destino.
128
     * @param sourceParams
129
     *            Par?metros de transformaci?n para la fuente (en formato
130
     *            proj4).
131
     * @param targetParams
132
     *            Par?metros de transformaci?n para el destino (en formato
133
     *            proj4).
134
     * @throws CrsException
135
     */
136
    public COperation(ICrs sourceCrs, ICrs targetCrs, String sourceParams, String targetParams) throws CrsException {
137
        this.sourceCrs = sourceCrs;
138
        this.targetCrs = targetCrs;
139
        this.sourceParams = sourceParams;
140
        this.targetParams = targetParams;
141

    
142
        if (sourceParams != null)
143
            source = new CrsProj(sourceCrs.getProj4String() + sourceParams);
144
        else
145
            source = sourceCrs.getCrsProj();
146
        if (targetParams != null)
147
            target = new CrsProj(targetCrs.getProj4String() + targetParams);
148
        else
149
            target = targetCrs.getCrsProj();
150
    }
151

    
152
    /**
153
     * Realiza la operaci?n de transformaci?n sobre un punto. Si exiten
154
     * par?metros de transformaci?n (<code>paramsCrsProj</code>) se utilizan en
155
     * lugar del CRS fuente o destino, seg?n indique <code>paramsInTarget</code>
156
     * .
157
     *
158
     * @throws OperationCrsException
159
     *
160
     */
161
    private Point2D operate(Point2D pt) throws CrsException, OperationCrsException {
162
        double x = pt.getX();
163
        double y = pt.getY();
164

    
165
        int errno = 0;
166
        String msg = "";
167
        int errtype = 0;
168

    
169
        double[] transformed = { 0, 0, 0 };
170
        initializeCoordinateTransformation();
171
        gdal.PushErrorHandler( "CPLQuietErrorHandler" );
172
        gdal.ErrorReset();
173
        if (coordinateTransformation != null) { // && inverseCoordinateTransformation != null) {
174
            coordinateTransformation.TransformPoint(transformed, x, y, 0);
175
        }
176

    
177
        gdal.PopErrorHandler();
178
        errno = gdal.GetLastErrorNo();
179
        msg = gdal.GetLastErrorMsg();
180
        errtype = gdal.GetLastErrorType();
181

    
182
        Point2D.Double result = null;
183
        if (errno != 0 || errtype != 0 || !msg.isEmpty()) {
184
            // FIXME:
185
            // gdal no devuelve m?s de 20 errores por transformaci?n,
186
            // si queremos de los devuelva todos tenemos que anular la
187
            // transformaci?n cada vez que se produce un error
188
            if (msg
189
                .equalsIgnoreCase("Reprojection failed, err = -14, further errors will be supressed on the transform object.")) {
190
                resetCoordinateTransformation();
191
            }
192

    
193
            throw new CoordTransRuntimeException(sourceCrs, targetCrs, x, y);
194
        }
195
        result = new Point2D.Double(transformed[0], transformed[1]);
196
        return result;
197
    }
198

    
199
    private void initializeCoordinateTransformation() {
200
        if (coordinateTransformation == null) {
201

    
202
            int errno = 0;
203
            String msg = "";
204
            int errtype = 0;
205

    
206
            gdal.ErrorReset();
207
            gdal.PushErrorHandler( "CPLQuietErrorHandler" );
208
            coordinateTransformation =
209
                CoordinateTransformation.CreateCoordinateTransformation(source.getSpatialReference(),
210
                    target.getSpatialReference());
211
            gdal.PopErrorHandler();
212
            errno = gdal.GetLastErrorNo();
213
            msg = gdal.GetLastErrorMsg();
214
            errtype = gdal.GetLastErrorType();
215
            if (errno != 0 || errtype != 0 || !msg.isEmpty()) {
216
                logger.warn("Can't initialize coordinate transformation from "+sourceCrs.getAbrev()+" to "+targetCrs.getAbrev()+" "+errno + " "+errtype+" "+msg+".");
217
            }
218
        }
219
    }
220

    
221
    private void resetCoordinateTransformation() {
222
        coordinateTransformation = null;
223
        initializeCoordinateTransformation();
224
    }
225

    
226
    public IProjection getPOrig() {
227
        return (IProjection) sourceCrs;
228
    }
229

    
230
    public IProjection getPDest() {
231
        return (IProjection) targetCrs;
232
    }
233

    
234
    public Point2D convert(Point2D ptOrig, Point2D ptDest) throws CoordTransRuntimeException {
235
        try {
236
            ptDest = operate(ptOrig);
237
        } catch (CrsException e) {
238
            logger.error("Can't operate over point orig (" + ptOrig.toString() + ").", e);
239
            throw new IllegalStateException(e.getMessage());
240
        } catch (OperationCrsException e) {
241
            logger.error("Can't operate over point orig (" + ptOrig.toString() + ").", e);
242
            throw new IllegalStateException(e.getMessage());
243
        }
244
        return ptDest;
245
    }
246

    
247
    public Rectangle2D convert(Rectangle2D rect) throws CoordTransRuntimeException {
248
        Point2D pt1 = new Point2D.Double(rect.getMinX(), rect.getMinY());
249
        Point2D pt2 = new Point2D.Double(rect.getMaxX(), rect.getMaxY());
250
        Point2D pt3 = new Point2D.Double(rect.getMinX(), rect.getMaxY());
251
        Point2D pt4 = new Point2D.Double(rect.getMaxX(), rect.getMinY());
252
        try {
253
            pt1 = operate(pt1);
254
            pt2 = operate(pt2);
255
            pt3 = operate(pt3);
256
            pt4 = operate(pt4);
257
        } catch (CrsException e) {
258
            logger.error("Can't operate over rect (" + rect.toString() + ").", e);
259
            throw new IllegalStateException(e.getMessage());
260
        } catch (OperationCrsException e) {
261
            logger.error("Can't operate over rect (" + rect.toString() + ").", e);
262
            throw new IllegalStateException(e.getMessage());
263
        }
264

    
265
        double min_x = Math.min(Math.min(pt1.getX(), pt2.getX()), Math.min(pt3.getX(), pt4.getX()));
266
        double min_y = Math.min(Math.min(pt1.getY(), pt2.getY()), Math.min(pt3.getY(), pt4.getY()));
267
        double max_x = Math.max(Math.max(pt1.getX(), pt2.getX()), Math.max(pt3.getX(), pt4.getX()));
268
        double max_y = Math.max(Math.max(pt1.getY(), pt2.getY()), Math.max(pt3.getY(), pt4.getY()));
269

    
270
        return new Rectangle2D.Double(min_x, min_y, max_x - min_x, max_y - min_y);
271
    }
272

    
273
    public ICoordTrans getInverted() {
274
        COperation operation;
275
        try {
276
            operation = new COperation(targetCrs, sourceCrs, targetParams, sourceParams);
277
            return operation;
278
        } catch (CrsException e) {
279
            logger.error("Can't get operation.", e);
280
            return null;
281
        }
282
    }
283
    /*
284
     * public void setParamsCrsProj(CrsProj paramsCrs, boolean inTarget){
285
     * this.paramsInTarget = inTarget; this.paramsCrsProj = paramsCrs; }
286
     */
287
}