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

Generated by: LCOV version 1.14