void _faceIjkPentToCellBoundary()

in src/h3lib/lib/faceijk.c [499:598]


void _faceIjkPentToCellBoundary(const FaceIJK *h, int res, int start,
                                int length, CellBoundary *g) {
    int adjRes = res;
    FaceIJK centerIJK = *h;
    FaceIJK fijkVerts[NUM_PENT_VERTS];
    _faceIjkPentToVerts(&centerIJK, &adjRes, fijkVerts);

    // If we're returning the entire loop, we need one more iteration in case
    // of a distortion vertex on the last edge
    int additionalIteration = length == NUM_PENT_VERTS ? 1 : 0;

    // convert each vertex to lat/lng
    // adjust the face of each vertex as appropriate and introduce
    // edge-crossing vertices as needed
    g->numVerts = 0;
    FaceIJK lastFijk;
    for (int vert = start; vert < start + length + additionalIteration;
         vert++) {
        int v = vert % NUM_PENT_VERTS;

        FaceIJK fijk = fijkVerts[v];

        _adjustPentVertOverage(&fijk, adjRes);

        // all Class III pentagon edges cross icosa edges
        // note that Class II pentagons have vertices on the edge,
        // not edge intersections
        if (isResolutionClassIII(res) && vert > start) {
            // find hex2d of the two vertexes on the last face

            FaceIJK tmpFijk = fijk;

            Vec2d orig2d0;
            _ijkToHex2d(&lastFijk.coord, &orig2d0);

            int currentToLastDir = adjacentFaceDir[tmpFijk.face][lastFijk.face];

            const FaceOrientIJK *fijkOrient =
                &faceNeighbors[tmpFijk.face][currentToLastDir];

            tmpFijk.face = fijkOrient->face;
            CoordIJK *ijk = &tmpFijk.coord;

            // rotate and translate for adjacent face
            for (int i = 0; i < fijkOrient->ccwRot60; i++) _ijkRotate60ccw(ijk);

            CoordIJK transVec = fijkOrient->translate;
            _ijkScale(&transVec, unitScaleByCIIres[adjRes] * 3);
            _ijkAdd(ijk, &transVec, ijk);
            _ijkNormalize(ijk);

            Vec2d orig2d1;
            _ijkToHex2d(ijk, &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};

            Vec2d *edge0;
            Vec2d *edge1;
            switch (adjacentFaceDir[tmpFijk.face][fijk.face]) {
                case IJ:
                    edge0 = &v0;
                    edge1 = &v1;
                    break;
                case JK:
                    edge0 = &v1;
                    edge1 = &v2;
                    break;
                case KI:
                default:
                    assert(adjacentFaceDir[tmpFijk.face][fijk.face] == KI);
                    edge0 = &v2;
                    edge1 = &v0;
                    break;
            }

            // find the intersection and add the lat/lng point to the result
            Vec2d inter;
            _v2dIntersect(&orig2d0, &orig2d1, edge0, edge1, &inter);
            _hex2dToGeo(&inter, tmpFijk.face, adjRes, 1,
                        &g->verts[g->numVerts]);
            g->numVerts++;
        }

        // convert vertex to lat/lng and add to the result
        // vert == start + NUM_PENT_VERTS is only used to test for possible
        // intersection on last edge
        if (vert < start + NUM_PENT_VERTS) {
            Vec2d vec;
            _ijkToHex2d(&fijk.coord, &vec);
            _hex2dToGeo(&vec, fijk.face, adjRes, 1, &g->verts[g->numVerts]);
            g->numVerts++;
        }

        lastFijk = fijk;
    }
}