Line data Source code
1 : /******************************************************************************
2 : * $Id$
3 : *
4 : * Project: libgeotiff
5 : * Purpose: Code to abstract translation between pixel/line and PCS
6 : * coordinates.
7 : * Author: Frank Warmerdam, warmerda@home.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 1999, Frank Warmerdam
11 : *
12 : * SPDX-License-Identifier: MIT
13 : *****************************************************************************/
14 :
15 : #include <math.h>
16 : #include <stddef.h>
17 :
18 : #include "geotiff.h"
19 : #include "geo_tiffp.h" /* external TIFF interface */
20 : #include "geo_keyp.h" /* private interface */
21 : #include "geokeys.h"
22 :
23 : /************************************************************************/
24 : /* inv_geotransform() */
25 : /* */
26 : /* Invert a 6 term geotransform style matrix. */
27 : /************************************************************************/
28 :
29 0 : static int inv_geotransform( double *gt_in, double *gt_out )
30 :
31 : {
32 : /* we assume a 3rd row that is [0 0 1] */
33 :
34 : /* Compute determinate */
35 :
36 0 : const double det = gt_in[0] * gt_in[4] - gt_in[1] * gt_in[3];
37 :
38 0 : if( fabs(det) < 0.000000000000001 )
39 0 : return 0;
40 :
41 0 : const double inv_det = 1.0 / det;
42 :
43 : /* compute adjoint, and divide by determinate */
44 :
45 0 : gt_out[0] = gt_in[4] * inv_det;
46 0 : gt_out[3] = -gt_in[3] * inv_det;
47 :
48 0 : gt_out[1] = -gt_in[1] * inv_det;
49 0 : gt_out[4] = gt_in[0] * inv_det;
50 :
51 0 : gt_out[2] = ( gt_in[1] * gt_in[5] - gt_in[2] * gt_in[4]) * inv_det;
52 0 : gt_out[5] = (-gt_in[0] * gt_in[5] + gt_in[2] * gt_in[3]) * inv_det;
53 :
54 0 : return 1;
55 : }
56 :
57 : /************************************************************************/
58 : /* GTIFTiepointTranslate() */
59 : /************************************************************************/
60 :
61 : static
62 0 : int GTIFTiepointTranslate( int gcp_count, double * gcps_in, double * gcps_out,
63 : double x_in, double y_in,
64 : double *x_out, double *y_out )
65 :
66 : {
67 : (void) gcp_count;
68 : (void) gcps_in;
69 : (void) gcps_out;
70 : (void) x_in;
71 : (void) y_in;
72 : (void) x_out;
73 : (void) y_out;
74 :
75 : /* I would appreciate a _brief_ block of code for doing second order
76 : polynomial regression here! */
77 0 : return FALSE;
78 : }
79 :
80 :
81 : /************************************************************************/
82 : /* GTIFImageToPCS() */
83 : /************************************************************************/
84 :
85 : /**
86 : * Translate a pixel/line coordinate to projection coordinates.
87 : *
88 : * At this time this function does not support image to PCS translations for
89 : * tiepoints-only definitions, only pixelscale and transformation matrix
90 : * formulations.
91 : *
92 : * @param gtif The handle from GTIFNew() indicating the target file.
93 : * @param x A pointer to the double containing the pixel offset on input,
94 : * and into which the easting/longitude will be put on completion.
95 : * @param y A pointer to the double containing the line offset on input,
96 : * and into which the northing/latitude will be put on completion.
97 : *
98 : * @return TRUE if the transformation succeeds, or FALSE if it fails. It may
99 : * fail if the file doesn't have properly setup transformation information,
100 : * or it is in a form unsupported by this function.
101 : */
102 :
103 0 : int GTIFImageToPCS( GTIF *gtif, double *x, double *y )
104 :
105 : {
106 0 : tiff_t *tif=gtif->gt_tif;
107 :
108 : int tiepoint_count;
109 0 : double *tiepoints = 0;
110 0 : if (!(gtif->gt_methods.get)(tif, GTIFF_TIEPOINTS,
111 : &tiepoint_count, &tiepoints ))
112 0 : tiepoint_count = 0;
113 :
114 : int count;
115 0 : double *pixel_scale = 0;
116 0 : if (!(gtif->gt_methods.get)(tif, GTIFF_PIXELSCALE, &count, &pixel_scale ))
117 0 : count = 0;
118 :
119 : int transform_count;
120 0 : double *transform = 0;
121 0 : if (!(gtif->gt_methods.get)(tif, GTIFF_TRANSMATRIX,
122 : &transform_count, &transform ))
123 0 : transform_count = 0;
124 :
125 : /* -------------------------------------------------------------------- */
126 : /* If the pixelscale count is zero, but we have tiepoints use */
127 : /* the tiepoint based approach. */
128 : /* -------------------------------------------------------------------- */
129 0 : int res = FALSE;
130 0 : if( tiepoint_count > 6 && count == 0 )
131 : {
132 0 : res = GTIFTiepointTranslate( tiepoint_count / 6,
133 : tiepoints, tiepoints + 3,
134 : *x, *y, x, y );
135 : }
136 :
137 : /* -------------------------------------------------------------------- */
138 : /* If we have a transformation matrix, use it. */
139 : /* -------------------------------------------------------------------- */
140 0 : else if( transform_count == 16 )
141 : {
142 0 : const double x_in = *x;
143 0 : const double y_in = *y;
144 :
145 0 : *x = x_in * transform[0] + y_in * transform[1] + transform[3];
146 0 : *y = x_in * transform[4] + y_in * transform[5] + transform[7];
147 :
148 0 : res = TRUE;
149 : }
150 :
151 : /* -------------------------------------------------------------------- */
152 : /* For now we require one tie point, and a valid pixel scale. */
153 : /* -------------------------------------------------------------------- */
154 0 : else if( count < 3 || tiepoint_count < 6 )
155 : {
156 0 : res = FALSE;
157 : }
158 :
159 : else
160 : {
161 0 : *x = (*x - tiepoints[0]) * pixel_scale[0] + tiepoints[3];
162 0 : *y = (*y - tiepoints[1]) * (-1 * pixel_scale[1]) + tiepoints[4];
163 :
164 0 : res = TRUE;
165 : }
166 :
167 : /* -------------------------------------------------------------------- */
168 : /* Cleanup */
169 : /* -------------------------------------------------------------------- */
170 0 : if(tiepoints)
171 0 : _GTIFFree(tiepoints);
172 0 : if(pixel_scale)
173 0 : _GTIFFree(pixel_scale);
174 0 : if(transform)
175 0 : _GTIFFree(transform);
176 :
177 0 : return res;
178 : }
179 :
180 : /************************************************************************/
181 : /* GTIFPCSToImage() */
182 : /************************************************************************/
183 :
184 : /**
185 : * Translate a projection coordinate to pixel/line coordinates.
186 : *
187 : * At this time this function does not support PCS to image translations for
188 : * tiepoints-only based definitions, only matrix and pixelscale/tiepoints
189 : * formulations are supposed.
190 : *
191 : * @param gtif The handle from GTIFNew() indicating the target file.
192 : * @param x A pointer to the double containing the pixel offset on input,
193 : * and into which the easting/longitude will be put on completion.
194 : * @param y A pointer to the double containing the line offset on input,
195 : * and into which the northing/latitude will be put on completion.
196 : *
197 : * @return TRUE if the transformation succeeds, or FALSE if it fails. It may
198 : * fail if the file doesn't have properly setup transformation information,
199 : * or it is in a form unsupported by this function.
200 : */
201 :
202 0 : int GTIFPCSToImage( GTIF *gtif, double *x, double *y )
203 :
204 : {
205 0 : tiff_t *tif=gtif->gt_tif;
206 0 : int result = FALSE;
207 :
208 : /* -------------------------------------------------------------------- */
209 : /* Fetch tiepoints and pixel scale. */
210 : /* -------------------------------------------------------------------- */
211 0 : double *tiepoints = NULL;
212 : int tiepoint_count;
213 0 : if (!(gtif->gt_methods.get)(tif, GTIFF_TIEPOINTS,
214 : &tiepoint_count, &tiepoints ))
215 0 : tiepoint_count = 0;
216 :
217 : int count;
218 0 : double *pixel_scale = NULL;
219 0 : if (!(gtif->gt_methods.get)(tif, GTIFF_PIXELSCALE, &count, &pixel_scale ))
220 0 : count = 0;
221 :
222 0 : int transform_count = 0;
223 0 : double *transform = NULL;
224 0 : if (!(gtif->gt_methods.get)(tif, GTIFF_TRANSMATRIX,
225 : &transform_count, &transform ))
226 0 : transform_count = 0;
227 :
228 : /* -------------------------------------------------------------------- */
229 : /* If the pixelscale count is zero, but we have tiepoints use */
230 : /* the tiepoint based approach. */
231 : /* -------------------------------------------------------------------- */
232 0 : if( tiepoint_count > 6 && count == 0 )
233 : {
234 0 : result = GTIFTiepointTranslate( tiepoint_count / 6,
235 : tiepoints + 3, tiepoints,
236 : *x, *y, x, y );
237 : }
238 :
239 : /* -------------------------------------------------------------------- */
240 : /* Handle matrix - convert to "geotransform" format, invert and */
241 : /* apply. */
242 : /* -------------------------------------------------------------------- */
243 0 : else if( transform_count == 16 )
244 : {
245 0 : const double x_in = *x;
246 0 : const double y_in = *y;
247 : double gt_in[6];
248 0 : gt_in[0] = transform[0];
249 0 : gt_in[1] = transform[1];
250 0 : gt_in[2] = transform[3];
251 0 : gt_in[3] = transform[4];
252 0 : gt_in[4] = transform[5];
253 0 : gt_in[5] = transform[7];
254 :
255 : double gt_out[6];
256 0 : if( !inv_geotransform( gt_in, gt_out ) )
257 0 : result = FALSE;
258 : else
259 : {
260 0 : *x = x_in * gt_out[0] + y_in * gt_out[1] + gt_out[2];
261 0 : *y = x_in * gt_out[3] + y_in * gt_out[4] + gt_out[5];
262 :
263 0 : result = TRUE;
264 : }
265 : }
266 :
267 : /* -------------------------------------------------------------------- */
268 : /* For now we require one tie point, and a valid pixel scale. */
269 : /* -------------------------------------------------------------------- */
270 0 : else if( count >= 3 && tiepoint_count >= 6 )
271 : {
272 0 : *x = (*x - tiepoints[3]) / pixel_scale[0] + tiepoints[0];
273 0 : *y = (*y - tiepoints[4]) / (-1 * pixel_scale[1]) + tiepoints[1];
274 :
275 0 : result = TRUE;
276 : }
277 :
278 : /* -------------------------------------------------------------------- */
279 : /* Cleanup. */
280 : /* -------------------------------------------------------------------- */
281 0 : if(tiepoints)
282 0 : _GTIFFree(tiepoints);
283 0 : if(pixel_scale)
284 0 : _GTIFFree(pixel_scale);
285 0 : if(transform)
286 0 : _GTIFFree(transform);
287 :
288 0 : return result;
289 : }
|