1 : /******************************************************************************
2 : *
3 : * Purpose: Implementation of the APMODEL segment and storage objects.
4 : *
5 : ******************************************************************************
6 : * Copyright (c) 2010
7 : * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
8 : *
9 : * Permission is hereby granted, free of charge, to any person obtaining a
10 : * copy of this software and associated documentation files (the "Software"),
11 : * to deal in the Software without restriction, including without limitation
12 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 : * and/or sell copies of the Software, and to permit persons to whom the
14 : * Software is furnished to do so, subject to the following conditions:
15 : *
16 : * The above copyright notice and this permission notice shall be included
17 : * in all copies or substantial portions of the Software.
18 : *
19 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 : * DEALINGS IN THE SOFTWARE.
26 : ****************************************************************************/
27 : #include "pcidsk_airphoto.h"
28 : #include "pcidsk_exception.h"
29 : #include "segment/cpcidskapmodel.h"
30 :
31 : #include <utility>
32 : #include <vector>
33 : #include <cassert>
34 : #include <cstring>
35 :
36 : using namespace PCIDSK;
37 :
38 : /**
39 : * Construct a new PCIDSK Airphoto Model Interior Orientation
40 : * parameters store.
41 : */
42 : PCIDSKAPModelIOParams::PCIDSKAPModelIOParams(std::vector<double> const& imgtofocalx,
43 : std::vector<double> const& imgtofocaly,
44 : std::vector<double> const& focaltocolumn,
45 : std::vector<double> const& focaltorow,
46 : double focal_len,
47 : std::pair<double, double> const& prin_pt,
48 0 : std::vector<double> const& radial_dist) :
49 : imgtofocalx_(imgtofocalx), imgtofocaly_(imgtofocaly), focaltocolumn_(focaltocolumn),
50 : focaltorow_(focaltorow), focal_len_(focal_len), prin_point_(prin_pt),
51 0 : rad_dist_coeff_(radial_dist)
52 : {
53 0 : }
54 :
55 0 : std::vector<double> const& PCIDSKAPModelIOParams::GetImageToFocalPlaneXCoeffs(void) const
56 : {
57 0 : return imgtofocalx_;
58 : }
59 :
60 0 : std::vector<double> const& PCIDSKAPModelIOParams::GetImageToFocalPlaneYCoeffs(void) const
61 : {
62 0 : return imgtofocaly_;
63 : }
64 :
65 0 : std::vector<double> const& PCIDSKAPModelIOParams::GetFocalPlaneToColumnCoeffs(void) const
66 : {
67 0 : return focaltocolumn_;
68 : }
69 :
70 0 : std::vector<double> const& PCIDSKAPModelIOParams::GetFocalPlaneToRowCoeffs(void) const
71 : {
72 0 : return focaltorow_;
73 : }
74 :
75 0 : double PCIDSKAPModelIOParams::GetFocalLength(void) const
76 : {
77 0 : return focal_len_;
78 : }
79 :
80 0 : std::pair<double, double> const& PCIDSKAPModelIOParams::GetPrincipalPoint(void) const
81 : {
82 0 : return prin_point_;
83 : }
84 :
85 0 : std::vector<double> const& PCIDSKAPModelIOParams::GetRadialDistortionCoeffs(void) const
86 : {
87 0 : return rad_dist_coeff_;
88 : }
89 :
90 : /**
91 : * Construct a new PCIDSK Airphoto Model Exterior Orientation parameters
92 : * storage object.
93 : */
94 : PCIDSKAPModelEOParams::PCIDSKAPModelEOParams(std::string const& rotation_type,
95 : std::vector<double> const& earth_to_body,
96 : std::vector<double> const& perspect_cen,
97 0 : unsigned int epsg_code) :
98 : rot_type_(rotation_type), earth_to_body_(earth_to_body),
99 0 : perspective_centre_pos_(perspect_cen), epsg_code_(epsg_code)
100 : {
101 0 : }
102 :
103 0 : std::string PCIDSKAPModelEOParams::GetEarthToBodyRotationType(void) const
104 : {
105 0 : return rot_type_;
106 : }
107 :
108 0 : std::vector<double> const& PCIDSKAPModelEOParams::GetEarthToBodyRotation(void) const
109 : {
110 0 : return earth_to_body_;
111 : }
112 :
113 0 : std::vector<double> const& PCIDSKAPModelEOParams::GetPerspectiveCentrePosition(void) const
114 : {
115 0 : return perspective_centre_pos_;
116 : }
117 :
118 0 : unsigned int PCIDSKAPModelEOParams::GetEPSGCode(void) const
119 : {
120 0 : return epsg_code_;
121 : }
122 :
123 : /**
124 : * Miscellaneous camera parameters for the AP Model
125 : */
126 : PCIDSKAPModelMiscParams::PCIDSKAPModelMiscParams(std::vector<double> const& decentering_coeffs,
127 : std::vector<double> const& x3dcoord,
128 : std::vector<double> const& y3dcoord,
129 : std::vector<double> const& z3dcoord,
130 : double radius,
131 : double rff,
132 : double min_gcp_hgt,
133 : double max_gcp_hgt,
134 : bool is_prin_pt_off,
135 : bool has_dist,
136 : bool has_decent,
137 0 : bool has_radius) :
138 : decentering_coeffs_(decentering_coeffs), x3dcoord_(x3dcoord), y3dcoord_(y3dcoord),
139 : z3dcoord_(z3dcoord), radius_(radius), rff_(rff), min_gcp_hgt_(min_gcp_hgt),
140 : max_gcp_hgt_(max_gcp_hgt), is_prin_pt_off_(is_prin_pt_off),
141 0 : has_dist_(has_dist), has_decent_(has_decent), has_radius_(has_radius)
142 : {
143 0 : }
144 :
145 0 : std::vector<double> const& PCIDSKAPModelMiscParams::GetDecenteringDistortionCoeffs(void) const
146 : {
147 0 : return decentering_coeffs_;
148 : }
149 :
150 0 : std::vector<double> const& PCIDSKAPModelMiscParams::GetX3DCoord(void) const
151 : {
152 0 : return x3dcoord_;
153 : }
154 :
155 0 : std::vector<double> const& PCIDSKAPModelMiscParams::GetY3DCoord(void) const
156 : {
157 0 : return y3dcoord_;
158 : }
159 :
160 0 : std::vector<double> const& PCIDSKAPModelMiscParams::GetZ3DCoord(void) const
161 : {
162 0 : return z3dcoord_;
163 : }
164 :
165 0 : double PCIDSKAPModelMiscParams::GetRadius(void) const
166 : {
167 0 : return radius_;
168 : }
169 :
170 0 : double PCIDSKAPModelMiscParams::GetRFF(void) const
171 : {
172 0 : return rff_;
173 : }
174 :
175 0 : double PCIDSKAPModelMiscParams::GetGCPMinHeight(void) const
176 : {
177 0 : return min_gcp_hgt_;
178 : }
179 :
180 0 : double PCIDSKAPModelMiscParams::GetGCPMaxHeight(void) const
181 : {
182 0 : return max_gcp_hgt_;
183 : }
184 :
185 0 : bool PCIDSKAPModelMiscParams::IsPrincipalPointOffset(void) const
186 : {
187 0 : return is_prin_pt_off_;
188 : }
189 :
190 0 : bool PCIDSKAPModelMiscParams::HasDistortion(void) const
191 : {
192 0 : return has_dist_;
193 : }
194 :
195 0 : bool PCIDSKAPModelMiscParams::HasDecentering(void) const
196 : {
197 0 : return has_decent_;
198 : }
199 :
200 0 : bool PCIDSKAPModelMiscParams::HasRadius(void) const
201 : {
202 0 : return has_radius_;
203 : }
204 :
205 : /**
206 : * Create a new PCIDSK APMODEL segment
207 : */
208 0 : CPCIDSKAPModelSegment::CPCIDSKAPModelSegment(PCIDSKFile *file, int segment, const char *segment_pointer) :
209 0 : CPCIDSKSegment(file, segment, segment_pointer)
210 : {
211 0 : filled_ = false;
212 0 : io_params_ = NULL;
213 0 : eo_params_ = NULL;
214 0 : misc_params_ = NULL;
215 0 : UpdateFromDisk();
216 0 : }
217 :
218 0 : CPCIDSKAPModelSegment::~CPCIDSKAPModelSegment()
219 : {
220 0 : delete io_params_;
221 0 : delete eo_params_;
222 0 : delete misc_params_;
223 0 : }
224 :
225 0 : unsigned int CPCIDSKAPModelSegment::GetWidth(void) const
226 : {
227 0 : if (!filled_) {
228 0 : ThrowPCIDSKException("Failed to determine width from APModel.");
229 : }
230 0 : return width_;
231 : }
232 :
233 0 : unsigned int CPCIDSKAPModelSegment::GetHeight(void) const
234 : {
235 0 : if (!filled_) {
236 0 : ThrowPCIDSKException("Failed to determine height from APModel.");
237 : }
238 0 : return height_;
239 : }
240 :
241 0 : unsigned int CPCIDSKAPModelSegment::GetDownsampleFactor(void) const
242 : {
243 0 : if (!filled_) {
244 0 : ThrowPCIDSKException("Failed to determine APModel downsample factor.");
245 : }
246 0 : return downsample_;
247 : }
248 :
249 : // Interior Orientation Parameters
250 0 : PCIDSKAPModelIOParams const& CPCIDSKAPModelSegment::GetInteriorOrientationParams(void) const
251 : {
252 0 : if (io_params_ == NULL) {
253 0 : ThrowPCIDSKException("There was a failure in reading the APModel IO params.");
254 : }
255 0 : return *io_params_;
256 : }
257 :
258 : // Exterior Orientation Parameters
259 0 : PCIDSKAPModelEOParams const& CPCIDSKAPModelSegment::GetExteriorOrientationParams(void) const
260 : {
261 0 : if (eo_params_ == NULL) {
262 0 : ThrowPCIDSKException("There was a failure in reading the APModel EO params.");
263 : }
264 0 : return *eo_params_;
265 : }
266 :
267 0 : PCIDSKAPModelMiscParams const& CPCIDSKAPModelSegment::GetAdditionalParams(void) const
268 : {
269 0 : if (misc_params_ == NULL) {
270 0 : ThrowPCIDSKException("There was a failure in reading the APModel camera params.");
271 : }
272 0 : return *misc_params_;
273 : }
274 :
275 0 : std::string CPCIDSKAPModelSegment::GetMapUnitsString(void) const
276 : {
277 0 : return map_units_;
278 : }
279 :
280 0 : std::string CPCIDSKAPModelSegment::GetUTMUnitsString(void) const
281 : {
282 0 : return map_units_;
283 : }
284 :
285 0 : std::vector<double> const& CPCIDSKAPModelSegment::GetProjParams(void) const
286 : {
287 0 : return proj_parms_;
288 : }
289 :
290 : /************************************************************************/
291 : /* BinaryToAPInfo() */
292 : /************************************************************************/
293 : /**
294 : * Convert the contents of the PCIDSKBuffer buf to a set of APModel
295 : * params
296 : *
297 : * @param buf A reference pointer to a PCIDSKBuffer
298 : * @param eo_params A pointer to EO params to be populated
299 : * @param io_params A pointer to IO params to be populated
300 : * @param misc_params A pointer to camera params to be populated
301 : * @param pixels The number of pixels in the image
302 : * @param lines The number of lines in the image
303 : * @param downsample The downsampling factor applied
304 : * @param map_units the map units/geosys string
305 : * @param utm_units the UTM units string
306 : */
307 : namespace {
308 : void BinaryToAPInfo(PCIDSKBuffer& buf,
309 : PCIDSKAPModelEOParams*& eo_params,
310 : PCIDSKAPModelIOParams*& io_params,
311 : PCIDSKAPModelMiscParams*& misc_params,
312 : unsigned int& pixels,
313 : unsigned int& lines,
314 : unsigned int& downsample,
315 : std::string& map_units,
316 : std::vector<double>& proj_parms,
317 0 : std::string& utm_units)
318 :
319 : {
320 0 : proj_parms.clear();
321 0 : map_units.clear();
322 0 : utm_units.clear();
323 : /* -------------------------------------------------------------------- */
324 : /* Read the header block */
325 : /* -------------------------------------------------------------------- */
326 :
327 0 : if(strncmp(buf.buffer,"APMODEL ",8))
328 : {
329 0 : std::string magic(buf.buffer, 8);
330 : ThrowPCIDSKException("Bad segment magic found. Found: [%s] expecting [APMODEL ]",
331 0 : magic.c_str());
332 : }
333 :
334 : /* -------------------------------------------------------------------- */
335 : /* Allocate the APModel. */
336 : /* -------------------------------------------------------------------- */
337 :
338 0 : if (!strncmp(&buf.buffer[22],"DS",2))
339 0 : downsample = buf.GetInt(22, 3);
340 :
341 : /* -------------------------------------------------------------------- */
342 : /* Read the values */
343 : /* -------------------------------------------------------------------- */
344 0 : pixels = buf.GetInt(0 * 22 + 512, 22);
345 0 : lines = buf.GetInt(1 * 22 + 512, 22);
346 0 : double focal_length = buf.GetDouble(2 * 22 + 512, 22);
347 0 : std::vector<double> perspective_centre(3);
348 0 : perspective_centre[0] = buf.GetDouble(3 * 22 + 512, 22);
349 0 : perspective_centre[1] = buf.GetDouble(4 * 22 + 512, 22);
350 0 : perspective_centre[2] = buf.GetDouble(5 * 22 + 512, 22);
351 :
352 0 : std::vector<double> earth_to_body(3);
353 0 : earth_to_body[0] = buf.GetDouble(6 * 22 + 512, 22);
354 0 : earth_to_body[1] = buf.GetDouble(7 * 22 + 512, 22);
355 0 : earth_to_body[2] = buf.GetDouble(8 * 22 + 512, 22);
356 :
357 : // NOTE: PCIDSK itself doesn't support storing information
358 : // about the rotation type, nor the EPSG code for the
359 : // transformation. However, in the (not so distant)
360 : // future, we will likely want to add this support to
361 : // the APMODEL segment (or perhaps a future means of
362 : // storing airphoto information).
363 : eo_params = new PCIDSKAPModelEOParams("",
364 : earth_to_body,
365 : perspective_centre,
366 0 : -1);
367 :
368 0 : std::vector<double> x3d(3);
369 0 : std::vector<double> y3d(3);
370 0 : std::vector<double> z3d(3);
371 :
372 0 : x3d[0] = buf.GetDouble(9 * 22 + 512, 22);
373 0 : x3d[1] = buf.GetDouble(10 * 22 + 512, 22);
374 0 : x3d[2] = buf.GetDouble(11 * 22 + 512, 22);
375 0 : y3d[0] = buf.GetDouble(12 * 22 + 512, 22);
376 0 : y3d[1] = buf.GetDouble(13 * 22 + 512, 22);
377 0 : y3d[2] = buf.GetDouble(14 * 22 + 512, 22);
378 0 : z3d[0] = buf.GetDouble(15 * 22 + 512, 22);
379 0 : z3d[1] = buf.GetDouble(16 * 22 + 512, 22);
380 0 : z3d[2] = buf.GetDouble(17 * 22 + 512, 22);
381 :
382 0 : std::vector<double> img_to_focal_plane_x(4);
383 0 : std::vector<double> img_to_focal_plane_y(4);
384 0 : img_to_focal_plane_x[0] = buf.GetDouble(18 * 22 + 512, 22);
385 0 : img_to_focal_plane_x[1] = buf.GetDouble(19 * 22 + 512, 22);
386 0 : img_to_focal_plane_x[2] = buf.GetDouble(20 * 22 + 512, 22);
387 0 : img_to_focal_plane_x[3] = buf.GetDouble(21 * 22 + 512, 22);
388 :
389 0 : img_to_focal_plane_y[0] = buf.GetDouble(0 * 22 + 512 * 2, 22);
390 0 : img_to_focal_plane_y[1] = buf.GetDouble(1 * 22 + 512 * 2, 22);
391 0 : img_to_focal_plane_y[2] = buf.GetDouble(2 * 22 + 512 * 2, 22);
392 0 : img_to_focal_plane_y[3] = buf.GetDouble(3 * 22 + 512 * 2, 22);
393 :
394 0 : std::vector<double> focal_to_cols(4);
395 0 : std::vector<double> focal_to_lines(4);
396 0 : focal_to_cols[0] = buf.GetDouble(4 * 22 + 512 * 2, 22);
397 0 : focal_to_cols[1] = buf.GetDouble(5 * 22 + 512 * 2, 22);
398 0 : focal_to_cols[2] = buf.GetDouble(6 * 22 + 512 * 2, 22);
399 0 : focal_to_cols[3] = buf.GetDouble(7 * 22 + 512 * 2, 22);
400 :
401 0 : focal_to_lines[0] = buf.GetDouble(8 * 22 + 512 * 2, 22);
402 0 : focal_to_lines[1] = buf.GetDouble(9 * 22 + 512 * 2, 22);
403 0 : focal_to_lines[2] = buf.GetDouble(10 * 22 + 512 * 2, 22);
404 0 : focal_to_lines[3] = buf.GetDouble(11 * 22 + 512 * 2, 22);
405 :
406 0 : std::pair<double, double> principal_point;
407 :
408 0 : principal_point.first = buf.GetDouble(12 * 22 + 512 * 2, 22);
409 0 : principal_point.second = buf.GetDouble(13 * 22 + 512 * 2, 22);
410 :
411 0 : std::vector<double> radial_distortion(8);
412 0 : radial_distortion[0] = buf.GetDouble(14 * 22 + 512 * 2, 22);
413 0 : radial_distortion[1] = buf.GetDouble(15 * 22 + 512 * 2, 22);
414 0 : radial_distortion[2] = buf.GetDouble(16 * 22 + 512 * 2, 22);
415 0 : radial_distortion[3] = buf.GetDouble(17 * 22 + 512 * 2, 22);
416 0 : radial_distortion[4] = buf.GetDouble(18 * 22 + 512 * 2, 22);
417 0 : radial_distortion[5] = buf.GetDouble(19 * 22 + 512 * 2, 22);
418 0 : radial_distortion[6] = buf.GetDouble(20 * 22 + 512 * 2, 22);
419 0 : radial_distortion[7] = buf.GetDouble(21 * 22 + 512 * 2, 22);
420 :
421 : // We have enough information now to construct the interior
422 : // orientation parameters
423 : io_params = new PCIDSKAPModelIOParams(img_to_focal_plane_x,
424 : img_to_focal_plane_y,
425 : focal_to_cols,
426 : focal_to_lines,
427 : focal_length,
428 : principal_point,
429 0 : radial_distortion);
430 :
431 0 : std::vector<double> decentering(4);
432 0 : decentering[0] = buf.GetDouble(0 * 22 + 512 * 3, 22);
433 0 : decentering[1] = buf.GetDouble(1 * 22 + 512 * 3, 22);
434 0 : decentering[2] = buf.GetDouble(2 * 22 + 512 * 3, 22);
435 0 : decentering[3] = buf.GetDouble(3 * 22 + 512 * 3, 22);
436 :
437 0 : double radius = buf.GetDouble(4 * 22 + 512 * 3, 22);
438 0 : double rff = buf.GetDouble(5 * 22 + 512 * 3, 22);
439 0 : double gcp_min_height = buf.GetDouble(6 * 22 + 512 * 3, 22);
440 0 : double gcp_max_height = buf.GetDouble(7 * 22 + 512 * 3, 22);
441 0 : bool prin_off = buf.GetInt(8 * 22 + 512 * 3, 22) != 0;
442 0 : bool distort_true = buf.GetInt(9 * 22 + 512 * 3, 22) != 0;
443 0 : bool has_decentering = buf.GetInt(10 * 22 + 512 * 3, 22) != 0;
444 0 : bool has_radius = buf.GetInt(11 * 22 + 512 * 3, 22) != 0;
445 :
446 : // Fill in the camera parameters
447 : misc_params = new PCIDSKAPModelMiscParams(decentering,
448 : x3d,
449 : y3d,
450 : z3d,
451 : radius,
452 : rff,
453 : gcp_min_height,
454 : gcp_max_height,
455 : prin_off,
456 : distort_true,
457 : has_decentering,
458 0 : has_radius);
459 :
460 :
461 : /* -------------------------------------------------------------------- */
462 : /* Read the projection required */
463 : /* -------------------------------------------------------------------- */
464 0 : buf.Get(512 * 4, 16, map_units);
465 :
466 0 : if (!strncmp(buf.Get(512 * 4 + 16, 3), "UTM", 3))
467 : {
468 0 : buf.Get(512 * 4, 3, utm_units);
469 0 : }
470 :
471 : //ProjParms2Info(szTmp, APModel->sProjection);
472 : // Parse the Proj Params
473 :
474 0 : }
475 : } // end anonymous namespace
476 :
477 0 : void CPCIDSKAPModelSegment::UpdateFromDisk(void)
478 : {
479 0 : if (filled_) {
480 0 : return;
481 : }
482 :
483 : // Start reading in the APModel segment. APModel segments should be
484 : // 7 blocks long.
485 0 : if (data_size < (1024 + 7 * 512)) {
486 : ThrowPCIDSKException("APMODEL segment is smaller than expected. A "
487 0 : "segment of size %d was found", data_size);
488 : }
489 0 : buf.SetSize(data_size - 1024);
490 0 : ReadFromFile(buf.buffer, 0, data_size - 1024);
491 :
492 : // Expand it using an analogue to a method pulled from GDB
493 : BinaryToAPInfo(buf,
494 : eo_params_,
495 : io_params_,
496 : misc_params_,
497 : width_,
498 : height_,
499 : downsample_,
500 : map_units_,
501 : proj_parms_,
502 0 : utm_units_);
503 :
504 : // Done, mark ourselves as having been properly filled
505 0 : filled_ = true;
506 : }
|