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