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

iTowns / itowns / 10902507646

17 Sep 2024 11:56AM UTC coverage: 86.931% (-0.03%) from 86.964%
10902507646

push

github

Desplandis
release v2.44.2

2791 of 3694 branches covered (75.55%)

Branch coverage included in aggregate %.

24241 of 27402 relevant lines covered (88.46%)

1027.5 hits per line

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

85.4
/src/Layer/GeometryLayer.js
1
import Layer from 'Layer/Layer';
1✔
2
import Picking from 'Core/Picking';
1✔
3
import { CACHE_POLICIES } from 'Core/Scheduler/Cache';
1✔
4
import ObjectRemovalHelper from 'Process/ObjectRemovalHelper';
1✔
5

1✔
6
/**
1✔
7
 * Fires when the opacity of the layer has changed.
1✔
8
 * @event GeometryLayer#opacity-property-changed
1✔
9
 */
1✔
10

1✔
11
/**
1✔
12
 * @property {boolean} isGeometryLayer - Used to checkout whether this layer is
1✔
13
 * a GeometryLayer. Default is true. You should not change this, as it is used
1✔
14
 * internally for optimisation.
1✔
15
 * @property {number} [zoom.max=Infinity] - this is the maximum zoom beyond which it'll be hidden.
1✔
16
 * The `max` is constant and the value is `Infinity` because there's no maximum display level after which it is hidden.
1✔
17
 * This property is used only if the layer is attached to {@link TiledGeometryLayer}.
1✔
18
 * @property {number} [zoom.min=0] - this is the minimum zoom from which it'll be visible.
1✔
19
 * This property is used only if the layer is attached to {@link TiledGeometryLayer}.
1✔
20
 */
1✔
21
class GeometryLayer extends Layer {
1✔
22
    /**
1✔
23
     * A layer usually managing a geometry to display on a view. For example, it
1✔
24
     * can be a layer of buildings extruded from a a WFS stream.
1✔
25
     *
1✔
26
     * @extends Layer
1✔
27
     *
1✔
28
     * @param {string} id - The id of the layer, that should be unique. It is
1✔
29
     * not mandatory, but an error will be emitted if this layer is added a
1✔
30
     * {@link View} that already has a layer going by that id.
1✔
31
     * @param {THREE.Object3D} object3d - The object3D used to contain the
1✔
32
     * geometry of the GeometryLayer. It is usually a `THREE.Group`, but it can
1✔
33
     * be anything inheriting from a `THREE.Object3D`.
1✔
34
     * @param {Object} [config] - Optional configuration, all elements in it
1✔
35
     * will be merged as is in the layer. For example, if the configuration
1✔
36
     * contains three elements `name, protocol, extent`, these elements will be
1✔
37
     * available using `layer.name` or something else depending on the property
1✔
38
     * name.
1✔
39
     * @param {Source} [config.source] - Description and options of the source.
1✔
40
     *
1✔
41
     * @throws {Error} `object3d` must be a valid `THREE.Object3d`.
1✔
42
     *
1✔
43
     * @example
1✔
44
     * // Create a GeometryLayer
1✔
45
     * const geometry = new GeometryLayer('buildings', new THREE.Object3D(), {
1✔
46
     *      source: {
1✔
47
     *          url: 'http://server.geo/wfs?',
1✔
48
     *          protocol: 'wfs',
1✔
49
     *          format: 'application/json'
1✔
50
     *      },
1✔
51
     * });
1✔
52
     *
1✔
53
     * // Add the layer
1✔
54
     * view.addLayer(geometry);
1✔
55
     */
1✔
56
    constructor(id, object3d, config = {}) {
1!
57
        config.cacheLifeTime = config.cacheLifeTime ?? CACHE_POLICIES.GEOMETRY;
83✔
58

83✔
59
        // Remove this part when Object.assign(this, config) will be removed from Layer Constructor
83✔
60
        const visible = config.visible;
83✔
61
        delete config.visible;
83✔
62
        super(id, config);
83✔
63

83✔
64
        this.isGeometryLayer = true;
83✔
65

83✔
66
        if (!object3d || !object3d.isObject3D) {
83!
67
            throw new Error(`Missing/Invalid object3d parameter (must be a
×
68
                three.js Object3D instance)`);
×
69
        }
×
70

83✔
71
        if (object3d.type === 'Group' && object3d.name === '') {
83✔
72
            object3d.name = id;
63✔
73
        }
63✔
74

83✔
75
        Object.defineProperty(this, 'object3d', {
83✔
76
            value: object3d,
83✔
77
            writable: false,
83✔
78
            configurable: true,
83✔
79
        });
83✔
80

83✔
81
        this.opacity = 1.0;
83✔
82
        this.wireframe = false;
83✔
83

83✔
84
        this.attachedLayers = [];
83✔
85
        this.visible = visible ?? true;
83✔
86
        Object.defineProperty(this.zoom, 'max', {
83✔
87
            value: Infinity,
83✔
88
            writable: false,
83✔
89
        });
83✔
90

83✔
91
        // Feature options
83✔
92
        this.filteringExtent = !this.source.isFileSource;
83✔
93
        this.structure = '3d';
83✔
94
    }
83✔
95

1✔
96
    get visible() {
1✔
97
        return this.object3d.visible;
148✔
98
    }
148✔
99

1✔
100
    set visible(value) {
1✔
101
        if (this.object3d.visible !== value) {
83!
102
            const event = { type: 'visible-property-changed', previous: {}, new: {} };
×
103
            event.previous.visible = this.object3d.visible;
×
104
            event.new.visible = value;
×
105
            this.dispatchEvent(event);
×
106
            this.object3d.visible = value;
×
107
        }
×
108
    }
83✔
109

1✔
110
    // Attached layers expect to receive the visual representation of a
1✔
111
    // layer (= THREE object with a material).  So if a layer's update
1✔
112
    // function don't process this kind of object, the layer must provide a
1✔
113
    // getObjectToUpdateForAttachedLayers function that returns the correct
1✔
114
    // object to update for attached layer.
1✔
115
    // See 3dtilesLayer or PotreeLayer for examples.
1✔
116
    // eslint-disable-next-line arrow-body-style
1✔
117
    getObjectToUpdateForAttachedLayers(obj) {
1✔
118
        if (obj.parent && obj.material) {
4!
119
            return {
×
120
                element: obj,
×
121
                parent: obj.parent,
×
122
            };
×
123
        }
×
124
    }
4✔
125

1✔
126
    // Placeholder
1✔
127
    // eslint-disable-next-line
1✔
128
    postUpdate() {}
1✔
129

1✔
130
    // Placeholder
1✔
131
    // eslint-disable-next-line
1✔
132
    culling() {
1✔
133
        return true;
×
134
    }
×
135

1✔
136
    /**
1✔
137
     * Attach another layer to this one. Layers attached to a GeometryLayer will
1✔
138
     * be available in `geometryLayer.attachedLayers`.
1✔
139
     *
1✔
140
     * @param {Layer} layer - The layer to attach, that must have an `update`
1✔
141
     * method.
1✔
142
     */
1✔
143
    attach(layer) {
1✔
144
        if (!layer.update) {
41!
145
            throw new Error(`Missing 'update' function -> can't attach layer
×
146
                ${layer.id}`);
×
147
        }
×
148
        this.attachedLayers.push(layer);
41✔
149
        // To traverse GeometryLayer object3d attached
41✔
150
        layer.parent = this;
41✔
151
    }
41✔
152

1✔
153
    /**
1✔
154
     * Detach a layer attached to this one. See {@link attach} to learn how to
1✔
155
     * attach a layer.
1✔
156
     *
1✔
157
     * @param {Layer} layer - The layer to detach.
1✔
158
     *
1✔
159
     * @return {boolean} Confirmation of the detachment of the layer.
1✔
160
     */
1✔
161
    detach(layer) {
1✔
162
        const count = this.attachedLayers.length;
1✔
163
        this.attachedLayers = this.attachedLayers.filter(attached => attached.id != layer.id);
1✔
164
        layer.parent = undefined;
1✔
165
        return this.attachedLayers.length < count;
1✔
166
    }
1✔
167

1✔
168
    /**
1✔
169
     * All layer's 3D objects are removed from the scene and disposed from the video device.
1✔
170
     * @param {boolean} [clearCache=false] Whether to clear the layer cache or not
1✔
171
     */
1✔
172
    delete(clearCache) {
1✔
173
        if (clearCache) {
2!
174
            this.cache.clear();
×
175
        }
×
176

2✔
177
        // if Layer is attached
2✔
178
        if (this.parent) {
2!
179
            ObjectRemovalHelper.removeChildrenAndCleanupRecursively(this, this.parent.object3d);
×
180
        }
×
181

2✔
182
        if (this.object3d.parent) {
2✔
183
            this.object3d.parent.remove(this.object3d);
2✔
184
        }
2✔
185
        ObjectRemovalHelper.removeChildrenAndCleanupRecursively(this, this.object3d);
2✔
186
    }
2✔
187

1✔
188
    /**
1✔
189
     * Picking method for this layer.
1✔
190
     *
1✔
191
     * @param {View} view - The view instance.
1✔
192
     * @param {Object} coordinates - The coordinates to pick in the view. It
1✔
193
     * should have at least `x` and `y` properties.
1✔
194
     * @param {number} radius - Radius of the picking circle.
1✔
195
     * @param {Array} target - target to push result.
1✔
196
     *
1✔
197
     * @return {Array} An array containing all targets picked under the
1✔
198
     * specified coordinates.
1✔
199
     */
1✔
200
    pickObjectsAt(view, coordinates, radius = this.options.defaultPickingRadius, target = []) {
1✔
201
        return Picking.pickObjectsAt(view, coordinates, radius, this.object3d, target);
×
202
    }
×
203
}
1✔
204

1✔
205
export default GeometryLayer;
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

© 2026 Coveralls, Inc