Skip to content

Commit

Permalink
Replace smoothing iterators with indices
Browse files Browse the repository at this point in the history
Replacing iterators with indices just in case
the iterators were the cause of some
unexpected runtime patterns observed while
re-running the experiment using a GCC build.
  • Loading branch information
rhysgoldstein committed Feb 2, 2024
1 parent 2dbf0cc commit 12e1a15
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 61 deletions.
43 changes: 22 additions & 21 deletions include/central64/smoothing/GreedySmoothing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,43 +28,44 @@ void GreedySmoothing<L>::SmoothPath(std::vector<Offset2D>& pathVertices)
{
// Create a vector of the path vertices to be retained.
std::vector<Offset2D> retainedVertices{};

// Create an iterator A that advances from the first
// Create an index A that advances from the first
// path vertex to just beyond the final path vertex.
auto iterA = std::begin(pathVertices);
while (iterA != std::end(pathVertices)) {
// Retain the vertex pointed to by iterator A.
retainedVertices.push_back(*iterA);
int indexA = 0;
int vertexCount = int(pathVertices.size());
while (indexA < vertexCount) {
// Retain the vertex at index A.
retainedVertices.push_back(pathVertices[indexA]);

// If iterator A points to the final path vertex, advance it.
// If index A points to the final path vertex, advance it.
// Otherwise, use line-of-sight checks to find the next vertex to retain.
if (iterA == std::end(pathVertices) - 1) {
++iterA;
if (indexA == vertexCount - 1) {
++indexA;
}
else {
// Create an iterator B that advances from the first position after
// iterator A to the first vertex for which the line of sight is broken.
auto iterB = iterA + 1;
Offset2D uniqueOffset = *iterB - *iterA;
// Create an index B that advances from the first position after
// A to the first vertex for which the line of sight is broken.
int indexB = indexA + 1;
Offset2D uniqueOffset = pathVertices[indexB] - pathVertices[indexA];
bool lineOfSight = true;
while (lineOfSight && iterB != std::end(pathVertices)) {
// Obtain the offset between the vertex of iterator B and the preceding vertex.
const Offset2D offset = *iterB - *(iterB - 1);
while (lineOfSight && indexB < vertexCount) {
// Obtain the offset between the vertex of B and the preceding vertex.
const Offset2D offset = pathVertices[indexB] - pathVertices[indexB - 1];

// Perform the line-of-sight check only if the offsets have not all been identical.
if (offset != uniqueOffset) {
uniqueOffset = { 0, 0 };
lineOfSight = Grid().LineOfSight(*iterA, *iterB);
lineOfSight = Grid().LineOfSight(pathVertices[indexA], pathVertices[indexB]);
}

// If the line of sight is not yet broken, advance iterator B.
// If the line of sight is not yet broken, advance B.
if (lineOfSight) {
++iterB;
++indexB;
}
}

// Advance iterator A to the first position before the vertex of iterator B.
iterA = iterB - 1;
// Advance A to the first position before the vertex of B.
indexA = indexB - 1;
}
}

Expand Down
81 changes: 41 additions & 40 deletions include/central64/smoothing/TentpoleSmoothing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,90 +33,91 @@ void TentpoleSmoothing<L>::SmoothPath(std::vector<Offset2D>& pathVertices)
if (!pathVertices.empty()) {
// Create an iterator A that advances from the first path vertex to the
// final path vertex, and an iterator C that remains ahead of iterator A.
auto iterA = std::begin(pathVertices);
auto iterC = iterA + 1;
while (iterA != std::end(pathVertices)) {
int indexA = 0;
int indexC = indexA + 1;
int vertexCount = int(pathVertices.size());
while (indexA < vertexCount) {
// Retain the vertex pointed to by iterator A.
retainedVertices.push_back(*iterA);
retainedVertices.push_back(pathVertices[indexA]);

// If iterator A points to the final path vertex, advance it.
// If index A points to the final path vertex, advance it.
// Otherwise, use line-of-sight checks to find the next vertex to retain.
if (iterA == std::end(pathVertices) - 1) {
++iterA;
if (indexA == vertexCount - 1) {
++indexA;
}
else {
// Determine if these is a single offset for all moves between iterators A and C.
Offset2D uniqueOffset = *(iterA + 1) - *iterA;
for (auto iterB = iterA + 1; iterB < iterC; ++iterB) {
const Offset2D offset = *iterB - *(iterB - 1);
// Determine if these is a single offset for all moves between A and C.
Offset2D uniqueOffset = pathVertices[indexA + 1] - pathVertices[indexA];
for (int indexB = indexA + 1; indexB < indexC; ++indexB) {
const Offset2D offset = pathVertices[indexB] - pathVertices[indexB - 1];
if (offset != uniqueOffset) {
uniqueOffset = { 0, 0 };
}
}

// Advance iterator C to the first vertex for which the line of sight is broken.
// Advance C to the first vertex for which the line of sight is broken.
bool lineOfSight = true;
while (lineOfSight && iterC != std::end(pathVertices)) {
// Obtain the offset between the vertex of iterator C and the preceding vertex.
Offset2D offset = *iterC - *(iterC - 1);
while (lineOfSight && indexC < vertexCount) {
// Obtain the offset between the vertex of C and the preceding vertex.
Offset2D offset = pathVertices[indexC] - pathVertices[indexC - 1];

// Perform the line-of-sight check only if the offsets have not all been identical.
if (offset != uniqueOffset) {
uniqueOffset = { 0, 0 };
lineOfSight = Grid().LineOfSight(*iterA, *iterC);
lineOfSight = Grid().LineOfSight(pathVertices[indexA], pathVertices[indexC]);
}

// If the line of sight is not yet broken, advance iterator C.
// If the line of sight is not yet broken, advance C.
if (lineOfSight) {
++iterC;
++indexC;
}
}

// If iterator C has advanced beyond the final path vertex,
// advance iterator A to the final path vertex. Otherwise,
// create an iterator B that backtracks from iterator C
// If C has advanced beyond the final path vertex,
// advance A to the final path vertex. Otherwise,
// create an index B that backtracks from C
// in search of the optimal tentpole position.
if (iterC == std::end(pathVertices)) {
iterA = iterC - 1;
if (indexC == vertexCount) {
indexA = indexC - 1;
}
else {
// Create an iterator B that backtracks from the first position before
// iterator C to the first vertex for which the line of sight between
// B and C is broken. Keep track of the tentpole location (`nextIterA`)
// that yields the shortest two-segment path between iterators A and C.
auto iterB = iterC - 1;
uniqueOffset = *iterB - *iterC;
// Create an index B that backtracks from the first position before
// C to the first vertex for which the line of sight between
// B and C is broken. Keep track of the tentpole location (`nextIndexA`)
// that yields the shortest two-segment path between A and C.
int indexB = indexC - 1;
uniqueOffset = pathVertices[indexB] - pathVertices[indexC];
lineOfSight = true;
double shortestDistance = std::numeric_limits<double>::infinity();
auto nextIterA = std::end(pathVertices);
while (lineOfSight && iterB != iterA) {
// Obtain the offset between the vertex of iterator B and the successing vertex.
Offset2D offset = *iterB - *(iterB + 1);
int nextIndexA = vertexCount;
while (lineOfSight && indexB != indexA) {
// Obtain the offset between the vertex of B and the successing vertex.
Offset2D offset = pathVertices[indexB] - pathVertices[indexB + 1];

// Perform the line-of-sight check only if the offsets have not all been identical.
if (offset != uniqueOffset) {
uniqueOffset = { 0, 0 };
lineOfSight = Grid().LineOfSight(*iterB, *iterC);
lineOfSight = Grid().LineOfSight(pathVertices[indexB], pathVertices[indexC]);
}

// If the line of sight is not yet broken, the (1) check whether the new tentpole
// location produces the shortest path so far, and (2) move iterator B backward.
if (lineOfSight) {
Offset2D offsetAB = *iterB - *iterA;
Offset2D offsetBC = *iterC - *iterB;
Offset2D offsetAB = pathVertices[indexB] - pathVertices[indexA];
Offset2D offsetBC = pathVertices[indexC] - pathVertices[indexB];
double distanceAB = sqrt(offsetAB.X()*offsetAB.X() + offsetAB.Y()*offsetAB.Y());
double distanceBC = sqrt(offsetBC.X()*offsetBC.X() + offsetBC.Y()*offsetBC.Y());
double distance = distanceAB + distanceBC;
if (distance < shortestDistance) {
shortestDistance = distance;
nextIterA = iterB;
nextIndexA = indexB;
}
--iterB;
--indexB;
}
}

// Advance iterator A to the optimal tentpole location.
iterA = nextIterA;
// Advance A to the optimal tentpole location.
indexA = nextIndexA;
}
}
}
Expand Down

0 comments on commit 12e1a15

Please sign in to comment.