I have a PostgreSQL / PostGIS database with polygons (which represent rooms of a floor in a building) in it. When I try plotting them using matplotlib (directly from database) or mapshaper (from a shapefile containing the polygons), the output looks normal. However, when OpenLayers (5.3.0) displays them - they're a bit skewed and elongated on the y-axis. I'm using ol-layerswitcher alongside OL.
Plotting the polygons in matplotlib:
Plotting the polygons in OpenLayers:
I've tried applying a "dirty fix" by scaling down on the y-axis in hopes of undoing the skewing effect, however scaling doesn't work and it actually somehow worsens the output (picture below).
This is map initialisation:
var mapView = new ol.View({
center: ol.proj.fromLonLat([14.426102028368888, 45.3375708862643]),
zoom: 20,
minZoom: 0
});
var levelsGroup = new ol.layer.Group({
'title': 'Katovi',
layers: []
});
levelsGroup.setZIndex(1);
var worldMap = new ol.layer.Tile({
source: new ol.source.OSM(),
zIndex: -1,
projection: 'EPSG:3857'
});
var map = new ol.Map({
layers: [
levelsGroup,
worldMap, // world map, for georeferencing
],
target: 'map',
view: mapView,
});
This is how OL is getting and parsing the data:
// ... get data from django with ajax
var singleLevel = new ol.layer.Group({
// create a layer group for the floor
floor_num: JSON.parse(data[0])['features'][0]['properties']['level'],
type: 'base',
combine: true,
visible: false,
layers: []
});
for(var j = 0; j < data.length; j++) {
// Parsing the JSON file from backend
var parsedPolyType = JSON.parse(data[j]);
var polyName = parsedPolyType['features'][0]["properties"]['name'];
// This will create a new vector layer with a source containing a single poly type (room or wall etc) for i-th floor
var singleType = new ol.layer.Vector({
source: new ol.source.Vector({
features: (new ol.format.GeoJSON()).readFeatures(parsedPolyType, { featureProjection: 'EPSG:3857' }),
})
});
for (var k = 0; k < singleType.getSource().getFeatures().length; k++) {
singlePoly = singleType.getSource().getFeatures()[k];
// [14.4253, 45.3371] are the coordinates of the bottom left point of the floor plan's bounding box
singlePoly.getGeometry().scale(1, 0.95, ol.proj.transform([14.4253, 45.3371], 'EPSG:4326', 'EPSG:3857'));
// style the geometry according to its type,
// if it's a polygon this will give it a black outline with white filling
createStyle(singlePoly, singlePoly.getProperties().type, singlePoly.getProperties().name);
}
singleLevel.getLayers().push(singleType);
}
var last_item = levelsGroup.getLayers().push(singleLevel) - 1;
levelGroups.push(singleLevel);
// switch to the new layer level and make it visible
switch_layer(levelsGroup, last_item);
This is the output I'm getting when trying to scale (1 on x-axis, 0.95 on y-axis):
In addition to being a bit scattered, some of the polygons lose their styling (the blue styling is OL default). The unstyled polygons are not scaled at all.
So, I have three questions:
1) Why are the polygons skewed in OpenLayers?
2) What am I doing wrong when trying to scale them down?
3) Is there a better way to fix this other this dirty fix?
EDIT:
Forgot to mention, the polygons in the database are in EPSG:4326.
Here is the code used for styling:
styles = {};
styles['room'] = {
strokeColor: 'rgb(0, 0, 0)',
strokeWidth: 3,
fillColor: 'rgba(255, 255, 255, 1)'
}
styles['room'] = jQuery.extend({}, defaultStyle, styles['room']);
styles['wall'] = {
strokeColor: 'rgb(0, 0, 0)',
strokeWidth: 1,
fillColor: 'rgba(200, 200, 200, 1)'
}
styles['wall'] = jQuery.extend({}, defaultStyle, styles['wall']);
function createStyle(singlePoly, styleName, polyName) {
if(styleName in styles) {
text = styleName == 'room' ? polyName : '';
singlePoly.setStyle(styleWrapper(styleName, text));
}
}
function styleWrapper(styleName, text) {
var curr_style = styles[styleName];
//returns a function which is used as a style for a polygon
return function() {
zoom = map.getView().getZoom();
return [
new ol.style.Style({
stroke: new ol.style.Stroke({
color: curr_style.strokeColor,
width: curr_style.strokeWidth
}),
fill: new ol.style.Fill({
color: curr_style.fillColor
}),
text: new ol.style.Text({
scale: curr_style.textScale,
text: zoom >= curr_style.minZoom ? text : ''
})
})
];
}
}
EDIT 2: