Statistics
| Revision:

root / trunk / extensions / extGeoreferencing / src / org / gvsig / georeferencing / process / geotransform / GeoTransformProcess.java @ 20876

History | View | Annotate | Download (11 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 Iba?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.georeferencing.process.geotransform;
42

    
43
import org.gvsig.raster.RasterProcess;
44
import org.gvsig.raster.datastruct.GeoPoint;
45
import org.gvsig.raster.util.RasterToolsUtil;
46

    
47
import Jama.Matrix;
48
import Jama.QRDecomposition;
49

    
50
/**
51
 *  Clase que representa una transformacion polinomial  para la convertir las
52
 *  coordenadas de una imagen en la imagen rectificada.
53
 *  
54
 *  
55
 *  @author Alejandro Mu?oz Sanchez (alejandro.munoz@uclm.es)
56
 *         @version 20/1/2008
57
 **/
58
public class GeoTransformProcess extends RasterProcess {
59

    
60
        // Lista de puntos de control.
61
        private GeoPoint gpcs[]= null;
62
        
63
        // porcentage del proceso global de la tarea
64
        private int percent=0;
65
        
66
        // orden del polinomio aproximador
67
        protected int orden = 0;
68
        
69
        // numero minimo de puntos 
70
        protected int minGPC=0;
71
        
72
        // Lista con los valores de las potencias de x e y  
73
        private int exp[][] = null;
74
        
75
        // rms total en las x
76
        private double rmsXTotal=0;
77
        
78
        // rms total en las y
79
        private double rmsYTotal=0;
80
        
81
        // rms total
82
        private double rmsTotal=0;
83
        
84
        GeoTransformDataResult resultData= null;
85
        
86
        //coeficientes polinomios conversion coordenadas reales a coordenadas pixel
87
        private double mapToPixelCoefX[]= null;
88
        private double mapToPixelCoefY[]=null;
89
        
90
        
91
        //coeficientes polinomio conversion coordenadas pixel a coordenadas reales
92
        private double pixelToMapCoefX[]= null;
93
        private double pixelToMapCoefY[]=null;
94
        
95
        /** 
96
        * Metodo que recoge los parametros del proceso de transformaci?n 
97
        * <LI>gpcs: lista de puntos de control</LI>> 
98
        * <LI> orden: orden del polinomio de transformacion </LI> 
99
        */
100
        public void init() {                
101
                gpcs = (GeoPoint[])getParam("gpcs");
102
                orden= (int)getIntParam("orden");
103
                minGPC = (orden+1)*(orden+2)/2;
104
            exp = new int[minGPC][2];
105
            resetErrors();
106
            resultData= new GeoTransformDataResult();
107
                // Chequear si el numero de puntos es suficiente para determinar la transformacion de orden n. 
108
                if(!enoughPoints()){
109
                        minGPC=0;                
110
                }
111
        }
112
        
113
        /**
114
         * Inicializa los valores de los errores a 0
115
         */
116
        private void resetErrors() {
117
                for (int i = 0; i < gpcs.length; i++) 
118
                        gpcs[i].resetErrors();
119
        }
120
        
121
        /**
122
         * @return true si se proporciona el numero minimo de puntos de entrada 
123
         * para la transformaci?n de orden seleccionado. false en caso contrario.
124
         * */                
125
        public boolean enoughPoints() {
126
                return (gpcs.length>=minGPC);
127
        }
128

    
129
        /**
130
         * Obtiene el resultado del proceso.
131
         * @return
132
         */
133
        public Object getResult() {
134
                return resultData;
135
        }
136
        
137
        /**
138
         *  Proceso
139
         **/
140
        public void process() {
141
                if(minGPC > 0) {
142
                        // Obtencion los polinomios de transformaci?n 
143
                        calculatePolinomialCoefs();
144
                        // calculo de los resultados
145
                        calculateRMSerror();
146
                        // Se almacenan los resultados en dataResult
147
                        resultData.setGpcs(gpcs);
148
                        resultData.setPixelToMapCoefX(pixelToMapCoefX);
149
                        resultData.setPixelToMapCoefY(pixelToMapCoefY);
150
                        resultData.setMapToPixelCoefX(mapToPixelCoefX);
151
                        resultData.setMapToPixelCoefY(mapToPixelCoefY);
152
                        resultData.setRmsXTotal(rmsXTotal);
153
                        resultData.setRmsYTotal(rmsYTotal);
154
                        resultData.setRmsTotal(rmsTotal);
155
                        resultData.setPolynomialOrden(orden);
156
                        
157
                        if(externalActions!=null)
158
                                externalActions.end(resultData);
159
                        return;
160
                }
161
                resultData = null;
162
        }
163

    
164

    
165
        
166
         /**
167
     *  Calculo de los coeficientes de los polinomios de aproximacion.
168
     * */
169
        public void calculatePolinomialCoefs(){
170
                double matrixD[][]= new double [minGPC][minGPC]; 
171
                double matrixD2[][]= new double [minGPC][minGPC]; 
172
                double result[]= new double[minGPC];
173
                double result2[]= new double[minGPC];
174
                double result3[]= new double[minGPC];
175
                double result4[]= new double[minGPC];
176
                int k=-1;
177
                // Obtencion de la primera fila de la matriz
178
                for (int filas=0; filas<minGPC;filas++)
179
                {        k=-1;                        
180
                for (int i=0; i<=orden; i++)
181
                        for(int j=0; j<=i; j++){
182
                                k++;
183
                                for(int v=0; v<gpcs.length;v++){
184
                                        if(gpcs[v].active){
185
                                                matrixD[filas][k]+=(Math.pow(gpcs[v].pixelPoint.getX(),i-j)* Math.pow(gpcs[v].pixelPoint.getX(),exp[filas][0]))
186
                                                * (Math.pow(gpcs[v].pixelPoint.getY(),j)* Math.pow(gpcs[v].pixelPoint.getY(),exp[filas][1]));        
187
                                                matrixD2[filas][k]+=(Math.pow(gpcs[v].mapPoint.getX(),i-j)* Math.pow(gpcs[v].mapPoint.getX(),exp[filas][0]))
188
                                                * (Math.pow(gpcs[v].mapPoint.getY(),j)* Math.pow(gpcs[v].mapPoint.getY(),exp[filas][1]));        
189
                                        }
190
                                
191
                                }
192
                                // Para la fila 0 se guardan los exponentes
193
                                if(filas==0){
194
                                        exp[k][0]=i-j;
195
                                        exp[k][1]=j;
196

    
197
                                        // Se calcula el resultado de !!!!!
198
                                        for(int v=0; v<gpcs.length;v++){
199
                                                if(gpcs[v].active){
200
                                                        result[k]+=(Math.pow(gpcs[v].pixelPoint.getX(),i-j)* Math.pow(gpcs[v].pixelPoint.getX(),exp[filas][0]))
201
                                                                * (Math.pow(gpcs[v].pixelPoint.getY(),j)* Math.pow(gpcs[v].pixelPoint.getY(),exp[filas][1]))*gpcs[v].mapPoint.getY();        
202
                                
203
                                                        result2[k]+=(Math.pow(gpcs[v].mapPoint.getX(),i-j)* Math.pow(gpcs[v].mapPoint.getX(),exp[filas][0]))
204
                                                                * (Math.pow(gpcs[v].mapPoint.getY(),j)* Math.pow(gpcs[v].mapPoint.getY(),exp[filas][1]))*gpcs[v].pixelPoint.getY();
205
                                                
206
                                                        result3[k]+=(Math.pow(gpcs[v].pixelPoint.getX(),i-j)* Math.pow(gpcs[v].pixelPoint.getX(),exp[filas][0]))
207
                                                        * (Math.pow(gpcs[v].pixelPoint.getY(),j)* Math.pow(gpcs[v].pixelPoint.getY(),exp[filas][1]))*gpcs[v].mapPoint.getX();
208
                                                
209
                                                        result4[k]+=(Math.pow(gpcs[v].mapPoint.getX(),i-j)* Math.pow(gpcs[v].mapPoint.getX(),exp[filas][0]))
210
                                                        * (Math.pow(gpcs[v].mapPoint.getY(),j)* Math.pow(gpcs[v].mapPoint.getY(),exp[filas][1]))*gpcs[v].pixelPoint.getX();        
211
                                                
212
                                                
213
                                                }
214
                                        }        
215
                                }
216
                        }
217
                }
218
                
219
                Matrix matrixResult= new Matrix(matrixD);
220
                Matrix matrixResult2= new Matrix(matrixD2);
221
                pixelToMapCoefY=solveSystem(matrixResult,result);        
222
                mapToPixelCoefY=  solveSystem(matrixResult2,result2);
223
                pixelToMapCoefX=solveSystem(matrixResult,result3);        
224
                mapToPixelCoefX=  solveSystem(matrixResult2,result4);
225
        }
226
        
227
        
228

    
229
        /**
230
         * @return array con la solucion al sistema de ecuadiones.
231
         * */
232
        public double[] solveSystem(Matrix matrix, double columResult[]){
233
                double xCoef []= new double[minGPC];
234
                double [][]a= new double[columResult.length][1]; 
235
                for (int i=0; i<columResult.length;i++)
236
                        a[i][0]=columResult[i];
237
                Matrix c=null;
238
                
239
                if(matrix.det()==0.0){
240
                        QRDecomposition descomposition = new QRDecomposition(matrix);
241
                        Matrix A= new Matrix(a);
242
                        c=descomposition.solve(A);
243
                }
244
                else        
245
                        c= matrix.solve(new Matrix(a));
246
                for (int i=0; i<columResult.length;i++)
247
                        xCoef[i]=c.get(i,0);
248
                return xCoef;
249
        }
250
        
251
        
252
        /**
253
         * @return vector con los RMS 
254
         * */
255
        public void calculateRMSerror() {
256
                
257
                int numgpcs= gpcs.length;
258
                double rmsxTotal=0;
259
                double rmsyTotal=0;
260
                rmsTotal=0;
261
                int num=0;
262
                
263
                for(int im_point = 0; im_point < numgpcs; im_point++) {
264
                        if (gpcs[im_point].active)
265
                        {
266
                                double tmp[]= getCoordMap(gpcs[im_point].pixelPoint.getX(),gpcs[im_point].pixelPoint.getY());
267
                                double tmp2[]= getCoordPixel(tmp[0],tmp[1]);
268
                                gpcs[im_point].setEvaluateX(tmp2[0]);
269
                                gpcs[im_point].setEvaluateY(tmp2[1]);
270
                                gpcs[im_point].setErrorX(Math.pow(gpcs[im_point].getEvaluateX() - gpcs[im_point].pixelPoint.getX(), 2));
271
                                rmsxTotal += gpcs[im_point].getErrorX();
272
                                gpcs[im_point].setErrorY(Math.pow(gpcs[im_point].getEvaluateY() - gpcs[im_point].pixelPoint.getY(), 2));
273
                                rmsyTotal +=gpcs[im_point].getErrorY();
274
                                gpcs[im_point].setRms(Math.sqrt(gpcs[im_point].getErrorX() +gpcs[im_point].getErrorY()));
275
                                rmsTotal += gpcs[im_point].getRms();
276
                                num++;
277
                        }
278
                }
279
                
280
                this.rmsTotal =Math.sqrt( rmsTotal / num); 
281
                this.rmsXTotal = Math.sqrt(rmsxTotal / num);
282
                this.rmsYTotal = Math.sqrt(rmsyTotal / num);
283
                
284
        }
285
                
286
        /**
287
         *  @return error total para la coordenada X
288
         * */
289
        public double getRMSx(){
290
                return rmsXTotal;        
291
        }
292
        
293
        
294
        /**
295
         *  @return error total para la coordenada y
296
         * */
297
        public double getRMSy() {
298
                return rmsYTotal;        
299
        }
300
        
301
        /**
302
         *  @return error total
303
         * */
304
        public double getRMSTotal() {
305
                return rmsTotal;        
306
        }
307
        
308
        /*
309
         * (non-Javadoc)
310
         * @see org.gvsig.gui.beans.incrementabletask.IIncrementable#getTitle()
311
         */
312
        public String getTitle() {
313
                return RasterToolsUtil.getText(this, "transformacion");
314
        }
315

    
316
        /*
317
         * (non-Javadoc)
318
         * @see org.gvsig.raster.RasterProcess#getLog()
319
         */
320
        public String getLog() {
321
                return RasterToolsUtil.getText(this, "calculando_transformacion");
322
        }
323

    
324
        /*
325
         * (non-Javadoc)
326
         * @see org.gvsig.gui.beans.incrementabletask.IIncrementable#getPercent()
327
         */
328
        public int getPercent() {
329
                return percent;
330
        }
331

    
332
        
333

    
334
        /**
335
         *  Funci?n que evalua el polinomio de transformaci?n para obtener las coordenadas
336
         *  reales de unas coordenadas pixeles que se pasan como parametros.
337
         * @param x coordenada x del punto
338
         * @param y coordenada y del punto
339
         * @return resultado de la evaluaci?n para x e y
340
         * */
341
        public double[] getCoordMap(double x, double y){
342
                //setExpPolinomial();
343
                double eval[]= new double [2];        
344
                for(int i=0; i<pixelToMapCoefX.length;i++)
345
                {
346
                        eval[0]+=pixelToMapCoefX[i] * Math.pow(x, exp[i][0]) * Math.pow(y,exp[i][1]);
347
                        eval[1]+=pixelToMapCoefY[i] * Math.pow(x, exp[i][0]) * Math.pow(y, exp[i][1]);
348
                }        
349
                return eval;
350
        }
351

    
352
        
353
        /**
354
         *  Funci?n que evalua el polinomio de transformaci?n para obtener las coordenadas
355
         *  pixeles de unas coordenadas mapa en un proceso de transformacion.
356
         * @param x coordenada x del punto
357
         * @param y coordenada y del punto
358
         * @return resultado de la evaluaci?n para x e y
359
         * */
360
        public double[] getCoordPixel(double x, double y){
361
                //setExpPolinomial();
362
                double eval[]= new double [2];        
363
                for(int i=0; i<pixelToMapCoefX.length;i++)
364
                {
365
                        eval[0]+=mapToPixelCoefX[i] * Math.pow(x, exp[i][0]) * Math.pow(y,exp[i][1]);
366
                        eval[1]+=mapToPixelCoefY[i] * Math.pow(x, exp[i][0]) * Math.pow(y, exp[i][1]);
367
                }        
368
                return eval;
369
        }
370

    
371
        
372
        /*private void setExpPolinomial(){
373
                if(exp==null)
374
                        {
375
                                int minGPC=(orden+1)*(orden+2)/2;
376
                                exp=new int[minGPC][2];
377
                                int k=-1;
378
                                for (int i=0; i<=orden; i++){
379
                                        for(int j=0; j<=i; j++){
380
                                                k++;
381
                                                exp[k][0]=i-j;
382
                                                exp[k][1]=j;
383
                                        }
384
                                }
385
                        }        
386
        }*/
387
        
388
}
389