in src/h3lib/lib/faceijk.c [672:773]
void _faceIjkToGeoBoundary(const FaceIJK* h, int res, int isPentagon,
GeoBoundary* g) {
if (isPentagon) {
_faceIjkPentToGeoBoundary(h, res, g);
return;
}
int adjRes = res;
FaceIJK centerIJK = *h;
FaceIJK fijkVerts[NUM_HEX_VERTS];
_faceIjkToVerts(¢erIJK, &adjRes, fijkVerts);
// convert each vertex to lat/lon
// adjust the face of each vertex as appropriate and introduce
// edge-crossing vertices as needed
g->numVerts = 0;
int lastFace = -1;
Overage lastOverage = NO_OVERAGE;
for (int vert = 0; vert < NUM_HEX_VERTS + 1; vert++) {
int v = vert % NUM_HEX_VERTS;
FaceIJK fijk = fijkVerts[v];
int pentLeading4 = 0;
Overage overage = _adjustOverageClassII(&fijk, adjRes, pentLeading4, 1);
/*
Check for edge-crossing. Each face of the underlying icosahedron is a
different projection plane. So if an edge of the hexagon crosses an
icosahedron edge, an additional vertex must be introduced at that
intersection point. Then each half of the cell edge can be projected
to geographic coordinates using the appropriate icosahedron face
projection. Note that Class II cell edges have vertices on the face
edge, with no edge line intersections.
*/
if (isResClassIII(res) && vert > 0 && fijk.face != lastFace &&
lastOverage != FACE_EDGE) {
// find hex2d of the two vertexes on original face
int lastV = (v + 5) % NUM_HEX_VERTS;
Vec2d orig2d0;
_ijkToHex2d(&fijkVerts[lastV].coord, &orig2d0);
Vec2d orig2d1;
_ijkToHex2d(&fijkVerts[v].coord, &orig2d1);
// find the appropriate icosa face edge vertexes
int maxDim = maxDimByCIIres[adjRes];
Vec2d v0 = {3.0 * maxDim, 0.0};
Vec2d v1 = {-1.5 * maxDim, 3.0 * M_SQRT3_2 * maxDim};
Vec2d v2 = {-1.5 * maxDim, -3.0 * M_SQRT3_2 * maxDim};
int face2 = ((lastFace == centerIJK.face) ? fijk.face : lastFace);
Vec2d* edge0;
Vec2d* edge1;
switch (adjacentFaceDir[centerIJK.face][face2]) {
case IJ:
edge0 = &v0;
edge1 = &v1;
break;
case JK:
edge0 = &v1;
edge1 = &v2;
break;
case KI:
default:
assert(adjacentFaceDir[centerIJK.face][face2] == KI);
edge0 = &v2;
edge1 = &v0;
break;
}
// find the intersection and add the lat/lon point to the result
Vec2d inter;
_v2dIntersect(&orig2d0, &orig2d1, edge0, edge1, &inter);
/*
If a point of intersection occurs at a hexagon vertex, then each
adjacent hexagon edge will lie completely on a single icosahedron
face, and no additional vertex is required.
*/
bool isIntersectionAtVertex =
_v2dEquals(&orig2d0, &inter) || _v2dEquals(&orig2d1, &inter);
if (!isIntersectionAtVertex) {
_hex2dToGeo(&inter, centerIJK.face, adjRes, 1,
&g->verts[g->numVerts]);
g->numVerts++;
}
}
// convert vertex to lat/lon and add to the result
// vert == NUM_HEX_VERTS is only used to test for possible intersection
// on last edge
if (vert < NUM_HEX_VERTS) {
Vec2d vec;
_ijkToHex2d(&fijk.coord, &vec);
_hex2dToGeo(&vec, fijk.face, adjRes, 1, &g->verts[g->numVerts]);
g->numVerts++;
}
lastFace = fijk.face;
lastOverage = overage;
}
}