is there possible for set rotation and scale to raster static image source in open layer 6 - gis

I am using open layers 6 lib for map rendering and events.
my application needed same like this example http://viglino.github.io/ol-ext/examples/layer/map.geoimage.html i.e. Example have ol.source.GeoImage..
I have tried
I am displaying raster images on map using this sample code is
const url = imagurl;
const extent = [0, 0, imageData.width, imageData.height];
const projection = new Projection({
code: 'xkcd-image',
units: 'pixels',
extent,
});
const imageLayer = new ImageLayer({
source: new Static({
url,
projection,
imageExtent: extent,
}),
});
and i am using affine transformation lib and returns scaling, rotation and transformation..
its giving the values
scaling : 327.805670381418,327.805670381418
rotation : -0.1310210334156003
transformation : 7179251.8557908312,6022627.228704552
i need to add this code into ol-6 static image source
source: new ol.source.GeoImage(
{ image,
imageCenter: transformation,
imageScale: scaling,
imageRotate: rotation,
//projection: pixelProjectio
})
suggest or help on this.. thanks in advance.. and save my days..

Related

flutter_map WMS with custom CRS fails to load map image: Failed to decode Image data

I'm trying to create a simple flutter map widget that gets layers from a WMS server.
The server is this.
And you can see the its capabilities here.
Specifically, I want to use the layer "AMS_1956-1957".
As this layer is served in the CRS EPSG:4258, I'm creating a custom CRS for this FlutterMap to use (as it's stated in the documentation that only WGS84 (EPSG:4326) and Google Mercator (EPSG:3857) projections are supported).
I'm creating this custom CRS following the instructions here.
I'm getting the Proj4 definition string for this CRS (EPSG:4258) from here, as stated in the documentation: "+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs"
So the code for creating the custom CRS is this:
var resolutions = <double>[32768, 16384, 8192, 4096, 2048, 1024, 512, 256, 128];
var maxZoom = (resolutions.length - 1).toDouble();
var epsg4258CRS = Proj4Crs.fromFactory(
code: 'EPSG:4258',
proj4Projection: proj4.Projection.add("EPSG:4258",
'+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs'),
resolutions: resolutions,
);
Then I'm using this CRS in my FlutterMap widget as follows (again, based in the documentation).
#override
Widget build(BuildContext context) {
return FlutterMap(
options: MapOptions(
center: LatLng(41.61, -2.52),
zoom: 3.0,
),
layers: [
TileLayerOptions(
wmsOptions: WMSTileLayerOptions(
baseUrl: 'https://www.ign.es/wms/pnoa-historico?',
layers: ['AMS_1956-1957'],
crs: epsg4258CRS,
),
),
MarkerLayerOptions(
markers: [
Marker(
width: 5.0,
height: 5.0,
point: LatLng(41.61, -2.52),
builder: (ctx) => Container(
child: const FlutterLogo(),
),
),
],
),
],
);
}
}
The pointer is shown, so I guess it's doing something, but no map image is shown, and it returns the following error:
ImageCodecException: Failed to decode image data. Image source:
https://www.ign.es/wms/pnoa-historico?&service=WMS&request=GetMap&layers=AMS_1956-1957&styles=&format=image%2Fpng&srs=EPSG%3A4258&version=1.1.1&transparent=true&width=256&height=256&bbox=180,-90,180,-90
Ok, the WMS is working, as I can access it via QGIS, for example.
If I open the "image source" url created by flutter via browser it doesn't seem to work.
Plus, the bbox values in the url doesn't seem to make much sense, as they lie outside of the CRS boundaries. And the centering and zoom values I'm giving it doesn't seem to make any effect either...
If I try to open the url with different bbox values closer to the boundaries of the layer it shows something at least:
https://www.ign.es/wms/pnoa-historico?&service=WMS&request=GetMap&layers=AMS_1956-1957&styles=&format=image%2Fpng&srs=EPSG%3A4258&version=1.1.1&transparent=true&width=256&height=256&bbox=-9.5,2.5,12,44
Although I don't really fully understand what these numbers refer to (max x, min x, max y, min y?? // top-left corner, bottom-right corner // etc. ??)
Any help on what might be happening here will be much appreciated, thank you!

Why Does Text Markup Size Varies Based on Zoom?

When loading text markups from a database, the text markups show up in a different size based on the current zoom of the viewer. How do I make text markups show at a static size regardless of zoom?
function saveFreeformMarkup(markup){
let markupObject = {
x: markup.position.x,
y: markup.position.y,
width: markup.size.x,
height:markup.size.y,
type: TEXT_MARKUP_TYPE,
text: $(`#freeText`).val(),
urn_id: urn[`id`],
active: ACTIVE
};
$.ajax({
... send markupObject to database ...
});
}
function loadSingleMarkup(markup, markupTool){
let MarkupsCore = Autodesk.Viewing.Extensions.Markups.Core;
let text = new MarkupsCore.MarkupText(markup.id + ID_INCREMENT, markupTool, markup.text);
markupTool.addMarkup(text);
text.setSize({ x: markup.x, y: markup.y}, markup.width, markup.height);
text.setText(markup.text);
text.updateStyle(true);
}
This is because there's an handler attached to the camera change event that adjusts the viewbox of the SVG per the updated bounds of the current view when navigation (scaling/panning) occurs.
To overcome this you can piggyback the onCameraChange handler of the MarkupCore extension (be sure to do this prior to the event binding to the upper chain that is before entering the edit mode) and apply scaling to the SVG based on the current camera pivot values and the ones recorded when you added the markups:
MarkupsCore.originalOnCameraChange = MarkupsCore.onCameraChange;
MarkupsCore.onCameraChange = function(event){
let scaleString = calculateScale(originalPivot, viewer.autocam.pivot);
this.svg.setAttribute('transform', scaleString);
this.originalOnCameraChange(event)
}
See here for details on SVG transform.
Will leave it up to you to implement the calculations or even a better approach to transform the markups in response to navigation.
I was able to fix the issue by changing the loadSingleMarkup() function to the following
const FONT_SIZE_SCALE = 90;
function loadSingleMarkup(markup, markupTool){
let MarkupsCore = Autodesk.Viewing.Extensions.Markups.Core;
let text = new MarkupsCore.MarkupText(markup.id + ID_INCREMENT, markupTool, markup.text);
markupTool.addMarkup(text);
text.setSize({ x: markup.x, y: markup.y}, markup.width, markup.height);
text.setText(markup.text);
text.style[`font-size`] = 12 / FONT_SIZE_SCALE;
text.updateStyle(true);
}
(adding text.style[`font-size`] = 12 / FONT_SIZE_SCALE;)

How to set width to SimplePolylineGeometry primitive in CesiumJS

I have this code, which adds polyline primitive to scene.
function createPolyline(startPosition, endPosition) {
Cesium.SimplePolylineGeometry({
positions : [startPosition, endPosition]
});
var geometry = Cesium.SimplePolylineGeometry.createGeometry(polyline);
return scene.primitives.add(new Cesium.Primitive({
geometryInstances : new Cesium.GeometryInstance({
geometry : geometry,
attributes : {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.SPRINGGREEN)
}
}),
appearance : new Cesium.PerInstanceColorAppearance()
}));
}
How do I set width of this polyline?
The recommended way to add a polyline is with the Entity API, like this
var greenLine = viewer.entities.add({
polyline : {
positions : [startPosition, endPosition],
width : 5,
material : Cesium.Color.SPRINGGREEN
}
});
But, if you want to skip the Entity layer and use the Primitive Graphics layer directly, you can do that too. Your sample code above has some issues. First, you're calling the Cesium.SimplePolylineGeometry constructor without the new keyword, and without saving the result, and this is not the correct use pattern for this kind of code. Second, the SimplePolylineGeometry class itself does not support line widths greater than what the WebGL implementation supports, which on Windows machines running ANGLE, is only 1 pixel wide. To get around this limitation, use the normal (non-simple) polylines, like this:
var polylines = scene.primitives.add(new Cesium.PolylineCollection());
var polyline = polylines.add({
positions : Cesium.PolylinePipeline.generateCartesianArc({
positions : [startPosition, endPosition]
}),
material : Cesium.Material.fromType('Color', {
color : Cesium.Color.SPRINGGREEN
}),
width: 5
});
SimplePolylineGeometry does not support line width. You need to use PolylineGeometry instead and pass the "width" options to the constructor. Also, you should be using PolylineColorAppearance as your appearance, not PerInstanceColorAppearance.

In OL3, vector data layer not visible after map setCenter or zoom

Migrating a map to use OL3. When I call map.getView().setCenter or map.getView().zoom on the map, the map behaves correctly, but my vector data layer is no longer visible. I have to do a MouseWheelZoom interaction on the map and then the data layer shows up. This is similar to the issue found in this unanswered Stackoverflow post (How to reload WMTS Tiles after progromattically changing the map center and zoom?) except my map tiles render properly, it is my vector layer that is not visible.
I am creating the WMS tiles layer and map with this:
div = #get 'element'
layers = [ new (ol.layer.Tile)(
title: 'Imagery'
source: new (ol.source.TileWMS)(
url: WMS_VMAP_MAP_SERVER_URL
name: 'VMAP'
params:
LAYERS: 'basic'
FORMAT: 'image/png'
TRANSPARENT: true)) ]
map = new (ol.Map)(
interactions: ol.interaction.defaults().extend([ new (ol.interaction.Select)(style: selectedIconStyle) ])
controls: ol.control.defaults().extend([ new (ol.control.ScaleLine)(units: 'nautical') ])
layers: layers
target: div
view: new (ol.View)(
projection: 'EPSG:4326'
center: [
0
0
]
zoom: 1
maxResolution: 0.703125))
an individual feature is created using this:
feature = new ol.Feature({
geometry: new ol.geom.Point([lng, lat], 'XY'),
title: 'some title'
latitude: lat
longitude: lng
})
vectorSource.addFeature feature
the vector layer is add using this:
vectorLayer = new (ol.layer.Vector)(
source: vectorSource #new (ol.source.Vector)({})
style: circleIconStyle #my defined icon style
id: 'MYDATA'
)
map.addLayer vectorLayer
and when the following event fires...
map.on('singleclick', (e) ->
map.forEachFeatureAtPixel(e.pixel, ((feature, layer) ->
...
)
)
...as part of the event handler I am doing this:
map.getView().setCenter [
feature.get('longitude')
feature.get('latitude')
]
map.getView().setZoom 3
The map centers and zooms correctly, but my vector layer data does not show up by default. Is there something else I am not doing or calling in order to refresh the data layers after setCenter or zoom on the view? or is it something else I have incorrect in how I am setting this up?
thanx
Fixed. The issue was the coordinates were being treated as strings for the Geometry and not numbers. The fix is to ensure that where coordinates are being set, that they are explicitly treated as a number to remove ambiguity from the equation. So everywhere I set a lat/lon (or latitude/longitude) in the map code, I used Number(lat) and Number(lon) instead.
Props to Eric Lemoine for his answering of another issue located at http://comments.gmane.org/gmane.comp.gis.openlayers.devel.ol3/4773 as that is where I saw his solution to that marker display problem and thought it might address mine as well. And it did.

OpenLayers, how restricting WMS layer extent

I'm able to create an OpenLayers Map with maxExtent and restrictedExtent properties.
Also I have play with WMS layer and its maxExtent property, but the problem comes when use singleTile in the WMS layer.
What I want is to have a WMS layer that gets only one image from server but restricted to the bounds I want. Because this I used singleTile=true, ratio=1 and maxExtend=my_desired_extent.
But it always request the whole map view.
Any ideas how to achieve it.
Thanks in advance.
Next code shows a map with a base layer and a costline line layer I would like to use in singleTile mode and limiting the are they must request to WMS:
<script type="text/javascript" src="http://openlayers.org/api/2.11/OpenLayers.js"></script>
<div id="map" style="width: 700px; height: 500px;"></div>
<script type="text/javascript">
var map = new OpenLayers.Map("map");
var wms = new OpenLayers.Layer.WMS("OpenLayers WMS Basic", "http://labs.metacarta.com/wms/vmap0",
{
layers: 'basic'
});
map.addLayer(wms);
var restricted = new OpenLayers.Layer.WMS("Coast Line", "http://labs.metacarta.com/wms/vmap0",
{
layers: 'coastline_01,coastline_02'
},
{
opacity: 0.6,
singleTile: true,
ratio: 1,
isBaseLayer: false,
maxExtent: OpenLayers.Bounds.fromString("-10,-90,30,90")
});
map.addLayer(restricted);
map.setCenter(new OpenLayers.LonLat(0,40), 3);
</script>
I'm looking at OpenLayers source and seems what I want is not implemented so I need to create some WMS subclass or redefine some WMs layer methods.
I would appreciate any help.
Thanks.
If you are looking at restricting the whole map to the extent your talking about and not allowing users to pan outside of the extent you can try something like the following.
var extent = new OpenLayers.Bounds({-10,-90,30,90});
function init() {
var options = {
restrictedExtent: extent
};
map = new OpenLayers.Map('map', options);
var restricted = new OpenLayers.Layer.WMS("Coast Line", "http://labs.metacarta.com/wms/vmap0",
{
layers: 'coastline_01,coastline_02'
},
{
opacity: 0.6,
singleTile: true,
ratio: 1,
isBaseLayer: false
});
map.addLayer(restricted);
The difference here is that I have set the extent on the whole map not just the layer. Note that you will need to control the maximum zoom level as well. If you don't a user can still zoom out and data passed the extents will be shown though they will not be able to pan the view on the map.
If you want the map to pan outside of the extent specified but just not that layer then there are a number of approaches.
If you have access the the WMS server that the layer is served from you could add a setting there to restrict the extent of the layer server.
Check this link http://docs.geoserver.org/latest/en/user/webadmin/data/layers.html and read the "Bounding Boxes Section"
If you don't have access to the WMS server and you just want to restrict the area that is requested from the WMS server from the client side you could try using the OpenLayers.layer.WMS class with a different strategy. See below for an example:
var myfilter = new OpenLayers.Filter.Spatial({
type: OpenLayers.Filter.Spatial.BBOX,
value: OpenLayers.Bounds.({-10,-90,20,90})})
var filterStrategy = new OpenLayers.Strategy.Filter({filter: myFilter});
var restricted = new OpenLayers.Layer.WMS("Coast Line", "http://labs.metacarta.com/wms/vmap0",
{
layers: 'coastline_01,coastline_02'
},
{
opacity: 0.6,
singleTile: true,
ratio: 1,
isBaseLayer: false,
strategies: [filterStrategy]
});
map.addLayer(restricted);
Please note that I have not tested this code and it may take a little refining to get it to work.