Fix createUnion function and added createUnion tests

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
This commit is contained in:
Gaspar Capello 2019-06-05 14:44:13 -03:00 committed by David Capello
parent 364b0d2088
commit 2366bee6d4
3 changed files with 383 additions and 63 deletions

View File

@ -30,87 +30,78 @@ static void addPointsWithoutDuplicatingLastOne(int x, int y, std::vector<gfx::Po
// createUnion() joins a single scan point "x" (a pixel in other words)
// to the input vector "pairs".
// Each pair of elements from "pairs" vector is a representation
// of a scan segment.
// Each pair "pairs[i], pairs[i+1]" is a representation
// of a horizontal scan segment "i".
// An added scan point "x" to the "pairs" vector is represented
// by two consecutive values of "x".
// by two consecutive values of "x" if it is an insolated point.
// If "x" is between or next to a scan segment, this function creates an
// union, making a fusion between "x" <-> "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<int>& pairs,
const int x,
int& ints)
bool algorithm::createUnion(std::vector<int>& 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)

View File

@ -15,7 +15,7 @@ namespace doc {
namespace algorithm {
void polygon(int vertices, const int* points, void* data, AlgoHLine proc);
bool createUnion(std::vector<int>& pairs, const int x, int& ints);
}
}

View File

@ -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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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);