Converting OpenLayers Polygon to GeoJSON with different projection - javascript

Similar to the problem found in this question
How to convert OpenLayers polygon coordinates into latitude and longitude?
I have setup a basic map to capture a user defined polygon and convert it to GeoJSON, whilst I'm able to do this with its native projection (ESPG:3857) I would like to take the captured GeoJSON and convert it to EPSG:4326 - which I will then save away. Using the above method of capturing the feature on the drawend event and performing a transform however removes the polygon as the new co-ordinates are not represented in the projection of the map any longer. I am unable to figure out how to to save the GeoJSON in the format I need without deleting the existing polygon
I have tried performing this by using getFeatures on the vector source of the polygon and then performing a transform from the projection i'm using to the projection I want, but this still returns the same coords, I have also (like the linked article) tried using the the writeFeatureObject but it still saves incorrectly
https://jsfiddle.net/20gxo3nt/
dragBox.on('drawend', function(evt){
/* geom = evt.feature.getGeometry().transform('EPSG:3857', 'EPSG:4326');
console.log(geom.getCoordinates()); */
});
$( "#save" ).click(function() {
var geom=vectorSource.getFeatures();
console.log(geom);
var writer=new ol.format.GeoJSON();
var geoJsonStr = writer.writeFeatures(geom);
console.log (geom.proj.transform('EPSG:3857', 'EPSG:4326'));
/* console.log(geoJsonStr) */
});
Uncommenting the code on the drawend event will correctly console.log the co-ordinates,as well as demonstrate polygon disappearing

To get a new geojson
var geom = [];
vectorSource.forEachFeature( function(feature) { geom.push(new ol.Feature(feature.getGeometry().clone().transform('EPSG:3857', 'EPSG:4326'))); } );
var writer = new ol.format.GeoJSON();
var geoJsonStr = writer.writeFeatures(geom);
console.log(geoJsonStr);

Openlayers 6, no need to loop on features
var format = new ol.format["GeoJSON"]();
var geoJsonStr = format.writeFeatures(vectorSource.getFeatures(), { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857'});

Related

load csv into leaflet and convert coordinates with proj4

This question involves the use of:
leaflet.js (used to create my map)
leaflet omnivore plugin (used to load my csv data file)
and proj4 (used to convert easting/northing to lat/lon)
My code below loads a stamen map with leaflet, and then uses omnivore to load my csv file.
In order to display the csv geo data on my map i need to first convert the easting/northing coordinates to lat/lon. The next sections of code contain the logic to do this, and it works successfully for the single coordinate sample within the console.log at the bottom.
But I have no idea how to use this logic on my full csv file. There is one column for easting, one for northing in the file - ultimately i want to my code to convert all these to lat lon, and plot them as points on my map.
var map = L.map('map').setView([51.44, -1.01], 8);
L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner-background/{z}/{x}/{y}.{ext}',
{
subdomains: 'abcd',
minZoom: 8,
maxZoom: 20,
ext: 'png'
}).addTo(map);
var dataset = omnivore.csv('assets_cwy_new simple.csv');
var osgb = '+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 +units=m +no_defs ';
var wgs84 = '+proj=longlat +datum=WGS84 +no_defs ';
console.log(proj4(osgb,wgs84,[514545.49,215008.4]));
As you figured out, you can use Proj4Leaflet plugin with Proj4js to convert your easting/northing coordinates into WGS84 lng/lat. Do not forget to revert the coordinates into lat/lng for Leaflet.
Now to have leaflet-omnivore use the correct columns from your CSV file, you have to use the parser_options (2nd parameter of your call to omnivore.csv), which are actually passed to the underlying library csv2geojson. These options let you specify the latitude and longitude fields of your CSV file. For now you have only easting/northing, but we can convert them later on:
var csv2geojsonOptions = {
latfield: 'northing',
lonfield: 'easting',
delimiter: ','
}
omnivore.csv('./assets_cwy_new_simple.csv', csv2geojsonOptions);
Next, you need to convert your easting/northing coordinates into WGS84 lng/lat coordinates, using proj4leaflet. To have omnivore perform this conversion on each of your lines, you have to use the customLayer (3rd parameter of your call to omnivore.csv). It is actually just a preconfigured Leaflet GeoJSON Layer Group. With this group, you can use its coordsToLatLng option to implement your conversion with proj4leaflet:
var customLayer = L.geoJSON(null, {
coordsToLatLng: projCoordsToLatLng
});
function projCoordsToLatLng(coords) {
return lngLatToLatLng(proj4(osgb, wgs84, coords));
}
function lngLatToLatLng(lngLat) {
return [lngLat[1], lngLat[0]];
}
omnivore.csv('./assets_cwy_new_simple.csv', csv2geojsonOptions, customLayer);
Live example: https://plnkr.co/edit/Dj9Mukig8PAHUYinsapJ?p=preview

Fitting map bounds to raster layer

I've ran across all fitbounds tutorials for Mapbox and still cannot figure out how refocus my map on a given raster layer. I have a menu that toggles a number of older maps and would like to refit the map at each turn.
Here's what I have so far. mapnumber is the string for my raster map.
var coordinates = map.getBounds(mapnumber);
var bounds = new mapboxgl.LngLatBounds(coordinates[0], coordinates[0]);
map.fitBounds({bounds});
The bounds are there, I just cannot use fitbounds on them. This is the error.
lng_lat.js:97 Uncaught Error: `LngLatLike` argument must be specified
as a LngLat instance, an object {lng: <lng>, lat: <lat>}, or an array
of [<lng>, <lat>]
Uncaught Error: LngLatLike argument must be specified
as a LngLat instance
It looks like you're using mapboxgl.LngLatBounds incorrectly. You'll need to pass in two LngLat instances, rather than two coordinates. The API docs have an example that creates a point for the southwest and northeast corners of your bounding box:
var sw = new mapboxgl.LngLat(-73.9876, 40.7661);
var ne = new mapboxgl.LngLat(-73.9397, 40.8002);
var llb = new mapboxgl.LngLatBounds(sw, ne);
Then you can use map.fitBounds() with the bounding box
map.fitBounds(llb);
UPDATE: answering follow up question
how can I extract the two sets (sw and ne) from the raster?
You can use the map.getSource() method. Pass in the source ID of your raster layer and that will return an object that has a bounds property. Use this bounds property to pass into map.fitBounds().
var bounds = map.getSource('mapbox://username.source-id').bounds;
map.fitBounds(bounds);
Here's a working example: https://codepen.io/mapsam/pen/RZvyBQ

leaflet how to add circle by coordinates?

Next code is add circle to map:
var mylayer = L.circle([60, 54.75621], 200).addTo(Window.map);
but I want to add coordinates from variable: eq.coordinates
console.log(eq.coordinates);
Print on console: POINT(31.5 42.2)
I want to do something like:
var mylayer = L.circle(eq.coordinates).addTo(Window.map);
L.circle wants latlng coordinates.
If you want to use pixel coordinates you have to convert them to latlng coordinates using http://leafletjs.com/reference-1.0.0.html#map-containerpointtolayerpoint
If you could put an example online, this would help helping you

OpenLayers LonLat transform

I want to use decimal Lon and Lat like Google Maps uses. But it seems I need to transform the LonLat object in OpenLayers, e.g.
var map, layer;
function init(){
map = new OpenLayers.Map('map');
layer = new OpenLayers.Layer.OSM( "Simple OSM Map");
map.addLayer(layer);
map.setCenter(
new OpenLayers.LonLat(-1.60400390625, 54.07228265560386).transform(
new OpenLayers.Projection("EPSG:4326"),
map.getProjectionObject()
), 6
);
var markers = new OpenLayers.Layer.Markers( "Markers" );
map.addLayer(markers);
var size = new OpenLayers.Size(21,25);
var offset = new OpenLayers.Pixel(0,0);
var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png', size, offset);
markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(-1.60400390625, 54.07228265560386).transform(new OpenLayers.Projection("EPSG:4326"),map.getProjectionObject()),icon));
}
Each time I place a marker the position needs to be transformed to EPSG:4326. Is there a way to tell the map to always use this projection?
Whether you can set the projection on a map or not, depends on which service you are using for the base layer. As far as I know, OSM only provides its rendered tiles in EPSG:900913, so there is no way around transforming your coordinates before adding them to the map. You could search for a service that provides its tiles in multiple projections, but I haven't seen one that is free to use so far. An alternative would be to render your own tiles in the needed projection and provide them through your own tile server.
Let's suppose you have such a map, you can change the projection using OpenLayers.Map.setOptions() like this:
map.setOptions({
projection: "EPSG:4326"
});
But you may also need to set some projection related properties, like maxExtent etc. See this question.

Openlayers - Projection issues when getting latitude/longitude from a point

I'm trying to get the latitude/longitude from a draggable marker with Openlayers and OSM but I can't find the good settings for the projection conversion, what I am doing wrong ?
Here is the code: http://pastie.org/2300321 (see addMarker l140 & updateTargets l153) & and a little demo test.
If you submit an address, then drag the marker, the longitude and latitude are wrong. I tested a few different projections but I'm not sure what I've to useā€¦
I think the problem is inside updateTargets method:
var point = this.feature.geometry;
var pixel = new OpenLayers.Pixel(point.x, point.y);
var coord = this.map.getLonLatFromPixel(pixel).transform(
new OpenLayers.Projection("EPSG:900913"),
new OpenLayers.Projection("EPSG:4326")
);
this.feature.geometry is already specified in lon/lat coordinates, not in pixels. So I suggest that you skip second line and do the conversion from OpenStreetMap projection to lon/lat directly on geometry object:
var coord = this.feature.geometry.transform(
new OpenLayers.Projection("EPSG:900913"),
new OpenLayers.Projection("EPSG:4326")
);

Categories

Resources