Skip to content

Commit

Permalink
Restructured for fewer lines of usage
Browse files Browse the repository at this point in the history
  • Loading branch information
ponlawat-w committed Nov 24, 2023
1 parent f948988 commit 745a3e9
Show file tree
Hide file tree
Showing 12 changed files with 227 additions and 563 deletions.
199 changes: 46 additions & 153 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,186 +4,79 @@

## Instructions

This extension is an interaction type in OpenLayers which requires a few setup steps:

### 1. Vector layer for OSM ways
```bash
npm install ol-osmwaysnap
```

To begin with, it is necessary to setup a vector layer that contains OSM ways. Using builtin `OSMWaySource` class that automatically fetches ways from OpenStreetMap using OverpassAPI, or alternatively, it can also be used with other linestring feature layer.
Create an instance of class `OSMWaySnap` and add it to map. (Default snapping to OSM roads)

```ts
import VectorLayer from 'ol/layer/Vector';
import { OSMWaySource } from 'ol-osmwaysnap';
import VectorSource from 'ol/source/Vector';
import { OSMWaySnap } from 'ol-osmwaysnap';

// Default: Snap to roads (OSM highway)
const osmWayLayer = new VectorLayer({
source: new OSMWaySource({
maximumResolution: 5,
fetchBufferSize: 250,
overpassEndpointURL: 'https://...' // Choose one instance from https://wiki.openstreetmap.org/wiki/Overpass_API#Public_Overpass_API_instances
}),
style: OSMWaySource.getDefaultStyle()
const targetLayer = new VectorLayer<VectorSource<Feature<LineString>>>({
source: new VectorSource<Feature<LineString>>()
});
map.addLayer(targetLayer);

// Snap to railways
const osmWayLayer = new VectorLayer({
source: new OSMWaySource({
maximumResolution: 5,
fetchBufferSize: 250,
overpassQuery: '(way["railway"];>;);',
overpassEndpointURL: 'https://...' // Choose one instance from https://wiki.openstreetmap.org/wiki/Overpass_API#Public_Overpass_API_instances
}),
style: OSMWaySource.getDefaultStyle()
// Default: Snap to roads (OSM highway)
const interaction = new OSMWaySnap({
source: targetLayer.getSource(),
maximumResolution: 5,
fetchBufferSize: 250,
overpassEndpointURL: 'https://...' // Choose one instance from https://wiki.openstreetmap.org/wiki/Overpass_API#Public_Overpass_API_instances
});
map.addInteraction(interaction);
```

### 2. Add interactions

There are at least 2 interactions to be added in order for the extension to work 1) `OSMWaySnap` and 2) `Snap` interaction from default OpenLayers interactions.
Or specify a custom OverpassQL for different way elements, for example to railways.

```ts
import { OSMWaySnap } from 'ol-osmwaysnap';
import Snap from 'ol/interaction/Snap';

map.addInteraction(new OSMWaySnap({
source: targetFeatureLayer.getSource(),
waySource: osmWayLayer.getSource()
}));
map.addInteraction(new Snap({
source: osmWayLayer.getSource()
}));
// Snap to railways
const interaction = new OSMWaySnap({
source: targetLayer.getSource(),
maximumResolution: 5,
fetchBufferSize: 250,
overpassQuery: '(way["railway"];>;);',
overpassEndpointURL: 'https://...' // Choose one instance from https://wiki.openstreetmap.org/wiki/Overpass_API#Public_Overpass_API_instances
});
map.addInteraction(interaction);
```

## Examples

### Using as module
Or use a custom vector source (not OSM) for snapping.

```ts
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import OSM from 'ol/source/OSM';
import Snap from 'ol/interaction/Snap';
import LineString from 'ol/geom/LineString';
import Feature from 'ol/Feature';
import { OSMWaySource, OSMWaySnap } from 'ol-osmwaysnap';

const basemap = new TileLayer({ source: new OSM() });

const osmWaySource = new OSMWaySource({
const interaction = new OSMWaySnap({
source: targetLayer.getSource(),
waySource: someVectorSource
maximumResolution: 5,
fetchBufferSize: 250,
overpassEndpointURL: 'https://...' // Choose one instance from https://wiki.openstreetmap.org/wiki/Overpass_API#Public_Overpass_API_instances
fetchBufferSize: 250
});
map.addInteraction(interaction);
```

const targetFeaturesLayer = new VectorLayer<VectorSource<Feature<LineString>>>({
source: new VectorSource<Feature<LineString>>()
});
const osmWayLayer = new VectorLayer({source: osmWaySource, style: OSMWaySource.getDefaultStyle()});

const map = new Map({
target: 'map',
layers: [basemap, osmWayLayer, targetFeaturesLayer],
view: new View({
center: [11018989, 2130015],
zoom: 16
})
});
## Examples
TODO

map.addInteraction(new OSMWaySnap({
source: targetFeaturesLayer.getSource()!,
waySource: osmWayLayer.getSource()!
}));
map.addInteraction(new Snap({
source: osmWayLayer.getSource()!
}));
```
## Constructor Options

### Using as CDN

```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/ol.css">
<style>
#map {
width: 100%;
height: 90vh;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="status"></div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ol.js"></script>
<script src="https://www.unpkg.com/ol-osmwaysnap/dist/webpack/index.js"></script>
<script lang="js">
const basemap = new ol.layer.Tile({ source: new ol.source.OSM() });
const targetFeaturesLayer = new ol.layer.Vector({
source: new ol.source.Vector()
});
const osmWayLayer = new ol.layer.Vector({
source: new OSMWaySnap.OSMWaySource({
maximumResolution: 5,
fetchBufferSize: 250,
overpassEndpointURL: 'https://...' // Choose one instance from https://wiki.openstreetmap.org/wiki/Overpass_API#Public_Overpass_API_instances
}),
style: OSMWaySnap.OSMWaySource.getDefaultStyle()
});
osmWayLayer.getSource().on('featuresloadstart', () => {
document.getElementById('status').innerHTML = 'Loading…';
});
osmWayLayer.getSource().on('featuresloadend', () => {
document.getElementById('status').innerHTML = '';
});
osmWayLayer.getSource().on('featuresloaderror', () => {
document.getElementById('status').innerHTML = 'ERROR';
});
const map = new ol.Map({
target: 'map',
layers: [basemap, osmWayLayer, targetFeaturesLayer],
view: new ol.View({
center: [11018989, 2130015],
zoom: 16
})
});
map.addInteraction(new OSMWaySnap.OSMWaySnap({
source: targetFeaturesLayer.getSource(),
waySource: osmWayLayer.getSource()
}));
map.addInteraction(new ol.interaction.Snap({
source: osmWayLayer.getSource()
}));
</script>
</body>
</html>
```
### For `OSMWaySnap`

## Options
- `autoFocus?: boolean` - True to automatically fit map view to next candidantes. (default: true)
- `focusPadding?: number` - Used with autoFocus, specify number to add padding to view fitting. (default: 50 !PROJECTION SENSITIVE!)
- `sketchStyle?: StyleLike` - Style of sketch features (default is predefined, overwrite if necessary)
- `source: VectorSource<Feature<LineString>>` - Target source of edition
- `waySource?: VectorSource<Feature<LineString>>` - Ways source for snapping (default to a new instance of OSMOverpassWaySource)
- `createAndAddWayLayer?: boolean` - Create a new way layer from way source (if provided) and add to map (default: true)
- `wrapX?: boolean` - WrapX

### `OSMWaySource` constructor options
### extended options if `waySource` is not provided

- `cachedFeaturesCount: number` - The number of features to store before getting cleared. This is to prevent heavy memory consumption.
- `fetchBufferSize: number` - Buffer size to apply to the extent of fetching OverpassAPI. This is to prevent excessive call despite slight map view panning. **USE THE SAME PROJECTION WITH THE LAYER**.
- `maximumResolution: number` - Map view resolution to start fetching OverpassAPI. This is to prevent fetching elements in too big extent. **USE THE SAME PROJECTION WITH THE LAYER**
- `overpassQuery: string` - OverpassQL statement(s) to fetch, excluding settings and out statements.
- `overpassEndpointURL?: string` - OverpassAPI endpoint URL (https://wiki.openstreetmap.org/wiki/Overpass_API#Public_Overpass_API_instances)
- `overpassQuery: string` - OverpassQL statement for ways to fetch, default to OSM highways.

### `OSMWaySnap` constructor options

- `autoFocus?: boolean` - True to automatically fit map view to next candidantes.
- `focusPadding?: number` - Used with autoFocus, specify number to add padding to view fitting.
- `sketchStyle?: StyleLike` - Style of sketch features.
- `source: VectorSource<Feature<LineString>>` - Target source of edition.
- `waySource: VectorSource<Feature<LineString>>` - Source to OSMWays for snapping.
- `wrapX?: boolean`

---
52 changes: 24 additions & 28 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@

<div id="status"></div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ol.js"></script>
<script src="https://www.unpkg.com/ol-osmwaysnap/dist/webpack/index.js"></script>
<script src="../dist/webpack/index.js"></script>
<!-- <script src="https://www.unpkg.com/ol-osmwaysnap/dist/webpack/index.js"></script> -->
<script lang="js">
const basemap = new ol.layer.Tile({ source: new ol.source.OSM() });

Expand All @@ -55,28 +56,9 @@
})
});

const osmWayLayer = new ol.layer.Vector({
source: new OSMWaySnap.OSMWaySource({
maximumResolution: 5,
fetchBufferSize: 250,
overpassEndpointURL: 'https://...' // Choose one instance from https://wiki.openstreetmap.org/wiki/Overpass_API#Public_Overpass_API_instances
}),
style: OSMWaySnap.OSMWaySource.getDefaultStyle()
});

osmWayLayer.getSource().on('featuresloadstart', () => {
document.getElementById('status').innerHTML = 'Loading from OSM…';
});
osmWayLayer.getSource().on('featuresloadend', () => {
document.getElementById('status').innerHTML = '';
});
osmWayLayer.getSource().on('featuresloaderror', () => {
document.getElementById('status').innerHTML = 'ERROR';
});

const map = new ol.Map({
target: 'map',
layers: [basemap, osmWayLayer, targetFeaturesLayer],
layers: [basemap, targetFeaturesLayer],
view: new ol.View({
center: [11018989, 2130015],
zoom: 16
Expand All @@ -85,12 +67,21 @@

const interaction = new OSMWaySnap.OSMWaySnap({
source: targetFeaturesLayer.getSource(),
waySource: osmWayLayer.getSource()
maximumResolution: 5,
fetchBufferSize: 250,
overpassEndpointURL: 'https://overpass.kumi.systems/api/interpreter' // Choose one instance from https://wiki.openstreetmap.org/wiki/Overpass_API#Public_Overpass_API_instances
});
map.addInteraction(interaction);
map.addInteraction(new ol.interaction.Snap({
source: osmWayLayer.getSource()
}));

interaction.getWaySource().on('featuresloadstart', () => {
document.getElementById('status').innerHTML = 'Loading from OSM…';
});
interaction.getWaySource().on('featuresloadend', () => {
document.getElementById('status').innerHTML = '';
});
interaction.getWaySource().on('featuresloaderror', () => {
document.getElementById('status').innerHTML = 'ERROR';
});

const wkt = new ol.format.WKT();
const geojson = new ol.format.GeoJSON();
Expand All @@ -99,10 +90,15 @@
setTimeout(() => {
const feature = interaction.activeFeature;
if (!feature) return;

const geom = feature.getGeometry().clone().transform(
map.getView().getProjection(),
new ol.proj.Projection({ code: 'EPSG:4326' })
);

document.getElementById('vertices').innerHTML = feature.getGeometry().getCoordinates().length;
document.getElementById('wkt').innerHTML = wkt.writeGeometry(feature.getGeometry());
document.getElementById('geojson').innerHTML = geojson.writeGeometry(feature.getGeometry());
document.getElementById('vertices').innerHTML = geom.getCoordinates().length;
document.getElementById('wkt').innerHTML = wkt.writeGeometry(geom);
document.getElementById('geojson').innerHTML = geojson.writeGeometry(geom);
}, 200);
});
</script>
Expand Down
21 changes: 17 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
{
"name": "ol-osmwaysnap",
"version": "0.0.3",
"version": "0.1.0",
"description": "OpenLayers Interaction Extension for Snapping Ways from OSM using Overpass API",
"keywords": [
"osm", "openstreetmap", "openlayers", "gis", "map", "road-snapping"
"osm",
"openstreetmap",
"openlayers",
"gis",
"map",
"road-snapping"
],
"main": "dist/index.js",
"scripts": {
Expand All @@ -30,5 +35,8 @@
"typescript": "^5.3.2",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0"
},
"dependencies": {
"ol-osmoverpass": "^0.1.0"
}
}
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { default as OSMWaySnap } from './interaction';
export { default as OSMWaySource } from './source';
export { default as OSMWaySnap, type OSMWaySnapOptions } from './interaction';
export { default as LineStringUtils } from './line-string-utils';
Loading

0 comments on commit 745a3e9

Please sign in to comment.