LCOV - code coverage report
Current view: top level - alg/marching_squares - contour_generator.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 60 61 98.4 %
Date: 2024-05-02 22:57:13 Functions: 53 67 79.1 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Marching squares
       4             :  * Purpose:  Classes for contour generation
       5             :  * Author:   Hugo Mercier, <hugo dot mercier at oslandia dot com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2018, Oslandia <infos at oslandia dot com>
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #ifndef MARCHING_SQUARES_CONTOUR_GENERATOR_H
      30             : #define MARCHING_SQUARES_CONTOUR_GENERATOR_H
      31             : 
      32             : #include <vector>
      33             : #include <algorithm>
      34             : 
      35             : #include "gdal.h"
      36             : 
      37             : #include "utility.h"
      38             : #include "point.h"
      39             : #include "square.h"
      40             : 
      41             : namespace marching_squares
      42             : {
      43             : 
      44             : template <typename ContourWriter, typename LevelGenerator>
      45             : class ContourGenerator
      46             : {
      47             :   public:
      48          42 :     ContourGenerator(size_t width, size_t height, bool hasNoData,
      49             :                      double noDataValue, ContourWriter &writer,
      50             :                      LevelGenerator &levelGenerator)
      51             :         : width_(width), height_(height), hasNoData_(hasNoData),
      52             :           noDataValue_(noDataValue), previousLine_(), writer_(writer),
      53          42 :           levelGenerator_(levelGenerator)
      54             :     {
      55          42 :         previousLine_.resize(width_);
      56          42 :         std::fill(previousLine_.begin(), previousLine_.end(), NaN);
      57          42 :     }
      58             : 
      59        2639 :     CPLErr feedLine(const double *line)
      60             :     {
      61        2639 :         if (lineIdx_ <= height_)
      62             :         {
      63        2639 :             feedLine_(line);
      64        2635 :             if (lineIdx_ == height_)
      65             :             {
      66             :                 // last line
      67          37 :                 feedLine_(nullptr);
      68             :             }
      69             :         }
      70        2635 :         return CE_None;
      71             :     }
      72             : 
      73             :   private:
      74             :     size_t width_;
      75             :     size_t height_;
      76             :     bool hasNoData_;
      77             :     double noDataValue_;
      78             : 
      79             :     size_t lineIdx_ = 0;
      80             : 
      81             :     std::vector<double> previousLine_;
      82             : 
      83             :     ContourWriter &writer_;
      84             :     LevelGenerator &levelGenerator_;
      85             : 
      86             :     class ExtendedLine
      87             :     {
      88             :       public:
      89        5352 :         ExtendedLine(const double *line, size_t size, bool hasNoData,
      90             :                      double noDataValue)
      91             :             : line_(line), size_(size), hasNoData_(hasNoData),
      92        5352 :               noDataValue_(noDataValue)
      93             :         {
      94        5352 :         }
      95             : 
      96     1589640 :         double value(int idx) const
      97             :         {
      98     1589640 :             if (line_ == nullptr)
      99        5344 :                 return NaN;
     100     1584296 :             if (idx < 0 || idx >= int(size_))
     101       10622 :                 return NaN;
     102     1573674 :             double v = line_[idx];
     103     1573674 :             if (hasNoData_ && v == noDataValue_)
     104          12 :                 return NaN;
     105     1573662 :             return v;
     106             :         }
     107             : 
     108             :       private:
     109             :         const double *line_;
     110             :         size_t size_;
     111             :         bool hasNoData_;
     112             :         double noDataValue_;
     113             :     };
     114             : 
     115        2676 :     void feedLine_(const double *line)
     116             :     {
     117        2676 :         writer_.beginningOfLine();
     118             : 
     119        2676 :         ExtendedLine previous(&previousLine_[0], width_, hasNoData_,
     120             :                               noDataValue_);
     121        2676 :         ExtendedLine current(line, width_, hasNoData_, noDataValue_);
     122      400082 :         for (int colIdx = -1; colIdx < int(width_); colIdx++)
     123             :         {
     124      397410 :             const ValuedPoint upperLeft(colIdx + 1 - .5, lineIdx_ - .5,
     125             :                                         previous.value(colIdx));
     126      397410 :             const ValuedPoint upperRight(colIdx + 1 + .5, lineIdx_ - .5,
     127             :                                          previous.value(colIdx + 1));
     128      397410 :             const ValuedPoint lowerLeft(colIdx + 1 - .5, lineIdx_ + .5,
     129             :                                         current.value(colIdx));
     130      397410 :             const ValuedPoint lowerRight(colIdx + 1 + .5, lineIdx_ + .5,
     131             :                                          current.value(colIdx + 1));
     132             : 
     133      794820 :             Square(upperLeft, upperRight, lowerLeft, lowerRight)
     134      397410 :                 .process(levelGenerator_, writer_);
     135             :         }
     136        2672 :         if (line != nullptr)
     137        2635 :             std::copy(line, line + width_, previousLine_.begin());
     138        2672 :         lineIdx_++;
     139             : 
     140        2672 :         writer_.endOfLine();
     141        2672 :     }
     142             : };
     143             : 
     144             : template <typename ContourWriter, typename LevelGenerator>
     145             : inline ContourGenerator<ContourWriter, LevelGenerator> *
     146             : newContourGenerator(size_t width, size_t height, bool hasNoData,
     147             :                     double noDataValue, ContourWriter &writer,
     148             :                     LevelGenerator &levelGenerator)
     149             : {
     150             :     return new ContourGenerator<ContourWriter, LevelGenerator>(
     151             :         width, height, hasNoData, noDataValue, writer, levelGenerator);
     152             : }
     153             : 
     154             : template <typename ContourWriter, typename LevelGenerator>
     155             : class ContourGeneratorFromRaster
     156             :     : public ContourGenerator<ContourWriter, LevelGenerator>
     157             : {
     158             :   public:
     159          26 :     ContourGeneratorFromRaster(const GDALRasterBandH band, bool hasNoData,
     160             :                                double noDataValue, ContourWriter &writer,
     161             :                                LevelGenerator &levelGenerator)
     162             :         : ContourGenerator<ContourWriter, LevelGenerator>(
     163          78 :               GDALGetRasterBandXSize(band), GDALGetRasterBandYSize(band),
     164             :               hasNoData, noDataValue, writer, levelGenerator),
     165          26 :           band_(band)
     166             :     {
     167          26 :     }
     168             : 
     169          26 :     bool process(GDALProgressFunc progressFunc = nullptr,
     170             :                  void *progressData = nullptr)
     171             :     {
     172          26 :         size_t width = GDALGetRasterBandXSize(band_);
     173          26 :         size_t height = GDALGetRasterBandYSize(band_);
     174          52 :         std::vector<double> line;
     175          26 :         line.resize(width);
     176             : 
     177        2633 :         for (size_t lineIdx = 0; lineIdx < height; lineIdx++)
     178             :         {
     179        5224 :             if (progressFunc &&
     180        2612 :                 progressFunc(double(lineIdx) / height, "Processing line",
     181             :                              progressData) == FALSE)
     182           0 :                 return false;
     183             : 
     184             :             CPLErr error =
     185        2612 :                 GDALRasterIO(band_, GF_Read, 0, int(lineIdx), int(width), 1,
     186        2612 :                              &line[0], int(width), 1, GDT_Float64, 0, 0);
     187        2612 :             if (error != CE_None)
     188             :             {
     189           1 :                 CPLDebug("CONTOUR", "failed fetch %d %d", int(lineIdx),
     190             :                          int(width));
     191           1 :                 return false;
     192             :             }
     193        2611 :             this->feedLine(&line[0]);
     194             :         }
     195          21 :         if (progressFunc)
     196          21 :             progressFunc(1.0, "", progressData);
     197          21 :         return true;
     198             :     }
     199             : 
     200             :   private:
     201             :     const GDALRasterBandH band_;
     202             : 
     203             :     ContourGeneratorFromRaster(const ContourGeneratorFromRaster &) = delete;
     204             :     ContourGeneratorFromRaster &
     205             :     operator=(const ContourGeneratorFromRaster &) = delete;
     206             : };
     207             : 
     208             : }  // namespace marching_squares
     209             : 
     210             : #endif

Generated by: LCOV version 1.14