Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for edge directions in getH3UnidirectionalEdgeBoundary #78

Merged
merged 6 commits into from
Jun 14, 2018

Conversation

nrabinowitz
Copy link
Collaborator

Fixes #75. This isn't the most elegant fix, but it does get the vertices into the correct order.

Longer term, I think the best option here is to do what we do in h3SetToVertexGraph, getting the edges and then walking them. But at the moment this was a bit too clunky to implement; it might be easier after a refactor of the VertexGraph structure.

int expectedVertices[][2] = {{3, 4}, {1, 2}, {2, 3},
{5, 0}, {4, 5}, {0, 1}};

for (int res = 0; res < 13; res++) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the current approach fails at res > 12 because of the geo comparison precision.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth adding as a comment.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

@coveralls
Copy link

coveralls commented Jun 12, 2018

Coverage Status

Coverage remained the same at 100.0% when pulling 2d93522 on nrabinowitz:edge-boundary into 1d3360f on uber:master.

@@ -212,6 +213,15 @@ void H3_EXPORT(getH3UnidirectionalEdgesFromHexagon)(H3Index origin,
}
}

bool _hasMatchingVertex(GeoCoord* vertex, GeoBoundary* boundary) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These arguments should be const.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will update.

// end of the edge, not the beginning.
// TODO: This is fine for this limited case, but it might be
// better/cleaner to use a VertexGraph for this
printf("%d, %d\n", i,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please delete debugging statement

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, sorry. Will delete.

k++;
}
}
}
// If we postponed adding the last vertex, add it now
if (postponedVertex.lat && postponedVertex.lon) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look safe, since (0,0) is a valid set of coordinates.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. Is there a better option here? The only thing I can think of is to add an additional var like hasPostponedVertex, which is pretty ugly.

Copy link
Contributor

@isaachier isaachier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments. Still struggling with the concepts here, but I'll read more of https://uber.github.io/h3 when I am less tired.

int expectedVertices[][2] = {{3, 4}, {1, 2}, {2, 3},
{5, 0}, {4, 5}, {0, 1}};

for (int res = 0; res < 13; res++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth adding as a comment.

H3Index sf = H3_EXPORT(geoToH3)(&sfGeo, 9);
H3Index sf;
GeoBoundary boundary;
GeoBoundary edgeBoundary;
H3Index* edges = calloc(6, sizeof(H3Index));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somewhat outside of your changeset, but why is calloc here instead of STACK_ARRAY_CALLOC (https://github.com/uber/h3/blob/master/src/h3lib/include/stackAlloc.h#L29)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly likely because this was written before we introduced that. Will update.

H3_EXPORT(getH3UnidirectionalEdgeBoundary)(edges[i], &gb);
t_assert(gb.numVerts == 2, "Got the expected number of vertices back");
int expectedVertices[][2] = {{3, 4}, {1, 2}, {2, 3},
{5, 0}, {4, 5}, {0, 1}};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Waiting on this when you have a chance.

t_assert(gb.numVerts == 3,
"Got the expected number of vertices back for a Class III "
"pentagon");
int expectedVertices[][3] = {{-1, -1, -1}, {2, 3, 4}, {4, 5, 6},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added, that's what I get for trying to multitask.

H3Index pentagon;
GeoBoundary boundary;
GeoBoundary edgeBoundary;
H3Index* edges = calloc(6, sizeof(H3Index));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same stack allocation question.

for (int j = 0; j < edgeBoundary.numVerts; j++) {
t_assert(
geoAlmostEqual(&edgeBoundary.verts[j],
&boundary.verts[expectedVertices[i][j]]),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm too tired to figure this out at the moment. Looks fun :).

@@ -212,6 +213,15 @@ void H3_EXPORT(getH3UnidirectionalEdgesFromHexagon)(H3Index origin,
}
}

bool _hasMatchingVertex(const GeoCoord* vertex, const GeoBoundary* boundary) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will update.

// If we are on vertex 0, we need to handle the case where it's the
// end of the edge, not the beginning.
// TODO: This is fine for this limited case, but it might be
// better/cleaner to use a VertexGraph for this
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are better off avoiding allocations involved in creating a VertexGraph and hacking a solution with only the given inputs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, probably true. It just irks me slightly that this is basically the same thing we're doing in h3SetToVertexGraph but we're doing it totally differently :/. Also bothers me that this is O(n^2), even though n is guaranteed to be <= 10 and is usually 6. I'll drop the comment though, I doubt there'd be any benefit.

if (i == 0 &&
!_hasMatchingVertex(&origin.verts[i + 1], &destination)) {
postponedVertex = origin.verts[i];
hasPostponedVertex = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is zero a valid vertex? If not, you can just check that postponedVertex != 0 instead of maintaining a separate flag.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

postponedVertex is a GeoCoord struct, and unfortunately, as @isaacbrodsky points out, it's valid to have all the fields in the struct initialized to 0. So I don't know of another way to check whether postponedVertex has been set or not, hence the flag. Open to suggestions.

gb->numVerts = k;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleted newline from end of file. Put a little marker here to show me.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. I'm surprised clang-format doesn't have some sort of opinion on that. Will fix.

@@ -32,7 +33,7 @@ BEGIN_TESTS(h3UniEdge);

TEST(h3IndexesAreNeighbors) {
H3Index sf = H3_EXPORT(geoToH3)(&sfGeo, 9);
H3Index* ring = calloc(H3_EXPORT(maxKringSize)(1), sizeof(H3Index));
STACK_ARRAY_CALLOC(H3Index, ring, H3_EXPORT(maxKringSize)(1));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

* @param boundary Geo boundary to look in
* @return Whether a match was found
*/
static bool _hasMatchingVertex(const GeoCoord* vertex,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great!

H3_EXPORT(getH3UnidirectionalEdgeBoundary)(edges[i], &gb);
t_assert(gb.numVerts == 2, "Got the expected number of vertices back");
int expectedVertices[][2] = {{3, 4}, {1, 2}, {2, 3},
{5, 0}, {4, 5}, {0, 1}};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Waiting on this when you have a chance.

const int expectedVertices[][3] = {{-1, -1, -1}, {2, 3, 4}, {4, 5, 6},
{8, 9, 0}, {6, 7, 8}, {0, 1, 2}};

for (int res = 1; res < 13; res += 2) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add comments for why we don't test all resolutions.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

@isaachier
Copy link
Contributor

It seems Travis CI wants you to format the code.

Copy link
Contributor

@isaachier isaachier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving changes, but please reformat.

@nrabinowitz
Copy link
Collaborator Author

Yeah, having more trouble with this than expected due to laptop theft :(. Should update shortly.

@CLAassistant
Copy link

CLAassistant commented Jun 14, 2018

CLA assistant check
All committers have signed the CLA.

@nrabinowitz nrabinowitz merged commit efafcd2 into uber:master Jun 14, 2018
mrdvt92 pushed a commit to mrdvt92/h3 that referenced this pull request Jun 19, 2022
Fix for edge directions in getH3UnidirectionalEdgeBoundary
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Edge direction in getH3UnidirectionalEdgeBoundary is inconsistent
5 participants