-
Notifications
You must be signed in to change notification settings - Fork 503
Optimize the face locating logic #63
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, thanks for your contribution! I have a few comments, but the overall optimization looks good to me. Please remember to sign the CLA so we can merge your changes.
src/h3lib/include/h3api.h
Outdated
@@ -67,6 +67,15 @@ typedef struct { | |||
double lon; ///< longitude in radians | |||
} GeoCoord; | |||
|
|||
/** @struct Point |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this structure is not used by the public facing API. could you move it to geoCoord.h or faceIjk.h?
src/h3lib/include/geoCoord.h
Outdated
@@ -47,4 +47,9 @@ double _geoDistKm(const GeoCoord* p1, const GeoCoord* p2); | |||
double _geoAzimuthRads(const GeoCoord* p1, const GeoCoord* p2); | |||
void _geoAzDistanceRads(const GeoCoord* p1, double az, double distance, | |||
GeoCoord* p2); | |||
|
|||
void _geoToPoint(const GeoCoord* geo, Point* point); | |||
void _pointToGeo(const Point* point, GeoCoord* geo); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please delete the unused _pointToGeo declaration.
src/h3lib/lib/faceijk.c
Outdated
@@ -56,6 +56,29 @@ static const GeoCoord faceCenterGeo[NUM_ICOSA_FACES] = { | |||
{-1.054751253523952054, 1.794075294689396615}, // face 19 | |||
}; | |||
|
|||
static const Point faceCenterPoint[NUM_ICOSA_FACES] = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add /** @brief icosahedron face centers in x/y/z on the unit sphere */
Since all of the coordinate systems describe a point, using |
Maybe Vec3d to parallel Vec2d? |
I agree with |
Agree with @isaacbrodsky's comments, but this looks great to me otherwise. Thanks for submitting! |
FWIW the perf benefit here is reflected in the existing benchmark script as well: master:
PR:
|
Thanks for the quick response. I just updated the change accordingly. For the new |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am ok with leaving moving Vec3d to a future PR.
src/h3lib/lib/faceijk.c
Outdated
@@ -359,18 +383,27 @@ void _geoToFaceIjk(const GeoCoord* g, int res, FaceIJK* h) { | |||
* @param face The icosahedral face containing the spherical coordinates. | |||
* @param v The 2D hex coordinates of the cell containing the point. | |||
*/ | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: there is an unneeded extra line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, removed it.
Optimize the face locating logic
Hi, our was investigating the geo-indexing libraries recently. While comparing H3 and S2, we found the index calculation method (geoToH3) is a lot slower than that for S2. The icosahedron projection and the hexagon cells does require more calculation, but it shouldn't like that.
After reading the code, I found the triangle functions are heavily used in H3, while S2 uses 3D points to do the spherical calculation, which can largely reduce the amount of sin/cos calls.
Just logic deciding which face the point is projected to, it make 120 triangle function calls. (For each face, make 3 cos, 2 sin, 1 acos calls to get the great circle distance). Indeed, at most 5 triangle function calls is necessary.
With the optimization proposal, we only need to calculate the cos/sin of the lat/lon of the given GeoCoord to translate it into (x, y, z), and calculate acos once to get the great cycle distance for later calculation of the IJK.
I tested the performance with a simple routine,
And here's the result