Destroyed Vector Use Cases (markdown)
@@ -1,194 +0,0 @@
|
||||
**Outdated!**
|
||||
|
||||
## Vector Use Cases
|
||||
|
||||
These use cases describe common scenarios for loading, rendering, and editing vector data.
|
||||
|
||||
### Load data once from static file
|
||||
|
||||
User has a static file (e.g. GeoJSON) hosted on the same origin as their application. User expects data to be loaded and rendered in the map projection.
|
||||
|
||||
**Alternative 1**
|
||||
|
||||
```js
|
||||
|
||||
// assume features.json is a FeatureCollection in EPSG:4326
|
||||
var vector = new ol.layer.Vector({
|
||||
source: new ol.source.Vector({
|
||||
protocol: new ol.protocol.HTTP({
|
||||
url: './data/features.json'
|
||||
}),
|
||||
parser: new ol.parser.GeoJSON()
|
||||
})
|
||||
});
|
||||
|
||||
var map = new ol.Map({
|
||||
target: 'map',
|
||||
layers: [vector],
|
||||
view: new ol.View2D({
|
||||
projection: 'EPSG:1234',
|
||||
center: ol.projection.transform(
|
||||
new ol.Coordinate(139.7, 35.7), 'EPSG:4326', 'EPSG:1234'),
|
||||
zoom: 9
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
This alternative can be implemented if the layer knows the map projection. The vector layer is responsible for calling `source.protocol.read({success: callback})` where the callback calls `source.parser.parseFeatures(data, {projection: projection})` (`data` is supplied to the callback and `projection` comes from the map's view). The layer maintains a cache of features in the map view's projection, and these are supplied on demand to layer's the renderer.
|
||||
|
||||
_Questions/comments from Eric:_
|
||||
|
||||
How do we know that the transform's source projection is EPSG:4326? It's not specified anywhere in the application code. Maybe you assume that the user/external projection is EPSG:4326 by default?
|
||||
|
||||
**Answer from Tim**: GeoJSON describes the CRS. For formats that don't describe their CRS, the user would provide a projection property on the source.
|
||||
|
||||
You say that "This alternative can be implemented if the layer knows the map projection". Why? The layer renderer knows about the map/view projection, so I think it could be the one providing the projection (the transform's target projection). As I see it the transform operation would occur during the first `render` pass, the one occurring when the layer is added to the map.
|
||||
|
||||
I've also been thinking about where to store the transformed data. But before that: in most cases, do we really want/need to store both the original data and the transformed data? I'd say no.
|
||||
|
||||
In ol2 if the layer projection isn't the same as the map projection the layer's strategy does an **in-place** transformation of the data - no copy of the original data is kept. Do we really want to do differently in ol3? I know that stores can be shared between maps, etc. We could think about a `copyOnTransform` option on stores, which would be `false` by default, as we don't need the original data in the common cases.
|
||||
|
||||
Really the store could (a) transform in place, (b) copy on transform, or (c) refuse to transform and return `null` to the renderer. The store would decide based on user options/hints (e.g. `copyOnTransform`). I think the default behavior should (a), i.e. transform in place if the view projection is not the same as the data projection.
|
||||
|
||||
### Generate features in app and add to a layer
|
||||
|
||||
User writes an application that generates features at run time. These features are added to the layer for display and interaction (e.g. popup on selection).
|
||||
|
||||
**Alternative 1**
|
||||
|
||||
```js
|
||||
// a vector layer with no source means user will be manually adding features
|
||||
var vector = new ol.layer.Vector();
|
||||
|
||||
var map = new ol.Map({
|
||||
target: 'map',
|
||||
layers: [vector]
|
||||
view: new ol.View2D({
|
||||
projection: 'EPSG:1234',
|
||||
center: ol.projection.transform(
|
||||
new ol.Coordinate(-111, 45), 'EPSG:4326', 'EPSG:1234'),
|
||||
zoom: 3
|
||||
})
|
||||
});
|
||||
|
||||
var parser = new ol.parser.GeoJSON();
|
||||
|
||||
vector.addFeatures(parser, {
|
||||
type: 'FeatureCollection',
|
||||
features: [{
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [-111, 45]
|
||||
},
|
||||
properties: {
|
||||
foo: 'bar'
|
||||
}
|
||||
}]
|
||||
});
|
||||
```
|
||||
|
||||
In this alternative, the vector layer has no source set - meaning the user will be manually generating features. This alternative can be implemented if the layer knows about the map projection. In the `addFeatures` method, the layer calls `parser.readFeatures(data, {projection: projection})` where `data` is the first argument to `addFeatures` and `projection` is the map view's projection.
|
||||
|
||||
_Questions/comments from Eric:_
|
||||
|
||||
In my alternative, and based on my comments for the previous use-case, the app would add features to the source.
|
||||
|
||||
**Alternative 2**
|
||||
|
||||
```js
|
||||
var vector = new ol.layer.Vector({
|
||||
source: new ol.source.Vector({
|
||||
projection: 'EPSG:4326'
|
||||
})
|
||||
});
|
||||
|
||||
var map = new ol.Map({
|
||||
target: 'map',
|
||||
layers: [vector]
|
||||
view: new ol.View2D({
|
||||
projection: 'EPSG:1234',
|
||||
center: ol.projection.transform(
|
||||
new ol.Coordinate(-111, 45), 'EPSG:4326', 'EPSG:1234'),
|
||||
zoom: 3
|
||||
})
|
||||
});
|
||||
|
||||
var parser = new ol.parser.GeoJSON();
|
||||
|
||||
vector.getSource().addFeatures(parser, {
|
||||
type: 'FeatureCollection',
|
||||
features: [{
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [-111, 45]
|
||||
},
|
||||
properties: {
|
||||
foo: 'bar'
|
||||
}
|
||||
}]
|
||||
});
|
||||
```
|
||||
|
||||
`addFeatures` would add the data to the source, but wouldn't transform the data (the source doesn't know about the view projection). Again, the data would be transformed on the next `render` pass.
|
||||
|
||||
### Load data based on map extent
|
||||
|
||||
User has a service that provides vector features for requests with an arbitrary BBOX (e.g. a WFS). Data source contains hundreds of millions of features with worldwide coverage (e.g. OSM) and the user only wants to display a small subset, updating rendered features as the user navigates around the map.
|
||||
|
||||
**Alternative 1**
|
||||
|
||||
```js
|
||||
var vector = new ol.layer.WFS({
|
||||
namespace: 'http://example.org/#osm'
|
||||
type: 'roads'
|
||||
});
|
||||
|
||||
var map = new ol.Map({
|
||||
target: 'map',
|
||||
layers: [vector]
|
||||
view: new ol.View2D({
|
||||
projection: 'EPSG:1234',
|
||||
center: ol.projection.transform(
|
||||
new ol.Coordinate(-111, 45), 'EPSG:4326', 'EPSG:1234'),
|
||||
zoom: 3
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
This alternative can be implemented if the layer knows about the map. The WFS layer creates a WFS protocol, a GML parser, a BBOX strategy by default. The layer creates a vector source with the protocol and the parser (these are the two things associated with the data source). The bbox strategy listens for changes in map extent. When the previous data bounds become invalid, the bbox strategy notifies the layer that new data is needed, and the layer calls `source.protocol.read({success: callback})`. The provided callback would call `source.parser.readFeatures(data, {projection: projection})` with the provided data and the map view's projection. The resulting features would replace the existing features (or new ones would be added and features outside the data bounds would be removed).
|
||||
|
||||
_Questions/comments from Eric:_
|
||||
|
||||
The API looks good to me, although, again, I think a projection should be specified in the source options if the projection of the data received from the server isn't the same as the view projection.
|
||||
|
||||
Why does the strategy need to listen for view changes? As the map moves, the layer renderer requests more data from the source. The source can then request data from the server, using a strategy that depends on the strategy configured in the source. For example, if the strategy is a bbox strategy the first tile request from the Canvas renderer will trigger a server request for the entire view extent (a sort of meta-tile). Bottom line is I think it would be good not to have multiple paths of communication between map/renderer and layer/source, `renderFrame` is the communication path.
|
||||
|
||||
### Edit existing features and synchronize them with a server
|
||||
|
||||
The user loads a vector layer with a very large number of features. He then modifies a few of them, and saves the modified features back to the server. The feature currently being edited should be on top, and the system should maintain good performance even if the underlying layer contains a very large number of features. Only the modified features should be sent back to the server. Example case: editing OSM building outlines.
|
||||
|
||||
### Pure vector layers
|
||||
|
||||
Some data are represented most compactly as vector features. It should be possible to include them as first-class layers. Example: overlaying roads on satellite imagery.
|
||||
|
||||
### Markers and labels maintain orientation even when the map is rotated
|
||||
|
||||
Map rotation is useful, for example so that "up" corresponds to the direction in which the user is moving. However, labels and markers should not rotate with the map, and should instead always be aligned horizontally.
|
||||
|
||||
### Sub-feature styling
|
||||
|
||||
The user wishes to style a feature, e.g. a line string, according to some value that varies across the feature. It should be possible to "sub-style" a feature, e.g. to vary the color of a GPS tracklog by the speed of movement at that point.
|
||||
|
||||
### Vector simplification
|
||||
|
||||
The user has vector features with a high number of points. To render the feature efficiently it should be possible to (automatically) simplify features based on the current zoom level. Only the visible part should be rendered if the user has zoomed into the feature.
|
||||
|
||||
### 3D buildings, terrain tiles
|
||||
|
||||
3D buildings and TIN terrain tiles are fundamentally vector data. The vector data representation must support these data.
|
||||
|
||||
### Dense vector data
|
||||
|
||||
The user has [thousands](https://groups.google.com/forum/?fromgroups=#!searchin/leaflet-js/1500/leaflet-js/0SloJWSNbrg/XCtut0jhWqUJ) or [hundreds of thousands](https://groups.google.com/forum/?fromgroups=#!topic/leaflet-js/ytp2n-QLIH8) of vector features.
|
||||
Reference in New Issue
Block a user