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