• 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

96.43
/src/Source/FileSource.js
1
import Source from 'Source/Source';
1✔
2
import Cache from 'Core/Scheduler/Cache';
1✔
3
import CRS from 'Core/Geographic/Crs';
1✔
4

1✔
5
/**
1✔
6
 * An object defining the source of a single resource to get from a direct
1✔
7
 * access. It inherits from {@link Source}. There is multiple ways of adding a
1✔
8
 * resource here:
1✔
9
 * <ul>
1✔
10
 *  <li>add the file like any other sources, using the `url` property.</li>
1✔
11
 *  <li>fetch the file, and give the data to the source using the `fetchedData`
1✔
12
 *  property.</li>
1✔
13
 *  <li>fetch the file, parse it and git the parsed data to the source using the
1✔
14
 *  `features` property.</li>
1✔
15
 * </ul>
1✔
16
 * See the examples below for real use cases.
1✔
17
 *
1✔
18
 * @extends Source
1✔
19
 *
1✔
20
 * @property {boolean} isFileSource - Used to checkout whether this source is a
1✔
21
 * FileSource. Default is true. You should not change this, as it is used
1✔
22
 * internally for optimisation.
1✔
23
 * @property {*} fetchedData - Once the file has been loaded, the resulting data
1✔
24
 * is stored in this property.
1✔
25
 * @property {*} features - Once the file has been loaded and parsed, the
1✔
26
 * resulting data is stored in this property.
1✔
27
 *
1✔
28
 * @example <caption>Simple: create a source, a layer, and let iTowns taking
1✔
29
 * care of everything.</caption>
1✔
30
 * const kmlSource = new itowns.FileSource({
1✔
31
 *     url: 'https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/croquis.kml',
1✔
32
 *     crs: 'EPSG:4326',
1✔
33
 *     fetcher: itowns.Fetcher.xml,
1✔
34
 *     parser: itowns.KMLParser.parse,
1✔
35
 * });
1✔
36
 *
1✔
37
 * const kmlLayer = new itowns.ColorLayer('Kml', {
1✔
38
 *     name: 'kml',
1✔
39
 *     transparent: true,
1✔
40
 *     crs: view.tileLayer.extent.crs,
1✔
41
 *     source: kmlSource,
1✔
42
 * });
1✔
43
 *
1✔
44
 * view.addLayer(kmlLayer);
1✔
45
 *
1✔
46
 * @example <caption>Advanced: fetch some data, create a source, a layer, and
1✔
47
 * let iTowns do the parsing and converting.</caption>
1✔
48
 * // Parse and Convert by iTowns
1✔
49
 * itowns.Fetcher.xml('https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/ULTRA2009.gpx')
1✔
50
 *     .then(function _(gpx) {
1✔
51
 *         const gpxSource = new itowns.FileSource({
1✔
52
 *             data: gpx,
1✔
53
 *             crs: 'EPSG:4326',
1✔
54
 *             parser: itowns.GpxParser.parse,
1✔
55
 *         });
1✔
56
 *
1✔
57
 *         const gpxLayer = new itowns.ColorLayer('Gpx', {
1✔
58
 *             name: 'Ultra 2009',
1✔
59
 *             transparent: true,
1✔
60
 *             source: gpxSource,
1✔
61
 *         });
1✔
62
 *
1✔
63
 *         return view.addLayer(gpxLayer);
1✔
64
 *     });
1✔
65
 *
1✔
66
 * @example <caption>More advanced: create a layer, fetch some data, parse the
1✔
67
 * data, append a source to the layer and add the layer to iTowns.</caption>
1✔
68
 * // Create a layer
1✔
69
 * const ariege = new itowns.GeometryLayer('ariege', new itowns.THREE.Group());
1✔
70
 *
1✔
71
 * // Specify update method and conversion
1✔
72
 * ariege.update = itowns.FeatureProcessing.update;
1✔
73
 * ariege.convert = itowns.Feature2Mesh.convert({
1✔
74
 *     color: () => new itowns.THREE.Color(0xffcc00),
1✔
75
 *     extrude: () => 5000,
1✔
76
 * });
1✔
77
 *
1✔
78
 * itowns.Fetcher.json('https://raw.githubusercontent.com/gregoiredavid/france-geojson/master/departements/09-ariege/departement-09-ariege.geojson')
1✔
79
 *     .then(function _(geojson) {
1✔
80
 *         return itowns.GeoJsonParser.parse(geojson, {
1✔
81
 *             in: { crs: 'EPSG:4326' },
1✔
82
 *             out: { crs: view.tileLayer.extent.crs,
1✔
83
 *                      style: new itowns.Style({
1✔
84
 *                          fill: {
1✔
85
 *                              color: new itowns.THREE.Color(0xffcc00),
1✔
86
 *                              extrusion_height: () => 5000,
1✔
87
 *                      }),
1✔
88
 *                  },
1✔
89
 *             },
1✔
90
 *         });
1✔
91
 *     }).then(function _(features) {
1✔
92
 *         ariege.source = new itowns.FileSource({
1✔
93
 *             crs: 'EPSG:4326',
1✔
94
 *             features,
1✔
95
 *         });
1✔
96
 *
1✔
97
 *         return view.addLayer(ariegeLayer);
1✔
98
 *     });
1✔
99
 */
1✔
100
class FileSource extends Source {
1✔
101
    /**
1✔
102
     * @param {Object} source - An object that can contain all properties of a
1✔
103
     * FileSource and {@link Source}. Only `crs` is mandatory, but if it
1✔
104
     * presents in `features` under the property `crs`, it is fine.
1✔
105
     */
1✔
106
    constructor(source) {
1✔
107
        /* istanbul ignore next */
16✔
108
        if (source.parsedData) {
16!
109
            console.warn('FileSource parsedData parameter is deprecated, use features instead of.');
×
110
            source.features = source.features || source.parsedData;
×
111
        }
×
112
        /* istanbul ignore next */
16✔
113
        if (source.projection) {
16!
114
            console.warn('FileSource projection parameter is deprecated, use crs instead.');
×
115
            source.crs = source.crs || source.projection;
×
116
        }
×
117
        if (!source.crs) {
16✔
118
            if (source.features && source.features.crs) {
2✔
119
                source.crs = source.features.crs;
1✔
120
            } else {
1✔
121
                throw new Error('source.crs is required in FileSource');
1✔
122
            }
1✔
123
        }
2✔
124

15✔
125
        if (!source.url && !source.fetchedData && !source.features) {
16✔
126
            throw new Error(`url, fetchedData and features are not set in
1✔
127
                FileSource; at least one needs to be present`);
1✔
128
        }
1✔
129

14✔
130
        // the fake url is for when we use the fetchedData or features mode
14✔
131
        source.url = source.url || 'none';
16✔
132
        super(source);
16✔
133

16✔
134
        this.isFileSource = true;
16✔
135

16✔
136
        this.fetchedData = source.fetchedData;
16✔
137
        if (!this.fetchedData && !source.features) {
16✔
138
            this.whenReady = this.fetcher(this.urlFromExtent(), this.networkOptions).then((f) => {
3✔
139
                this.fetchedData = f;
3✔
140
            });
3✔
141
        } else if (source.features) {
16✔
142
            this._featuresCaches[source.features.crs] = new Cache();
3✔
143
            this._featuresCaches[source.features.crs].setByArray(Promise.resolve(source.features), [0]);
3✔
144
        }
3✔
145

14✔
146
        this.whenReady.then(() => this.fetchedData);
14✔
147

14✔
148
        this.zoom = { min: 0, max: Infinity };
14✔
149
    }
14✔
150

1✔
151
    urlFromExtent() {
1✔
152
        return this.url;
6✔
153
    }
6✔
154

1✔
155
    onLayerAdded(options) {
1✔
156
        options.in = this;
18✔
157
        super.onLayerAdded(options);
18✔
158
        let features = this._featuresCaches[options.out.crs].getByArray([0]);
18✔
159
        if (!features) {
18✔
160
            options.out.buildExtent = this.crs != 'EPSG:4978';
10✔
161
            if (options.out.buildExtent) {
10✔
162
                options.out.forcedExtentCrs = options.out.crs != 'EPSG:4978' ? options.out.crs : CRS.formatToEPSG(this.crs);
10✔
163
            }
10✔
164
            features = this.parser(this.fetchedData, options);
10✔
165
            this._featuresCaches[options.out.crs].setByArray(features, [0]);
10✔
166
        }
10✔
167
        features.then((data) => {
18✔
168
            if (data.extent) {
18✔
169
                this.extent = data.extent.clone();
14✔
170
                // Transform local extent to data.crs projection.
14✔
171
                if (this.extent.crs == data.crs) {
14✔
172
                    this.extent.applyMatrix4(data.matrixWorld);
8✔
173
                }
8✔
174
            }
14✔
175
        });
18✔
176
    }
18✔
177

1✔
178
    /**
1✔
179
     * load  data from cache or Fetch/Parse data.
1✔
180
     * The loaded data is a Feature or Texture.
1✔
181
     *
1✔
182
     * @param      {Extent}  extent   extent requested parsed data.
1✔
183
     * @param      {FeatureBuildingOptions|Layer}  out  The feature returned options
1✔
184
     * @return     {FeatureCollection|Texture}  The parsed data.
1✔
185
     */
1✔
186
    loadData(extent, out) {
1✔
187
        return this._featuresCaches[out.crs].getByArray([0]);
11✔
188
    }
11✔
189

1✔
190
    extentInsideLimit(extent) {
1✔
191
        return this.extent.intersectsExtent(extent);
13✔
192
    }
13✔
193
}
1✔
194

1✔
195
export default FileSource;
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