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