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

Implement the cellToBoundary command for the h3 binary #818

Merged
merged 8 commits into from
Mar 25, 2024

Conversation

dfellis
Copy link
Collaborator

@dfellis dfellis commented Feb 22, 2024

Just this one command at first as I remember how we had structured the arg parsing API. Tested for correctness manually, I will see if/how testing this binary was set up shortly.

@coveralls
Copy link

coveralls commented Feb 22, 2024

Coverage Status

coverage: 98.827%. remained the same
when pulling 9d416a4 on h3-cellToBoundary-cmd
into a523fc6 on master.

@dfellis
Copy link
Collaborator Author

dfellis commented Feb 22, 2024

So... I don't see any tests for the h3 binary at all. Will like to discuss with you guys how we want to test it.

src/apps/filters/h3.c Outdated Show resolved Hide resolved
src/apps/filters/h3.c Outdated Show resolved Hide resolved
src/apps/filters/h3.c Outdated Show resolved Hide resolved
src/apps/filters/h3.c Outdated Show resolved Hide resolved
src/apps/filters/h3.c Outdated Show resolved Hide resolved
src/apps/filters/h3.c Outdated Show resolved Hide resolved
dfellis and others added 4 commits February 22, 2024 10:34
Co-authored-by: Isaac Brodsky <[email protected]>
…T where applicable, and eliminate hardwired constants in favor of sizeof trick @sahrk mentioned
@dfellis
Copy link
Collaborator Author

dfellis commented Mar 24, 2024

So... I don't see any tests for the h3 binary at all. Will like to discuss with you guys how we want to test it.

I finally found the tests near the bottom of the CMakeTests.cmake file, and then I updated them with the new WKT formatting and added the new test. No need to bring in more complicated machinery for these tests.

Copy link
Collaborator

@isaacbrodsky isaacbrodsky left a comment

Choose a reason for hiding this comment

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

please change lat, lng ordering for compatibility with existing WKT implementations

Comment on lines +149 to +150
printf("%.10lf %.10lf))\n", H3_EXPORT(radsToDegs)(cb.verts[0].lng),
H3_EXPORT(radsToDegs)(cb.verts[0].lat));
Copy link
Collaborator

@isaacbrodsky isaacbrodsky Mar 24, 2024

Choose a reason for hiding this comment

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

nit/note if this function gets reused, that it depends on numVerts > 0.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Is it possible for it to be zero and not produce an H3Error value that short-circuits it, though?

Copy link
Collaborator

Choose a reason for hiding this comment

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

As far as I know it should always have vertices if the return code is success

Copy link
Collaborator

@nrabinowitz nrabinowitz left a comment

Choose a reason for hiding this comment

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

This looks good - most of my comments are non-blocking questions about input/output and some of the existing structure of these commands

return false;
}
// Using WKT formatting for the output. TODO: Add support for JSON
// formatting
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm curious about plans for output and input formats here. I assume for output we'd want a -f or --format param similar to ogr2ogr. It would be easy to go overboard here, but I think at a minimum:

  • csv: 37.5012466151,-122.5003039349
  • wkt: POINT(-122.5003039349 37.5012466151)
  • geojson: {"type": "Point", "coordinates": [-122.5003039349 37.5012466151]}

We might also support json-array ([-122.5003039349 37.5012466151]) or json-object ({"lat":-122.5003039349, "lng": 37.5012466151}) and maybe an --ordering param specifying latlng or lnglat?

The parallel question is what inputs we support - accepting these formats as inputs is nicely symmetrical, but more painful than --lat=x --lng=y or bare arguments.

Not saying we should do any of this, but it might be nice to know where we plan to draw the line. I think a good yardstick should be how easy it is to pipe data from a tool like ogr2ogr to and from these CLI commands.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, this can definitely become a rabbit hole, here. There are other things to consider, for instance: should the csv output type include a headers row for the first one with lat,lng?

But also, how much of this can we generalize across these functions, and how much has to be hand-written per sub-command? The more of the latter the less I want to support everything under the sun and just suggest users to do things like h3 cellToLatLng -c 8928342e20fffff --geojson | jq .coordinates if they want other formats.

That's part of why I was thinking of going with a JSON-based output by default, because of the possibility of mangling the format more easily than any other, but went with WKT since that's what @isaacbrodsky suggested as an expected output.

I'm not personally familiar with ogr2ogr, though, so that's part of my bias towards a JSON-based format.

H3_EXPORT(radsToDegs)(ll.lng));
H3Error err = H3_EXPORT(cellToLatLng)(cell, &ll);
if (err) {
return false;
Copy link
Collaborator

Choose a reason for hiding this comment

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

For my info, why return true/false from these functions? Wouldn't we just want to return the error code, so callers would get a 0 exit code on success and a meaningful non-zero code on failure?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

So, I think we started work on this binary before H3Error was a thing and it was doing h3IsValid checks on the inputs/outputs to determine if it should exit with an error or not.

Then the conversion of that was done this way because it was the most straightforward. Bubbling up the H3Error does make sense to me. If you don't mind, I'll keep that refactor for when I add in the next sub-command.

@@ -102,6 +107,7 @@ bool latLngToCellCmd(int argc, char *argv[]) {
H3Index c;
H3Error e = H3_EXPORT(latLngToCell)(&ll, res, &c);

// TODO: Add support for JSON formatting
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does JSON formatting mean "8928342e20fffff" in this case? Also, does h3Println make piping harder than h3Print?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That or {"cell": "8928342e20fffff"}. I'm not sure which would be a better idea.

src/apps/filters/h3.c Outdated Show resolved Hide resolved
src/apps/filters/h3.c Outdated Show resolved Hide resolved
Arg *args[] = {&cellToBoundaryArg, &helpArg, &cellArg};
if (parseArgs(argc, argv, sizeof(args) / sizeof(Arg *), args, &helpArg,
"Convert an H3 cell to an array of latitude/longitude "
"coordinates defining its boundary")) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: Is it possible to reuse cellToBoundaryArg.helpText here instead of repeating it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I really want to DRY this stuff up, but I think I need to rework or add some macros to do so in a way that maintains its legibility. I left it here for now because I found it easier to read the code this way, but I will do a bigger refactor in a follow-up PR that's focused just on DRYing the code so we can debate that without holding up progress on implementing a sub-command.

.helpText =
"Convert an H3 cell to an array of latitude/longitude coordinates "
"defining its boundary",
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: Is it possible to define this a top-level static const so that we can reuse it instead of repeating it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

See my prior comment. Leaving DRY-ing it to another PR focused solely on that so we can better debate the merits/long-term maintenance.

@@ -140,6 +190,9 @@ int main(int argc, char *argv[]) {
if (has("latLngToCell", 1, argv) && latLngToCellCmd(argc, argv)) {
return 0;
}
if (has("cellToBoundary", 1, argv) && cellToBoundaryCmd(argc, argv)) {
return 0;
Copy link
Collaborator

Choose a reason for hiding this comment

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

As above, I would have gone with return cellToBoundaryCmd(argc, argv) and have each command return H3_ERROR

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I agree with you, but would like that to also be a separate PR.

@dfellis dfellis merged commit 5cd2831 into master Mar 25, 2024
34 checks passed
@dfellis dfellis deleted the h3-cellToBoundary-cmd branch March 25, 2024 23:29
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.

5 participants