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

iTowns / itowns / 8896060322

30 Apr 2024 01:56PM UTC coverage: 89.361% (-0.04%) from 89.402%
8896060322

push

github

Desplandis
docs(COPC): expose doc for COPCLayer and COPCSource

2712 of 3600 branches covered (75.33%)

Branch coverage included in aggregate %.

23226 of 25426 relevant lines covered (91.35%)

342.94 hits per line

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

96.65
/src/Source/Source.js
1
import Extent from 'Core/Geographic/Extent';
1✔
2
import GeoJsonParser from 'Parser/GeoJsonParser';
1✔
3
import KMLParser from 'Parser/KMLParser';
1✔
4
import GDFParser from 'Parser/GDFParser';
1✔
5
import GpxParser from 'Parser/GpxParser';
1✔
6
import GTXParser from 'Parser/GTXParser';
1✔
7
import ISGParser from 'Parser/ISGParser';
1✔
8
import VectorTileParser from 'Parser/VectorTileParser';
1✔
9
import Fetcher from 'Provider/Fetcher';
1✔
10
import Cache from 'Core/Scheduler/Cache';
1✔
11
import CRS from 'Core/Geographic/Crs';
1✔
12

1✔
13
export const supportedParsers = new Map([
1✔
14
    ['application/geo+json', GeoJsonParser.parse],
1✔
15
    ['application/json', GeoJsonParser.parse],
1✔
16
    ['application/kml', KMLParser.parse],
1✔
17
    ['application/gpx', GpxParser.parse],
1✔
18
    ['application/x-protobuf;type=mapbox-vector', VectorTileParser.parse],
1✔
19
    ['application/gtx', GTXParser.parse],
1✔
20
    ['application/isg', ISGParser.parse],
1✔
21
    ['application/gdf', GDFParser.parse],
1✔
22
]);
1✔
23

1✔
24
const noCache = { getByArray: () => {}, setByArray: a => a, clear: () => {} };
1✔
25

1✔
26
/**
1✔
27
 * @property {string} crs - data crs projection.
1✔
28
 * @property {boolean} isInverted - This option is to be set to the
1✔
29
 * correct value, true or false (default being false), if the computation of
1✔
30
 * the coordinates needs to be inverted to same scheme as OSM, Google Maps
1✔
31
 * or other system. See [this link]{@link
1✔
32
 * https://alastaira.wordpress.com/2011/07/06/converting-tms-tile-coordinates-to-googlebingosm-tile-coordinates}
1✔
33
 * for more informations.
1✔
34
 *
1✔
35
 */
1✔
36
class InformationsData {
1✔
37
    constructor(options) {
1✔
38
        /* istanbul ignore next */
1✔
39
        if (options.projection) {
117✔
40
            console.warn('Source projection parameter is deprecated, use crs instead.');
117!
41
            options.crs = options.crs || options.projection;
×
42
        }
×
43
        if (options.crs) {
117✔
44
            CRS.isValid(options.crs);
117✔
45
        }
117✔
46
        this.crs = options.crs;
1✔
47
    }
1✔
48
}
1✔
49
/**
1✔
50
 * This class describes parsing options.
1✔
51
 * @property {InformationsData|Source} in - data informations contained in the file.
1✔
52
 * @property {FeatureBuildingOptions|Layer} out - options indicates how the features should be built.
1✔
53
 */
1✔
54
// eslint-disable-next-line
1✔
55
class /* istanbul ignore next */ ParsingOptions {}
1✔
56

1✔
57
let uid = 0;
1✔
58

1✔
59
/**
1✔
60
 * @classdesc
1✔
61
 * Sources are object containing informations on how to fetch resources, from a
1✔
62
 * set source.
1✔
63
 *
1✔
64
 * To extend a Source, it is necessary to implement two functions:
1✔
65
 * `urlFromExtent` and `extentInsideLimit`.
1✔
66
 *
1✔
67
 * @extends InformationsData
1✔
68
 *
1✔
69
 * @property {boolean} isSource - Used to checkout whether this source is a
1✔
70
 * Source. Default is true. You should not change this, as it is used internally
1✔
71
 * for optimisation.
1✔
72
 * @property {number} uid - Unique uid mainly used to store data linked to this
1✔
73
 * source into Cache.
1✔
74
 * @property {string} url - The url of the resources that are fetched.
1✔
75
 * @property {string} format - The format of the resources that are fetched.
1✔
76
 * @property {function} fetcher - The method used to fetch the resources from
1✔
77
 * the source. iTowns provides some methods in {@link Fetcher}, but it can be
1✔
78
 * specified a custom one. This method should return a `Promise` containing the
1✔
79
 * fetched resource. If this property is set, it overrides the chosen fetcher
1✔
80
 * method with `format`.
1✔
81
 * @property {Object} networkOptions - Fetch options (passed directly to
1✔
82
 * `fetch()`), see [the syntax for more information]{@link
1✔
83
 * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Syntax}.
1✔
84
 * By default, set to `{ crossOrigin: 'anonymous' }`.
1✔
85
 * @property {string} crs - The crs projection of the resources.
1✔
86
 * @property {string} attribution - The intellectual property rights for the
1✔
87
 * resources.
1✔
88
 * @property {Extent} extent - The extent of the resources.
1✔
89
 * @property {function} parser - The method used to parse the resources attached
1✔
90
 * to the layer. iTowns provides some parsers, visible in the `Parser/` folder.
1✔
91
 * If the method is custom, it should return a `Promise` containing the parsed
1✔
92
 * resource. If this property is set, it overrides the default selected parser
1✔
93
 * method with `source.format`. If `source.format` is also empty, no parsing
1✔
94
 * action is done.
1✔
95
 * <br><br>
1✔
96
 * When calling this method, two parameters are passed:
1✔
97
 * <ul>
1✔
98
 *  <li>the fetched data, i.e. the data to parse</li>
1✔
99
 *  <li>an {@link ParsingOptions}  containing severals properties, set when this method is
1✔
100
 *  called: it is specific to each call, so the value of each property can vary
1✔
101
 *  depending on the current fetched tile for example</li>
1✔
102
 * </ul>
1✔
103
 */
1✔
104
class Source extends InformationsData {
1✔
105
    /**
1✔
106
     * @param {Object} source - An object that can contain all properties of a
1✔
107
     * Source. Only the `url` property is mandatory.
1✔
108
     *
1✔
109
     * @constructor
1✔
110
     */
117✔
111
    constructor(source) {
117✔
112
        super(source);
117✔
113
        this.isSource = true;
117✔
114

2✔
115
        if (!source.url) {
2✔
116
            throw new Error('New Source: url is required');
117✔
117
        }
115✔
118

115✔
119
        this.uid = uid++;
115✔
120

115✔
121
        this.url = source.url;
115✔
122
        this.format = source.format;
117✔
123
        this.fetcher = source.fetcher || Fetcher.get(source.format);
117✔
124
        this.parser = source.parser || supportedParsers.get(source.format) || ((d, opt) => { d.extent = opt.extent; return d; });
117✔
125
        this.isVectorSource = (source.parser || supportedParsers.get(source.format)) != undefined;
117✔
126
        this.networkOptions = source.networkOptions || { crossOrigin: 'anonymous' };
117✔
127
        this.attribution = source.attribution;
117✔
128
        /** @type {Promise<any>} */
117✔
129
        this.whenReady = Promise.resolve();
117✔
130
        this._featuresCaches = {};
117✔
131
        if (source.extent && !(source.extent.isExtent)) {
117✔
132
            this.extent = new Extent(this.crs, source.extent);
1✔
133
        } else {
2✔
134
            this.extent = source.extent;
1✔
135
        }
1✔
136
    }
1✔
137

1✔
138
    handlingError(err) {
1✔
139
        throw new Error(err);
1✔
140
    }
1✔
141

1✔
142
    /**
1✔
143
     * Generates an url from an extent. This url is a link to fetch the
1✔
144
     * resources inside the extent.
1✔
145
     *
1✔
146
     * @param {Extent} extent - Extent to convert in url.
1✔
147

1✔
148
     * @return {string} The URL constructed from the extent.
1✔
149
     */
1✔
150
    // eslint-disable-next-line
1✔
151
    urlFromExtent(extent) {
28✔
152
        throw new Error('In extended Source, you have to implement the method urlFromExtent!');
1✔
153
    }
1✔
154

1✔
155
    requestToKey(extent) {
1✔
156
        return [extent.zoom, extent.row, extent.col];
1✔
157
    }
1✔
158

1✔
159
    /**
1✔
160
     * Load  data from cache or Fetch/Parse data.
1✔
161
     * The loaded data is a Feature or Texture.
1✔
162
     *
1✔
163
     * @param      {Extent}  extent   extent requested parsed data.
1✔
164
     * @param      {FeatureBuildingOptions|Layer}  out     The feature returned options
1✔
165
     * @return     {FeatureCollection|Texture}  The parsed data.
8✔
166
     */
8✔
167
    loadData(extent, out) {
8✔
168
        const cache = this._featuresCaches[out.crs];
8✔
169
        const key = this.requestToKey(extent);
8✔
170
        // try to get parsed data from cache
8✔
171
        let features = cache.getByArray(key);
8✔
172
        if (!features) {
8✔
173
            // otherwise fetch/parse the data
8✔
174
            features = cache.setByArray(
8✔
175
                this.fetcher(this.urlFromExtent(extent), this.networkOptions)
8✔
176
                    .then(file => this.parser(file, { out, in: this, extent }))
3✔
177
                    .catch(err => this.handlingError(err)),
3✔
178
                key);
8✔
179

8✔
180
            /* istanbul ignore next */
1✔
181
            if (this.onParsedFile) {
1✔
182
                features.then((feat) => {
1✔
183
                    this.onParsedFile(feat);
81✔
184
                    console.warn('Source.onParsedFile was deprecated');
81✔
185
                    return feat;
73✔
186
                });
73✔
187
            }
73✔
188
        }
73✔
189
        return features;
73✔
190
    }
73✔
191

73✔
192
    /**
73✔
193
     * Called when layer added.
73✔
194
     *
73✔
195
     * @param {object} options
73✔
196
     */
73✔
197
    onLayerAdded(options) {
73✔
198
        // Added new cache by crs
81✔
199
        if (!this._featuresCaches[options.out.crs]) {
1✔
200
            // Cache feature only if it's vector data, the feature are cached in source.
1✔
201
            // It's not necessary to cache raster in Source,
2!
202
            // because it's already cached on layer.
2✔
203
            this._featuresCaches[options.out.crs] = this.isVectorSource ? new Cache() : noCache;
2!
204
        }
×
205
    }
×
206

×
207
    /**
×
208
     * Called when layer removed.
2✔
209
     *
1✔
210
     * @param {options}  [options={}] options
1✔
211
     */
1✔
212
    onLayerRemoved(options = {}) {
1✔
213
        // delete unused cache
1✔
214
        const unusedCache = this._featuresCaches[options.unusedCrs];
1✔
215
        if (unusedCache) {
1✔
216
            unusedCache.clear();
1✔
217
            delete this._featuresCaches[options.unusedCrs];
1✔
218
        }
1✔
219
    }
1✔
220

1✔
221
    /**
1✔
222
     * Tests if an extent is inside the source limits.
1✔
223
     *
1✔
224
     * @param {Extent} extent - Extent to test.
1✔
225

1✔
226
     * @return {boolean} True if the extent is inside the limit, false otherwise.
1✔
227
     */
1✔
228
    // eslint-disable-next-line
1✔
229
    extentInsideLimit(extent) {
1✔
230
        throw new Error('In extented Source, you have to implement the method extentInsideLimit!');
1✔
231
    }
1✔
232
}
1✔
233

1✔
234
export default Source;
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