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

iTowns / itowns / 7743821661

01 Feb 2024 03:41PM UTC coverage: 77.306% (-0.05%) from 77.36%
7743821661

Pull #2124

github

web-flow
Merge 9b8011e0b into 47d0c7cab
Pull Request #2124: Feat/google3d tiles

4108 of 6059 branches covered (0.0%)

Branch coverage included in aggregate %.

53 of 92 new or added lines in 3 files covered. (57.61%)

1 existing line in 1 file now uncovered.

8097 of 9729 relevant lines covered (83.23%)

1940.33 hits per line

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

66.39
/src/Provider/3dTilesProvider.js
1
import * as THREE from 'three';
1✔
2
import B3dmParser from 'Parser/B3dmParser';
1✔
3
import PntsParser from 'Parser/PntsParser';
1✔
4
import GLTFParser from 'Parser/GLTFParser';
1✔
5
import Fetcher from 'Provider/Fetcher';
1✔
6
import ReferLayerProperties from 'Layer/ReferencingLayerProperties';
1✔
7
import utf8Decoder from 'Utils/Utf8Decoder';
1✔
8
import PointsMaterial from 'Renderer/PointsMaterial';
1,676✔
9

10
function b3dmToMesh(data, layer, url) {
11
    const urlBase = THREE.LoaderUtils.extractUrlBase(url);
3✔
12
    const options = {
3✔
13
        gltfUpAxis: layer.tileset.asset.gltfUpAxis,
14
        urlBase,
15
        overrideMaterials: layer.overrideMaterials,
16
        doNotPatchMaterial: layer.doNotPatchMaterial,
17
        registeredExtensions: layer.registeredExtensions,
18
        layer,
19
    };
20
    return B3dmParser.parse(data, options).then((result) => {
3✔
21
        const batchTable = result.batchTable;
3✔
22
        // object3d is actually a THREE.Scene
23
        const object3d = result.gltf.scene;
3✔
24
        return { batchTable, object3d };
3✔
25
    });
26
}
27

28
function gltfToMesh(data, layer, url) {
NEW
29
    const urlBase = THREE.LoaderUtils.extractUrlBase(url);
×
NEW
30
    return GLTFParser.parse(data, urlBase).then(result => ({ object3d: result.scene }));
×
31
}
32

33
function pntsParse(data, layer) {
34
    return PntsParser.parse(data, layer.registeredExtensions).then((result) => {
×
35
        const material = layer.material ?
×
36
            layer.material.clone() :
37
            new PointsMaterial({
38
                size: 0.05,
39
                mode: layer.pntsMode,
40
                shape: layer.pntsShape,
41
                classification: layer.classification,
42
                sizeMode: layer.pntsSizeMode,
43
                minAttenuatedSize: layer.pntsMinAttenuatedSize,
44
                maxAttenuatedSize: layer.pntsMaxAttenuatedSize,
45
            });
46

47
        // refer material properties in the layer so when layers opacity and visibility is updated, the material is
48
        // automatically updated
49
        ReferLayerProperties(material, layer);
×
50

51
        // creation points with geometry and material
52
        const points = new THREE.Points(result.point.geometry, material);
×
53

54
        if (result.point.offset) {
×
55
            points.position.copy(result.point.offset);
×
56
        }
57

58
        return { object3d: points,
×
59
            batchTable: result.batchTable,
60
        };
61
    });
62
}
63

64
export function configureTile(tile, layer, metadata, parent) {
65
    tile.frustumCulled = false;
10✔
66
    tile.layer = layer;
10✔
67

68
    // parse metadata
69
    if (metadata.transform) {
10✔
70
        tile.applyMatrix4(metadata.transform);
5✔
71
    }
72
    tile.geometricError = metadata.geometricError;
10✔
73
    tile.tileId = metadata.tileId;
10✔
74
    if (metadata.refine) {
10✔
75
        tile.additiveRefinement = (metadata.refine.toUpperCase() === 'ADD');
3✔
76
    } else {
77
        tile.additiveRefinement = parent ? (parent.additiveRefinement) : false;
7✔
78
    }
79
    tile.viewerRequestVolume = metadata.viewerRequestVolume;
10✔
80
    tile.boundingVolume = metadata.boundingVolume;
10✔
81
    tile.updateMatrixWorld();
10✔
82
}
83

84
function executeCommand(command) {
85
    const layer = command.layer;
4✔
86
    const metadata = command.metadata;
4✔
87
    const tile = new THREE.Object3D();
4✔
88
    configureTile(tile, layer, metadata, command.requester);
4✔
89
    // Patch for supporting 3D Tiles pre 1.0 (metadata.content.url) and 1.0
90
    // (metadata.content.uri)
91
    const path = metadata.content && (metadata.content.url || metadata.content.uri);
4✔
92

93
    const setLayer = (obj) => {
4✔
94
        obj.userData.metadata = metadata;
14✔
95
        obj.layer = layer;
14✔
96
    };
97
    if (path) {
4✔
98
        // Check if we have relative or absolute url (with tileset's lopocs for example)
99
        let url = path.startsWith('http') ? path : metadata.baseURL + path;
3!
100
        if (layer.source.isC3DTilesGoogleSource) {
3!
NEW
101
            url = layer.source.getTileUrl(url);
×
102
        }
103
        const supportedFormats = {
3✔
104
            b3dm: b3dmToMesh,
105
            pnts: pntsParse,
106
            gltf: gltfToMesh,
107
        };
108
        return Fetcher.arrayBuffer(url, layer.source.networkOptions).then((result) => {
3✔
109
            if (result !== undefined) {
3!
110
                let func;
111
                const magic = utf8Decoder.decode(new Uint8Array(result, 0, 4));
3✔
112
                if (magic[0] === '{') {
3!
113
                    result = JSON.parse(utf8Decoder.decode(new Uint8Array(result)));
×
NEW
114
                    let newPrefix = '';
×
115
                    // Another specifics of 3D tiles from Google: tilesets in tilesets are required from the root base
116
                    // url and not from their parent base url
NEW
117
                    if (layer.source.isC3DTilesGoogleSource) {
×
NEW
118
                        newPrefix = layer.source.baseUrl;
×
119
                    } else {
NEW
120
                        newPrefix = url.slice(0, url.lastIndexOf('/') + 1);
×
121
                    }
UNCOV
122
                    layer.tileset.extendTileset(result, metadata.tileId, newPrefix, layer.registeredExtensions);
×
123
                } else if (magic == 'b3dm') {
3!
124
                    func = supportedFormats.b3dm;
3✔
125
                } else if (magic == 'pnts') {
×
126
                    func = supportedFormats.pnts;
×
NEW
127
                } else if (magic == 'glTF') {
×
NEW
128
                    func = supportedFormats.gltf;
×
129
                } else {
130
                    return Promise.reject(`Unsupported magic code ${magic}`);
×
131
                }
132
                if (func) {
3!
133
                    // TODO: request should be delayed if there is a viewerRequestVolume
134
                    return func(result, layer, url).then((content) => {
3✔
135
                        tile.content = content.object3d;
3✔
136
                        if (content.batchTable) {
3!
137
                            tile.batchTable = content.batchTable;
3✔
138
                        }
139
                        tile.add(content.object3d);
3✔
140
                        tile.traverse(setLayer);
3✔
141
                        return tile;
3✔
142
                    });
143
                }
144
            }
145
            tile.traverse(setLayer);
×
146
            return tile;
×
147
        });
148
    } else {
149
        tile.traverse(setLayer);
1✔
150
        return Promise.resolve(tile);
1✔
151
    }
152
}
153

154
export default {
1✔
155
    executeCommand,
156
};
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