LCOV - code coverage report
Current view: top level - autotest/cpp - test_marching_squares_square.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 237 237 100.0 %
Date: 2025-12-28 01:00:05 Functions: 58 58 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL algorithms
       4             :  * Purpose:  Tests for the marching squares algorithm
       5             :  * Author:   Hugo Mercier, <hugo dot mercier at oslandia dot com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2018, Hugo Mercier, <hugo dot mercier at oslandia dot com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "gdal_unit_test.h"
      14             : 
      15             : #include "gdal_alg.h"
      16             : 
      17             : #include "marching_squares/square.h"
      18             : #include "marching_squares/level_generator.h"
      19             : #include <vector>
      20             : #include <limits>
      21             : #include <map>
      22             : #include <fstream>
      23             : 
      24             : #include "gtest_include.h"
      25             : 
      26             : #if defined(__clang__)
      27             : #pragma clang diagnostic push
      28             : #pragma clang diagnostic ignored "-Wweak-vtables"
      29             : #endif
      30             : 
      31             : namespace test_marching_squares_square
      32             : {
      33             : using namespace marching_squares;
      34             : 
      35             : struct Writer
      36             : {
      37             :     typedef std::pair<Point, Point> Segment;
      38             : 
      39           6 :     void addSegment(int levelIdx, const Point &first, const Point &second)
      40             :     {
      41           6 :         contours[levelIdx].push_back(Segment(first, second));
      42           6 :     }
      43             : 
      44          11 :     void addBorderSegment(int levelIdx, const Point &first, const Point &second)
      45             :     {
      46          11 :         borders[levelIdx].push_back(Segment(first, second));
      47          11 :     }
      48             : 
      49             :     std::map<int, std::vector<Segment>> contours;
      50             :     std::map<int, std::vector<Segment>> borders;
      51             :     const bool polygonize = true;
      52             : };
      53             : 
      54             : // Common fixture with test data
      55             : struct test_ms_square : public ::testing::Test
      56             : {
      57             : };
      58             : 
      59             : // Dummy test
      60           4 : TEST_F(test_ms_square, dummy)
      61             : {
      62             :     {
      63           1 :         const double levels[] = {0, 4};
      64             :         FixedLevelRangeIterator levelGenerator(
      65           1 :             levels, 2, -std::numeric_limits<double>::infinity(),
      66           2 :             std::numeric_limits<double>::infinity());
      67           1 :         auto r = levelGenerator.range(0, 5.0);
      68           1 :         auto b = r.begin();
      69           1 :         EXPECT_EQ((*b).first, 1);
      70           1 :         EXPECT_EQ((*b).second, 4.0);
      71           1 :         auto e = r.end();
      72           1 :         EXPECT_EQ((*e).first, 2);
      73           1 :         EXPECT_EQ((*e).second, Inf);
      74             :     }
      75             :     {
      76             :         IntervalLevelRangeIterator levelGenerator(
      77           1 :             0, 4, -std::numeric_limits<double>::infinity());
      78           1 :         auto r = levelGenerator.range(0, 5.0);
      79           1 :         auto b = r.begin();
      80           1 :         EXPECT_EQ((*b).first, 1);
      81           1 :         EXPECT_EQ((*b).second, 4.0);
      82           1 :         auto e = r.end();
      83           1 :         EXPECT_EQ((*e).first, 2);
      84           1 :         EXPECT_EQ((*e).second, 8.0);
      85             :     }
      86             :     {
      87             :         IntervalLevelRangeIterator levelGenerator(
      88           1 :             0, 10, -std::numeric_limits<double>::infinity());
      89           1 :         auto r = levelGenerator.range(-18, 5.0);
      90           1 :         auto b = r.begin();
      91           1 :         EXPECT_EQ((*b).first, -1);
      92           1 :         EXPECT_EQ((*b).second, -10.0);
      93           1 :         auto e = r.end();
      94           1 :         EXPECT_EQ((*e).first, 1);
      95           1 :         EXPECT_EQ((*e).second, 10.0);
      96             :     }
      97             :     {
      98             :         ExponentialLevelRangeIterator levelGenerator(
      99           1 :             2, -std::numeric_limits<double>::infinity());
     100           1 :         auto r = levelGenerator.range(0, 5.0);
     101           1 :         auto b = r.begin();
     102           1 :         EXPECT_EQ((*b).first, 1);
     103           1 :         EXPECT_EQ((*b).second, 1.0);
     104           1 :         ++b;
     105           1 :         EXPECT_EQ((*b).first, 2);
     106           1 :         EXPECT_EQ((*b).second, 2.0);
     107           1 :         ++b;
     108           1 :         EXPECT_EQ((*b).first, 3);
     109           1 :         EXPECT_EQ((*b).second, 4.0);
     110           1 :         auto e = r.end();
     111           1 :         EXPECT_EQ((*e).first, 4);
     112           1 :         EXPECT_EQ((*e).second, 8.0);
     113             :     }
     114           1 : }
     115             : 
     116           4 : TEST_F(test_ms_square, only_zero)
     117             : {
     118             :     // Square with only 0, level = 0.1
     119           1 :     Square square(ValuedPoint(0, 1, 0), ValuedPoint(1, 1, 0),
     120           2 :                   ValuedPoint(0, 0, 0), ValuedPoint(1, 0, 0));
     121           1 :     Square::Segments segments(square.segments(.1));
     122             :     //
     123             :     //   0                    0
     124             :     //    +------------------+
     125             :     //    |                  |
     126             :     //    |                  |
     127             :     //    |                  |
     128             :     //    |                  |
     129             :     //    |                  |
     130             :     //    |                  |
     131             :     //    |                  |
     132             :     //    +------------------+
     133             :     //   0                    0
     134           1 :     EXPECT_EQ(segments.size(), size_t(0));
     135           1 : }
     136             : 
     137           4 : TEST_F(test_ms_square, only_one)
     138             : {
     139             :     // Square with only 1, level = 0.1
     140           1 :     Square square(ValuedPoint(0, 1, 1), ValuedPoint(1, 1, 1),
     141           2 :                   ValuedPoint(0, 0, 1), ValuedPoint(1, 0, 1));
     142             :     //
     143             :     //   1                    1
     144             :     //    +------------------+
     145             :     //    |                  |
     146             :     //    |                  |
     147             :     //    |                  |
     148             :     //    |                  |
     149             :     //    |                  |
     150             :     //    |                  |
     151             :     //    |                  |
     152             :     //    +------------------+
     153             :     //   1                    1
     154           1 :     Square::Segments segments(square.segments(.1));
     155           1 :     EXPECT_EQ(segments.size(), size_t(0));
     156           1 : }
     157             : 
     158           4 : TEST_F(test_ms_square, only_zero_level_1)
     159             : {
     160             :     // Square with only 1, level = 1.0
     161           1 :     Square square(ValuedPoint(0, 1, 1), ValuedPoint(1, 1, 1),
     162           2 :                   ValuedPoint(0, 0, 1), ValuedPoint(1, 0, 1));
     163             :     //
     164             :     //   1                    1
     165             :     //    +------------------+
     166             :     //    |                  |
     167             :     //    |                  |
     168             :     //    |                  |
     169             :     //    |                  |
     170             :     //    |                  |
     171             :     //    |                  |
     172             :     //    |                  |
     173             :     //    +------------------+
     174             :     //   1                    1
     175           1 :     Square::Segments segments(square.segments(1.0));
     176           1 :     EXPECT_EQ(segments.size(), size_t(0));
     177           1 : }
     178             : 
     179           4 : TEST_F(test_ms_square, one_segment)
     180             : {
     181             :     // Square with one segment, level = 0.1
     182           1 :     Square square(ValuedPoint(0, 1, 1), ValuedPoint(1, 1, 0),
     183           2 :                   ValuedPoint(0, 0, 0), ValuedPoint(1, 0, 0));
     184             :     //
     185             :     //   0                    0
     186             :     //    +------------------+
     187             :     //    |                  |
     188             :     //    |                  |
     189             :     //    |                  |
     190             :     //    |                  |
     191             :     //    |                  |
     192             :     //    o                  |
     193             :     //    | \                |
     194             :     //    +---o--------------+
     195             :     //   1                    0
     196           1 :     Square::Segments segments(square.segments(.1));
     197           1 :     EXPECT_EQ(segments.size(), size_t(1));
     198           1 :     EXPECT_TRUE(segments[0].first == Point(.9, 1));
     199           1 :     EXPECT_TRUE(segments[0].second == Point(0, .1));
     200           1 : }
     201             : 
     202           4 : TEST_F(test_ms_square, fudge_test_1)
     203             : {
     204             :     // Fudge test 1
     205           1 :     Square square(ValuedPoint(0, 1, 0), ValuedPoint(1, 1, 1),
     206           2 :                   ValuedPoint(0, 0, 1), ValuedPoint(1, 0, 1));
     207             :     //
     208             :     //   0                    1
     209             :     //    +------------------o
     210             :     //    |               __/|
     211             :     //    |            __/   |
     212             :     //    |         __/      |
     213             :     //    |       _/         |
     214             :     //    |    __/           |
     215             :     //    | __/              |
     216             :     //    |/                 |
     217             :     //    o------------------+
     218             :     //   1                    1
     219             :     //  (0,0)
     220             :     {
     221           1 :         Square::Segments segments(square.segments(0.0));
     222           1 :         EXPECT_EQ(segments.size(), size_t(0));
     223             :     }
     224             :     {
     225           1 :         Square::Segments segments(square.segments(1.0));
     226           1 :         EXPECT_EQ(segments.size(), size_t(1));
     227           1 :         EXPECT_NEAR(segments[0].first.x, 0.0, 0.001);
     228           1 :         EXPECT_NEAR(segments[0].first.y, 0.0, 0.001);
     229           1 :         EXPECT_NEAR(segments[0].second.x, 1.0, 0.001);
     230           1 :         EXPECT_NEAR(segments[0].second.y, 1.0, 0.001);
     231             :     }
     232           1 : }
     233             : 
     234           4 : TEST_F(test_ms_square, fudge_test_2)
     235             : {
     236             :     // Fudge test 2
     237           1 :     Square square(ValuedPoint(0, 1, 1), ValuedPoint(1, 1, 0),
     238           2 :                   ValuedPoint(0, 0, 0), ValuedPoint(1, 0, 0));
     239             :     //
     240             :     //   1                    0
     241             :     //    +o-----------------+
     242             :     //    o+                 |
     243             :     //    |                  |
     244             :     //    |                  |
     245             :     //    |                  |
     246             :     //    |                  |
     247             :     //    |                  |
     248             :     //    |                  |
     249             :     //    +------------------+
     250             :     //   0                    0
     251             :     // (0,0)
     252             :     {
     253           1 :         Square::Segments segments(square.segments(1.0));
     254           1 :         EXPECT_EQ(segments.size(), 1U);
     255           1 :         EXPECT_NEAR(segments[0].first.x, 0.0, 0.001);
     256           1 :         EXPECT_NEAR(segments[0].first.y, 1.0, 0.001);
     257           1 :         EXPECT_NEAR(segments[0].second.x, 0.0, 0.001);
     258           1 :         EXPECT_NEAR(segments[0].second.y, 1.0, 0.001);
     259             :     }
     260             :     {
     261           1 :         Square::Segments segments(square.segments(0.0));
     262           1 :         EXPECT_EQ(segments.size(), 0U);
     263             :     }
     264           1 : }
     265             : 
     266           4 : TEST_F(test_ms_square, nan)
     267             : {
     268             :     // A square with NaN
     269           1 :     const Square square(ValuedPoint(2.500000, 1.500000, 224.990005),
     270           1 :                         ValuedPoint(3.500000, 1.500000, NaN),
     271           1 :                         ValuedPoint(2.500000, 2.500000, 225.029999),
     272           2 :                         ValuedPoint(3.500000, 2.500000, 224.770004));
     273             : 
     274             :     //
     275             :     // 224.990005            NaN
     276             :     //    +------------------+
     277             :     //    |                  |
     278             :     //    |                  |
     279             :     //    |                  |
     280             :     //    |                  |
     281             :     //    |                  |
     282             :     //    |                  |
     283             :     //    |                  |
     284             :     //    +------------------+
     285             :     // 225.029999     224.770004
     286             : 
     287           1 :     const Square ul(square.upperLeftSquare());
     288           1 :     const Square ll(square.lowerLeftSquare());
     289             : 
     290             :     // upper left and lower left squares
     291             :     //
     292             :     // 224.990005 224.990005 NaN
     293             :     //    +--------+---------+
     294             :     //    |        |         |
     295             :     //    |        |         |
     296             :     //    |        |         |
     297             :     //    +--------+  224.930002
     298             :     // 225.010002  |         |
     299             :     //    |        |         |
     300             :     //    |    224.900001    |
     301             :     //    +--------+---------+
     302             :     // 225.029999     224.770004
     303             : 
     304           1 :     EXPECT_NEAR(ul.lowerLeft.value, 225.010002, 0.000001);
     305           1 :     EXPECT_NEAR(ul.lowerRight.value, 224.930002, 0.000001);
     306           1 :     EXPECT_NEAR(ul.upperRight.value, 224.990005, 0.000001);
     307           1 :     EXPECT_NEAR(ll.lowerRight.value, 224.900001, 0.000001);
     308             : 
     309           1 :     EXPECT_EQ(ul.lowerLeft.x, ll.upperLeft.x);
     310           1 :     EXPECT_EQ(ul.lowerLeft.y, ll.upperLeft.y);
     311           1 :     EXPECT_EQ(ul.lowerLeft.value, ll.upperLeft.value);
     312             : 
     313           1 :     EXPECT_EQ(ul.lowerRight.x, ll.upperRight.x);
     314           1 :     EXPECT_EQ(ul.lowerRight.y, ll.upperRight.y);
     315           1 :     EXPECT_EQ(ul.lowerRight.value, ll.upperRight.value);
     316             : 
     317           1 :     const Square::Segments segments_up(ul.segments(225));
     318           1 :     const Square::Segments segments_down(ll.segments(225));
     319             : 
     320             :     // segments on 225
     321             :     //
     322             :     // 224.990005 224.990005 NaN
     323             :     //    <--------<---------+
     324             :     //    |        |         |
     325             :     //    o_       |         |
     326             :     //    | \      |         |
     327             :     //    >--o-----<  224.930002
     328             :     // 225.01|002  |         |
     329             :     //    |  \     |         |
     330             :     //    |   |224.900001    |
     331             :     //    >---o----<---------+
     332             :     // 225.029999     224.770004
     333             : 
     334           1 :     EXPECT_EQ(segments_up.size(), 1);
     335           1 :     EXPECT_EQ(segments_down.size(), 1);
     336             : 
     337             :     // the two segments have a point in common
     338           1 :     EXPECT_EQ(segments_up[0].second, segments_down[0].first);
     339           1 : }
     340             : 
     341           4 : TEST_F(test_ms_square, border_test_1)
     342             : {
     343             :     // Border test 1
     344           1 :     const Square square(ValuedPoint(0.5, 0.5, NaN), ValuedPoint(1.5, 0.5, NaN),
     345           1 :                         ValuedPoint(0.5, 1.5, 272.87),
     346           2 :                         ValuedPoint(1.5, 1.5, 272.93));
     347             :     //
     348             :     //   NaN                NaN
     349             :     //    +------------------+
     350             :     //    |                  |
     351             :     //    |                  |
     352             :     //    |                  |
     353             :     //    |                  |
     354             :     //    |                  |
     355             :     //    |                  |
     356             :     //    |                  |
     357             :     //    +------------------+
     358             :     // 272.87             272.93
     359           1 :     const Square ll(square.lowerLeftSquare());
     360           1 :     const Square lr(square.lowerRightSquare());
     361             : 
     362             :     //
     363             :     //   NaN                NaN
     364             :     //    +------------------+
     365             :     //    |                  |
     366             :     //    |                  |
     367             :     // 272.87   272.90000 272.93
     368             :     //    +--------+---------+
     369             :     //    |        |         |
     370             :     //    |        |         |
     371             :     //    |        |         |
     372             :     //    +--------+---------+
     373             :     // 272.87   272.90000 272.93
     374             : 
     375           1 :     Square::Segments segments_l(ll.segments(272.9));
     376           1 :     Square::Segments segments_r(lr.segments(272.9));
     377             : 
     378             :     // the level falls exactly on corners
     379             :     // thanks to the fudge, each corner should be shifted away a bit
     380             : 
     381             :     //
     382             :     //   NaN                NaN
     383             :     //    +------------------+
     384             :     //    |                  |
     385             :     //    |                  |
     386             :     // 272.87   272.90000 272.93
     387             :     //    <-------o>--------->
     388             :     //    |       :|         |
     389             :     //    |       :|         |
     390             :     //    |       :|         |
     391             :     //    <-------o>--------->
     392             :     // 272.87   272.90000 272.93
     393             : 
     394           1 :     EXPECT_EQ(segments_l.size(), size_t(1));
     395           1 :     EXPECT_EQ(segments_r.size(), size_t(0));
     396           1 : }
     397             : 
     398           4 : TEST_F(test_ms_square, multiple_levels)
     399             : {
     400             :     // Multiple levels
     401             :     const Square square(
     402           1 :         ValuedPoint(0.5, 1.5, 272.99), ValuedPoint(1.5, 1.5, NaN),
     403           2 :         ValuedPoint(0.5, 0.5, 273.03), ValuedPoint(1.5, 0.5, 272.9));
     404             :     //
     405             :     // 272.99               NaN
     406             :     //    +------------------+
     407             :     //    |                  |
     408             :     //    |                  |
     409             :     //    |                  |
     410             :     //    |                  |
     411             :     //    |                  |
     412             :     //    |                  |
     413             :     //    |                  |
     414             :     //    +------------------+
     415             :     // 273.03             272.90
     416             : 
     417           1 :     const Square ul(square.upperLeftSquare());
     418             : 
     419             :     //
     420             :     // 272.99   272.99      NaN
     421             :     //    +---------+--------+
     422             :     //    |         |        |
     423             :     //    |         |        |
     424             :     //    |         |        |
     425             :     //    +---------+        |
     426             :     // 273.01    272.97      |
     427             :     //    |                  |
     428             :     //    |                  |
     429             :     //    +------------------+
     430             :     // 273.03             272.90
     431           1 :     EXPECT_TRUE((std::fabs(ul.lowerLeft.value - 273.01) < 0.01));
     432           1 :     EXPECT_TRUE((std::fabs(ul.lowerRight.value - 272.97) < 0.01));
     433           1 :     EXPECT_TRUE((std::fabs(ul.upperRight.value - 272.99) < 0.01));
     434             : 
     435             :     // We have a NaN value on the right, we should then have a right border
     436           1 :     EXPECT_TRUE((ul.borders == Square::RIGHT_BORDER));
     437             : 
     438           2 :     Writer writer;
     439             :     // levels starting at min and increasing by 0.1
     440             :     IntervalLevelRangeIterator levelGenerator(
     441           1 :         0, .1, -std::numeric_limits<double>::infinity());
     442             : 
     443           1 :     ul.process(levelGenerator, writer);
     444             : 
     445             :     // we only have a contour when level = 273.0
     446             :     // (0.5, 1.5)                  (1.5, 1.5)
     447             :     //      272.99   272.99      NaN
     448             :     //         +---------+--------+
     449             :     //         |         ||       |
     450             :     //         o         ||       |
     451             :     //         |\        ||       |
     452             :     //         +-o-------+        |
     453             :     //      273.01    272.97      |
     454             :     //         |                  |
     455             :     //         |                  |
     456             :     //         +------------------+
     457             :     //      273.03             272.90
     458             :     // (0.5, 0.5)                  (1.5, 0.5)
     459             : 
     460           1 :     EXPECT_TRUE((writer.contours.size() == 2));
     461           1 :     EXPECT_TRUE((writer.borders.size() == 1));
     462           1 :     EXPECT_TRUE((writer.contours.find(2730) != writer.contours.end()));
     463           1 :     EXPECT_TRUE((writer.contours.find(2731) != writer.contours.end()));
     464           1 :     EXPECT_TRUE((writer.borders.find(2730) != writer.borders.end()));
     465             :     // we have one segment border on the right
     466           1 :     EXPECT_TRUE((writer.borders[2730].size() == 1));
     467           1 :     EXPECT_TRUE((writer.contours[2730].size() == 1));
     468           1 :     EXPECT_TRUE((writer.contours[2731].size() == 1));
     469           1 : }
     470             : 
     471           4 : TEST_F(test_ms_square, border_test_3)
     472             : {
     473             :     // Border test 3
     474           1 :     Square square(ValuedPoint(0, 0, 10), ValuedPoint(1, 0, 5),
     475           2 :                   ValuedPoint(0, 1, NaN), ValuedPoint(1, 1, 4));
     476             :     // level value = 7
     477             :     //   10        7.5        5
     478             :     //    +---------+--------+
     479             :     //    |         |        |
     480             :     //    |        _o        |
     481             :     //    |      _/ |        |
     482             :     // 10 +====o====+ 6.33   |
     483             :     //    |                  |
     484             :     //    |                  |
     485             :     //    |                  |
     486             :     //    +------------------+
     487             :     //   NaN                  4
     488           1 :     const Square ul(square.upperLeftSquare());
     489             :     // "Lower left value",
     490           1 :     EXPECT_TRUE((std::fabs(ul.lowerLeft.value - 10.00) < 0.01));
     491             :     // "Lower right value",
     492           1 :     EXPECT_TRUE((std::fabs(ul.lowerRight.value - 6.33) < 0.01));
     493             :     // "Upper right value",
     494           1 :     EXPECT_TRUE((std::fabs(ul.upperRight.value - 7.50) < 0.01));
     495             : 
     496             :     // We have a NaN value on the right, we should then have a right border
     497             :     // "We have the lower border",
     498           1 :     EXPECT_TRUE(ul.borders == Square::LOWER_BORDER);
     499             : 
     500             :     {
     501             :         // ... with a level interval
     502           2 :         Writer writer;
     503             :         IntervalLevelRangeIterator levelGenerator(
     504           1 :             7, 5, -std::numeric_limits<double>::infinity());
     505           1 :         ul.process(levelGenerator, writer);
     506             : 
     507             :         // we have one contour at 7 and 12
     508             :         // and two borders: one, at 7 and the second at >7 (12)
     509             :         // "We have 2 borders",
     510           1 :         EXPECT_EQ(writer.borders.size(), size_t(2));
     511             :         // "We have 2 contours",
     512           1 :         EXPECT_EQ(writer.contours.size(), size_t(2));
     513             : 
     514             :         // "Border at 0",
     515           1 :         EXPECT_TRUE(writer.borders.find(0) != writer.borders.end());
     516             :         // "Border at 1",
     517           1 :         EXPECT_TRUE(writer.borders.find(1) != writer.borders.end());
     518             :         // "No contour at 0",
     519           1 :         EXPECT_TRUE(writer.contours.find(0) != writer.contours.end());
     520             :         // and we have one contour and 2 borders
     521             :         // "1 contour at 0",
     522           1 :         EXPECT_EQ(writer.contours[0].size(), size_t(1));
     523             :         // "1 border at 0",
     524           1 :         EXPECT_EQ(writer.borders[0].size(), size_t(1));
     525             :         // "1 border at 1",
     526           1 :         EXPECT_EQ(writer.borders[1].size(), size_t(1));
     527             :         // the border at 7.0 is around 0.5, 0.5
     528             :         // "Border at 1 is around 0.5, 0.5",
     529           1 :         EXPECT_TRUE((writer.borders[0][0].first.x == 0.5 &&
     530             :                      writer.borders[0][0].first.y == 0.5) ||
     531             :                     (writer.borders[0][0].second.x == 0.5 &&
     532             :                      writer.borders[0][0].second.y == 0.5));
     533             :         // the border at 12.0 is around 0, 0.5
     534             :         // "Border at 1 is around 0, 0.5",
     535           1 :         EXPECT_TRUE((writer.borders[1][0].first.x == 0.0 &&
     536             :                      writer.borders[1][0].first.y == 0.5) ||
     537             :                     (writer.borders[1][0].second.x == 0.0 &&
     538             :                      writer.borders[1][0].second.y == 0.5));
     539             :     }
     540             : 
     541             :     // test with a fixed set of levels
     542             :     {
     543           2 :         Writer writer;
     544           2 :         std::vector<double> levels = {7.0};
     545             :         FixedLevelRangeIterator levelGenerator(
     546           1 :             &levels[0], 1, -std::numeric_limits<double>::infinity(),
     547           2 :             std::numeric_limits<double>::infinity());
     548           1 :         ul.process(levelGenerator, writer);
     549             : 
     550             :         // we have one contour at 7 and 12
     551             :         // and two borders: one, at 7 and the second at >7 (12)
     552             :         // "We have 2 borders",
     553           1 :         EXPECT_EQ(writer.borders.size(), size_t(2));
     554             :         // "We have 2 contours",
     555           1 :         EXPECT_EQ(writer.contours.size(), size_t(2));
     556             : 
     557             :         // "Border at 0",
     558           1 :         EXPECT_TRUE(writer.borders.find(0) != writer.borders.end());
     559             :         // "Border at 1",
     560           1 :         EXPECT_TRUE(writer.borders.find(1) != writer.borders.end());
     561             :         // "No contour at 0",
     562           1 :         EXPECT_TRUE(writer.contours.find(0) != writer.contours.end());
     563             :         // and we have one contour and 2 borders
     564             :         // "1 contour at 0",
     565           1 :         EXPECT_EQ(writer.contours[0].size(), size_t(1));
     566             :         // "1 border at 0",
     567           1 :         EXPECT_EQ(writer.borders[0].size(), size_t(1));
     568             :         // "1 border at 1",
     569           1 :         EXPECT_EQ(writer.borders[1].size(), size_t(1));
     570             :         // the border at 7.0 is around 0.5, 0.5
     571             :         // "Border at 1 is around 0.5, 0.5",
     572           1 :         EXPECT_TRUE((writer.borders[0][0].first.x == 0.5 &&
     573             :                      writer.borders[0][0].first.y == 0.5) ||
     574             :                     (writer.borders[0][0].second.x == 0.5 &&
     575             :                      writer.borders[0][0].second.y == 0.5));
     576             :         // the border at 12.0 is around 0, 0.5
     577             :         // "Border at 1 is around 0, 0.5",
     578           1 :         EXPECT_TRUE((writer.borders[1][0].first.x == 0.0 &&
     579             :                      writer.borders[1][0].first.y == 0.5) ||
     580             :                     (writer.borders[1][0].second.x == 0.0 &&
     581             :                      writer.borders[1][0].second.y == 0.5));
     582             :     }
     583           1 : }
     584             : 
     585           4 : TEST_F(test_ms_square, level_value_below_square_values)
     586             : {
     587             :     // Test level value below square values
     588           1 :     Square square(ValuedPoint(0, 0, 10), ValuedPoint(1, 0, 5),
     589           2 :                   ValuedPoint(0, 1, 8), ValuedPoint(1, 1, 4));
     590             :     // level value = 2
     591             :     //   10                   5
     592             :     //    +------------------+
     593             :     //    |                  |
     594             :     //    |                  |
     595             :     //    |                  |
     596             :     //    |                  |
     597             :     //    |                  |
     598             :     //    |                  |
     599             :     //    |                  |
     600             :     //    +------------------+
     601             :     //    8                   4
     602             :     {
     603           2 :         Writer writer;
     604           2 :         std::vector<double> levels = {2.0};
     605             :         FixedLevelRangeIterator levelGenerator(
     606           1 :             &levels[0], 1, -std::numeric_limits<double>::infinity(),
     607           2 :             std::numeric_limits<double>::infinity());
     608           1 :         square.process(levelGenerator, writer);
     609           1 :         EXPECT_TRUE((writer.borders.size() == 0));
     610           1 :         EXPECT_TRUE((writer.contours.size() == 0));
     611             :     }
     612           1 : }
     613             : 
     614           4 : TEST_F(test_ms_square, full_border_test_1)
     615             : {
     616             :     // Full border test 1
     617           1 :     Square square(ValuedPoint(-0.5, -0.5, NaN), ValuedPoint(0.5, -0.5, NaN),
     618           2 :                   ValuedPoint(-0.5, 0.5, NaN), ValuedPoint(0.5, 0.5, 5));
     619             :     // level value = 0, 10
     620             :     //   NaN                NaN
     621             :     //    +------------------+
     622             :     //    |                  |
     623             :     //    |                  |
     624             :     //    |                  |
     625             :     //    |                  |
     626             :     //    |                  |
     627             :     //    |                  |
     628             :     //    |                  |
     629             :     //    +------------------+
     630             :     //   NaN                 5
     631             :     {
     632           2 :         Writer writer;
     633             :         IntervalLevelRangeIterator levelGenerator(
     634           1 :             0, 10.0, -std::numeric_limits<double>::infinity());
     635           1 :         square.process(levelGenerator, writer);
     636           1 :         EXPECT_TRUE((writer.borders.size() == 1));
     637           1 :         EXPECT_TRUE((writer.borders[1].size() == 2));
     638           1 :         EXPECT_TRUE(((writer.borders[1][0].first.x == 0.0 &&
     639             :                       writer.borders[1][0].first.y == 0.0) ||
     640             :                      (writer.borders[1][0].second.x == 0.0 &&
     641             :                       writer.borders[1][0].second.y == 0.0)));
     642           1 :         EXPECT_TRUE(((writer.borders[1][0].first.x == 0.5 &&
     643             :                       writer.borders[1][0].first.y == 0.0) ||
     644             :                      (writer.borders[1][0].second.x == 0.5 &&
     645             :                       writer.borders[1][0].second.y == 0.0)));
     646           1 :         EXPECT_TRUE(((writer.borders[1][1].first.x == 0.0 &&
     647             :                       writer.borders[1][1].first.y == 0.0) ||
     648             :                      (writer.borders[1][1].second.x == 0.0 &&
     649             :                       writer.borders[1][1].second.y == 0.0)));
     650           1 :         EXPECT_TRUE(((writer.borders[1][1].first.x == 0.0 &&
     651             :                       writer.borders[1][1].first.y == 0.0) ||
     652             :                      (writer.borders[1][1].second.x == 0.0 &&
     653             :                       writer.borders[1][1].second.y == 0.5)));
     654             :     }
     655           1 : }
     656             : 
     657           4 : TEST_F(test_ms_square, full_border_test_2)
     658             : {
     659             :     // Full border test 2
     660           1 :     Square square(ValuedPoint(-0.5, -0.5, NaN), ValuedPoint(0.5, -0.5, NaN),
     661           2 :                   ValuedPoint(-0.5, 0.5, NaN), ValuedPoint(0.5, 0.5, 5));
     662             :     // level value = 5.0, 10.0
     663             :     //   NaN                NaN
     664             :     //    +------------------+
     665             :     //    |                  |
     666             :     //    |                  |
     667             :     //    |                  |
     668             :     //    |                  |
     669             :     //    |                  |
     670             :     //    |                  |
     671             :     //    |                  |
     672             :     //    +------------------+
     673             :     //   NaN                 5
     674             :     {
     675           2 :         Writer writer;
     676             :         IntervalLevelRangeIterator levelGenerator(
     677           1 :             5.0, 5.0, -std::numeric_limits<double>::infinity());
     678           1 :         square.process(levelGenerator, writer);
     679           1 :         EXPECT_TRUE((writer.borders.size() == 1));
     680           1 :         EXPECT_TRUE((writer.borders[1].size() == 2));
     681           1 :         EXPECT_TRUE(((writer.borders[1][0].first.x == 0.0 &&
     682             :                       writer.borders[1][0].first.y == 0.0) ||
     683             :                      (writer.borders[1][0].second.x == 0.0 &&
     684             :                       writer.borders[1][0].second.y == 0.0)));
     685           1 :         EXPECT_TRUE(((writer.borders[1][0].first.x == 0.5 &&
     686             :                       writer.borders[1][0].first.y == 0.0) ||
     687             :                      (writer.borders[1][0].second.x == 0.5 &&
     688             :                       writer.borders[1][0].second.y == 0.0)));
     689           1 :         EXPECT_TRUE(((writer.borders[1][1].first.x == 0.0 &&
     690             :                       writer.borders[1][1].first.y == 0.0) ||
     691             :                      (writer.borders[1][1].second.x == 0.0 &&
     692             :                       writer.borders[1][1].second.y == 0.0)));
     693           1 :         EXPECT_TRUE(((writer.borders[1][1].first.x == 0.0 &&
     694             :                       writer.borders[1][1].first.y == 0.0) ||
     695             :                      (writer.borders[1][1].second.x == 0.0 &&
     696             :                       writer.borders[1][1].second.y == 0.5)));
     697             :     }
     698             :     {
     699           2 :         Writer writer;
     700           2 :         std::vector<double> levels = {5.0};
     701             :         FixedLevelRangeIterator levelGenerator(
     702           1 :             &levels[0], 1, -std::numeric_limits<double>::infinity(),
     703           2 :             std::numeric_limits<double>::infinity());
     704           1 :         square.process(levelGenerator, writer);
     705           1 :         EXPECT_TRUE((writer.borders.size() == 1));
     706           1 :         EXPECT_TRUE((writer.borders[1].size() == 2));
     707           1 :         EXPECT_TRUE(((writer.borders[1][0].first.x == 0.0 &&
     708             :                       writer.borders[1][0].first.y == 0.0) ||
     709             :                      (writer.borders[1][0].second.x == 0.0 &&
     710             :                       writer.borders[1][0].second.y == 0.0)));
     711           1 :         EXPECT_TRUE(((writer.borders[1][0].first.x == 0.5 &&
     712             :                       writer.borders[1][0].first.y == 0.0) ||
     713             :                      (writer.borders[1][0].second.x == 0.5 &&
     714             :                       writer.borders[1][0].second.y == 0.0)));
     715           1 :         EXPECT_TRUE(((writer.borders[1][1].first.x == 0.0 &&
     716             :                       writer.borders[1][1].first.y == 0.0) ||
     717             :                      (writer.borders[1][1].second.x == 0.0 &&
     718             :                       writer.borders[1][1].second.y == 0.0)));
     719           1 :         EXPECT_TRUE(((writer.borders[1][1].first.x == 0.0 &&
     720             :                       writer.borders[1][1].first.y == 0.0) ||
     721             :                      (writer.borders[1][1].second.x == 0.0 &&
     722             :                       writer.borders[1][1].second.y == 0.5)));
     723             :     }
     724           1 : }
     725             : }  // namespace test_marching_squares_square
     726             : 
     727             : #if defined(__clang__)
     728             : #pragma clang diagnostic pop
     729             : #endif

Generated by: LCOV version 1.14