I'm creating a feature of removing points from openlayers polygons when drawing. So there is my "configuration":
source = new ol.source.Vector({
wrapX: false,
});
raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
vector = new ol.layer.Vector({
source: source,
style: new ol.style.Style(/* some config */)
});
view = new ol.View({
center: defaultLonLatFormat,
zoom: 12
});
mapx = new ol.Map({
layers: [raster, vector],
target: 'target',
view: view
});
Code used to start drawing:
draw = new ol.interaction.Draw({
source: source,
type: 'Polygon',
});
mapx.addInteraction(draw);
Code used to remove last point:
draw.removeLastPoint();
draw.changed();
Everything works like a charm until polygon is open - until I connect last point with first point. After that removing last point makes nothing. Fortunatelly I can delete points with alt + click - it works until there is 3 points left which makes minimal closed polygon - triangle. Then even alt + click combination doesn't work. I've even tried this on OpenLayers examples - this same behaviour. So I've got three questions:
What happens after closing polygon, so I can't delete points with draw.removeLastPoint()?
Why I'm unable to delete last three points from polygon?
Any ideas how to achieve such functionality?
After the drawing is finished, the sketch is added to the target layer, and also removed from the draw interaction, so if you want to access it, you need to call
source.getFeatures();
any draw interaction functions do no longer have effect on it.
As written here, Polygon is:
Array of linear rings that define the polygon. The first linear ring of the array defines the outer-boundary or surface of the polygon. Each subsequent linear ring defines a hole in the surface of the polygon. A linear ring is an array of vertices' coordinates where the first coordinate and the last are equivalent.
Technically, when the outer boundary is not a linear ring it is not a valid polygon. When you have less than three coordinates, it is more of a line.
You can check the number of points in the polygon geometry and when trying to delete the third point, change the geometry to line (or more preciesly to LineString), and when deleting the second point change it to point.
Related
I need to create pushpins for the below input.
var Countries = ["Austria", "Brazil", "India", "Germany", "USA", "Malaysia"];
Microsoft.Maps.SpatialDataService.GeoDataAPIManager.getBoundary(Countries, geoDataRequestOptions, map,
(data) => {
var value = data.location;
if (data.results.length > 0 && data.results[0].Polygons !== null) {
var polygons = data.results[0].Polygons;
var dataBounds = Microsoft.Maps.LocationRect.fromShapes(data.results[0].Polygons);
var loc = new Microsoft.Maps.Location(dataBounds.center.latitude, dataBounds.center.longitude);
var pin = new Microsoft.Maps.Pushpin(loc, {
icon: svgIcon,
anchor: new Microsoft.Maps.Point(20 / 2, 20 / 2)
});
map.entities.push(pin);
locs.push(pin);
map.setView({ bounds: Microsoft.Maps.LocationRect.fromLocations(locs), padding: 80 });
}
});
}, 3000);
I am using GeoDataAPIManager to get the boundary polygons and get the center of the polygon to generate a pushpin. But when loading countries like Malaysia or USA, the pushpins are placed in the sea, as the getboundary() returns multiple polygons and getting the center of the polygon returns the center between the two boundaries which results in the pushpin placed in the sea.
Let me know if there is any alternate way to create the pushpin or to get the center of the polygon.
I already tried the spatial.Math module to get the center.
This is a common occurrence when working with polygons as their shape can be such that their center is not within the actually geometry. There are several different ways to do this.
Method 1: This method will fall back to the nearest point to the calculated center that's on the edge of the polygon.
Calculate centroid/center either using math library or rough center by using bounding box center.
Check to see if the point intersects the polygon, if not, calculate the closest point on the edge of the polygon (shortest distance), then use that point as your center.
Method 2: Focus just on the largest polygon.
If the geometry is a MultiPolygon, calculate the area and grab the polygon with the largest area. For the USA, this would give you the polygon for the mainland which is likely desired.
Try method 1, using just the largest polygon.
Method 3: Attempt to calculate a visual center using external library.
Convert the polygon to GeoJSON using the GeoJSON module in Bing Maps: https://www.bing.com/api/maps/sdkrelease/mapcontrol/isdk/geojsonwritetogeojson
Pass the geojson geometry into this library to calculate the visual center. https://github.com/mapbox/polylabel
I have given coordinates of two points. I can draw a LineString that is connecting these two points. What I'd like to achieve is having a LineString/MultiLineString that's connecting points but it's also a little longer (let's say 20% longer than distance between these two points) and it's extended after one point only.
What I currently have:
What I want to achieve:
My issue is that I don't know how to find position of third point which would indicate end of the line. It should be placed exactly along existing line in given distance. Any kind of map projection is not important, because I just want to have a line that will be always straight.
const markerOne = new ol.Feature({
geometry: new ol.geom.Point([-1000, -1000])
});
const markerTwo = new ol.Feature({
geometry: new ol.geom.Point([1000, 1000])
});
const lineStrEnd = ?;
const lineStr = new ol.Feature({
geometry: new ol.geom.LineString([markerOne.getGeometry().getCoordinates(), lineStrEnd])
});
HERE'S WORKING FIDDLE
The simplest way would be to scale the geometry, e.g. a linestring from markerOne to markerTwo increased by 20% with the scaling anchored at markerOne so the line extents beyond markerTwo
const lineStr = new ol.Feature({
geometry: new ol.geom.LineString([markerOne.getGeometry().getCoordinates(), markerTwo.getGeometry().getCoordinates()])
});
lineStr.getGeometry().scale(1.2, 1.2, markerOne.getGeometry().getCoordinates());
I am trying to create a heat map using openlayers.
What i want to do is say i have a custom score function which return some float value, i want to use that value to decide a color for data point.
Higher the value the darker is the color point (more towards red). Lesser the value the lighter the color point (more towards green or blue).
Please can someone suggest how i can achieve this.
My javascript code for heatmap is as below
var vector = new ol.layer.Heatmap({
source: new ol.source.Vector({
url: 'http://localhost:8080/heatmapKML',
format: new ol.format.KML({
extractStyles: false
})
}),
blur: 15,
radius: 5
});
var raster = new ol.layer.Tile({
source: new ol.source.Stamen({
layer: 'toner'
})
});
var map = new ol.Map({
layers: [raster, vector],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 3
})
});
Thanks
open layer heat map has few properties that can be tweaked. Refer open layer api documentation.
The weight property can be set to differentiate the color of a data point.
You can implement a custom score function on javascript side or on backend side and then fetch value in javascript side.
The point is that setting weight for each data point will define the color intensity for it.
So in the above code that i have shared, i just added below line before creating raster variable.
vector.getSource().on('addfeature', function(event) {
var score = event.feature.get('score');
event.feature.set('weight', score);
});
The value for score came from a custom score function defined at the backend.
As you can see the two data points have different color intensity.
This question already has an answer here:
Google Maps API Polygon with "Hole" In Center
(1 answer)
Closed 7 years ago.
First of all, for the issue you're going to read, I used this snippet of code to highlight my polygon :
Highlight polygon and tint rest of map using Google Maps
Here is my code (it's Angular) :
var boundaries = [];
// big area
var overlay = [
new $rootScope.googleApi.LatLng(80.0, -90.0),
new $rootScope.googleApi.LatLng(-60.0, -90.0),
new $rootScope.googleApi.LatLng(-60.0, 90.0),
new $rootScope.googleApi.LatLng(80.0, 90.0)
];
// my polygon
angular.forEach(settings_boundaries, function(val, key) {
boundaries.push(new $rootScope.googleApi.LatLng(val[1], val[0]));
});
// create a polygon with overlay first
var poly = new $rootScope.googleApi.Polygon({
paths: [overlay, boundaries],
strokeColor: "blue",
strokeWeight: "1",
fillColor: "black",
fillOpacity: 0.4,
clickable: false
});
poly.setMap(interactiveMap);
Now, the real problem is,
If I use these coordinates (which I don't remember how I got them in the first place) :
[[1.6101837158203125,49.00274483644452],
[1.6294097900390625,49.01175312475694],
[1.5947341918945312,48.98787759766659],
[1.6101837158203125,49.00274483644452]]
Everything works fine (as you can see here).
But if I use these ones :
[[1.6809940338134766,48.98337149775796],
[1.6791915893554688,48.96849847697763],
[1.7185020446777344,48.995199140974066],
[1.6809940338134766,48.98337149775796]]
This is not working anymore.
As you can see here.
I used this website to generate the coordinates :
http://www.the-di-lab.com/polygon/ (view screenshot)
I searched for a long time what the issue could be, but I have really no idea. It's approximately the same coordinates. The first lat,lon values are the same than the last ones, for both of them.
If you have any idea (I guess there's something special in the coordinates), I would like to know !
Thanks !
Structurally, the coordinates of the triangle are correct. Only a geometrical difference the first triangle (the one functioning) is drawn in a clockwise direction while the latter is drawn counterclockwise. I have already met a situation like this but I do not remember which site. Then try to reverse the direction of drawing of the triangle in this way:
[[1.6809940338134766,48.98337149775796],
[1.7185020446777344,48.995199140974066]
[1.6791915893554688,48.96849847697763]
[1.6809940338134766,48.98337149775796]]
By using the Bezier curve polyline draw function provided by nicoabie I was able to draw a curved line from one point on the map to another. The problem is that this function does not take in to account the fact that when a point is past the maximum coordinate mark it is not necessarily on the other side of the map, since it wraps around.
For example, drawing a curved line from Seattle to Tokyo. A regular polyline would go across the Pacific ocean, but the the curved line draws east across the whole globe.
geodesic: true does not work in this case since the line must have a consistent curvature.
My question is: can a consistently curved line be drawn that takes in to account map wrapping?
Use the option third "nowrap" argument of the google.maps.LatLng class to force all the relevant points to have the same sign (set it to true, it defaults to false).
gmarkers[10].setPosition(new google.maps.LatLng(35.689488,139.69170)); // Tokyo
gmarkers[0].setPosition(new google.maps.LatLng(47.60621,(360-122.332071),true)); // Seattle
boundsCenter.setPosition(new google.maps.LatLng(36.096756,(360-178.986565),true)); // control point 1
gmarkers[6].setPosition(new google.maps.LatLng(48.511996,180)); // control point 2
var curvedLine = new GmapsCubicBezier(gmarkers[0].getPosition().lat(), gmarkers[0].getPosition().lng(), boundsCenter.getPosition().lat(), boundsCenter.getPosition().lng(), gmarkers[6].getPosition().lat(), gmarkers[6].getPosition().lng(), gmarkers[10].getPosition().lat(), gmarkers[10].getPosition().lng(), 0.01, map);
working fiddle