From 2366bee6d459b858a2763151b63fe7221580c6c2 Mon Sep 17 00:00:00 2001 From: Gaspar Capello Date: Wed, 5 Jun 2019 14:44:13 -0300 Subject: [PATCH] Fix createUnion function and added createUnion tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The purpose of this fix is that createUnion handles situations which union results in contiguous segment collapses. Added some treatments of eventual illogical inputs arguments like: - pairs.size() < ints - ints is 1 - ints is a odd number Fixed treatment of some union cases like: - x == pairs[i+1] + 1 - x == pairs[i+1] Simplification of some vector::insert execution. Added a bool return type to know if the function was successfully executed when is called (used in tests). We change the “static void createUnion(…)” to “bool algorithm::createUnion(…)” to conditioning it to future tests. Added some comments modifications. Added tests to polygon_tests.cpp --- src/doc/algorithm/polygon.cpp | 115 +++++----- src/doc/algorithm/polygon.h | 2 +- src/doc/algorithm/polygon_tests.cpp | 329 ++++++++++++++++++++++++++++ 3 files changed, 383 insertions(+), 63 deletions(-) diff --git a/src/doc/algorithm/polygon.cpp b/src/doc/algorithm/polygon.cpp index e960f07bc..dd7174d0b 100644 --- a/src/doc/algorithm/polygon.cpp +++ b/src/doc/algorithm/polygon.cpp @@ -30,87 +30,78 @@ static void addPointsWithoutDuplicatingLastOne(int x, int y, std::vector "pairs[i], pairs[i+1]". +// Additionally, after the union step, this function handles +// overlapped situations respect to the nexts scan segments "i+2", +// "i+4", etc. // Note: "pairs" must be sorted prior execution of this function. -static void createUnion(std::vector& pairs, - const int x, - int& ints) +bool algorithm::createUnion(std::vector& pairs, + const int x, + int& ints) { - bool unionDone = false; - ASSERT(ints >= 0); if (ints == 0) { - pairs.push_back(x); - pairs.push_back(x); - ints+=2; - return; + pairs.insert(pairs.begin(), 2, x); + ints = 2; + return true; } + else if (pairs.size() < ints || ints == 1) { + // Error + return false; + } + else if (ints%2 == 1) + ints--; - for (int i=0; i < ints - (ints%2); i+=2) { - // Case: - // pairs[i] pairs[i+1] + for (int i=0; i < ints; i+=2) { + // Case: pairs[i] pairs[i+1] // O --------- O // -x- if (x == pairs[i] - 1) { pairs[i] = x; - unionDone = true; - break; + return true; } - // Case: - // pairs[i] pairs[i+1] + // Case: pairs[i] pairs[i+1] // O --------- O // -x- else if (x < pairs[i] - 1) { - pairs.insert(pairs.begin()+i, x); - pairs.insert(pairs.begin()+i, x); - ints+=2; - unionDone = true; - break; + pairs.insert(pairs.begin() + i, 2, x); + ints += 2; + return true; } - // Case: - // pairs[i] pairs[i+1] - // O --------- O - // -x- - else if (x == pairs[i+1] + 1) { - unionDone = true; - if (i + 2 <= ints - 2) { - if (pairs[i+2] == x) { - // Simplification: - pairs.erase(pairs.begin() + (i+1)); - pairs.erase(pairs.begin() + (i+1)); - ints-=2; - break; - } - } + // Case: pairs[i] pairs[i+1] + // O --------- O + // -x- + // or -x- + else if (x == pairs[i+1] + 1 || x == pairs[i+1]) { pairs[i+1] = x; - break; - } - // Case: - // pairs[i] pairs[i+1] - // O --------- O - // -x- - else if (x >= pairs[i] && x <= pairs[i+1]) { - unionDone = true; - break; + while (ints > i+2 && pairs[i+2] <= x+1) { + pairs.erase(pairs.begin() + (i+1)); + pairs.erase(pairs.begin() + (i+1)); + ints -= 2; + if (i+2 >= pairs.size()) + break; + } + return true; } + // Case: pairs[i] pairs[i+1] + // O --------- O + // -x- + else if (x >= pairs[i] && x < pairs[i+1]) + return true; } - // Case: - // pairs[i] pairs[i+1] - // O --------- O - // -x- - if (x > pairs[ints-1] && !unionDone) { - if (pairs.size() == ints) { - pairs.push_back(x); - pairs.push_back(x); - } - else { - pairs.insert(pairs.begin() + ints, x); - pairs.insert(pairs.begin() + ints, x); - } - ints+=2; + // Case: pairs[i] pairs[i+1] + // O --------- O + // -x- + if (x > pairs[ints-1]) { + pairs.insert(pairs.begin() + ints, 2, x); + ints += 2; + return true; } + return false; } void algorithm::polygon(int vertices, const int* points, void* data, AlgoHLine proc) diff --git a/src/doc/algorithm/polygon.h b/src/doc/algorithm/polygon.h index 16f061a05..3128287cc 100644 --- a/src/doc/algorithm/polygon.h +++ b/src/doc/algorithm/polygon.h @@ -15,7 +15,7 @@ namespace doc { namespace algorithm { void polygon(int vertices, const int* points, void* data, AlgoHLine proc); - + bool createUnion(std::vector& pairs, const int x, int& ints); } } diff --git a/src/doc/algorithm/polygon_tests.cpp b/src/doc/algorithm/polygon_tests.cpp index 0d26e3c7e..28f51f572 100644 --- a/src/doc/algorithm/polygon_tests.cpp +++ b/src/doc/algorithm/polygon_tests.cpp @@ -29,6 +29,9 @@ void captureHscanSegment (int x1, int y, int x2, void* scanDataResults) { results->scanLines.push_back(scanSegment(x1, y, x2)); } +// polygon() function TESTS: +// ========================= + TEST(Polygon, HorizontalLine1Test) { // P0-----P1 @@ -437,6 +440,332 @@ TEST(Polygon, Polygon2Test) } } +// createUnion() function TESTS: +// ============================= +// Function Tests to ensure correct results when: +// testA1 : pairs.size() == 0 / ints == 0 +// testA2 : pairs.size() == 0 / ints > 0 (with ints even number) +// testA3 : pairs.size() == 0 / ints == 1 +// testA4 : pairs.size() == 1 / ints > 0 (with ints even number) +// +// Pre-condition fulfilled: pairs.size() >= 2 (even elements number) +// testB1 : ints > pairs.size() +// testB2 : ints == 0 +// testB3 : ints == 1 +// testB4 : ints < 0 +// +// Pre-condition fulfilled: pairs.size() >= 2 / ints >= 2 (with ints even number) +// testC1 : x == pairs[i] +// testC2 : x == pairs[i+1] +// testC3 : x == pairs[i]-1 +// testC4 : x == pairs[i+1]+1 +// testC5 : x < pairs[i]-1 +// testC6 : x > pairs[i+1]+1 +// testC7 : pairs[i] < x < pairs[i+1] +// testC8 : x == pairs[i+1]+1 && x == pairs[i+2]+1 +// testC9 : special case +// testC10 : special case + +TEST(createUnion, testA1) +{ + // testA1 : pairs.size() == 0 / ints == 0 + int ints = 0; + int x = 2; + std::vector pairs; + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), true); + EXPECT_EQ(pairs[0], 2); + EXPECT_EQ(pairs[1], 2); + EXPECT_EQ(ints, 2); +} + +TEST(createUnion, testA2) +{ + // testA2 : pairs.size() == 0 / ints > 0 (with ints even number) + int ints = 2; + int x = 5; + std::vector pairs; + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), false); +} + +TEST(createUnion, testA3) +{ + // testA3 : pairs.size() == 0 / ints == 1 + int ints = 1; + int x = 5; + std::vector pairs; + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), false); +} + +TEST(createUnion, testA4) +{ + // testA4 : pairs.size() == 1 / ints > 0 (with ints even number) + int ints = 2; + int x = 5; + std::vector pairs; + pairs.push_back(0); + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), false); +} + +// Next tests have the following condition fulfilled: +// pairs.size() >= 2 (even elements number) +// testB1 : ints > pairs.size() +// testB2 : ints == 0 +// testB3 : ints == 1 +// testB4 : ints < 0 +TEST(createUnion, testB1) +{ + // testB1 : ints > pairs.size() + // pairs.size() >= 2 (even elements number) + int ints = 3; + int x = 5; + std::vector pairs; + pairs.push_back(0); + pairs.push_back(0); + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), false); +} + +TEST(createUnion, testB2) +{ + // testB2 : ints == 0 + // pairs.size() >= 2 (even elements number) + int ints = 0; + int x = 5; + std::vector pairs; + pairs.push_back(0); + pairs.push_back(0); + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), true); + EXPECT_EQ(pairs[0], 5); + EXPECT_EQ(pairs[1], 5); + EXPECT_EQ(ints, 2); +} + +TEST(createUnion, testB3) +{ + // testB3 : ints == 1 + // pairs.size() >= 2 (even elements number) + int ints = 1; + int x = 5; + std::vector pairs; + pairs.push_back(0); + pairs.push_back(0); + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), false); +} + +TEST(createUnion, testB4) +{ + // testB4 : ints < 0 + int ints = -1; + int x = 5; + std::vector pairs; + pairs.push_back(0); + pairs.push_back(0); + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), false); +} + +// Next tests have the following condition fulfilled: +// pairs.size() >= 2 / ints >= 2 (with ints even number) +// testC1 : x == pairs[i] +// testC2 : x == pairs[i+1] +// testC3 : x == pairs[i]-1 +// testC4 : x == pairs[i+1]+1 +// testC5 : x < pairs[i]-1 +// testC6 : x > pairs[i+1]+1 +// testC7 : pairs[i] < x < pairs[i+1] +// testC9 : special case +// testC10 : special case + +TEST(createUnion, testC1) +{ + // testC1 : x == pairs[i] + // pairs.size() >= 2 / ints >= 2 (with ints even number) + int ints = 4; + int x = 0; + std::vector pairs; + pairs.push_back(0); + pairs.push_back(1); + pairs.push_back(4); + pairs.push_back(5); + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), true); + EXPECT_EQ(pairs[0], 0); + EXPECT_EQ(pairs[1], 1); + EXPECT_EQ(pairs[2], 4); + EXPECT_EQ(pairs[3], 5); + EXPECT_EQ(ints, 4); +} + +TEST(createUnion, testC2) +{ + // testC2 : x == pairs[i+1] + // pairs.size() >= 2 / ints >= 2 (with ints even number) + int ints = 4; + int x = 1; + std::vector pairs; + pairs.push_back(0); + pairs.push_back(1); + pairs.push_back(4); + pairs.push_back(5); + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), true); + EXPECT_EQ(pairs[0], 0); + EXPECT_EQ(pairs[1], 1); + EXPECT_EQ(pairs[2], 4); + EXPECT_EQ(pairs[3], 5); + EXPECT_EQ(ints, 4); +} + +TEST(createUnion, testC3) +{ + // testC3 : x == pairs[i]-1 + // pairs.size() >= 2 / ints >= 2 (with ints even number) + int ints = 4; + int x = -1; + std::vector pairs; + pairs.push_back(0); + pairs.push_back(1); + pairs.push_back(4); + pairs.push_back(5); + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), true); + EXPECT_EQ(pairs[0], -1); + EXPECT_EQ(pairs[1], 1); + EXPECT_EQ(pairs[2], 4); + EXPECT_EQ(pairs[3], 5); + EXPECT_EQ(ints, 4); +} + +TEST(createUnion, testC4) +{ + // testC4 : x == pairs[i+1]+1 + // pairs.size() >= 2 / ints >= 2 (with ints even number) + int ints = 4; + int x = 2; + std::vector pairs; + pairs.push_back(0); + pairs.push_back(1); + pairs.push_back(4); + pairs.push_back(5); + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), true); + EXPECT_EQ(pairs[0], 0); + EXPECT_EQ(pairs[1], 2); + EXPECT_EQ(pairs[2], 4); + EXPECT_EQ(pairs[3], 5); + EXPECT_EQ(ints, 4); +} + +TEST(createUnion, testC5) +{ + // testC5 : x < pairs[i]-1 + // pairs.size() >= 2 / ints >= 2 (with ints even number) + int ints = 4; + int x = -2; + std::vector pairs; + pairs.push_back(0); + pairs.push_back(1); + pairs.push_back(4); + pairs.push_back(5); + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), true); + EXPECT_EQ(pairs[0], -2); + EXPECT_EQ(pairs[1], -2); + EXPECT_EQ(pairs[2], 0); + EXPECT_EQ(pairs[3], 1); + EXPECT_EQ(pairs[4], 4); + EXPECT_EQ(pairs[5], 5); + EXPECT_EQ(ints, 6); +} + +TEST(createUnion, testC6) +{ + // testC6 : x > pairs[i+1]+1 + // pairs.size() >= 2 / ints >= 2 (with ints even number) + int ints = 4; + int x = 7; + std::vector pairs; + pairs.push_back(0); + pairs.push_back(1); + pairs.push_back(4); + pairs.push_back(5); + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), true); + EXPECT_EQ(pairs[0], 0); + EXPECT_EQ(pairs[1], 1); + EXPECT_EQ(pairs[2], 4); + EXPECT_EQ(pairs[3], 5); + EXPECT_EQ(pairs[4], 7); + EXPECT_EQ(pairs[5], 7); + EXPECT_EQ(ints, 6); +} + +TEST(createUnion, testC7) +{ + // testC7 : pairs[i] < x < pairs[i+1] + // pairs.size() >= 2 / ints >= 2 (with ints even number) + int ints = 2; + int x = 3; + std::vector pairs; + pairs.push_back(0); + pairs.push_back(5); + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), true); + EXPECT_EQ(pairs[0], 0); + EXPECT_EQ(pairs[1], 5); + EXPECT_EQ(ints, 2); +} + +TEST(createUnion, testC8) +{ + // testC8 : x == pairs[i+1]+1 && x == pairs[i+2]+1 + // pairs.size() >= 2 / ints >= 2 (with ints even number) + int ints = 4; + int x = 3; + std::vector pairs; + pairs.push_back(0); + pairs.push_back(2); + pairs.push_back(3); + pairs.push_back(4); + + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), true); + EXPECT_EQ(pairs[0], 0); + EXPECT_EQ(pairs[1], 4); + EXPECT_EQ(ints, 2); +} + +TEST(createUnion, testC9) +{ + // testC9 : special case + // pairs.size() >= 2 / ints >= 2 (with ints even number) + int ints = 6; + int x = 1; + std::vector pairs; + pairs.push_back(0); + pairs.push_back(0); + pairs.push_back(1); + pairs.push_back(1); + pairs.push_back(2); + pairs.push_back(4); + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), true); + EXPECT_EQ(pairs[0], 0); + EXPECT_EQ(pairs[1], 4); + EXPECT_EQ(ints, 2); +} + +TEST(createUnion, testC10) +{ + // testC10 : special case + // pairs.size() >= 2 / ints >= 2 (with ints even number) + int ints = 4; + int x = 3; + std::vector pairs; + pairs.push_back(0); + pairs.push_back(3); + pairs.push_back(4); + pairs.push_back(7); + pairs.push_back(0); + pairs.push_back(0); + pairs.push_back(0); + pairs.push_back(0); + EXPECT_EQ(doc::algorithm::createUnion(pairs, x, ints), true); + EXPECT_EQ(pairs[0], 0); + EXPECT_EQ(pairs[1], 7); + EXPECT_EQ(ints, 2); +} + + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv);