Coverage Report

Created: 2025-11-15 08:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}