LCOV - code coverage report
Current view: top level - alg/marching_squares - contour_generator.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 59 61 96.7 %
Date: 2024-11-21 22:18:42 Functions: 44 44 100.0 %

          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             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #ifndef MARCHING_SQUARES_CONTOUR_GENERATOR_H
      14             : #define MARCHING_SQUARES_CONTOUR_GENERATOR_H
      15             : 
      16             : #include <vector>
      17             : #include <algorithm>
      18             : 
      19             : #include "gdal.h"
      20             : 
      21             : #include "utility.h"
      22             : #include "point.h"
      23             : #include "square.h"
      24             : 
      25             : namespace marching_squares
      26             : {
      27             : 
      28             : template <typename ContourWriter, typename LevelGenerator>
      29             : class ContourGenerator
      30             : {
      31             :   public:
      32          47 :     ContourGenerator(size_t width, size_t height, bool hasNoData,
      33             :                      double noDataValue, ContourWriter &writer,
      34             :                      LevelGenerator &levelGenerator)
      35             :         : width_(width), height_(height), hasNoData_(hasNoData),
      36             :           noDataValue_(noDataValue), previousLine_(), writer_(writer),
      37          47 :           levelGenerator_(levelGenerator)
      38             :     {
      39          47 :         previousLine_.resize(width_);
      40          47 :         std::fill(previousLine_.begin(), previousLine_.end(), NaN);
      41          47 :     }
      42             : 
      43        4020 :     CPLErr feedLine(const double *line)
      44             :     {
      45        4020 :         if (lineIdx_ <= height_)
      46             :         {
      47        4020 :             feedLine_(line);
      48        4020 :             if (lineIdx_ == height_)
      49             :             {
      50             :                 // last line
      51          46 :                 feedLine_(nullptr);
      52             :             }
      53             :         }
      54        4020 :         return CE_None;
      55             :     }
      56             : 
      57             :   private:
      58             :     size_t width_;
      59             :     size_t height_;
      60             :     bool hasNoData_;
      61             :     double noDataValue_;
      62             : 
      63             :     size_t lineIdx_ = 0;
      64             : 
      65             :     std::vector<double> previousLine_;
      66             : 
      67             :     ContourWriter &writer_;
      68             :     LevelGenerator &levelGenerator_;
      69             : 
      70             :     class ExtendedLine
      71             :     {
      72             :       public:
      73        8132 :         ExtendedLine(const double *line, size_t size, bool hasNoData,
      74             :                      double noDataValue)
      75             :             : line_(line), size_(size), hasNoData_(hasNoData),
      76        8132 :               noDataValue_(noDataValue)
      77             :         {
      78        8132 :         }
      79             : 
      80     2403948 :         double value(int idx) const
      81             :         {
      82     2403948 :             if (line_ == nullptr)
      83        8132 :                 return NaN;
      84     2395816 :             if (idx < 0 || idx >= int(size_))
      85       16172 :                 return NaN;
      86     2379642 :             double v = line_[idx];
      87     2379642 :             if (hasNoData_ && v == noDataValue_)
      88           0 :                 return NaN;
      89     2379642 :             return v;
      90             :         }
      91             : 
      92             :       private:
      93             :         const double *line_;
      94             :         size_t size_;
      95             :         bool hasNoData_;
      96             :         double noDataValue_;
      97             :     };
      98             : 
      99        4066 :     void feedLine_(const double *line)
     100             :     {
     101        4066 :         writer_.beginningOfLine();
     102             : 
     103        4066 :         ExtendedLine previous(&previousLine_[0], width_, hasNoData_,
     104             :                               noDataValue_);
     105        4066 :         ExtendedLine current(line, width_, hasNoData_, noDataValue_);
     106      605053 :         for (int colIdx = -1; colIdx < int(width_); colIdx++)
     107             :         {
     108      600987 :             const ValuedPoint upperLeft(colIdx + 1 - .5, lineIdx_ - .5,
     109             :                                         previous.value(colIdx));
     110      600987 :             const ValuedPoint upperRight(colIdx + 1 + .5, lineIdx_ - .5,
     111             :                                          previous.value(colIdx + 1));
     112      600987 :             const ValuedPoint lowerLeft(colIdx + 1 - .5, lineIdx_ + .5,
     113             :                                         current.value(colIdx));
     114      600987 :             const ValuedPoint lowerRight(colIdx + 1 + .5, lineIdx_ + .5,
     115             :                                          current.value(colIdx + 1));
     116             : 
     117     1201974 :             Square(upperLeft, upperRight, lowerLeft, lowerRight)
     118      600987 :                 .process(levelGenerator_, writer_);
     119             :         }
     120        4066 :         if (line != nullptr)
     121        4020 :             std::copy(line, line + width_, previousLine_.begin());
     122        4066 :         lineIdx_++;
     123             : 
     124        4066 :         writer_.endOfLine();
     125        4066 :     }
     126             : };
     127             : 
     128             : template <typename ContourWriter, typename LevelGenerator>
     129             : inline ContourGenerator<ContourWriter, LevelGenerator> *
     130             : newContourGenerator(size_t width, size_t height, bool hasNoData,
     131             :                     double noDataValue, ContourWriter &writer,
     132             :                     LevelGenerator &levelGenerator)
     133             : {
     134             :     return new ContourGenerator<ContourWriter, LevelGenerator>(
     135             :         width, height, hasNoData, noDataValue, writer, levelGenerator);
     136             : }
     137             : 
     138             : template <typename ContourWriter, typename LevelGenerator>
     139             : class ContourGeneratorFromRaster
     140             :     : public ContourGenerator<ContourWriter, LevelGenerator>
     141             : {
     142             :   public:
     143          31 :     ContourGeneratorFromRaster(const GDALRasterBandH band, bool hasNoData,
     144             :                                double noDataValue, ContourWriter &writer,
     145             :                                LevelGenerator &levelGenerator)
     146             :         : ContourGenerator<ContourWriter, LevelGenerator>(
     147          93 :               GDALGetRasterBandXSize(band), GDALGetRasterBandYSize(band),
     148             :               hasNoData, noDataValue, writer, levelGenerator),
     149          31 :           band_(band)
     150             :     {
     151          31 :     }
     152             : 
     153          31 :     bool process(GDALProgressFunc progressFunc = nullptr,
     154             :                  void *progressData = nullptr)
     155             :     {
     156          31 :         size_t width = GDALGetRasterBandXSize(band_);
     157          31 :         size_t height = GDALGetRasterBandYSize(band_);
     158          62 :         std::vector<double> line;
     159          31 :         line.resize(width);
     160             : 
     161        4023 :         for (size_t lineIdx = 0; lineIdx < height; lineIdx++)
     162             :         {
     163        7986 :             if (progressFunc &&
     164        3993 :                 progressFunc(double(lineIdx) / height, "Processing line",
     165             :                              progressData) == FALSE)
     166           0 :                 return false;
     167             : 
     168             :             CPLErr error =
     169        3993 :                 GDALRasterIO(band_, GF_Read, 0, int(lineIdx), int(width), 1,
     170        3993 :                              &line[0], int(width), 1, GDT_Float64, 0, 0);
     171        3993 :             if (error != CE_None)
     172             :             {
     173           1 :                 CPLDebug("CONTOUR", "failed fetch %d %d", int(lineIdx),
     174             :                          int(width));
     175           1 :                 return false;
     176             :             }
     177        3992 :             this->feedLine(&line[0]);
     178             :         }
     179          30 :         if (progressFunc)
     180          30 :             progressFunc(1.0, "", progressData);
     181          30 :         return true;
     182             :     }
     183             : 
     184             :   private:
     185             :     const GDALRasterBandH band_;
     186             : 
     187             :     ContourGeneratorFromRaster(const ContourGeneratorFromRaster &) = delete;
     188             :     ContourGeneratorFromRaster &
     189             :     operator=(const ContourGeneratorFromRaster &) = delete;
     190             : };
     191             : 
     192             : }  // namespace marching_squares
     193             : 
     194             : #endif

Generated by: LCOV version 1.14