root / trunk / extensions / extGeoreferencing / src / org / gvsig / georeferencing / process / geotransform / GeoTransformProcess.java @ 20914
History | View | Annotate | Download (11 KB)
1 | 18530 | nbrodin | /* 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 | 18673 | amunoz | |
43 | 18530 | nbrodin | import org.gvsig.raster.RasterProcess; |
44 | 18611 | nbrodin | import org.gvsig.raster.datastruct.GeoPoint; |
45 | import org.gvsig.raster.util.RasterToolsUtil; |
||
46 | 18530 | nbrodin | |
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 | 19175 | dguerrero | // Lista de puntos de control.
|
60 | 18530 | nbrodin | 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 | 18673 | amunoz | //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 | 18530 | nbrodin | /**
|
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 | 18611 | nbrodin | exp = new int[minGPC][2]; |
104 | resetErrors(); |
||
105 | 18530 | nbrodin | 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 | 18611 | nbrodin | * 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 | 18530 | nbrodin | * @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 | 18590 | nbrodin | /**
|
129 | * Obtiene el resultado del proceso.
|
||
130 | * @return
|
||
131 | */
|
||
132 | public Object getResult() { |
||
133 | return resultData;
|
||
134 | } |
||
135 | 18530 | nbrodin | |
136 | /**
|
||
137 | * Proceso
|
||
138 | **/
|
||
139 | public void process() { |
||
140 | 18611 | nbrodin | if(minGPC > 0) { |
141 | 19022 | amunoz | // Obtencion los polinomios de transformaci?n
|
142 | calculatePolinomialCoefs(); |
||
143 | 18530 | nbrodin | // calculo de los resultados
|
144 | calculateRMSerror(); |
||
145 | // Se almacenan los resultados en dataResult
|
||
146 | resultData.setGpcs(gpcs); |
||
147 | 18673 | amunoz | resultData.setPixelToMapCoefX(pixelToMapCoefX); |
148 | resultData.setPixelToMapCoefY(pixelToMapCoefY); |
||
149 | resultData.setMapToPixelCoefX(mapToPixelCoefX); |
||
150 | resultData.setMapToPixelCoefY(mapToPixelCoefY); |
||
151 | 18530 | nbrodin | 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 | 18590 | nbrodin | return;
|
159 | 18530 | nbrodin | } |
160 | 18590 | nbrodin | resultData = null;
|
161 | 18530 | nbrodin | } |
162 | |||
163 | |||
164 | |||
165 | /**
|
||
166 | 19022 | amunoz | * Calculo de los coeficientes de los polinomios de aproximacion.
|
167 | 18530 | nbrodin | * */
|
168 | 19022 | amunoz | public void calculatePolinomialCoefs(){ |
169 | double matrixD[][]= new double [minGPC][minGPC]; |
||
170 | double matrixD2[][]= new double [minGPC][minGPC]; |
||
171 | 18530 | nbrodin | double result[]= new double[minGPC]; |
172 | 18673 | amunoz | double result2[]= new double[minGPC]; |
173 | 19022 | amunoz | double result3[]= new double[minGPC]; |
174 | double result4[]= new double[minGPC]; |
||
175 | 18530 | nbrodin | 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 | 18673 | amunoz | for(int v=0; v<gpcs.length;v++){ |
183 | 19022 | amunoz | 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 | 18673 | amunoz | |
190 | } |
||
191 | 18530 | nbrodin | // 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 | 18673 | amunoz | for(int v=0; v<gpcs.length;v++){ |
198 | 19022 | amunoz | 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 | 18673 | amunoz | * (Math.pow(gpcs[v].pixelPoint.getY(),j)* Math.pow(gpcs[v].pixelPoint.getY(),exp[filas][1]))*gpcs[v].mapPoint.getY(); |
201 | |||
202 | 19022 | amunoz | result2[k]+=(Math.pow(gpcs[v].mapPoint.getX(),i-j)* Math.pow(gpcs[v].mapPoint.getX(),exp[filas][0])) |
203 | 18673 | amunoz | * (Math.pow(gpcs[v].mapPoint.getY(),j)* Math.pow(gpcs[v].mapPoint.getY(),exp[filas][1]))*gpcs[v].pixelPoint.getY(); |
204 | 19022 | amunoz | |
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 | 18673 | amunoz | } |
214 | 18530 | nbrodin | } |
215 | } |
||
216 | } |
||
217 | 20876 | amunoz | |
218 | 19022 | amunoz | Matrix matrixResult= new Matrix(matrixD);
|
219 | Matrix matrixResult2= new Matrix(matrixD2);
|
||
220 | 18788 | amunoz | pixelToMapCoefY=solveSystem(matrixResult,result); |
221 | mapToPixelCoefY= solveSystem(matrixResult2,result2); |
||
222 | 19022 | amunoz | pixelToMapCoefX=solveSystem(matrixResult,result3); |
223 | mapToPixelCoefX= solveSystem(matrixResult2,result4); |
||
224 | 18530 | nbrodin | } |
225 | 18673 | amunoz | |
226 | |||
227 | 18760 | amunoz | |
228 | 18530 | nbrodin | /**
|
229 | * @return array con la solucion al sistema de ecuadiones.
|
||
230 | * */
|
||
231 | 18788 | amunoz | public double[] solveSystem(Matrix matrix, double columResult[]){ |
232 | 18530 | nbrodin | 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 | 20876 | amunoz | Matrix c=null;
|
237 | if(matrix.det()==0.0){ |
||
238 | 20914 | amunoz | // Resolucion del sistema usando la libreria flanagan
|
239 | flanagan.math.Matrix matrixFL= new flanagan.math.Matrix(matrix.getArray());
|
||
240 | xCoef= matrixFL.solveLinearSet(columResult); |
||
241 | 20876 | amunoz | } |
242 | 20914 | amunoz | else{
|
243 | 20876 | amunoz | c= matrix.solve(new Matrix(a));
|
244 | 20914 | amunoz | for (int i=0; i<columResult.length;i++) |
245 | xCoef[i]=c.get(i,0);
|
||
246 | } |
||
247 | 18530 | nbrodin | return xCoef;
|
248 | } |
||
249 | |||
250 | |||
251 | /**
|
||
252 | * @return vector con los RMS
|
||
253 | * */
|
||
254 | 18611 | nbrodin | public void calculateRMSerror() { |
255 | 18774 | amunoz | |
256 | 18530 | nbrodin | int numgpcs= gpcs.length;
|
257 | double rmsxTotal=0; |
||
258 | double rmsyTotal=0; |
||
259 | 18774 | amunoz | rmsTotal=0;
|
260 | 19029 | amunoz | int num=0; |
261 | 18530 | nbrodin | |
262 | 18611 | nbrodin | for(int im_point = 0; im_point < numgpcs; im_point++) { |
263 | 19022 | amunoz | 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 | 19029 | amunoz | num++; |
276 | 19022 | amunoz | } |
277 | 18530 | nbrodin | } |
278 | 18774 | amunoz | |
279 | 19029 | amunoz | this.rmsTotal =Math.sqrt( rmsTotal / num); |
280 | this.rmsXTotal = Math.sqrt(rmsxTotal / num); |
||
281 | this.rmsYTotal = Math.sqrt(rmsyTotal / num); |
||
282 | 18530 | nbrodin | |
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 | 18611 | nbrodin | public double getRMSy() { |
297 | 18530 | nbrodin | return rmsYTotal;
|
298 | } |
||
299 | |||
300 | /**
|
||
301 | 18768 | amunoz | * @return error total
|
302 | 18530 | nbrodin | * */
|
303 | 18611 | nbrodin | public double getRMSTotal() { |
304 | 18530 | nbrodin | return rmsTotal;
|
305 | } |
||
306 | |||
307 | 18611 | nbrodin | /*
|
308 | * (non-Javadoc)
|
||
309 | * @see org.gvsig.gui.beans.incrementabletask.IIncrementable#getTitle()
|
||
310 | */
|
||
311 | 18530 | nbrodin | public String getTitle() { |
312 | 18611 | nbrodin | return RasterToolsUtil.getText(this, "transformacion"); |
313 | 18530 | nbrodin | } |
314 | |||
315 | 18611 | nbrodin | /*
|
316 | * (non-Javadoc)
|
||
317 | * @see org.gvsig.raster.RasterProcess#getLog()
|
||
318 | */
|
||
319 | 18530 | nbrodin | public String getLog() { |
320 | 18611 | nbrodin | return RasterToolsUtil.getText(this, "calculando_transformacion"); |
321 | 18530 | nbrodin | } |
322 | |||
323 | 18611 | nbrodin | /*
|
324 | * (non-Javadoc)
|
||
325 | * @see org.gvsig.gui.beans.incrementabletask.IIncrementable#getPercent()
|
||
326 | */
|
||
327 | 18530 | nbrodin | public int getPercent() { |
328 | return percent;
|
||
329 | } |
||
330 | |||
331 | |||
332 | 18768 | amunoz | |
333 | 18760 | amunoz | /**
|
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 | 20006 | amunoz | //setExpPolinomial();
|
342 | 18760 | amunoz | 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 | 20006 | amunoz | //setExpPolinomial();
|
361 | 18760 | amunoz | 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 | 20006 | amunoz | /*private void setExpPolinomial(){
|
372 | 18760 | amunoz | 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 | 20006 | amunoz | }*/
|
386 | 18760 | amunoz | |
387 | 18530 | nbrodin | } |