I'm trying to create a custom Polygon style for my layer style.
I receive some information about position, orientation and age for a number of objects and I want to represent those as zoom independent (like using Icons or RegularShapes) isosceles triangles, pointing at an angle and color-coded according to age.
I have a good idea of the color-coding and rotation part, but I'm stumped at creating an isosceles triangle using the style objects provided by OpenLayers.
This is what I have so far:
style = [new ol.style.Style({
geometry: function(feature) {
return new ol.geom.Polygon([[
[0, 0],
[2, 0],
[1, 3]
]]);
},
fill: new ol.style.Fill({color: '#000'}) //black right now
})]
Related
I have my map object created like this:
new ol.Map({
...
view: new ol.View({
center: ol.proj.transform([15,49], 'EPSG:4326', 'EPSG:3857'),
zoom: 10,
minZoom: 7,
maxZoom: 18,
extent: ol.proj.transformExtent([11.8, 48.4, 19.2, 51.2], 'EPSG:4326', 'EPSG:3857')
})
});
Let's say I have a big polygon "A" ( see the picture below ). I have a smaller polygon "B", which sticks to one side of the polygon "A". An external system calculates polygon "B" coordinates using WGS coordinates - points "pt1" and "pt2" are positioned on connection between point "pt3" and "pt4". When I draw both polygon on my map, points "pt1" and "pt2" are not positioned on connection between point "pt3" and "pt4". I think, it's because OpenLayers connect points "pt3" and "pt4" by direct line. This connection is straight line on the globe, so on my map, it should be curve. And that's why, I think, the polygon "B" is not aligned with the polygon "A" although it is on the globe. Is there a way, how to fix this?
Is there a parameter to set a minimum radius for features to cluster? - so that when a set of points or features are within some minimum distance, they form a cluster, otherwise not?
ol.source.Cluster() has two parameters that look promising, but don't seem to work as expected.
distance: Minimum distance in pixels between clusters. Default is 20.
extent: An array of numbers representing an extent: [minx, miny,
maxx, maxy].
Not quite sure what "but don't seem to work as expected." means?? How does it not work as expected??
distance property of ol.source.Cluster tells the layer when to group objects based on the distance set. It can be changed when creating the cluster layer. For example:
var locationSource = new ol.source.Vector({
url: loc_url,
format: new ol.format.GeoJSON({
defaultDataProjection :'EPSG:3857'
}),
loader: vectorLoader,
strategy: ol.loadingstrategy.all
});
var LOCclusterSource = new ol.source.Cluster({
distance: 5,
source: locationSource
});
I usually change the distance object until I find the desired distance so group/cluster object look right on the map.
The radius of a group object on a map layer can be change via a style function for the map layer. Many example of style functions exist here on stack.
Here is a hacked up example that I use to increase the radius of cluster/group objects on the map layer so it's visually obvious that it is a group/cluster object:
NOTE: You can have different shapes on the same layer too using a style function. https://openlayers.org/en/latest/examples/regularshape.html
// Location Map Layer Properties
var locLyrProps = {
"radius": 8,
"CORadius": 12,
"groupRadius": 10,
"borderWidth": 2,
"color": [0, 0, 0, 0.5],
"txtMaxRes": 20,
"txtOffsetY": -20
};
var styleFunction = function() {
return function(feature,resolution) {
var style;
var props = locLyrProps;
var radius;
var lyrTyp;
var gotGroup = false;
var features = feature.get('features');
if (features.length == 1) { //Individual map object because length = 1
style = new ol.style.Style({ //Square layer object
image: new ol.style.RegularShape({
radius: radius,
points: 4,
angle: Math.PI / 4,
fill: createFillStyle(feature),
stroke: createStrokeStyle(feature, resolution)
}),
text: createTextStyle(feature, resolution)
});
} else {
var rad = props.radius;
if (features.length > 1) { //If cluster/group of features increase radius of group object so group objects stand out a bit
rad = props.groupRadius; //If cluster/group object is found, set cluster/group radius for it
gotGroup = true;
}
console.log('circle radius: ' + rad);
style = new ol.style.Style({
image: new ol.style.Circle({
radius: rad,
fill: createFillStyle(feature),
stroke: createStrokeStyle(feature, resolution, gotGroup)
}),
text: createTextStyle(feature, resolution, props, gotGroup)
});
}
return [style];
};
};
When the highstock chart data set has multiple points on the same axis ex:
data: [[0,0], [0, 100], [1, 100], [1,200], [4, 100], [4, 200]]
the point doesn't always choose the highest number by default. It looks like it randomly selects one of the numbers on the same axis.
Here's my fiddler example: http://jsfiddle.net/ceo1y97m/
As you can see when you hover over the different points, it's not always displaying the highest point's Y value. How do I get this to show only the highest point's value?
Edit: Here is the reason that I have multiple x values that are the same:
Let's say the line represents the amount of money you deposit into an account over time. In the line's legend I want to display the amount you've deposited over the period that you're viewing. This would be the furthest point right's Y value minus the furthest point left's Y value. If I don't include the duplicate Y values, this calculation is incorrect.
See updated fiddler to show this error on the legend value (zoom in and out to change the legend values): https://jsfiddle.net/LS384/822/
The two data sets look identical, but the legend values are different, because both points on the same axis aren't displayed.
I'm not sure that this is how the step chart was intended to be used, you should have just 1 value per axis point.
What you could do is filter your data to just keep the highest value for each point
data: [[0,0], [0, 100], [1, 100], [1,200], [4, 100], [4, 200]]
for (var i in data) {
if (filteredData[data[i][0]] == undefined) {
filteredData[data[i][0]] = data[i]
} else {
if (filteredData[data[i][0]][1] < data[i][1]) {
filteredData[data[i][0]] = data[i];
}
}
}
here is your edited filter with the chart looking the same and you desired behaviour http://jsfiddle.net/ceo1y97m/4/
Edit:
I made a workaround, i hid the unfiltered data, used the filtered data for display and gave it the same color as the unfiltered one, and in the function that calculates the difference i use the unfiltered data(ch.series[0].data])
Here is the fiddle with your expected behaviour https://jsfiddle.net/LS384/826/
I would process the data, so you have one point per x value with additional information - multiple values. I treat { x, y } as the information about how the point should be visualised plus add the array with all additional values which allow to make the proper calculations.
This:
[
[0, 0],
[0, 100],
[1, 100],
[1, 200],
[1, 300],
becomes this:
[{
x: 0,
y: 100,
values: [0, 100]
}, {
x: 1,
y: 300,
values: [100, 200, 300]
}]
With points defined as the above, you can access the values via point.options.values and calculate the difference.
example: http://jsfiddle.net/jqdh79vv/
I am new to OpenLayers and would appreciate any help I can get. How do you convert from pixel-based-coordinates to lat/lon? I'm using OL3 to view and draw features on a static image (6494 x 7687 jpg) using projection:
var projection = new ol.proj.Projection({
code: 'xkcd-image',
units: 'pixels',
extent: [0, 0, 6494, 7687]
});
At the end of a polygan draw I have this, which works fine:
draw.on('drawend', function (event) {
var coord = event.feature.getGeometry().getCoordinates();
console.log("YOU DREW A Polygon with coord="+coord);
});
Is there an easy way to convert the above pixel-based coordinates of the polygon to Lat/Lon coordinates? I do have the lat/lons of the four corners of the image.
Instead of specifying a custom pixel projection, configure your static image source with the imageExtent set to your corner coordinates, and set its projection to 'EPSG:4326':
new ol.source.ImageStatic({
// ...
imageExtent: [minLon, minLat, maxLon, maxLat],
projection: 'EPSG:4326'
})
If you want to show your image without being distorted, you have to configure your view with projection: 'EPSG:4326' as well. You'll then be working with geographic coordinates throughout.
Something similar is also shown in one of the official examples: http://openlayers.org/en/latest/examples/reprojection-image.html. The difference is that raster reprojection is used there, because image and view are in different projection.
The goal is to be able to zoom onto a high-res picture (11520x11520) that I have split into 256x256 squares. I took the large image and resized it to 80%, 60%, 40%, 20% and 8.89%. Then, for each of the images from 100% to 8.89%, I split them. It's to make an interactive video game map like this: http://www.ark-survival.net/en/dynamic-livemap/
I have tried this:
var map = new ol.Map({
target: 'ark_map',
layers: [
new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'images/map/{z}/map_{x}_{y}.png',
tileSize: 256,
maxZoom: 5
})
})
],
view: new ol.View({
center: [50, 50],
zoom: 5,
minZoom: 0
})
});
The result: I only see the top left corner on any zoom used. I've seen many examples and many questions, but combining static tiles and XYZ (on pixels) has never come up.
Here is the JS Fiddle.
How do you combine static tiles and XYZ coordinates based on a pixel system?
You have a very weird tile layout. What you describe maps to this set of resolutions:
var resolutions = [
45/4,
45/4/2*0.889,
45/4/4*0.889,
45/4/6*0.889,
45/4/8*0.889
];
With that, you can configure an ol.tilegrid.TileGrid:
new ol.tilegrid.TileGrid({
origin: [0, 11520],
resolutions: resolutions
})
See updated fiddle for the full code: https://jsfiddle.net/6moqu7q8/4/.