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

Generated by: LCOV version 1.14