Statistics
| Revision:

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

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

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

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

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

    
163

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

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

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

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

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

    
331
        
332

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

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

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