diff --git a/radiantcore/patch/algorithm/General.cpp b/radiantcore/patch/algorithm/General.cpp index 3e109896b8..76f6634f92 100644 --- a/radiantcore/patch/algorithm/General.cpp +++ b/radiantcore/patch/algorithm/General.cpp @@ -12,6 +12,7 @@ #include "string/convert.h" #include "scenelib.h" #include "command/ExecutionFailure.h" +#include "PatchIterators.h" namespace patch { @@ -419,6 +420,31 @@ PatchNodePtr createdMergedPatch(const PatchNodePtr& patchNode1, const PatchNodeP return newPatchNode; } +namespace +{ + +// Returns true if all the elements in the given sequences are equal +inline bool isEqual(const PatchControlIterator& sequence1, const PatchControlIterator& sequence2) +{ + // If the iterators are invalid from the start, return false + if (!sequence1.isValid() || !sequence2.isValid()) + { + return false; + } + + for (auto p1 = sequence1, p2 = sequence2; p1.isValid() && p2.isValid(); ++p1, ++p2) + { + if (p1->vertex != p2->vertex) + { + return false; + } + } + + return true; +} + +} + PatchNodePtr createdMergedPatch(const PatchNodePtr& patchNode1, const PatchNodePtr& patchNode2) { constexpr double WELD_EPSILON = 0.001; @@ -439,6 +465,19 @@ PatchNodePtr createdMergedPatch(const PatchNodePtr& patchNode1, const PatchNodeP if (patch1.getWidth() == patch2.getWidth()) { + // Row dimensions match, compare the first and last row of this patch to the + // first and last row of the other patch + SinglePatchRowIterator patch1FirstRow(patch1, 0); + SinglePatchRowIterator patch1LastRow(patch1, patch1.getWidth() - 1); + + SinglePatchRowIterator patch2FirstRow(patch2, 0); + SinglePatchRowIterator patch2LastRow(patch2, patch2.getWidth() - 1); + + if (isEqual(patch1FirstRow, patch2FirstRow)) + { + + } + row1 = 0; row2 = 0; diff --git a/radiantcore/patch/algorithm/PatchIterators.h b/radiantcore/patch/algorithm/PatchIterators.h index 71a2bfe5e0..ca73b85526 100644 --- a/radiantcore/patch/algorithm/PatchIterators.h +++ b/radiantcore/patch/algorithm/PatchIterators.h @@ -34,7 +34,7 @@ class PatchControlIterator // Moves this iterator forward by one step Forwarder _forward; -protected: +public: PatchControlIterator(IPatch& patch, int row, int col, Forwarder forward) : _patch(patch), _row(row), @@ -45,7 +45,6 @@ class PatchControlIterator PatchControlIterator(const PatchControlIterator& other) = default; PatchControlIterator& operator=(const PatchControlIterator& other) = default; -public: // Post-increment i++ PatchControlIterator operator++(int) { @@ -121,11 +120,11 @@ class PatchControlIterator }; // An iterator traversing a single row of a patch -class PatchRowIterator : +class SinglePatchRowIterator : public PatchControlIterator { public: - PatchRowIterator(IPatch& patch, std::size_t row) : + SinglePatchRowIterator(IPatch& patch, std::size_t row) : PatchControlIterator(patch, static_cast(row), 0, moveToNextCol) {} @@ -137,11 +136,11 @@ class PatchRowIterator : }; // An iterator traversing a single column of a patch -class PatchColumnIterator : +class SinglePatchColumnIterator : public PatchControlIterator { public: - PatchColumnIterator(IPatch& patch, std::size_t col) : + SinglePatchColumnIterator(IPatch& patch, std::size_t col) : PatchControlIterator(patch, 0, static_cast(col), moveToNextRow) {} @@ -152,4 +151,76 @@ class PatchColumnIterator : } }; +// An iterator traversing a the given patch column-wise, iterating over +// one row after the other (which are optionally constrained to [startRow..endRow]) +class ColumnWisePatchIterator : + public PatchControlIterator +{ +public: + ColumnWisePatchIterator(IPatch& patch) : + ColumnWisePatchIterator(patch, 0, patch.getHeight() - 1) + { + assert(patch.getHeight() > 0); + } + + ColumnWisePatchIterator(IPatch& patch, std::size_t startRow, std::size_t endRow) : + PatchControlIterator(patch, startRow, 0, std::bind(ColumnWisePatchIterator::moveNext, std::placeholders::_1, patch, endRow)) + {} + +private: + static void moveNext(PatchControlIterator& it, const IPatch& patch, std::size_t endRow) + { + auto nextColumn = it.getColumn() + 1; + auto nextRow = it.getRow(); + + if (nextColumn >= patch.getWidth()) + { + // Advance to the next row + // If that doesn't succeed, just leave the indices out of bounds + if (++nextRow <= endRow) + { + nextColumn = 0; + } + } + + it.set(nextRow, nextColumn); + } +}; + +// An iterator traversing a the given patch row-wise, iterating over +// one column after the other (which are optionally constrained to [startColumn..endColumn]) +class RowWisePatchIterator : + public PatchControlIterator +{ +public: + RowWisePatchIterator(IPatch& patch) : + RowWisePatchIterator(patch, 0, patch.getWidth() - 1) + { + assert(patch.getWidth() > 0); + } + + RowWisePatchIterator(IPatch& patch, std::size_t startColumn, std::size_t endColumn) : + PatchControlIterator(patch, startColumn, 0, std::bind(RowWisePatchIterator::moveNext, std::placeholders::_1, patch, endColumn)) + {} + +private: + static void moveNext(PatchControlIterator& it, const IPatch& patch, std::size_t endColumn) + { + auto nextRow = it.getRow() + 1; + auto nextColumn = it.getColumn(); + + if (nextRow >= patch.getHeight()) + { + // Advance to the next column + // If that doesn't succeed, just leave the indices out of bounds + if (++nextColumn <= endColumn) + { + nextRow = 0; + } + } + + it.set(nextRow, nextColumn); + } +}; + }