Implement the cellToBoundary command for the h3 binary#818
Conversation
|
So... I don't see any tests for the |
Co-authored-by: Isaac Brodsky <isaac@isaacbrodsky.com>
…T where applicable, and eliminate hardwired constants in favor of sizeof trick @sahrk mentioned
I finally found the tests near the bottom of the |
isaacbrodsky
left a comment
There was a problem hiding this comment.
please change lat, lng ordering for compatibility with existing WKT implementations
| printf("%.10lf %.10lf))\n", H3_EXPORT(radsToDegs)(cb.verts[0].lng), | ||
| H3_EXPORT(radsToDegs)(cb.verts[0].lat)); |
There was a problem hiding this comment.
nit/note if this function gets reused, that it depends on numVerts > 0.
There was a problem hiding this comment.
Is it possible for it to be zero and not produce an H3Error value that short-circuits it, though?
There was a problem hiding this comment.
As far as I know it should always have vertices if the return code is success
nrabinowitz
left a comment
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.5003039349wkt: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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
| H3Index c; | ||
| H3Error e = H3_EXPORT(latLngToCell)(&ll, res, &c); | ||
|
|
||
| // TODO: Add support for JSON formatting |
There was a problem hiding this comment.
Does JSON formatting mean "8928342e20fffff" in this case? Also, does h3Println make piping harder than h3Print?
There was a problem hiding this comment.
That or {"cell": "8928342e20fffff"}. I'm not sure which would be a better idea.
| 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")) { |
There was a problem hiding this comment.
Nit: Is it possible to reuse cellToBoundaryArg.helpText here instead of repeating it?
There was a problem hiding this comment.
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", | ||
| }; |
There was a problem hiding this comment.
Nit: Is it possible to define this a top-level static const so that we can reuse it instead of repeating it?
There was a problem hiding this comment.
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.
| return 0; | ||
| } | ||
| if (has("cellToBoundary", 1, argv) && cellToBoundaryCmd(argc, argv)) { | ||
| return 0; |
There was a problem hiding this comment.
As above, I would have gone with return cellToBoundaryCmd(argc, argv) and have each command return H3_ERROR
There was a problem hiding this comment.
I agree with you, but would like that to also be a separate PR.
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.