I want to implement this example http://api.geoext.org/1.1/examples/feature-grid.html made of geoext and openlayers, that feature grid is populated of a geojson file
In my development I have a geojson file with utm format, this is a single feature of my file (the coordinates are utm)
{"geometry": {"type": "Point", "coordinates": [7535169.36, 402844.172]}, "type": "Feature", "properties": {"NOMBRE": "LA VICTORIA", "CODIGO": "1702"}, "id": "1702"}
I tried to show the points in my code, but I can't see anything, this is my code
// create feature store, binding it to the vector layer
store = new GeoExt.data.FeatureStore({
layer: vecCiudades,
fields: [
{ name: 'NOMBRE' },
{ name: 'CODIGO' }
],
proxy: new GeoExt.data.ProtocolProxy({
protocol: new OpenLayers.Protocol.HTTP({
url: "data/summits.json",
format: new OpenLayers.Format.GeoJSON({
ignoreExtraDims: true,
internalProjection: new OpenLayers.Projection("EPSG:900913"),
externalProjection: new OpenLayers.Projection("EPSG:4326")
})
})
}),
autoLoad: true
});
as you can see, I tried to specify the internal and external projection of the feature store, my implementation looks like the example of the link mentioned above, but when I select a city the map is located to a wrong place (the place is shown near south pole, but it has to be near south america)
Thanks in advance
For what reason FeatureStore..? Just define layer as following:
var vecCiudades = new OpenLayers.Layer.Vector('MyLayer', {
strategies:[new OpenLayers.Strategy.BBOX()],
isBaseLayer:false,
projection:new OpenLayers.Projection("EPSG:900913"),
styleMap:new OpenLayers.StyleMap(null),
transitionEffect:'resize',
protocol:new OpenLayers.Protocol.HTTP({
url: "data/summits.json",
format:new OpenLayers.Format.GeoJSON({
ignoreExtraDims:true
}),
readWithPOST:false,
updateWithPOST:false,
srsInBBOX:true
})
});
Also register following event on map:
map.events.register("moveend", this, function (e) {
vecCiudades.refresh({force:true});
});
That will reread GeoJSON anytime moved or zoomed map and request will contain bounding box of visible area so you can only send features that going to be visible not all of them.
Related
So what I want is for all the clusters and markers to be visible from the start. that is, when entering the page. But that's not the case.
Everything that should be on the map loads completely sporadically. Like when i hit hard refresh some times it suddenly wont load.
const bounds = Map.current
? Map.current.getMap().getBounds().toArray().flat()
: null;
The code block above might be the issue. When the map is empty of markers and clusters this code block logs null aswell. How can i use this in useEffect if that could work?
Cluster code:
const points = useMemo(
() =>
data.map((store) => ({
type: "Feature",
properties: {
cluster: false,
storeId: store.id,
category: store.country_code,
},
geometry: {
type: "Point",
coordinates: [store.coords[0], store.coords[1]],
},
})),
[data]
);
const bounds = Map.current
? Map.current.getMap().getBounds().toArray().flat()
: null;
const { clusters } = useSupercluster({
points,
bounds,
zoom: viewport.zoom,
options: { radius: 75, maxZoom: 20 },
});
Before and after refresh/move on map/saving code/pretty much anything
So when i console log this:
Before:
After:
#Kruzt are you using Mapbox GL JS? In that case, I'm not sure there's a need for the supercluster library. Have you tried something like this example? https://docs.mapbox.com/mapbox-gl-js/example/cluster/
Using Open Layers and leaflet-sidebar-v2, I've added the sidebar to my map, this works. However, I also need to add another layer to my map, this layer will outline each country. I have the coordinates stored in a 'borders.json' file. I'm attempting to use D3.json to to import the border coordinates and then L.geoJson to add the new layer to my map.
I'm currently getting the following error message:
Uncaught TypeError: t.getLayerStatesArray is not a function
Here is the relevant part of my code..
var map = new ol.Map({
target: "map",
layers: [
new ol.layer.Tile({
source: new ol.source.OSM(),
}),
],
view: new ol.View({
center: ol.proj.transform([7, 51.2], "EPSG:4326", "EPSG:3857"),
zoom: 3,
}),
});
var sidebar = new ol.control.Sidebar({
element: "sidebar",
position: "left",
});
map.addControl(sidebar);
d3.json(("borders.json"), function (json){
function style(feature) {
return {
fillColor: "transparent",
weight: 1,
opacity: 0.4,
color: 'grey',
fillOpacity: 0.3
}
}
geojson = L.geoJson(json, {
style: style,
}).addTo(map);
})
I think I might be adding the geojson layer to my map incorrectly, but I can't figure out what is wrong. I've spent quite a bit of time playing with it, but no luck.
Any helps is appreciated.
Cheers,
Beat
It might be hard to tell what the problem is without knowing other possible relevant parts of your code. I'd start by checking that the contents of borders.json follows valid GeoJSON format.
This is likely unrelated to your question, but is there a reason that you've declared style as a function like function style(feature) { ... }?
It looks like the style attribute of L.geoJson accepts an object rather than a function.
I want to add clustering to my map from mapbox, I followed the getting started as they suggest:
https://www.mapbox.com/install/js/cdn-add/
And now I have a map, I also added some of my own markers, which are users from my backend that have lats and longs.
So I have a map and some markers.
Now, I want to add clustering, and in the example:
https://docs.mapbox.com/mapbox-gl-js/example/cluster/
they add a source:
map.addSource("earthquakes", {
})
which I don't have, and at this moment I don't think I even need. because I can see the tiles and my markers.
I thought about adding a source, but which source? I don't need a source, I already have what I needed, the tiles and the markers... but the cluster option is in the addSource method on the map. So.. I'm lost here.
This is what they show in the example, but as I said, I don't have or need any other source, as I already see the tiles and my markers, I just want to cluster.
map.addSource("earthquakes", {
type: "geojson",
data: "https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson",
cluster: true,
clusterMaxZoom: 14, // Max zoom to cluster points on
clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)
});```
I found the solution,
I had to create a geoJson object from my users like this:
const geoJsonMarkers = users.map( (place, i ) => {
const [placeLng, placeLat] = place.location.coordinates;
const position = { lat: placeLat, lng: placeLng };
return {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [position.lng, position.lat]
},
"properties": {
"name": place.name
}
}
})
const usersArray = {
"features": geoJsonMarkers
}
And then pass it to the data property of the source like so:
map.on('load', function() {
// Add a new source from our GeoJSON data and set the
// 'cluster' option to true. GL-JS will add the point_count property to your source data.
map.addSource("users", {
type: "geojson",
// Point to GeoJSON data. This example visualizes all M1.0+ earthquakes
// from 12/22/15 to 1/21/16 as logged by USGS' Earthquake hazards program.
data: usersArray,
cluster: true,
clusterMaxZoom: 14, // Max zoom to cluster points on
clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)
});
...
the addSource name is arbitrary, could be anything in my case are users so I called it users.
I have being playing around with MapBox and I am having some issues with getting the GeoLocation API to send data back to the map and update the it.
This is what I got right now:
mapboxgl.accessToken = 'TOKEN-HERE';
var map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mapbox/streets-v9',
center: [-0.968539, 54.562917],
zoom: 9
});
map.on('style.load', function() {
map.addSource("myMap", {
"type": "geojson",
"data": "https://api.mapbox.com/geocoding/v5/mapbox.places/UK_ADDRESS_HERE.json?country=gb&types=address&autocomplete=true&access_token=TOEKN"
});
map.addLayer({
'id': 'test1',
'type': 'line',
'source': 'myMap',
'interactive': true
});
});
The answer may lie with how you are encoding UK_ADDRESS_HERE.
https://api.mapbox.com/geocoding/v5/mapbox.places/UK_ADDRESS_HERE.json
The request format for the Mapbox Geocding API requires that since the {query} parameter can contain any value, it should be URL-encoded.
That means that a simple geocode request like 10 Downing Street, Westminster must be encoded using encodeURIComponent to 10%20Downing%20Street%2C%20Westminster.
Try this and verify that your request is proper.
curl https://api.tiles.mapbox.com/geocoding/v5/mapbox.places/10%20Downing%20Street%2C%20London.json?access_token=${MAPBOX_ACCESS_TOKEN}
After reading a very good tutorial on how to edit WFS with OpenLayers, I've tried replicating it but with my own WFS layer from Geoserver. Need some Javascript help finding what's wrong with it.
I managed to load the WFS and my basemap successfully and managed to get the buttons to show up. The buttons appear correctly like in the working example from that page but, for some reason the geometry data isn't being saved. Every time a user draws something, a new id is created on the table but its associated geometry column is left empty
The bit for posting is:
var formatWFS = new ol.format.WFS();
var formatGML = new ol.format.GML({
featureNS: 'http://geoserver.org/bftchamber',
featureType: 'bft',
srsName: 'EPSG:27700'
});
var transactWFS = function(p,f) {
switch(p) {
case 'insert':
node = formatWFS.writeTransaction([f],null,null,formatGML);
break;
case 'update':
node = formatWFS.writeTransaction(null,[f],null,formatGML);
break;
case 'delete':
node = formatWFS.writeTransaction(null,null,[f],formatGML);
break;
}
s = new XMLSerializer();
str = s.serializeToString(node);
$.ajax('http://localhost:8080/geoserver/wfs',{
type: 'POST',
dataType: 'xml',
processData: false,
contentType: 'text/xml',
data: str
}).done();
}
Fiddle with the whole code (apologies if it looks messy, most of it comes from the working example 2 )
https://jsfiddle.net/Luffydude/ex06jr1e/6/
The app looks like this:
Also even though my WFS appears correctly along the river Thames when I load it in QGIS, in my app it appears somewhere else in the ocean even though I specified EPSG 27700 (though this is just a minor annoyance at the moment).
My main problem now is how to make the edit buttons save user edits to the WFS layer?
I haven't really looked at OpenLayers in anger for a while and I kind of let slip updating my working examples. I just put together a new JSFiddle with simple WFS-T insert for polygons.
I use Geoserver 2.8 in production (2.9 in dev and testing).
Database backend is PostGIS 2.1 in production (2.2 dev).
The fiddle uses OpenLayers 3.16.
A few notes to my setup. I tend to have all geometries in EPSG:3857 and I do not specify the SRS in PostGIS. Haters gonna hate but I simply set my geometry column to geometry. This way I can get lines, points and polygons in the same table. I cannot see the mixed geometry in QGIS but this is a simple test setup. It's important that the geometry field is called geometry. It's probably possible but I could not make this work with the field being called the_geom or geom. In that case a record is inserted but the geometry field is empty as described in the post. I believe this is the problem.
CREATE TABLE wfs_geom
(
id bigint NOT NULL,
geometry geometry,
CONSTRAINT wfs_geom_pkey PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE wfs_geom
OWNER TO geoserver;
Here is the code bit from the jsfiddle.
var formatWFS = new ol.format.WFS();
var formatGML = new ol.format.GML({
featureNS: 'https://geolytix.net/wfs',
featureType: 'wfs_geom',
srsName: 'EPSG:3857'
});
var s = new XMLSerializer();
var sourceWFS = new ol.source.Vector({
loader: function (extent) {
$.ajax('https://maps.geolytix.net/geoserver/geolytix.wfs/wfs', {
type: 'GET',
data: {
service: 'WFS',
version: '1.1.0',
request: 'GetFeature',
typename: 'wfs_geom',
srsname: 'EPSG:3857',
bbox: extent.join(',') + ',EPSG:3857'
}
}).done(function (response) {
sourceWFS.addFeatures(formatWFS.readFeatures(response));
});
},
strategy: ol.loadingstrategy.bbox,
projection: 'EPSG:3857'
});
var layerWFS = new ol.layer.Vector({
source: sourceWFS
});
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM({
url: 'https://cartodb-basemaps-{a-d}.global.ssl.fastly.net/light_nolabels/{z}/{x}/{y}.png',
opaque: false,
attributions: []
})
}),
layerWFS
],
view: new ol.View({
center: ol.proj.fromLonLat([-0.1, 51.50]),
zoom: 13
})
});
var interaction = new ol.interaction.Draw({
type: 'Polygon',
source: layerWFS.getSource()
});
map.addInteraction(interaction);
interaction.on('drawend', function (e) {
$.ajax('https://maps.geolytix.net/geoserver/geolytix.wfs/wfs', {
type: 'POST',
dataType: 'xml',
contentType: 'text/xml',
data: s.serializeToString(formatWFS.writeTransaction([e.feature], null, null, formatGML))
}).done();
});