LTP GCOV extension - code coverage report
Current view: directory - frmts/pcidsk/sdk/segment - cpcidskgcp2segment.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 123
Code covered: 1.6 % Executed lines: 2

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Purpose: Implementation of access to a PCIDSK GCP2 Segment
       4                 :  * 
       5                 :  ******************************************************************************
       6                 :  * Copyright (c) 2009
       7                 :  * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, 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                 : #include "segment/cpcidskgcp2segment.h"
      28                 : 
      29                 : #include "pcidsk_gcp.h"
      30                 : #include "pcidsk_exception.h"
      31                 : 
      32                 : #include <cstring>
      33                 : #include <iostream>
      34                 : #include <vector>
      35                 : #include <string>
      36                 : 
      37                 : using namespace PCIDSK;
      38                 : 
      39                 : struct CPCIDSKGCP2Segment::PCIDSKGCP2SegInfo
      40               0 : {
      41                 :     std::vector<PCIDSK::GCP> gcps;
      42                 :     unsigned int num_gcps;
      43                 :     PCIDSKBuffer seg_data;
      44                 :     
      45                 :     std::string map_units;
      46                 :     unsigned int num_proj;
      47                 :     bool changed;
      48                 : };
      49                 : 
      50               0 : CPCIDSKGCP2Segment::CPCIDSKGCP2Segment(PCIDSKFile *file, int segment, const char *segment_pointer)
      51               0 :     : CPCIDSKSegment(file, segment, segment_pointer), loaded_(false)
      52                 : {
      53               0 :     pimpl_ = new PCIDSKGCP2SegInfo;
      54               0 :     pimpl_->gcps.clear();
      55               0 :     pimpl_->changed = false;
      56               0 :     Load();
      57               0 : }
      58                 :  
      59               0 : CPCIDSKGCP2Segment::~CPCIDSKGCP2Segment()
      60                 : {
      61               0 :     RebuildSegmentData();
      62               0 :     delete pimpl_;
      63               0 : }
      64                 : 
      65               0 : void CPCIDSKGCP2Segment::Load()
      66                 : {
      67               0 :     if (loaded_) {
      68               0 :         return;
      69                 :     }
      70                 :     
      71                 :     // Read the the segment in. The first block has information about
      72                 :     // the structure of the GCP segment (how many, the projection, etc.)
      73               0 :     pimpl_->seg_data.SetSize(data_size - 1024);
      74               0 :     ReadFromFile(pimpl_->seg_data.buffer, 0, data_size - 1024);
      75                 :     
      76                 :     // check for 'GCP2    ' in the first 8 bytes
      77               0 :     if (std::strncmp(pimpl_->seg_data.buffer, "GCP2    ", 8) != 0) {
      78                 :         // Assume it's an empty segment, so we can mark loaded_ = true,
      79                 :         // write it out and return
      80               0 :         pimpl_->changed = true;
      81               0 :         pimpl_->map_units = "LAT/LONG D000";
      82               0 :         pimpl_->num_gcps = 0;
      83               0 :         loaded_ = true;
      84               0 :         return;
      85                 :     }
      86                 :     
      87                 :     // Check the number of blocks field's validity
      88               0 :     unsigned int num_blocks = pimpl_->seg_data.GetInt(8, 8);
      89                 :     
      90               0 :     if (((data_size - 1024 - 512) / 512) != num_blocks) {
      91                 :         //ThrowPCIDSKException("Calculated number of blocks (%d) does not match "
      92                 :         //    "the value encoded in the GCP2 segment (%d).", ((data_size - 1024 - 512)/512), 
      93                 :         //    num_blocks);
      94                 :         // Something is messed up with how GDB generates these segments... nice.
      95                 :     }
      96                 :     
      97               0 :     pimpl_->num_gcps = pimpl_->seg_data.GetInt(16, 8);
      98                 :     
      99                 :     // Extract the map units string:
     100               0 :     pimpl_->map_units = std::string(pimpl_->seg_data.buffer + 24, 16);
     101                 :     
     102                 :     // Get the number of alternative projections (should be 0!)
     103               0 :     pimpl_->num_proj = pimpl_->seg_data.GetInt(40, 8);
     104               0 :     if (pimpl_->num_proj != 0) {
     105                 :         ThrowPCIDSKException("There are alternative projections contained in this "
     106               0 :             "GCP2 segment. This functionality is not supported in libpcidsk.");
     107                 :     }
     108                 :     
     109                 :     // Load the GCPs into the vector of PCIDSK::GCPs
     110               0 :     for (unsigned int i = 0; i < pimpl_->num_gcps; i++)
     111                 :     {
     112               0 :         unsigned int offset = 512 + i * 256;
     113               0 :         bool is_cp = pimpl_->seg_data.buffer[offset] == 'C';
     114               0 :         double pixel = pimpl_->seg_data.GetDouble(offset + 6, 14);
     115               0 :         double line = pimpl_->seg_data.GetDouble(offset + 20, 14);
     116                 :         
     117               0 :         double elev = pimpl_->seg_data.GetDouble(offset + 34, 12);
     118               0 :         double x = pimpl_->seg_data.GetDouble(offset + 48, 22);
     119               0 :         double y = pimpl_->seg_data.GetDouble(offset + 70, 22);
     120                 :         
     121                 :         PCIDSK::GCP::EElevationDatum elev_datum = pimpl_->seg_data.buffer[offset + 47] != 'M' ? 
     122               0 :             GCP::EEllipsoidal : GCP::EMeanSeaLevel;
     123                 :         
     124               0 :         char elev_unit_c = pimpl_->seg_data.buffer[offset + 46];
     125                 :         PCIDSK::GCP::EElevationUnit elev_unit = elev_unit_c == 'M' ? GCP::EMetres :
     126                 :             elev_unit_c == 'F' ? GCP::EInternationalFeet :
     127               0 :             elev_unit_c == 'A' ? GCP::EAmericanFeet : GCP::EUnknown;
     128                 :         
     129               0 :         double pix_err = pimpl_->seg_data.GetDouble(offset + 92, 10);
     130               0 :         double line_err = pimpl_->seg_data.GetDouble(offset + 102, 10);
     131               0 :         double elev_err = pimpl_->seg_data.GetDouble(offset + 112, 10);
     132                 :         
     133               0 :         double x_err = pimpl_->seg_data.GetDouble(offset + 122, 14);
     134               0 :         double y_err = pimpl_->seg_data.GetDouble(offset + 136, 14);
     135                 :         
     136               0 :         std::string gcp_id(pimpl_->seg_data.buffer + 192, 64);
     137                 :         
     138                 :         PCIDSK::GCP gcp(x, y, elev,
     139                 :                         line, pixel, gcp_id, pimpl_->map_units, 
     140                 :                         x_err, y_err, elev_err,
     141               0 :                         line_err, pix_err);
     142               0 :         gcp.SetElevationUnit(elev_unit);
     143               0 :         gcp.SetElevationDatum(elev_datum);  
     144               0 :         gcp.SetCheckpoint(is_cp);          
     145                 :         
     146               0 :         pimpl_->gcps.push_back(gcp);
     147                 :     } 
     148                 :     
     149               0 :     loaded_ = true;
     150                 : }
     151                 : 
     152                 :  // Return all GCPs in the segment
     153               0 : std::vector<PCIDSK::GCP> const& CPCIDSKGCP2Segment::GetGCPs(void) const
     154                 : {
     155               0 :     return pimpl_->gcps;
     156                 : }
     157                 :  
     158                 : // Write the given GCPs to the segment. If the segment already
     159                 : // exists, it will be replaced with this one.
     160               0 : void CPCIDSKGCP2Segment::SetGCPs(std::vector<PCIDSK::GCP> const& gcps)
     161                 : {
     162               0 :     pimpl_->num_gcps = gcps.size();
     163               0 :     pimpl_->gcps = gcps; // copy them in
     164               0 :     pimpl_->changed = true;
     165                 :     
     166               0 :     RebuildSegmentData();
     167               0 : }
     168                 :  
     169                 : // Return the count of GCPs in the segment
     170               0 : unsigned int  CPCIDSKGCP2Segment::GetGCPCount(void) const
     171                 : {
     172               0 :     return pimpl_->num_gcps;
     173                 : }
     174                 : 
     175               0 : void CPCIDSKGCP2Segment::RebuildSegmentData(void)
     176                 : {
     177               0 :     if (pimpl_->changed == false) {
     178               0 :         return;
     179                 :     }
     180                 :     
     181                 :     // Rebuild the segment data based on the contents of the struct
     182               0 :     int num_blocks = (pimpl_->num_gcps + 1) / 2;
     183                 :     
     184                 :     // This will have to change when we have proper projections support
     185               0 :     if (pimpl_->gcps.size() > 0 &&
     186                 :         pimpl_->map_units != pimpl_->gcps[0].GetMapUnits()) {
     187               0 :         pimpl_->map_units = pimpl_->gcps[0].GetMapUnits();
     188                 :     }
     189                 :     
     190               0 :     data_size = num_blocks * 512 + 1024;
     191                 :     
     192               0 :     pimpl_->seg_data.SetSize(num_blocks * 512 + 512);
     193                 :     
     194                 :     // Write out the first few fields
     195               0 :     pimpl_->seg_data.Put("GCP2    ", 0, 8);
     196               0 :     pimpl_->seg_data.Put(num_blocks, 8, 8);
     197               0 :     pimpl_->seg_data.Put((int)pimpl_->gcps.size(), 16, 8);
     198               0 :     pimpl_->seg_data.Put(pimpl_->map_units.c_str(), 24, 16);
     199               0 :     pimpl_->seg_data.Put((int)0, 40, 8);
     200                 :     
     201                 :     // Time to write GCPs out:
     202                 :     std::vector<PCIDSK::GCP>::const_iterator iter =
     203               0 :         pimpl_->gcps.begin();
     204                 :     
     205               0 :     unsigned int id = 0;
     206               0 :     while (iter != pimpl_->gcps.end()) {
     207               0 :         std::size_t offset = 512 + id * 256;
     208                 :         
     209               0 :         if ((*iter).IsCheckPoint()) {
     210               0 :             pimpl_->seg_data.Put("C", offset, 1);
     211                 :         } else {
     212               0 :             pimpl_->seg_data.Put("G", offset, 1);
     213                 :         }
     214                 :         
     215               0 :         pimpl_->seg_data.Put("0", offset + 1, 5);
     216                 :         
     217                 :         // Start writing out the GCP values
     218               0 :         pimpl_->seg_data.Put((*iter).GetPixel(), offset + 6, 14);
     219               0 :         pimpl_->seg_data.Put((*iter).GetLine(), offset + 20, 14);
     220               0 :         pimpl_->seg_data.Put((*iter).GetZ(), offset + 34, 12);
     221                 :         
     222                 :         GCP::EElevationUnit unit;
     223                 :         GCP::EElevationDatum datum;
     224               0 :         (*iter).GetElevationInfo(datum, unit);
     225                 :         
     226                 :         char unit_c[2];
     227                 :         
     228               0 :         switch (unit)
     229                 :         {
     230                 :         case GCP::EMetres:
     231                 :         case GCP::EUnknown:
     232               0 :             unit_c[0] = 'M';
     233               0 :             break;
     234                 :         case GCP::EAmericanFeet:
     235               0 :             unit_c[0] = 'A';
     236               0 :             break;
     237                 :         case GCP::EInternationalFeet:
     238               0 :             unit_c[0] = 'F';
     239                 :             break;
     240                 :         }
     241                 :         
     242                 :         char datum_c[2];
     243                 :         
     244               0 :         switch(datum)
     245                 :         {
     246                 :         case GCP::EEllipsoidal:
     247               0 :             datum_c[0] = 'E';
     248               0 :             break;
     249                 :         case GCP::EMeanSeaLevel:
     250               0 :             datum_c[0] = 'M';
     251                 :             break;
     252                 :         }
     253                 : 
     254               0 :     unit_c[1] = '\0';
     255               0 :     datum_c[1] = '\0';
     256                 :         
     257               0 :         unit_c[1] = '\0';
     258               0 :         datum_c[1] = '\0';
     259                 :         
     260                 :         // Write out elevation information
     261               0 :         pimpl_->seg_data.Put(unit_c, offset + 46, 1);
     262               0 :         pimpl_->seg_data.Put(datum_c, offset + 47, 1);
     263                 :         
     264               0 :         pimpl_->seg_data.Put((*iter).GetX(), offset + 48, 22);
     265               0 :         pimpl_->seg_data.Put((*iter).GetY(), offset + 70, 22);
     266               0 :         pimpl_->seg_data.Put((*iter).GetPixelErr(), offset + 92, 10);
     267               0 :         pimpl_->seg_data.Put((*iter).GetLineErr(), offset + 102, 10);
     268               0 :         pimpl_->seg_data.Put((*iter).GetZErr(), offset + 112, 10);
     269               0 :         pimpl_->seg_data.Put((*iter).GetXErr(), offset + 122, 14);
     270               0 :         pimpl_->seg_data.Put((*iter).GetYErr(), offset + 136, 14);
     271               0 :         pimpl_->seg_data.Put((*iter).GetIDString(), offset + 192, 64);
     272                 :         
     273               0 :         id++;
     274               0 :         iter++;
     275                 :     }
     276                 :     
     277               0 :     WriteToFile(pimpl_->seg_data.buffer, 0, pimpl_->seg_data.buffer_size);
     278                 :     
     279               0 :     pimpl_->changed = false;
     280                 : }
     281                 :  
     282                 : // Clear a GCP Segment
     283               0 : void  CPCIDSKGCP2Segment::ClearGCPs(void)
     284                 : {
     285               0 :     pimpl_->num_gcps = 0;
     286               0 :     pimpl_->gcps.clear();
     287               0 :     pimpl_->changed = true;
     288                 :     
     289               0 :     RebuildSegmentData();
     290             896 : }
     291             448 : 

Generated by: LTP GCOV extension version 1.5