1 : /******************************************************************************
2 : *
3 : * Purpose: Implementation of the CPCIDSKRPCModelSegment class.
4 : *
5 : ******************************************************************************
6 : * Copyright (c) 2009
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 :
28 : #include "pcidsk_rpc.h"
29 : #include "segment/cpcidsksegment.h"
30 : #include "core/pcidsk_utils.h"
31 : #include "pcidsk_exception.h"
32 : #include "segment/cpcidskrpcmodel.h"
33 :
34 : #include <vector>
35 : #include <string>
36 : #include <cassert>
37 : #include <cstring>
38 :
39 : using namespace PCIDSK;
40 :
41 : // Struct to store details of the RPC model
42 : struct CPCIDSKRPCModelSegment::PCIDSKRPCInfo
43 0 : {
44 : bool userrpc; // whether or not the RPC was generated from GCPs
45 : bool adjusted; // Whether or not the RPC has been adjusted
46 : int downsample; // Epipolar Downsample factor
47 :
48 : unsigned int pixels; // pixels in the image
49 : unsigned int lines; // lines in the image
50 :
51 : unsigned int num_coeffs; // number of coefficientsg
52 :
53 : std::vector<double> pixel_num; // numerator, pixel direction
54 : std::vector<double> pixel_denom; // denominator, pixel direction
55 : std::vector<double> line_num; // numerator, line direction
56 : std::vector<double> line_denom; // denominator, line direction
57 :
58 : // Scale/offset coefficients in the ground domain
59 : double x_off;
60 : double x_scale;
61 :
62 : double y_off;
63 : double y_scale;
64 :
65 : double z_off;
66 : double z_scale;
67 :
68 : // Scale/offset coefficients in the raster domain
69 : double pix_off;
70 : double pix_scale;
71 :
72 : double line_off;
73 : double line_scale;
74 :
75 : std::vector<double> x_adj; // adjusted X values
76 : std::vector<double> y_adj; // adjusted Y values
77 :
78 : std::string sensor_name; // the name of the sensor
79 :
80 : std::string map_units; // the map units string
81 :
82 : // TODO: Projection Info
83 :
84 : // The raw segment data
85 : PCIDSKBuffer seg_data;
86 : };
87 :
88 0 : CPCIDSKRPCModelSegment::CPCIDSKRPCModelSegment(PCIDSKFile *file, int segment,const char *segment_pointer) :
89 : CPCIDSKSegment(file, segment, segment_pointer), pimpl_(new CPCIDSKRPCModelSegment::PCIDSKRPCInfo),
90 0 : loaded_(false),mbModified(false)
91 : {
92 0 : Load();
93 0 : }
94 :
95 :
96 0 : CPCIDSKRPCModelSegment::~CPCIDSKRPCModelSegment()
97 : {
98 0 : delete pimpl_;
99 0 : }
100 :
101 : // Load the contents of the segment
102 0 : void CPCIDSKRPCModelSegment::Load()
103 : {
104 : // Check if we've already loaded the segment into memory
105 0 : if (loaded_) {
106 0 : return;
107 : }
108 :
109 0 : assert(data_size - 1024 == 7 * 512);
110 :
111 0 : pimpl_->seg_data.SetSize((int) (data_size - 1024)); // should be 7 * 512
112 :
113 0 : ReadFromFile(pimpl_->seg_data.buffer, 0, data_size - 1024);
114 :
115 : // The RPC Model Segment is defined as follows:
116 : // RFMODEL Segment: 7 512-byte blocks
117 :
118 : // Block 1:
119 : // Bytes 0-7: 'RFMODEL '
120 : // Byte 8: User Provided RPC (1: user-provided, 0: computed from GCPs)
121 : // Bytes 22-23: 'DS'
122 : // Bytes 24-26: Downsample factor used during Epipolar Generation
123 : // Bytes 27-29: '2ND' -- no clue what this means
124 : // Bytes 30-35: 'SENSOR'
125 : // Bytes 36: Sensor Name (NULL terminated)
126 :
127 0 : if (std::strncmp(pimpl_->seg_data.buffer, "RFMODEL ", 8))
128 : {
129 0 : pimpl_->seg_data.Put("RFMODEL",0,8);
130 0 : pimpl_->userrpc = false;
131 0 : pimpl_->adjusted = false;
132 0 : pimpl_->seg_data.Put("DS",22,2);
133 0 : pimpl_->downsample = 1;
134 0 : pimpl_->seg_data.Put("SENSOR",30,6);
135 0 : pimpl_->num_coeffs = 20;
136 0 : loaded_ = true;
137 0 : return;
138 : // Something has gone terribly wrong!
139 : /*throw PCIDSKException("A segment that was previously identified as an RFMODEL "
140 : "segment does not contain the appropriate data. Found: [%s]",
141 : std::string(pimpl_->seg_data.buffer, 8).c_str());*/
142 : }
143 :
144 : // Determine if this is user-provided
145 0 : pimpl_->userrpc = pimpl_->seg_data.buffer[8] == '1' ? true : false;
146 :
147 : // Check for the DS characters
148 0 : pimpl_->downsample = 1;
149 0 : if (!std::strncmp(&pimpl_->seg_data.buffer[22], "DS", 2))
150 : {
151 : // Read the downsample factor
152 0 : pimpl_->downsample = pimpl_->seg_data.GetInt(24, 3);
153 : }
154 :
155 : //This is requiered if writting with PCIDSKIO
156 : //and reading with GDBIO (probably because of legacy issue)
157 : // see Bugzilla 255 and 254.
158 0 : bool bSecond = false;
159 0 : if (!std::strncmp(&pimpl_->seg_data.buffer[27], "2ND", 3))
160 : {
161 0 : bSecond = true;
162 : }
163 :
164 : // Sensor name:
165 0 : if (!std::strncmp(&pimpl_->seg_data.buffer[30], "SENSOR", 6)) {
166 0 : pimpl_->sensor_name = std::string(&pimpl_->seg_data.buffer[36]);
167 : } else {
168 0 : pimpl_->sensor_name = "";
169 : }
170 :
171 : // Block 2:
172 : // Bytes 0-3: Number of coefficients
173 : // Bytes 4-13: Number of pixels
174 : // Bytes 14-23: Number of lines
175 : // Bytes 24-45: Longitude offset
176 : // Bytes 46-67: Longitude scale
177 : // Bytes 68-89: Latitude Offset
178 : // Bytes 90-111: Latitude Scale
179 : // Bytes 112-133: Height offset
180 : // Bytes 134-155: Height scale
181 : // Bytes 156-177: Sample offset
182 : // Bytes 178-199: Sample scale
183 : // Bytes 200-221: Line offset
184 : // Bytes 222-243: line scale
185 : // Bytes 244-375: Adjusted X coefficients (5 * 22 bytes)
186 : // Bytes 376-507: Adjusted Y coefficients (5 * 22 bytes)
187 : // if bSecond is false, then the coefficient are stored
188 : // at others positions
189 : // every value takes 22 bytes.
190 :
191 0 : if(bSecond)
192 : {
193 0 : pimpl_->num_coeffs = pimpl_->seg_data.GetInt(512, 4);
194 :
195 0 : if (pimpl_->num_coeffs * 22 > 512) {
196 : // this segment is malformed. Throw an exception.
197 : throw PCIDSKException("RFMODEL segment coefficient count requires more "
198 : "than one block to store. There is an error in this segment. The "
199 0 : "number of coefficients according to the segment is %d.", pimpl_->num_coeffs);
200 : }
201 :
202 0 : pimpl_->lines = pimpl_->seg_data.GetInt(512 + 4, 10);
203 0 : pimpl_->pixels = pimpl_->seg_data.GetInt(512 + 14, 10);
204 0 : pimpl_->x_off = pimpl_->seg_data.GetDouble(512 + 24, 22);
205 0 : pimpl_->x_scale = pimpl_->seg_data.GetDouble(512 + 46, 22);
206 0 : pimpl_->y_off = pimpl_->seg_data.GetDouble(512 + 68, 22);
207 0 : pimpl_->y_scale = pimpl_->seg_data.GetDouble(512 + 90, 22);
208 0 : pimpl_->z_off = pimpl_->seg_data.GetDouble(512 + 112, 22);
209 0 : pimpl_->z_scale = pimpl_->seg_data.GetDouble(512 + 134, 22);
210 0 : pimpl_->pix_off = pimpl_->seg_data.GetDouble(512 + 156, 22);
211 0 : pimpl_->pix_scale = pimpl_->seg_data.GetDouble(512 + 178, 22);
212 0 : pimpl_->line_off = pimpl_->seg_data.GetDouble(512 + 200, 22);
213 0 : pimpl_->line_scale = pimpl_->seg_data.GetDouble(512 + 222, 22);
214 :
215 0 : pimpl_->adjusted = false;
216 : // Read in adjusted X coefficients
217 0 : for (unsigned int i = 0; i <= 5; i++)
218 : {
219 0 : double tmp = pimpl_->seg_data.GetDouble(512 + 244 + (i * 22), 22);
220 0 : pimpl_->x_adj.push_back(tmp);
221 0 : if (0.0 != tmp)
222 : {
223 0 : pimpl_->adjusted = true;
224 : }
225 : }
226 :
227 : // Read in adjusted Y coefficients
228 0 : for (unsigned int i = 0; i <= 5; i++)
229 : {
230 0 : double tmp = pimpl_->seg_data.GetDouble(512 + 376 + (i * 22), 22);
231 0 : pimpl_->y_adj.push_back(tmp);
232 0 : if (0.0 != tmp)
233 : {
234 0 : pimpl_->adjusted = true;
235 : }
236 : }
237 : }
238 : else
239 : {
240 0 : pimpl_->num_coeffs = pimpl_->seg_data.GetInt(512, 22);
241 :
242 0 : if (pimpl_->num_coeffs * 22 > 512) {
243 : // this segment is malformed. Throw an exception.
244 : throw PCIDSKException("RFMODEL segment coefficient count requires more "
245 : "than one block to store. There is an error in this segment. The "
246 0 : "number of coefficients according to the segment is %d.", pimpl_->num_coeffs);
247 : }
248 :
249 0 : pimpl_->lines = pimpl_->seg_data.GetInt(512 + 22, 22);
250 0 : pimpl_->pixels = pimpl_->seg_data.GetInt(512 + 2*22,22);
251 0 : pimpl_->x_off = pimpl_->seg_data.GetDouble(512 + 3*22, 22);
252 0 : pimpl_->x_scale = pimpl_->seg_data.GetDouble(512 + 4*22, 22);
253 0 : pimpl_->y_off = pimpl_->seg_data.GetDouble(512 + 5*22, 22);
254 0 : pimpl_->y_scale = pimpl_->seg_data.GetDouble(512 + 6*22, 22);
255 0 : pimpl_->z_off = pimpl_->seg_data.GetDouble(512 + 7*22, 22);
256 0 : pimpl_->z_scale = pimpl_->seg_data.GetDouble(512 + 8*22, 22);
257 0 : pimpl_->pix_off = pimpl_->seg_data.GetDouble(512 + 9*22, 22);
258 0 : pimpl_->pix_scale = pimpl_->seg_data.GetDouble(512 + 10*22, 22);
259 0 : pimpl_->line_off = pimpl_->seg_data.GetDouble(512 + 11*22, 22);
260 0 : pimpl_->line_scale = pimpl_->seg_data.GetDouble(512 + 12*22, 22);
261 :
262 0 : pimpl_->adjusted = false;
263 : // Read in adjusted X coefficients
264 0 : for (unsigned int i = 0; i <= 3; i++)
265 : {
266 0 : double tmp = pimpl_->seg_data.GetDouble(512 + 12*22 + (i * 22), 22);
267 0 : pimpl_->x_adj.push_back(tmp);
268 0 : if (0.0 != tmp)
269 : {
270 0 : pimpl_->adjusted = true;
271 : }
272 : }
273 0 : pimpl_->x_adj.push_back(0.0);
274 0 : pimpl_->x_adj.push_back(0.0);
275 0 : pimpl_->x_adj.push_back(0.0);
276 :
277 : // Read in adjusted Y coefficients
278 0 : for (unsigned int i = 0; i <= 3; i++)
279 : {
280 0 : double tmp = pimpl_->seg_data.GetDouble(512 + 16*22 + (i * 22), 22);
281 0 : pimpl_->y_adj.push_back(tmp);
282 0 : if (0.0 != tmp)
283 : {
284 0 : pimpl_->adjusted = true;
285 : }
286 : }
287 0 : pimpl_->y_adj.push_back(0.0);
288 0 : pimpl_->y_adj.push_back(0.0);
289 0 : pimpl_->y_adj.push_back(0.0);
290 : }
291 :
292 : // Block 3:
293 : // Block 3 contains the numerator coefficients for the pixel rational polynomial
294 : // Number of Coefficients * 22 bytes
295 0 : for (unsigned int i = 0; i < pimpl_->num_coeffs; i++) {
296 0 : pimpl_->pixel_num.push_back(pimpl_->seg_data.GetDouble(2 * 512 + (i * 22), 22));
297 : }
298 :
299 : // Block 4:
300 : // Block 4 contains the denominator coefficients for the pixel rational polynomial
301 : // Number of Coefficients * 22 bytes
302 0 : for (unsigned int i = 0; i < pimpl_->num_coeffs; i++) {
303 0 : pimpl_->pixel_denom.push_back(pimpl_->seg_data.GetDouble(3 * 512 + (i * 22), 22));
304 : }
305 :
306 : // Block 5:
307 : // Block 5 contains the numerator coefficients for the line rational polynomial
308 : // Number of Coefficients * 22 bytes
309 0 : for (unsigned int i = 0; i < pimpl_->num_coeffs; i++) {
310 0 : pimpl_->line_num.push_back(pimpl_->seg_data.GetDouble(4 * 512 + (i * 22), 22));
311 : }
312 :
313 : // Block 6:
314 : // Block 6 contains the denominator coefficients for the line rational polynomial
315 : // Number of Coefficients * 22 bytes
316 0 : for (unsigned int i = 0; i < pimpl_->num_coeffs; i++) {
317 0 : pimpl_->line_denom.push_back(pimpl_->seg_data.GetDouble(5 * 512 + (i * 22), 22));
318 : }
319 :
320 : // Block 7:
321 : // Bytes 0-15: MapUnits string
322 : // Bytes 256-511: ProjInfo_t, serialized
323 0 : pimpl_->map_units = std::string(&pimpl_->seg_data.buffer[6 * 512], 16);
324 :
325 : // We've now loaded the structure up with data. Mark it as being loaded
326 : // properly.
327 0 : loaded_ = true;
328 :
329 : }
330 :
331 0 : void CPCIDSKRPCModelSegment::Write(void)
332 : {
333 : //We are not writing if nothing was loaded.
334 0 : if (!loaded_) {
335 0 : return;
336 : }
337 :
338 : // The RPC Model Segment is defined as follows:
339 : // RFMODEL Segment: 7 512-byte blocks
340 :
341 : // Block 1:
342 : // Bytes 0-7: 'RFMODEL '
343 : // Byte 8: User Provided RPC (1: user-provided, 0: computed from GCPs)
344 : // Bytes 22-23: 'DS'
345 : // Bytes 24-26: Downsample factor used during Epipolar Generation
346 : // Bytes 27-29: '2ND' -- no clue what this means
347 : // Bytes 30-35: 'SENSOR'
348 : // Bytes 36: Sensor Name (NULL terminated)
349 0 : pimpl_->seg_data.Put("RFMODEL",0,8);
350 :
351 : // Determine if this is user-provided
352 0 : pimpl_->seg_data.buffer[8] = pimpl_->userrpc ? '1' : '0';
353 :
354 : // Check for the DS characters
355 0 : pimpl_->seg_data.Put("DS",22,2);
356 0 : pimpl_->seg_data.Put(pimpl_->downsample,24,3);
357 :
358 : //This is requiered if writting with PCIDSKIO
359 : //and reading with GDBIO (probably because of legacy issue)
360 : // see Bugzilla 255 and 254.
361 0 : pimpl_->seg_data.Put("2ND",27,3);
362 :
363 : // Sensor name:
364 0 : pimpl_->seg_data.Put("SENSOR",30,6);
365 0 : pimpl_->seg_data.Put(pimpl_->sensor_name.c_str(),36,pimpl_->sensor_name.size());
366 :
367 : // Block 2:
368 : // Bytes 0-3: Number of coefficients
369 : // Bytes 4-13: Number of pixels
370 : // Bytes 14-23: Number of lines
371 : // Bytes 24-45: Longitude offset
372 : // Bytes 46-67: Longitude scale
373 : // Bytes 68-89: Latitude Offset
374 : // Bytes 90-111: Latitude Scale
375 : // Bytes 112-133: Height offset
376 : // Bytes 134-155: Height scale
377 : // Bytes 156-177: Sample offset
378 : // Bytes 178-199: Sample scale
379 : // Bytes 200-221: Line offset
380 : // Bytes 222-243: line scale
381 : // Bytes 244-375: Adjusted X coefficients (5 * 22 bytes)
382 : // Bytes 376-507: Adjusted Y coefficients (5 * 22 bytes)
383 :
384 0 : if (pimpl_->num_coeffs * 22 > 512) {
385 : // this segment is malformed. Throw an exception.
386 : throw PCIDSKException("RFMODEL segment coefficient count requires more "
387 : "than one block to store. There is an error in this segment. The "
388 0 : "number of coefficients according to the segment is %d.", pimpl_->num_coeffs);
389 : }
390 :
391 0 : pimpl_->seg_data.Put(pimpl_->num_coeffs,512, 4);
392 :
393 0 : pimpl_->seg_data.Put(pimpl_->lines,512 + 4, 10);
394 0 : pimpl_->seg_data.Put(pimpl_->pixels,512 + 14, 10);
395 0 : pimpl_->seg_data.Put(pimpl_->x_off,512 + 24, 22,"%22.14f");
396 0 : pimpl_->seg_data.Put(pimpl_->x_scale,512 + 46, 22,"%22.14f");
397 0 : pimpl_->seg_data.Put(pimpl_->y_off,512 + 68, 22,"%22.14f");
398 0 : pimpl_->seg_data.Put(pimpl_->y_scale,512 + 90, 22,"%22.14f");
399 0 : pimpl_->seg_data.Put(pimpl_->z_off,512 + 112, 22,"%22.14f");
400 0 : pimpl_->seg_data.Put(pimpl_->z_scale,512 + 134, 22,"%22.14f");
401 0 : pimpl_->seg_data.Put(pimpl_->pix_off,512 + 156, 22,"%22.14f");
402 0 : pimpl_->seg_data.Put(pimpl_->pix_scale,512 + 178, 22,"%22.14f");
403 0 : pimpl_->seg_data.Put(pimpl_->line_off,512 + 200, 22,"%22.14f");
404 0 : pimpl_->seg_data.Put(pimpl_->line_scale,512 + 222, 22,"%22.14f");
405 :
406 : // Read in adjusted X coefficients
407 0 : for (unsigned int i = 0; i <= 5; i++)
408 : {
409 0 : pimpl_->seg_data.Put(pimpl_->x_adj[i],512 + 244 + (i * 22), 22,"%22.14f");
410 0 : if(pimpl_->x_adj[i] != 0.0)
411 : {
412 0 : pimpl_->adjusted = true;
413 : }
414 : }
415 :
416 : // Read in adjusted Y coefficients
417 0 : for (unsigned int i = 0; i <= 5; i++)
418 : {
419 0 : pimpl_->seg_data.Put(pimpl_->y_adj[i],512 + 376 + (i * 22), 22,"%22.14f");
420 0 : if(pimpl_->y_adj[i] != 0.0)
421 : {
422 0 : pimpl_->adjusted = true;
423 : }
424 : }
425 :
426 : // Block 3:
427 : // Block 3 contains the numerator coefficients for the pixel rational polynomial
428 : // Number of Coefficients * 22 bytes
429 0 : for (unsigned int i = 0; i < pimpl_->num_coeffs; i++)
430 : {
431 0 : pimpl_->seg_data.Put(pimpl_->pixel_num[i],2 * 512 + (i * 22), 22,"%22.14f");
432 : }
433 :
434 : // Block 4:
435 : // Block 4 contains the denominator coefficients for the pixel rational polynomial
436 : // Number of Coefficients * 22 bytes
437 0 : for (unsigned int i = 0; i < pimpl_->num_coeffs; i++)
438 : {
439 0 : pimpl_->seg_data.Put(pimpl_->pixel_denom[i],3 * 512 + (i * 22), 22,"%22.14f");
440 : }
441 :
442 : // Block 5:
443 : // Block 5 contains the numerator coefficients for the line rational polynomial
444 : // Number of Coefficients * 22 bytes
445 0 : for (unsigned int i = 0; i < pimpl_->num_coeffs; i++)
446 : {
447 0 : pimpl_->seg_data.Put(pimpl_->line_num[i],4 * 512 + (i * 22), 22,"%22.14f");
448 : }
449 :
450 : // Block 6:
451 : // Block 6 contains the denominator coefficients for the line rational polynomial
452 : // Number of Coefficients * 22 bytes
453 0 : for (unsigned int i = 0; i < pimpl_->num_coeffs; i++)
454 : {
455 0 : pimpl_->seg_data.Put(pimpl_->line_denom[i],5 * 512 + (i * 22), 22,"%22.14f");
456 : }
457 :
458 : // Block 7:
459 : // Bytes 0-15: MapUnits string
460 : // Bytes 256-511: ProjInfo_t, serialized
461 0 : pimpl_->seg_data.Put(pimpl_->map_units.c_str(),6 * 512, 16);
462 :
463 0 : WriteToFile(pimpl_->seg_data.buffer,0,data_size-1024);
464 0 : mbModified = false;
465 : }
466 :
467 0 : std::vector<double> CPCIDSKRPCModelSegment::GetXNumerator(void) const
468 : {
469 0 : return pimpl_->pixel_num;
470 : }
471 :
472 0 : std::vector<double> CPCIDSKRPCModelSegment::GetXDenominator(void) const
473 : {
474 0 : return pimpl_->pixel_denom;
475 : }
476 :
477 0 : std::vector<double> CPCIDSKRPCModelSegment::GetYNumerator(void) const
478 : {
479 0 : return pimpl_->line_num;
480 : }
481 :
482 0 : std::vector<double> CPCIDSKRPCModelSegment::GetYDenominator(void) const
483 : {
484 0 : return pimpl_->line_denom;
485 : }
486 :
487 : // Set the RPC Coefficients
488 0 : void CPCIDSKRPCModelSegment::SetCoefficients(
489 : const std::vector<double>& xnum, const std::vector<double>& xdenom,
490 : const std::vector<double>& ynum, const std::vector<double>& ydenom)
491 : {
492 0 : if (xnum.size() != xdenom.size() || ynum.size() != ydenom.size() ||
493 : xnum.size() != ynum.size() || xdenom.size() != ydenom.size()) {
494 : throw PCIDSKException("All RPC coefficient vectors must be the "
495 0 : "same size.");
496 : }
497 :
498 0 : pimpl_->pixel_num = xnum;
499 0 : pimpl_->pixel_denom = xdenom;
500 0 : pimpl_->line_num = ynum;
501 0 : pimpl_->line_denom = ydenom;
502 0 : mbModified = true;
503 0 : }
504 :
505 : // Get the RPC offset/scale Coefficients
506 0 : void CPCIDSKRPCModelSegment::GetRPCTranslationCoeffs(double& xoffset, double& xscale,
507 : double& yoffset, double& yscale, double& zoffset, double& zscale,
508 : double& pixoffset, double& pixscale, double& lineoffset, double& linescale) const
509 : {
510 0 : xoffset = pimpl_->x_off;
511 0 : xscale = pimpl_->x_scale;
512 :
513 0 : yoffset = pimpl_->y_off;
514 0 : yscale = pimpl_->y_scale;
515 :
516 0 : zoffset = pimpl_->z_off;
517 0 : zscale = pimpl_->z_scale;
518 :
519 0 : pixoffset = pimpl_->pix_off;
520 0 : pixscale = pimpl_->pix_scale;
521 :
522 0 : lineoffset = pimpl_->line_off;
523 0 : linescale = pimpl_->line_scale;
524 0 : }
525 :
526 : // Set the RPC offset/scale Coefficients
527 0 : void CPCIDSKRPCModelSegment::SetRPCTranslationCoeffs(
528 : const double xoffset, const double xscale,
529 : const double yoffset, const double yscale,
530 : const double zoffset, const double zscale,
531 : const double pixoffset, const double pixscale,
532 : const double lineoffset, const double linescale)
533 : {
534 0 : pimpl_->x_off = xoffset;
535 0 : pimpl_->x_scale = xscale;
536 :
537 0 : pimpl_->y_off = yoffset;
538 0 : pimpl_->y_scale = yscale;
539 :
540 0 : pimpl_->z_off = zoffset;
541 0 : pimpl_->z_scale = zscale;
542 :
543 0 : pimpl_->pix_off = pixoffset;
544 0 : pimpl_->pix_scale = pixscale;
545 :
546 0 : pimpl_->line_off = lineoffset;
547 0 : pimpl_->line_scale = linescale;
548 :
549 0 : mbModified = true;
550 0 : }
551 :
552 : // Get the adjusted X values
553 0 : std::vector<double> CPCIDSKRPCModelSegment::GetAdjXValues(void) const
554 : {
555 0 : return pimpl_->x_adj;
556 : }
557 :
558 : // Get the adjusted Y values
559 0 : std::vector<double> CPCIDSKRPCModelSegment::GetAdjYValues(void) const
560 : {
561 0 : return pimpl_->y_adj;
562 : }
563 :
564 : // Set the adjusted X/Y values
565 0 : void CPCIDSKRPCModelSegment::SetAdjCoordValues(const std::vector<double>& xcoord,
566 : const std::vector<double>& ycoord)
567 : {
568 0 : if (xcoord.size() != 6 || ycoord.size() != 6) {
569 : throw PCIDSKException("X and Y adjusted coordinates must have "
570 0 : "length 6.");
571 : }
572 :
573 0 : pimpl_->x_adj = xcoord;
574 0 : pimpl_->y_adj = ycoord;
575 :
576 0 : mbModified = true;
577 0 : }
578 :
579 : // Get whether or not this is a user-generated RPC model
580 0 : bool CPCIDSKRPCModelSegment::IsUserGenerated(void) const
581 : {
582 0 : return pimpl_->userrpc;
583 : }
584 :
585 : // Set whether or not this is a user-generated RPC model
586 0 : void CPCIDSKRPCModelSegment::SetUserGenerated(bool usergen)
587 : {
588 0 : pimpl_->userrpc = usergen;
589 0 : mbModified = true;
590 0 : }
591 :
592 : // Get whether the model has been adjusted
593 0 : bool CPCIDSKRPCModelSegment::IsNominalModel(void) const
594 : {
595 0 : return !pimpl_->adjusted;
596 : }
597 :
598 : // Set whether the model has been adjusted
599 0 : void CPCIDSKRPCModelSegment::SetIsNominalModel(bool nominal)
600 : {
601 0 : pimpl_->adjusted = !nominal;
602 0 : mbModified = true;
603 0 : }
604 :
605 : // Get sensor name
606 0 : std::string CPCIDSKRPCModelSegment::GetSensorName(void) const
607 : {
608 0 : return pimpl_->sensor_name;
609 : }
610 :
611 : // Set sensor name
612 0 : void CPCIDSKRPCModelSegment::SetSensorName(const std::string& name)
613 : {
614 0 : pimpl_->sensor_name = name;
615 0 : mbModified = true;
616 0 : }
617 :
618 : // Output projection information of RPC Model
619 : // Get the Geosys String
620 0 : std::string CPCIDSKRPCModelSegment::GetGeosysString(void) const
621 : {
622 0 : return pimpl_->map_units;
623 : }
624 :
625 : // Set the Geosys string
626 0 : void CPCIDSKRPCModelSegment::SetGeosysString(const std::string& geosys)
627 : {
628 0 : if (geosys.size() > 16) {
629 : throw PCIDSKException("GeoSys/MapUnits string must be no more than "
630 0 : "16 characters to be valid.");
631 : }
632 0 : pimpl_->map_units = geosys;
633 0 : mbModified = true;
634 0 : }
635 :
636 : // Get number of lines
637 0 : unsigned int CPCIDSKRPCModelSegment::GetLines(void) const
638 : {
639 0 : return pimpl_->lines;
640 : }
641 :
642 0 : unsigned int CPCIDSKRPCModelSegment::GetPixels(void) const
643 : {
644 0 : return pimpl_->pixels;
645 : }
646 :
647 0 : void CPCIDSKRPCModelSegment::SetRasterSize(const unsigned int lines, const unsigned int pixels)
648 : {
649 0 : if (lines == 0 || pixels == 0) {
650 0 : throw PCIDSKException("Non-sensical raster dimensions provided: %ux%u", lines, pixels);
651 : }
652 :
653 0 : pimpl_->lines = lines;
654 0 : pimpl_->pixels = pixels;
655 0 : mbModified = true;
656 0 : }
657 :
658 0 : void CPCIDSKRPCModelSegment::SetDownsample(const unsigned int downsample)
659 : {
660 0 : if (downsample == 0) {
661 0 : throw PCIDSKException("Invalid downsample factor provided: %u", downsample);
662 : }
663 :
664 0 : pimpl_->downsample = downsample;
665 0 : mbModified = true;
666 0 : }
667 :
668 0 : unsigned int CPCIDSKRPCModelSegment::GetDownsample(void) const
669 : {
670 0 : return pimpl_->downsample;
671 : }
672 :
673 0 : void CPCIDSKRPCModelSegment::Synchronize()
674 : {
675 0 : if(mbModified)
676 : {
677 0 : this->Write();
678 : }
679 0 : }
680 :
|