1 /****************************************************************************** 2 * 3 * Purpose: Implementation of the CPCIDSKPolyModelSegment 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_poly.h" 29 #include "segment/cpcidsksegment.h" 30 #include "core/pcidsk_utils.h" 31 #include "pcidsk_exception.h" 32 #include "segment/cpcidskpolymodel.h" 33 34 #include <vector> 35 #include <string> 36 #include <cassert> 37 #include <cstring> 38 39 using namespace PCIDSK; 40 41 // Struct to store details of the RPC model 42 struct CPCIDSKPolyModelSegment::PCIDSKPolyInfo 43 { 44 // number of coefficients 45 unsigned int nNumCoeffs; 46 47 // pixels in the image 48 unsigned int nPixels; 49 // lines in the image 50 unsigned int nLines; 51 52 // Forward Coefficients (Geo2Img) 53 std::vector<double> vdfX1; 54 // Forward Coefficients (Geo2Img) 55 std::vector<double> vdfY1; 56 // Backward Coefficients Img2Geo 57 std::vector<double> vdfX2; 58 // Backward Coefficients Img2Geo 59 std::vector<double> vdfY2; 60 61 //map units of required projection 62 std::string oMapUnit; 63 //proj param info of required projection 64 std::vector<double> oProjectionInfo; 65 66 // The raw segment data 67 PCIDSKBuffer seg_data; 68 }; 69 70 CPCIDSKPolyModelSegment::CPCIDSKPolyModelSegment(PCIDSKFile *fileIn, 71 int segmentIn, 72 const char *segment_pointer) : 73 CPCIDSKSegment(fileIn, segmentIn, segment_pointer), 74 pimpl_(new CPCIDSKPolyModelSegment::PCIDSKPolyInfo), 75 loaded_(false),mbModified(false) 76 { 77 Load(); 78 } 79 80 81 CPCIDSKPolyModelSegment::~CPCIDSKPolyModelSegment() 82 { 83 delete pimpl_; 84 } 85 86 // Load the contents of the segment 87 void CPCIDSKPolyModelSegment::Load() 88 { 89 // Check if we've already loaded the segment into memory 90 if (loaded_) { 91 return; 92 } 93 94 if (data_size - 1024 != 7 * 512) 95 return ThrowPCIDSKException("Corrupted poly model?"); 96 97 pimpl_->seg_data.SetSize((int)(data_size - 1024)); // should be 7 * 512 98 99 ReadFromFile(pimpl_->seg_data.buffer, 0, data_size - 1024); 100 101 // The Polynomial Model Segment is defined as follows: 102 // Polynomial Segment: 7 512-byte blocks 103 104 // Block 1: 105 // Bytes 0-7: 'POLYMDL ' 106 if (std::strncmp(pimpl_->seg_data.buffer, "POLYMDL ", 8)) 107 { 108 pimpl_->seg_data.Put("POLYMDL ",0,8); 109 return; 110 // Something has gone terribly wrong! 111 /*throw PCIDSKException("A segment that was previously identified as an RFMODEL " 112 "segment does not contain the appropriate data. Found: [%s]", 113 std::string(pimpl_->seg_data.buffer, 8).c_str());*/ 114 } 115 116 // Block 2: number of coefficient and size 117 // Bytes 0-21: number of coefficients 118 // Bytes 22-41: number of pixels 119 // Bytes 42-61: number of lines 120 pimpl_->nNumCoeffs = pimpl_->seg_data.GetInt(512, 22); 121 pimpl_->nPixels = pimpl_->seg_data.GetInt(512 + 22, 22); 122 pimpl_->nLines = pimpl_->seg_data.GetInt(512 + 44, 22); 123 124 int i=0; 125 // Block 3: Forward Coefficients (Geo2Img) 126 // Each coefficient take 22 Bytes 127 for(i=0 ; i < (int)pimpl_->nNumCoeffs ; i++) 128 { 129 pimpl_->vdfX1.push_back(pimpl_->seg_data.GetDouble(2*512 + (i*22), 22)); 130 } 131 132 // Block 4: Forward Coefficients (Geo2Img) 133 // Each coefficient take 22 Bytes 134 for(i=0 ; i < (int)pimpl_->nNumCoeffs ; i++) 135 { 136 pimpl_->vdfY1.push_back(pimpl_->seg_data.GetDouble(3*512 + (i*22), 22)); 137 } 138 139 // Block 5: Backward Coefficients Img2Geo 140 // Each coefficient take 22 Bytes 141 for(i=0 ; i < (int)pimpl_->nNumCoeffs ; i++) 142 { 143 pimpl_->vdfX2.push_back(pimpl_->seg_data.GetDouble(4*512 + (i*22), 22)); 144 } 145 146 // Block 6: Backward Coefficients Img2Geo 147 // Each coefficient take 22 Bytes 148 for(i=0 ; i < (int)pimpl_->nNumCoeffs ; i++) 149 { 150 pimpl_->vdfY2.push_back(pimpl_->seg_data.GetDouble(5*512 + (i*22), 22)); 151 } 152 153 // Block 7: Required projection 154 // Bytes 0-16: The map units 155 // Bytes 17-511: the proj param info. 156 pimpl_->oMapUnit = pimpl_->seg_data.Get(6*512,17); 157 for(i=0 ; i < 19 ; i++) 158 { 159 pimpl_->oProjectionInfo.push_back(pimpl_->seg_data.GetDouble(6*512+17+i*26,26)); 160 } 161 162 // We've now loaded the structure up with data. Mark it as being loaded 163 // properly. 164 loaded_ = true; 165 } 166 167 void CPCIDSKPolyModelSegment::Write(void) 168 { 169 //We are not writing if nothing was loaded. 170 if (!loaded_) { 171 return; 172 } 173 174 // Block 1: 175 // Bytes 0-7: 'POLYMDL ' 176 pimpl_->seg_data.Put("POLYMDL ",0,8); 177 178 // Block 2: number of coefficient and size 179 // Bytes 0-21: number of coefficients 180 // Bytes 22-41: number of pixels 181 // Bytes 42-61: number of lines 182 pimpl_->seg_data.Put(pimpl_->nNumCoeffs,512, 22); 183 pimpl_->seg_data.Put(pimpl_->nPixels,512 + 22, 22); 184 pimpl_->seg_data.Put(pimpl_->nLines,512 + 44, 22); 185 186 int i=0; 187 assert(pimpl_->vdfX1.size() == pimpl_->nNumCoeffs); 188 assert(pimpl_->vdfX2.size() == pimpl_->nNumCoeffs); 189 assert(pimpl_->vdfY1.size() == pimpl_->nNumCoeffs); 190 assert(pimpl_->vdfY2.size() == pimpl_->nNumCoeffs); 191 // Block 3: Forward Coefficients (Geo2Img) 192 // Each coefficient take 22 Bytes 193 for(i=0 ; i < (int)pimpl_->nNumCoeffs ; i++) 194 { 195 pimpl_->seg_data.Put(pimpl_->vdfX1[i],2*512 + (i*22), 22,"%20.14f"); 196 } 197 198 // Block 4: Forward Coefficients (Geo2Img) 199 // Each coefficient take 22 Bytes 200 for(i=0 ; i < (int)pimpl_->nNumCoeffs ; i++) 201 { 202 pimpl_->seg_data.Put(pimpl_->vdfY1[i],3*512 + (i*22), 22,"%20.14f"); 203 } 204 205 // Block 5: Forward Coefficients (Geo2Img) 206 // Each coefficient take 22 Bytes 207 for(i=0 ; i < (int)pimpl_->nNumCoeffs ; i++) 208 { 209 pimpl_->seg_data.Put(pimpl_->vdfX2[i],4*512 + (i*22), 22,"%20.14f"); 210 } 211 212 // Block 6: Forward Coefficients (Geo2Img) 213 // Each coefficient take 22 Bytes 214 for(i=0 ; i < (int)pimpl_->nNumCoeffs ; i++) 215 { 216 pimpl_->seg_data.Put(pimpl_->vdfY2[i],5*512 + (i*22), 22,"%20.14f"); 217 } 218 219 assert(pimpl_->oMapUnit.size() <= 17); 220 assert(pimpl_->oProjectionInfo.size() <= 512-17-1); 221 // Block 7: Required projection 222 // Bytes 0-16: The map units 223 // Bytes 17-511: the proj param info. 224 pimpl_->seg_data.Put(" \0",6*512,17); 225 pimpl_->seg_data.Put(pimpl_->oMapUnit.c_str(),6*512,(int)pimpl_->oMapUnit.size()); 226 //19 because (511-17)/26 = 19 (26 is the size of one value) 227 for(i=0 ; i < 19 ; i++) 228 { 229 pimpl_->seg_data.Put(pimpl_->oProjectionInfo[i],6*512+17+(i*26),26,"%20.14f"); 230 } 231 232 WriteToFile(pimpl_->seg_data.buffer,0,data_size-1024); 233 mbModified = false; 234 } 235 236 std::vector<double> CPCIDSKPolyModelSegment::GetXForwardCoefficients() const 237 { 238 return pimpl_->vdfX1; 239 } 240 241 std::vector<double> CPCIDSKPolyModelSegment::GetYForwardCoefficients() const 242 { 243 return pimpl_->vdfY1; 244 } 245 246 std::vector<double> CPCIDSKPolyModelSegment::GetXBackwardCoefficients() const 247 { 248 return pimpl_->vdfX2; 249 } 250 251 std::vector<double> CPCIDSKPolyModelSegment::GetYBackwardCoefficients() const 252 { 253 return pimpl_->vdfY2; 254 } 255 256 void CPCIDSKPolyModelSegment::SetCoefficients(const std::vector<double>& oXForward, 257 const std::vector<double>& oYForward, 258 const std::vector<double>& oXBackward, 259 const std::vector<double>& oYBackward) 260 { 261 assert(oXForward.size() == oYForward.size()); 262 assert(oYForward.size() == oXBackward.size()); 263 assert(oXBackward.size() == oYBackward.size()); 264 pimpl_->vdfX1 = oXForward; 265 pimpl_->vdfY1 = oYForward; 266 pimpl_->vdfX2 = oXBackward; 267 pimpl_->vdfY2 = oYBackward; 268 pimpl_->nNumCoeffs = (unsigned int)oXForward.size(); 269 } 270 271 unsigned int CPCIDSKPolyModelSegment::GetPixels() const 272 { 273 return pimpl_->nPixels; 274 } 275 276 unsigned int CPCIDSKPolyModelSegment::GetLines() const 277 { 278 return pimpl_->nLines; 279 } 280 281 void CPCIDSKPolyModelSegment::SetRasterSize(unsigned int nLines,unsigned int nPixels) 282 { 283 pimpl_->nPixels = nPixels; 284 pimpl_->nLines = nLines; 285 } 286 287 std::string CPCIDSKPolyModelSegment::GetGeosysString() const 288 { 289 return pimpl_->oMapUnit; 290 } 291 292 void CPCIDSKPolyModelSegment::SetGeosysString(const std::string& oGeosys) 293 { 294 pimpl_->oMapUnit = oGeosys; 295 } 296 297 std::vector<double> CPCIDSKPolyModelSegment::GetProjParamInfo() const 298 { 299 return pimpl_->oProjectionInfo; 300 } 301 302 void CPCIDSKPolyModelSegment::SetProjParamInfo(const std::vector<double>& oInfo) 303 { 304 pimpl_->oProjectionInfo = oInfo; 305 while(pimpl_->oProjectionInfo.size() < 19) 306 { 307 pimpl_->oProjectionInfo.push_back(0.0); 308 } 309 } 310 311 void CPCIDSKPolyModelSegment::Synchronize() 312 { 313 if(mbModified) 314 { 315 this->Write(); 316 } 317 } 318 319