• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

iTowns / itowns / 9512125031

14 Jun 2024 07:09AM UTC coverage: 89.607% (+0.01%) from 89.593%
9512125031

push

github

AnthonyGlt
fix(MVT): add texture and subdivision size parameter

2707 of 3581 branches covered (75.59%)

Branch coverage included in aggregate %.

7 of 8 new or added lines in 4 files covered. (87.5%)

3 existing lines in 2 files now uncovered.

23296 of 25438 relevant lines covered (91.58%)

342.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.82
/src/Process/LayeredMaterialNodeProcessing.js
1
import { chooseNextLevelToFetch } from 'Layer/LayerUpdateStrategy';
1✔
2
import LayerUpdateState from 'Layer/LayerUpdateState';
1✔
3
import handlingError from 'Process/handlerNodeError';
1✔
4

1✔
5
function materialCommandQueuePriorityFunction(material) {
1✔
6
    // We know that 'node' is visible because commands can only be
9✔
7
    // issued for visible nodes.
9✔
8
    // TODO: need priorization of displayed nodes
9✔
9
    // Then prefer displayed node over non-displayed one
9✔
10
    return material.visible ? 100 : 10;
9!
11
}
1✔
12

1✔
13
function refinementCommandCancellationFn(cmd) {
1✔
14
    if (!cmd.requester.parent || !cmd.requester.material) {
1!
15
        return true;
1✔
16
    }
1✔
17
    // Cancel the command if the tile already has a better texture.
1✔
18
    // This is only needed for elevation layers, because we may have several
1✔
19
    // concurrent layers but we can only use one texture.
1✔
20
    if (cmd.layer.isElevationLayer && cmd.requester.material.getElevationLayer() &&
1!
21
        cmd.targetLevel <= cmd.requester.material.getElevationLayer().level) {
1!
22
        return true;
1✔
23
    }
1✔
24

1✔
25
    // Cancel the command if the layer was removed between command scheduling and command execution
1✔
26
    if (!cmd.requester.layerUpdateState[cmd.layer.id]
1✔
27
        || !cmd.layer.source._featuresCaches[cmd.layer.crs]) {
1!
28
        return true;
1✔
29
    }
9✔
30

9✔
31
    return !cmd.requester.material.visible;
9✔
32
}
9✔
33

9✔
34
function buildCommand(view, layer, extentsSource, extentsDestination, requester) {
9✔
35
    return {
9✔
36
        view,
9✔
37
        layer,
9✔
38
        extentsSource,
9✔
39
        extentsDestination,
9✔
40
        requester,
9✔
41
        priority: materialCommandQueuePriorityFunction(requester.material),
1✔
42
        earlyDropFunction: refinementCommandCancellationFn,
15✔
43
    };
15✔
44
}
15✔
45

15✔
46
export function updateLayeredMaterialNodeImagery(context, layer, node, parent) {
15!
47
    const material = node.material;
15✔
48
    if (!parent || !material) {
15✔
49
        return;
15✔
50
    }
15✔
51
    const extentsDestination = node.getExtentsByProjection(layer.crs);
15!
52

×
53
    const zoom = extentsDestination[0].zoom;
15✔
54
    if (zoom > layer.zoom.max || zoom < layer.zoom.min) {
15✔
55
        return;
15✔
56
    }
15✔
57

15✔
58
    let nodeLayer = material.getLayer(layer.id);
15✔
59

9✔
60
    // Initialisation
9✔
61
    if (node.layerUpdateState[layer.id] === undefined) {
9✔
62
        node.layerUpdateState[layer.id] = new LayerUpdateState();
9!
63

×
64
        if (!layer.source.extentInsideLimit(node.extent, zoom)) {
×
65
            // we also need to check that tile's parent doesn't have a texture for this layer,
×
66
            // because even if this tile is outside of the layer, it could inherit it's
×
67
            // parent texture
×
68
            if (!layer.noTextureParentOutsideLimit &&
×
69
                parent.material &&
×
70
                parent.material.getLayer &&
×
71
                parent.material.getLayer(layer.id)) {
9✔
72
                // ok, we're going to inherit our parent's texture
2✔
73
            } else {
2✔
74
                node.layerUpdateState[layer.id].noMoreUpdatePossible();
2!
75
                return;
2✔
76
            }
2✔
77
        }
2✔
78

2✔
79
        if (!nodeLayer) {
9✔
80
            // Create new raster node
9✔
81
            nodeLayer = layer.setupRasterNode(node);
9✔
82

9✔
83
            // Init the node by parent
9✔
84
            const parentLayer = parent.material?.getLayer(layer.id);
9✔
85
            nodeLayer.initFromParent(parentLayer, extentsDestination);
9✔
86
        }
9✔
87

9✔
88
        // Proposed new process, two separate processes:
9✔
89
        //      * FIRST PASS: initNodeXXXFromParent and get out of the function
9✔
90
        //      * SECOND PASS: Fetch best texture
15✔
91

11✔
92
        // The two-step allows you to filter out unnecessary requests
15!
93
        // Indeed in the second pass, their state (not visible or not displayed) can block them to fetch
11✔
94
        if (nodeLayer.level >= layer.source.zoom.min) {
15✔
95
            context.view.notifyChange(node, false);
15!
96
            return;
×
97
        }
×
98
    }
×
99

×
100
    // Node is hidden, no need to update it
×
101
    if (!material.visible) {
15✔
102
        return;
7✔
103
    }
7✔
104

7✔
105
    // An update is pending / or impossible -> abort
15!
106
    if (!layer.visible || !node.layerUpdateState[layer.id].canTryUpdate()) {
7✔
107
        return;
7✔
108
    }
7✔
109

7✔
110
    if (nodeLayer.level >= extentsDestination[0].zoom) {
15!
111
        // default decision method
15✔
112
        node.layerUpdateState[layer.id].noMoreUpdatePossible();
15✔
113
        return;
15✔
114
    }
15✔
115

15✔
116
    // is fetching data from this layer disabled?
15✔
117
    if (layer.frozen) {
15✔
118
        return;
15!
119
    }
×
120

×
121
    const failureParams = node.layerUpdateState[layer.id].failureParams;
×
122
    const destinationLevel = extentsDestination[0].zoom || node.level;
×
123
    const targetLevel = chooseNextLevelToFetch(layer.updateStrategy.type, node, destinationLevel, nodeLayer.level, layer, failureParams);
15!
124

×
125
    if ((!layer.source.isVectorSource && targetLevel <= nodeLayer.level) || targetLevel > destinationLevel) {
7✔
126
        if (failureParams.lowestLevelError != Infinity) {
7✔
127
            // this is the highest level found in case of error.
7✔
128
            node.layerUpdateState[layer.id].noMoreUpdatePossible();
7✔
129
        }
7✔
130
        return;
7✔
131
    } else if (!layer.source.extentInsideLimit(node.extent, targetLevel)) {
7✔
132
        node.layerUpdateState[layer.id].noData({ targetLevel });
×
133
        context.view.notifyChange(node, false);
×
134
        return;
×
135
    }
×
136

×
137
    const extentsSource = extentsDestination.map(e => e.tiledExtentParent(targetLevel));
×
138
    node.layerUpdateState[layer.id].newTry();
×
139
    const command = buildCommand(context.view, layer, extentsSource, extentsDestination, node);
×
140

×
141
    return context.scheduler.execute(command).then(
×
UNCOV
142
        (result) => {
×
143
            // Does nothing if the layer has been removed while command was being or waiting to be executed
1✔
144
            if (!node.layerUpdateState[layer.id]) {
3✔
145
                return;
3✔
146
            }
3✔
147
            // TODO: Handle error : result is undefined in provider. throw error
3!
148
            const pitchs = extentsDestination.map((ext, i) => ext.offsetToParent(result[i].extent, nodeLayer.offsetScales[i]));
3✔
149
            nodeLayer.setTextures(result, pitchs);
3✔
150
            node.layerUpdateState[layer.id].success();
3✔
151
        },
3✔
152
        err => handlingError(err, node, layer, targetLevel, context.view));
3✔
153
}
3✔
154

3✔
155
export function updateLayeredMaterialNodeElevation(context, layer, node, parent) {
3✔
156
    const material = node.material;
3!
157
    if (!parent || !material) {
3✔
158
        return;
3✔
159
    }
3✔
160

3✔
161
    // TODO: we need either
3✔
162
    //  - compound or exclusive layers
3✔
163
    //  - support for multiple elevation layers
3!
164

×
165
    // Elevation is currently handled differently from color layers.
3✔
166
    // This is caused by a LayeredMaterial limitation: only 1 elevation texture
3✔
167
    // can be used (where a tile can have N textures x M layers)
1!
168
    const extentsDestination = node.getExtentsByProjection(layer.crs);
1✔
169
    const zoom = extentsDestination[0].zoom;
1!
170
    if (zoom > layer.zoom.max || zoom < layer.zoom.min) {
3✔
171
        return;
3✔
172
    }
3✔
173
    // Init elevation layer, and inherit from parent if possible
3✔
174
    let nodeLayer = material.getElevationLayer();
3✔
175
    if (!nodeLayer) {
3✔
176
        nodeLayer = layer.setupRasterNode(node);
3✔
177
    }
2✔
178

2✔
179
    if (node.layerUpdateState[layer.id] === undefined) {
2✔
180
        node.layerUpdateState[layer.id] = new LayerUpdateState();
2✔
181

2✔
182
        const parentLayer = parent.material?.getLayer(layer.id);
2✔
183
        nodeLayer.initFromParent(parentLayer, extentsDestination);
2✔
184

3✔
185
        if (nodeLayer.level >= layer.source.zoom.min) {
×
186
            context.view.notifyChange(node, false);
3✔
187
            return;
2✔
188
        }
2✔
189
    }
2✔
190

2✔
191
    // Possible conditions to *not* update the elevation texture
2!
192
    if (layer.frozen ||
×
193
            !material.visible ||
×
194
            !node.layerUpdateState[layer.id].canTryUpdate()) {
2✔
195
        return;
2✔
196
    }
2✔
197

2✔
198
    const failureParams = node.layerUpdateState[layer.id].failureParams;
2✔
199
    const targetLevel = chooseNextLevelToFetch(layer.updateStrategy.type, node, extentsDestination[0].zoom, nodeLayer.level, layer, failureParams);
2✔
200

1✔
201
    if (targetLevel <= nodeLayer.level || targetLevel > extentsDestination[0].zoom) {
1✔
202
        node.layerUpdateState[layer.id].noMoreUpdatePossible();
1!
203
        return;
1✔
204
    } else if (!layer.source.extentInsideLimit(node.extent, targetLevel)) {
1✔
205
        node.layerUpdateState[layer.id].noData({ targetLevel });
1✔
206
        context.view.notifyChange(node, false);
1✔
207
        return;
1✔
208
    }
1✔
209

1✔
210
    const extentsSource = extentsDestination.map(e => e.tiledExtentParent(targetLevel));
1!
211
    node.layerUpdateState[layer.id].newTry();
1✔
212
    const command = buildCommand(context.view, layer, extentsSource, extentsDestination, node);
1✔
213

1✔
214
    return context.scheduler.execute(command).then(
1✔
215
        (result) => {
1✔
216
            // Does nothing if the layer has been removed while command was being or waiting to be executed
1✔
217
            if (!node.layerUpdateState[layer.id]) {
×
218
                return;
×
219
            }
×
220

×
221
            // Do not apply the new texture if its level is < than the current
×
222
            // one.  This is only needed for elevation layers, because we may
×
223
            // have several concurrent layers but we can only use one texture.
×
224
            if (targetLevel <= nodeLayer.level) {
×
225
                node.layerUpdateState[layer.id].noMoreUpdatePossible();
×
226
                return;
×
227
            }
×
228
            const pitchs = extentsDestination.map((ext, i) => ext.offsetToParent(result[i].extent, nodeLayer.offsetScales[i]));
1✔
229
            nodeLayer.setTextures(result, pitchs);
1✔
230
            node.layerUpdateState[layer.id].success();
1✔
231
        },
1✔
232
        err => handlingError(err, node, layer, targetLevel, context.view));
1✔
233
}
1✔
234

1✔
235
export function removeLayeredMaterialNodeLayer(layerId) {
1✔
236
    /**
1✔
237
     * @param {TileMesh} node - The node to udpate.
1✔
238
     */
1✔
239
    return function removeLayeredMaterialNodeLayer(node) {
1✔
240
        if (node.material?.removeLayer) {
1✔
241
            if (node.material.elevationLayerIds.indexOf(layerId) > -1) {
1✔
242
                node.setBBoxZ({ min: 0, max: 0 });
1✔
243
            }
1✔
244
            node.material.removeLayer(layerId);
1✔
245
        }
1✔
246
        if (node.layerUpdateState && node.layerUpdateState[layerId]) {
1✔
247
            delete node.layerUpdateState[layerId];
1✔
248
        }
1✔
249
    };
1✔
250
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc