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: 2025-01-18 12:42:00 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          58 :     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          58 :           levelGenerator_(levelGenerator)
      38             :     {
      39          58 :         previousLine_.resize(width_);
      40          58 :         std::fill(previousLine_.begin(), previousLine_.end(), NaN);
      41          58 :     }
      42             : 
      43        5166 :     CPLErr feedLine(const double *line)
      44             :     {
      45        5166 :         if (lineIdx_ <= height_)
      46             :         {
      47        5166 :             feedLine_(line);
      48        5166 :             if (lineIdx_ == height_)
      49             :             {
      50             :                 // last line
      51          57 :                 feedLine_(nullptr);
      52             :             }
      53             :         }
      54        5166 :         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       10446 :         ExtendedLine(const double *line, size_t size, bool hasNoData,
      74             :                      double noDataValue)
      75             :             : line_(line), size_(size), hasNoData_(hasNoData),
      76       10446 :               noDataValue_(noDataValue)
      77             :         {
      78       10446 :         }
      79             : 
      80     3131604 :         double value(int idx) const
      81             :         {
      82     3131604 :             if (line_ == nullptr)
      83       10446 :                 return NaN;
      84     3121156 :             if (idx < 0 || idx >= int(size_))
      85       20778 :                 return NaN;
      86     3100382 :             double v = line_[idx];
      87     3100382 :             if (hasNoData_ && v == noDataValue_)
      88           0 :                 return NaN;
      89     3100382 :             return v;
      90             :         }
      91             : 
      92             :       private:
      93             :         const double *line_;
      94             :         size_t size_;
      95             :         bool hasNoData_;
      96             :         double noDataValue_;
      97             :     };
      98             : 
      99        5223 :     void feedLine_(const double *line)
     100             :     {
     101        5223 :         writer_.beginningOfLine();
     102             : 
     103        5223 :         ExtendedLine previous(&previousLine_[0], width_, hasNoData_,
     104             :                               noDataValue_);
     105        5223 :         ExtendedLine current(line, width_, hasNoData_, noDataValue_);
     106      788125 :         for (int colIdx = -1; colIdx < int(width_); colIdx++)
     107             :         {
     108      782902 :             const ValuedPoint upperLeft(colIdx + 1 - .5, lineIdx_ - .5,
     109             :                                         previous.value(colIdx));
     110      782902 :             const ValuedPoint upperRight(colIdx + 1 + .5, lineIdx_ - .5,
     111             :                                          previous.value(colIdx + 1));
     112      782902 :             const ValuedPoint lowerLeft(colIdx + 1 - .5, lineIdx_ + .5,
     113             :                                         current.value(colIdx));
     114      782902 :             const ValuedPoint lowerRight(colIdx + 1 + .5, lineIdx_ + .5,
     115             :                                          current.value(colIdx + 1));
     116             : 
     117     1565802 :             Square(upperLeft, upperRight, lowerLeft, lowerRight)
     118      782902 :                 .process(levelGenerator_, writer_);
     119             :         }
     120        5223 :         if (line != nullptr)
     121        5166 :             std::copy(line, line + width_, previousLine_.begin());
     122        5223 :         lineIdx_++;
     123             : 
     124        5223 :         writer_.endOfLine();
     125        5223 :     }
     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          41 :     ContourGeneratorFromRaster(const GDALRasterBandH band, bool hasNoData,
     144             :                                double noDataValue, ContourWriter &writer,
     145             :                                LevelGenerator &levelGenerator)
     146             :         : ContourGenerator<ContourWriter, LevelGenerator>(
     147         123 :               GDALGetRasterBandXSize(band), GDALGetRasterBandYSize(band),
     148             :               hasNoData, noDataValue, writer, levelGenerator),
     149          41 :           band_(band)
     150             :     {
     151          41 :     }
     152             : 
     153          41 :     bool process(GDALProgressFunc progressFunc = nullptr,
     154             :                  void *progressData = nullptr)
     155             :     {
     156          41 :         size_t width = GDALGetRasterBandXSize(band_);
     157          41 :         size_t height = GDALGetRasterBandYSize(band_);
     158          82 :         std::vector<double> line;
     159          41 :         line.resize(width);
     160             : 
     161        5177 :         for (size_t lineIdx = 0; lineIdx < height; lineIdx++)
     162             :         {
     163       10274 :             if (progressFunc &&
     164        5137 :                 progressFunc(double(lineIdx) / height, "Processing line",
     165             :                              progressData) == FALSE)
     166           0 :                 return false;
     167             : 
     168             :             CPLErr error =
     169        5137 :                 GDALRasterIO(band_, GF_Read, 0, int(lineIdx), int(width), 1,
     170        5137 :                              &line[0], int(width), 1, GDT_Float64, 0, 0);
     171        5137 :             if (error != CE_None)
     172             :             {
     173           1 :                 CPLDebug("CONTOUR", "failed fetch %d %d", int(lineIdx),
     174             :                          int(width));
     175           1 :                 return false;
     176             :             }
     177        5136 :             this->feedLine(&line[0]);
     178             :         }
     179          40 :         if (progressFunc)
     180          40 :             progressFunc(1.0, "", progressData);
     181          40 :         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