Skip to content

Commit

Permalink
#5382: Add reverse column and row iterators
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Dec 8, 2020
1 parent 8160d63 commit 26e68f3
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 12 deletions.
66 changes: 54 additions & 12 deletions libs/patch/PatchIterators.h
Expand Up @@ -119,38 +119,80 @@ class PatchControlIterator
}
};

// An iterator traversing a single row of a patch
class SinglePatchRowIterator :
// An iterator traversing a single row of a patch (in defined order)
class SinglePatchRowIteratorBase :
public PatchControlIterator
{
public:
SinglePatchRowIterator(IPatch& patch, std::size_t row) :
PatchControlIterator(patch, static_cast<int>(row), 0, moveToNextCol)
SinglePatchRowIteratorBase(IPatch& patch, std::size_t row, std::size_t startCol, int delta) :
PatchControlIterator(patch, static_cast<int>(row), startCol,
std::bind(SinglePatchRowIteratorBase::moveToNextCol, std::placeholders::_1, delta))
{}

private:
static void moveToNextCol(PatchControlIterator& it)
static void moveToNextCol(PatchControlIterator& it, int delta)
{
it.set(it.getRow(), it.getColumn() + 1);
it.set(it.getRow(), it.getColumn() + delta);
}
};

// An iterator traversing a single column of a patch
class SinglePatchColumnIterator :
// An iterator traversing a single row of a patch
class SinglePatchRowIterator :
public SinglePatchRowIteratorBase
{
public:
SinglePatchRowIterator(IPatch& patch, std::size_t row) :
SinglePatchRowIteratorBase(patch, static_cast<int>(row), 0, +1)
{}
};

// An iterator traversing a single row of a patch in reverse order (starting from the highest column)
class SinglePatchRowReverseIterator :
public SinglePatchRowIteratorBase
{
public:
SinglePatchRowReverseIterator(IPatch& patch, std::size_t row) :
SinglePatchRowIteratorBase(patch, static_cast<int>(row), static_cast<int>(patch.getWidth() - 1), -1)
{}
};

// An iterator traversing a single column of a patch (in defined order)
class SinglePatchColumnIteratorBase :
public PatchControlIterator
{
public:
SinglePatchColumnIterator(IPatch& patch, std::size_t col) :
PatchControlIterator(patch, 0, static_cast<int>(col), moveToNextRow)
SinglePatchColumnIteratorBase(IPatch& patch, std::size_t col, std::size_t startRow, int delta) :
PatchControlIterator(patch, startRow, static_cast<int>(col),
std::bind(SinglePatchColumnIteratorBase::moveToNextRow, std::placeholders::_1, delta))
{}

private:
static void moveToNextRow(PatchControlIterator& it)
static void moveToNextRow(PatchControlIterator& it, int delta)
{
it.set(it.getRow() + 1, it.getColumn());
it.set(it.getRow() + delta, it.getColumn());
}
};

// An iterator traversing a single column of a patch
class SinglePatchColumnIterator :
public SinglePatchColumnIteratorBase
{
public:
SinglePatchColumnIterator(IPatch& patch, std::size_t row) :
SinglePatchColumnIteratorBase(patch, static_cast<int>(row), 0, +1)
{}
};

// An iterator traversing a single column of a patch in reverse order (starting from the highest row)
class SinglePatchColumnReverseIterator :
public SinglePatchColumnIteratorBase
{
public:
SinglePatchColumnReverseIterator(IPatch& patch, std::size_t row) :
SinglePatchColumnIteratorBase(patch, static_cast<int>(row), static_cast<int>(patch.getHeight() - 1), -1)
{}
};

// An iterator traversing a given patch column-wise, iterating over
// one column after the other (which are optionally constrained to [startColumn..endColumn])
class ColumnWisePatchIterator :
Expand Down
66 changes: 66 additions & 0 deletions test/PatchIterators.cpp
Expand Up @@ -194,6 +194,27 @@ void iterateOverSingleColum(IPatch& patch, std::size_t colToTest)
EXPECT_EQ(expected, expectedValues.end()); // assume no underflow
}

void iterateOverSingleColumReversely(IPatch& patch, std::size_t colToTest)
{
std::vector<Vector3> expectedValues;

// Fill the vector with the expected values
for (auto row = static_cast<int>(patch.getHeight()) - 1; row >= 0; --row)
{
expectedValues.push_back(patch.ctrlAt(row, colToTest).vertex);
}

patch::SinglePatchColumnReverseIterator it(patch, colToTest);
auto expected = expectedValues.begin();

while (it.isValid())
{
EXPECT_EQ((it++)->vertex, *(expected++));
}

EXPECT_EQ(expected, expectedValues.end()); // assume no underflow
}

TEST_F(PatchIteratorTest, IterateOverSingleColumn)
{
auto patch = createWorldspawnPatch(5, 7);
Expand All @@ -205,6 +226,17 @@ TEST_F(PatchIteratorTest, IterateOverSingleColumn)
iterateOverSingleColum(patch->getPatch(), 4);
}

TEST_F(PatchIteratorTest, IterateOverSingleColumnReversely)
{
auto patch = createWorldspawnPatch(5, 7);

iterateOverSingleColumReversely(patch->getPatch(), 0);
iterateOverSingleColumReversely(patch->getPatch(), 1);
iterateOverSingleColumReversely(patch->getPatch(), 2);
iterateOverSingleColumReversely(patch->getPatch(), 3);
iterateOverSingleColumReversely(patch->getPatch(), 4);
}

void iterateOverSingleRow(IPatch& patch, std::size_t rowToTest)
{
std::vector<Vector3> expectedValues;
Expand All @@ -226,6 +258,27 @@ void iterateOverSingleRow(IPatch& patch, std::size_t rowToTest)
EXPECT_EQ(expected, expectedValues.end()); // assume no underflow
}

void iterateOverSingleRowReversely(IPatch& patch, std::size_t rowToTest)
{
std::vector<Vector3> expectedValues;

// Fill the vector with the expected values
for (auto col = static_cast<int>(patch.getWidth()) - 1; col >= 0; --col)
{
expectedValues.push_back(patch.ctrlAt(rowToTest, col).vertex);
}

patch::SinglePatchRowReverseIterator it(patch, rowToTest);
auto expected = expectedValues.begin();

while (it.isValid())
{
EXPECT_EQ((it++)->vertex, *(expected++));
}

EXPECT_EQ(expected, expectedValues.end()); // assume no underflow
}

TEST_F(PatchIteratorTest, IterateOverSingleRow)
{
auto patch = createWorldspawnPatch(5, 7);
Expand All @@ -239,4 +292,17 @@ TEST_F(PatchIteratorTest, IterateOverSingleRow)
iterateOverSingleRow(patch->getPatch(), 6);
}

TEST_F(PatchIteratorTest, IterateOverSingleRowReversely)
{
auto patch = createWorldspawnPatch(5, 7);

iterateOverSingleRowReversely(patch->getPatch(), 0);
iterateOverSingleRowReversely(patch->getPatch(), 1);
iterateOverSingleRowReversely(patch->getPatch(), 2);
iterateOverSingleRowReversely(patch->getPatch(), 3);
iterateOverSingleRowReversely(patch->getPatch(), 4);
iterateOverSingleRowReversely(patch->getPatch(), 5);
iterateOverSingleRowReversely(patch->getPatch(), 6);
}

}

0 comments on commit 26e68f3

Please sign in to comment.