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

iTowns / itowns / 10635241580

30 Aug 2024 03:26PM UTC coverage: 86.966% (-2.8%) from 89.766%
10635241580

push

github

jailln
feat(3dtiles): add new OGC3DTilesLayer using 3d-tiles-renderer-js

Deprecate C3DTilesLayer (replaced by OGC3DTilesLayer).
Add new iGLTFLoader that loads gltf 1.0 and 2.0 files.

2791 of 3694 branches covered (75.55%)

Branch coverage included in aggregate %.

480 of 644 new or added lines in 8 files covered. (74.53%)

2144 existing lines in 111 files now uncovered.

24319 of 27479 relevant lines covered (88.5%)

1024.72 hits per line

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

64.12
/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) {
9✔
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
}
9✔
12

1✔
13
function refinementCommandCancellationFn(cmd) {
1✔
14
    if (!cmd.requester.parent || !cmd.requester.material) {
1!
UNCOV
15
        return true;
×
UNCOV
16
    }
×
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!
UNCOV
22
        return true;
×
UNCOV
23
    }
×
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!
UNCOV
28
        return true;
×
UNCOV
29
    }
×
30

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

1✔
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),
9✔
42
        earlyDropFunction: refinementCommandCancellationFn,
9✔
43
    };
9✔
44
}
9✔
45

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

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

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

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

9✔
64
        if (!layer.source.extentInsideLimit(node.extent, zoom)) {
9!
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 &&
×
UNCOV
71
                parent.material.getLayer(layer.id)) {
×
UNCOV
72
                // ok, we're going to inherit our parent's texture
×
UNCOV
73
            } else {
×
UNCOV
74
                node.layerUpdateState[layer.id].noMoreUpdatePossible();
×
UNCOV
75
                return;
×
UNCOV
76
            }
×
UNCOV
77
        }
×
78

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

2✔
83
            // Init the node by parent
2✔
84
            const parentLayer = parent.material?.getLayer(layer.id);
2!
85
            nodeLayer.initFromParent(parentLayer, extentsDestination);
2✔
86
        }
2✔
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
9✔
91

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

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

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

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

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

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

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

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

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

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

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

3✔
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)
3✔
168
    const extentsDestination = node.getExtentsByProjection(layer.crs);
3✔
169
    const zoom = extentsDestination[0].zoom;
3✔
170
    if (zoom > layer.zoom.max || zoom < layer.zoom.min) {
3!
UNCOV
171
        return;
×
UNCOV
172
    }
×
173
    // Init elevation layer, and inherit from parent if possible
3✔
174
    let nodeLayer = material.getElevationLayer();
3✔
175
    if (!nodeLayer) {
3!
UNCOV
176
        nodeLayer = layer.setupRasterNode(node);
×
UNCOV
177
    }
×
178

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

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

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

3✔
191
    // Possible conditions to *not* update the elevation texture
3✔
192
    if (layer.frozen ||
3✔
193
            !material.visible ||
3✔
194
            !node.layerUpdateState[layer.id].canTryUpdate()) {
3✔
195
        return;
1✔
196
    }
1✔
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

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

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

2✔
214
    return context.scheduler.execute(command).then(
2✔
215
        (result) => {
2✔
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]) {
1!
218
                return;
×
219
            }
×
220

1✔
221
            // Do not apply the new texture if its level is < than the current
1✔
222
            // one.  This is only needed for elevation layers, because we may
1✔
223
            // have several concurrent layers but we can only use one texture.
1✔
224
            if (targetLevel <= nodeLayer.level) {
1!
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
        },
2✔
232
        err => handlingError(err, node, layer, targetLevel, context.view));
2✔
233
}
2✔
234

1✔
235
export function removeLayeredMaterialNodeLayer(layerId) {
1✔
UNCOV
236
    /**
×
UNCOV
237
     * @param {TileMesh} node - The node to udpate.
×
UNCOV
238
     */
×
UNCOV
239
    return function removeLayeredMaterialNodeLayer(node) {
×
UNCOV
240
        if (node.material?.removeLayer) {
×
UNCOV
241
            if (node.material.elevationLayerIds.indexOf(layerId) > -1) {
×
UNCOV
242
                node.setBBoxZ({ min: 0, max: 0 });
×
UNCOV
243
            }
×
UNCOV
244
            node.material.removeLayer(layerId);
×
UNCOV
245
        }
×
UNCOV
246
        if (node.layerUpdateState && node.layerUpdateState[layerId]) {
×
UNCOV
247
            delete node.layerUpdateState[layerId];
×
UNCOV
248
        }
×
UNCOV
249
    };
×
UNCOV
250
}
×
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