summaryrefslogtreecommitdiff
path: root/src/mbgl/style/custom_tile_loader.cpp
blob: d5bebf00862a3ae2434b19dc19364e0c7ba2b953 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <mbgl/style/custom_tile_loader.hpp>

namespace mbgl {
namespace style {

CustomTileLoader::CustomTileLoader(const TileFunction& fetchTileFn, const TileFunction& cancelTileFn) {
    fetchTileFunction = fetchTileFn;
    cancelTileFunction = cancelTileFn;
}

void CustomTileLoader::fetchTile(const OverscaledTileID& tileID, ActorRef<SetTileDataFunction> callbackRef) {
    auto cachedTileData = dataCache.find(tileID.canonical);
    if (cachedTileData != dataCache.end()) {
        callbackRef.invoke(&SetTileDataFunction::operator(), *(cachedTileData->second));
    }
    auto tileCallbacks = tileCallbackMap.find(tileID.canonical);
    if (tileCallbacks == tileCallbackMap.end()) {
        auto tuple = std::make_tuple(tileID.overscaledZ, tileID.wrap, callbackRef);
        tileCallbackMap.insert({ tileID.canonical, std::vector<OverscaledIDFunctionTuple>(1, tuple) });
    } else {
        for (auto iter = tileCallbacks->second.begin(); iter != tileCallbacks->second.end(); iter++) {
            if (std::get<0>(*iter) == tileID.overscaledZ && std::get<1>(*iter) == tileID.wrap ) {
                std::get<2>(*iter) = callbackRef;
                return;
            }
        }
        tileCallbacks->second.emplace_back(std::make_tuple(tileID.overscaledZ, tileID.wrap, callbackRef));
    }
    if (cachedTileData == dataCache.end()) {
        invokeTileFetch(tileID.canonical);
    }
}

void CustomTileLoader::cancelTile(const OverscaledTileID& tileID) {
    if (tileCallbackMap.find(tileID.canonical) != tileCallbackMap.end()) {
        invokeTileCancel(tileID.canonical);
    }
}

void CustomTileLoader::removeTile(const OverscaledTileID& tileID) {
    auto tileCallbacks = tileCallbackMap.find(tileID.canonical);
    if (tileCallbacks == tileCallbackMap.end()) return;
    for (auto iter = tileCallbacks->second.begin(); iter != tileCallbacks->second.end(); iter++) {
        if (std::get<0>(*iter) == tileID.overscaledZ && std::get<1>(*iter) == tileID.wrap ) {
            tileCallbacks->second.erase(iter);
            invokeTileCancel(tileID.canonical);
            break;
        }
    }
    if (tileCallbacks->second.size() == 0) {
        tileCallbackMap.erase(tileCallbacks);
        dataCache.erase(tileID.canonical);
    }
}

void CustomTileLoader::setTileData(const CanonicalTileID& tileID, const GeoJSON& data) {

    auto iter = tileCallbackMap.find(tileID);
    if (iter == tileCallbackMap.end()) return;
    dataCache[tileID] = std::make_unique<mapbox::geojson::geojson>(std::move(data));;
    for (auto tuple : iter->second) {
        auto actor = std::get<2>(tuple);
        actor.invoke(&SetTileDataFunction::operator(), data);
    }
}

void CustomTileLoader::invalidateTile(const CanonicalTileID& tileID) {
    auto tileCallbacks = tileCallbackMap.find(tileID);
    if (tileCallbacks == tileCallbackMap.end()) { return; }
    for (auto iter = tileCallbacks->second.begin(); iter != tileCallbacks->second.end(); iter++) {
        auto actor = std::get<2>(*iter);
        actor.invoke(&SetTileDataFunction::operator(), mapbox::geojson::feature_collection());
        invokeTileCancel(tileID);
    }
    tileCallbackMap.erase(tileCallbacks);
    dataCache.erase(tileID);
}

void CustomTileLoader::invalidateRegion(const LatLngBounds& bounds, Range<uint8_t> ) {
    for (auto idtuple= tileCallbackMap.begin(); idtuple != tileCallbackMap.end(); idtuple++) {
        const LatLngBounds tileBounds(idtuple->first);
        if (tileBounds.intersects(bounds) || bounds.contains(tileBounds) || tileBounds.contains(bounds)) {
            for (auto iter = idtuple->second.begin(); iter != idtuple->second.end(); iter++) {
                auto actor = std::get<2>(*iter);
                actor.invoke(&SetTileDataFunction::operator(), mapbox::geojson::feature_collection());
                invokeTileCancel(idtuple->first);
                dataCache.erase(idtuple->first);
            }
            idtuple->second.clear();
        }
    }
}

void CustomTileLoader::invokeTileFetch(const CanonicalTileID& tileID) {
    if (fetchTileFunction != nullptr) {
        fetchTileFunction(tileID);
    }
}

void CustomTileLoader::invokeTileCancel(const CanonicalTileID& tileID) {
    if (cancelTileFunction != nullptr) {
        cancelTileFunction(tileID);
    }
}

} // namespace style
} // namespace mbgl