/src/gdal/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.cpp
Line | Count | Source |
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 | 2 | PCIDSKRPCSegment::~PCIDSKRPCSegment() = default; |
26 | | |
27 | | CPCIDSKRPCModelSegment::CPCIDSKRPCModelSegment(PCIDSKFile *fileIn, int segmentIn,const char *segment_pointer) : |
28 | 2 | CPCIDSKSegment(fileIn, segmentIn, segment_pointer), pimpl_(new CPCIDSKRPCModelSegment::PCIDSKRPCInfo), |
29 | 2 | loaded_(false),mbModified(false),mbEmpty(false) |
30 | 2 | { |
31 | 2 | try |
32 | 2 | { |
33 | 2 | Load(); |
34 | 2 | } |
35 | 2 | catch( const PCIDSKException& ) |
36 | 2 | { |
37 | 2 | delete pimpl_; |
38 | 2 | pimpl_ = nullptr; |
39 | 2 | throw; |
40 | 2 | } |
41 | 2 | } Unexecuted instantiation: PCIDSK::CPCIDSKRPCModelSegment::CPCIDSKRPCModelSegment(PCIDSK::PCIDSKFile*, int, char const*) PCIDSK::CPCIDSKRPCModelSegment::CPCIDSKRPCModelSegment(PCIDSK::PCIDSKFile*, int, char const*) Line | Count | Source | 28 | 2 | CPCIDSKSegment(fileIn, segmentIn, segment_pointer), pimpl_(new CPCIDSKRPCModelSegment::PCIDSKRPCInfo), | 29 | 2 | loaded_(false),mbModified(false),mbEmpty(false) | 30 | 2 | { | 31 | 2 | try | 32 | 2 | { | 33 | 2 | Load(); | 34 | 2 | } | 35 | 2 | catch( const PCIDSKException& ) | 36 | 2 | { | 37 | 2 | delete pimpl_; | 38 | 2 | pimpl_ = nullptr; | 39 | 2 | throw; | 40 | 2 | } | 41 | 2 | } |
|
42 | | |
43 | | |
44 | | CPCIDSKRPCModelSegment::~CPCIDSKRPCModelSegment() |
45 | 0 | { |
46 | 0 | delete pimpl_; |
47 | 0 | } |
48 | | |
49 | | // Load the contents of the segment |
50 | | void CPCIDSKRPCModelSegment::Load() |
51 | 2 | { |
52 | | // Check if we've already loaded the segment into memory |
53 | 2 | if (loaded_) { |
54 | 0 | return; |
55 | 0 | } |
56 | | |
57 | 2 | if(data_size == 1024) |
58 | 0 | { |
59 | 0 | mbEmpty = true; |
60 | 0 | return; |
61 | 0 | } |
62 | | |
63 | 2 | mbEmpty = false; |
64 | | |
65 | 2 | if( data_size != 1024 + 7 * 512 ) |
66 | 2 | { |
67 | 2 | return ThrowPCIDSKException("Wrong data_size in CPCIDSKRPCModelSegment"); |
68 | 2 | } |
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 | 0 | { |
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 | 0 | } |
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 | 0 | { |
110 | | // Read the downsample factor |
111 | 0 | pimpl_->downsample = pimpl_->seg_data.GetInt(24, 3); |
112 | 0 | } |
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 | 0 | { |
120 | 0 | bSecond = true; |
121 | 0 | } |
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 | 0 | } else { |
127 | 0 | pimpl_->sensor_name = ""; |
128 | 0 | } |
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 | 0 | { |
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 | 0 | "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 | 0 | } |
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 | 0 | { |
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 | 0 | { |
182 | 0 | pimpl_->adjusted = true; |
183 | 0 | } |
184 | 0 | } |
185 | | |
186 | | // Read in adjusted Y coefficients |
187 | 0 | for (unsigned int i = 0; i <= 5; i++) |
188 | 0 | { |
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 | 0 | { |
193 | 0 | pimpl_->adjusted = true; |
194 | 0 | } |
195 | 0 | } |
196 | 0 | } |
197 | 0 | else |
198 | 0 | { |
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 | 0 | "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 | 0 | } |
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 | 0 | { |
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 | 0 | { |
229 | 0 | pimpl_->adjusted = true; |
230 | 0 | } |
231 | 0 | } |
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 | 0 | { |
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 | 0 | { |
243 | 0 | pimpl_->adjusted = true; |
244 | 0 | } |
245 | 0 | } |
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 | 0 | } |
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 | 0 | } |
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 | 0 | } |
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 | 0 | } |
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 | 0 | } |
278 | | |
279 | | // Pad coefficients up to 20 |
280 | 0 | for (unsigned int i = pimpl_->num_coeffs; i < 20; ++i) |
281 | 0 | { |
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 | 0 | } |
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 | 0 | } |
298 | | |
299 | | void CPCIDSKRPCModelSegment::Write(void) |
300 | 0 | { |
301 | | //We are not writing if nothing was loaded. |
302 | 0 | if (!loaded_) { |
303 | 0 | return; |
304 | 0 | } |
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 | 0 | "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 | 0 | } |
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 | 0 | { |
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 | 0 | { |
380 | 0 | pimpl_->adjusted = true; |
381 | 0 | } |
382 | 0 | } |
383 | | |
384 | | // Read in adjusted Y coefficients |
385 | 0 | for (unsigned int i = 0; i <= 5; i++) |
386 | 0 | { |
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 | 0 | { |
390 | 0 | pimpl_->adjusted = true; |
391 | 0 | } |
392 | 0 | } |
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 | 0 | { |
399 | 0 | pimpl_->seg_data.Put(pimpl_->pixel_num[i],2 * 512 + (i * 22), 22,"%22.14f"); |
400 | 0 | } |
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 | 0 | { |
407 | 0 | pimpl_->seg_data.Put(pimpl_->pixel_denom[i],3 * 512 + (i * 22), 22,"%22.14f"); |
408 | 0 | } |
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 | 0 | { |
415 | 0 | pimpl_->seg_data.Put(pimpl_->line_num[i],4 * 512 + (i * 22), 22,"%22.14f"); |
416 | 0 | } |
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 | 0 | { |
423 | 0 | pimpl_->seg_data.Put(pimpl_->line_denom[i],5 * 512 + (i * 22), 22,"%22.14f"); |
424 | 0 | } |
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 | 0 | } |
436 | | |
437 | | std::vector<double> CPCIDSKRPCModelSegment::GetXNumerator(void) const |
438 | 0 | { |
439 | 0 | return pimpl_->pixel_num; |
440 | 0 | } |
441 | | |
442 | | std::vector<double> CPCIDSKRPCModelSegment::GetXDenominator(void) const |
443 | 0 | { |
444 | 0 | return pimpl_->pixel_denom; |
445 | 0 | } |
446 | | |
447 | | std::vector<double> CPCIDSKRPCModelSegment::GetYNumerator(void) const |
448 | 0 | { |
449 | 0 | return pimpl_->line_num; |
450 | 0 | } |
451 | | |
452 | | std::vector<double> CPCIDSKRPCModelSegment::GetYDenominator(void) const |
453 | 0 | { |
454 | 0 | return pimpl_->line_denom; |
455 | 0 | } |
456 | | |
457 | | // Set the RPC Coefficients |
458 | | 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 | 0 | { |
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 | 0 | } |
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 | 0 | } |
474 | | |
475 | | // Get the RPC offset/scale Coefficients |
476 | | 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 | 0 | { |
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 | | 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 | 0 | { |
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 | | std::vector<double> CPCIDSKRPCModelSegment::GetAdjXValues(void) const |
524 | 0 | { |
525 | 0 | return pimpl_->x_adj; |
526 | 0 | } |
527 | | |
528 | | // Get the adjusted Y values |
529 | | std::vector<double> CPCIDSKRPCModelSegment::GetAdjYValues(void) const |
530 | 0 | { |
531 | 0 | return pimpl_->y_adj; |
532 | 0 | } |
533 | | |
534 | | // Set the adjusted X/Y values |
535 | | void CPCIDSKRPCModelSegment::SetAdjCoordValues(const std::vector<double>& xcoord, |
536 | | const std::vector<double>& ycoord) |
537 | 0 | { |
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 | 0 | } |
542 | | |
543 | 0 | pimpl_->x_adj = xcoord; |
544 | 0 | pimpl_->y_adj = ycoord; |
545 | |
|
546 | 0 | mbModified = true; |
547 | 0 | } |
548 | | |
549 | | // Get whether or not this is a user-generated RPC model |
550 | | bool CPCIDSKRPCModelSegment::IsUserGenerated(void) const |
551 | 0 | { |
552 | 0 | return pimpl_->userrpc; |
553 | 0 | } |
554 | | |
555 | | // Set whether or not this is a user-generated RPC model |
556 | | void CPCIDSKRPCModelSegment::SetUserGenerated(bool usergen) |
557 | 0 | { |
558 | 0 | pimpl_->userrpc = usergen; |
559 | 0 | mbModified = true; |
560 | 0 | } |
561 | | |
562 | | // Get whether the model has been adjusted |
563 | | bool CPCIDSKRPCModelSegment::IsNominalModel(void) const |
564 | 0 | { |
565 | 0 | return !pimpl_->adjusted; |
566 | 0 | } |
567 | | |
568 | | // Set whether the model has been adjusted |
569 | | void CPCIDSKRPCModelSegment::SetIsNominalModel(bool nominal) |
570 | 0 | { |
571 | 0 | pimpl_->adjusted = !nominal; |
572 | 0 | mbModified = true; |
573 | 0 | } |
574 | | |
575 | | // Get sensor name |
576 | | std::string CPCIDSKRPCModelSegment::GetSensorName(void) const |
577 | 0 | { |
578 | 0 | return pimpl_->sensor_name; |
579 | 0 | } |
580 | | |
581 | | // Set sensor name |
582 | | void CPCIDSKRPCModelSegment::SetSensorName(const std::string& name) |
583 | 0 | { |
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 | | CPCIDSKRPCModelSegment::GetMapUnits(std::string& map_units, |
608 | | std::string& proj_parms) const |
609 | 0 | { |
610 | 0 | map_units = pimpl_->map_units; |
611 | 0 | proj_parms = pimpl_->proj_parms; |
612 | 0 | return; |
613 | 0 | }// 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 | | CPCIDSKRPCModelSegment::SetMapUnits(std::string const& map_units, |
636 | | std::string const& proj_parms) |
637 | 0 | { |
638 | 0 | if (map_units.size() > 16) |
639 | 0 | { |
640 | 0 | return ThrowPCIDSKException("GeoSys/MapUnits string must be no more than " |
641 | 0 | "16 characters to be valid."); |
642 | 0 | } |
643 | 0 | if (proj_parms.size() > 256) |
644 | 0 | { |
645 | 0 | return ThrowPCIDSKException("GeoSys/Projection parameters string must be no more than " |
646 | 0 | "256 characters to be valid."); |
647 | 0 | } |
648 | 0 | pimpl_->map_units = map_units; |
649 | 0 | pimpl_->proj_parms = proj_parms; |
650 | 0 | mbModified = true; |
651 | 0 | } |
652 | | |
653 | | // Get number of lines |
654 | | unsigned int CPCIDSKRPCModelSegment::GetLines(void) const |
655 | 0 | { |
656 | 0 | return pimpl_->lines; |
657 | 0 | } |
658 | | |
659 | | unsigned int CPCIDSKRPCModelSegment::GetPixels(void) const |
660 | 0 | { |
661 | 0 | return pimpl_->pixels; |
662 | 0 | } |
663 | | |
664 | | void CPCIDSKRPCModelSegment::SetRasterSize(const unsigned int lines, const unsigned int pixels) |
665 | 0 | { |
666 | 0 | if (lines == 0 || pixels == 0) { |
667 | 0 | return ThrowPCIDSKException("Nonsensical raster dimensions provided: %ux%u", |
668 | 0 | lines, pixels); |
669 | 0 | } |
670 | | |
671 | 0 | pimpl_->lines = lines; |
672 | 0 | pimpl_->pixels = pixels; |
673 | 0 | mbModified = true; |
674 | 0 | } |
675 | | |
676 | | void CPCIDSKRPCModelSegment::SetDownsample(const unsigned int downsample) |
677 | 0 | { |
678 | 0 | if (downsample == 0) { |
679 | 0 | return ThrowPCIDSKException("Invalid downsample factor provided: %u", downsample); |
680 | 0 | } |
681 | | |
682 | 0 | pimpl_->downsample = downsample; |
683 | 0 | mbModified = true; |
684 | 0 | } |
685 | | |
686 | | unsigned int CPCIDSKRPCModelSegment::GetDownsample(void) const |
687 | 0 | { |
688 | 0 | return pimpl_->downsample; |
689 | 0 | } |
690 | | |
691 | | void CPCIDSKRPCModelSegment::Synchronize() |
692 | 0 | { |
693 | 0 | if(mbModified) |
694 | 0 | { |
695 | 0 | this->Write(); |
696 | 0 | } |
697 | 0 | } |