Extending LineString/MultiLineString along existing Feature - javascript

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());

Related

Converting OpenLayers Polygon to GeoJSON with different projection

Similar to the problem found in this question
How to convert OpenLayers polygon coordinates into latitude and longitude?
I have setup a basic map to capture a user defined polygon and convert it to GeoJSON, whilst I'm able to do this with its native projection (ESPG:3857) I would like to take the captured GeoJSON and convert it to EPSG:4326 - which I will then save away. Using the above method of capturing the feature on the drawend event and performing a transform however removes the polygon as the new co-ordinates are not represented in the projection of the map any longer. I am unable to figure out how to to save the GeoJSON in the format I need without deleting the existing polygon
I have tried performing this by using getFeatures on the vector source of the polygon and then performing a transform from the projection i'm using to the projection I want, but this still returns the same coords, I have also (like the linked article) tried using the the writeFeatureObject but it still saves incorrectly
https://jsfiddle.net/20gxo3nt/
dragBox.on('drawend', function(evt){
/* geom = evt.feature.getGeometry().transform('EPSG:3857', 'EPSG:4326');
console.log(geom.getCoordinates()); */
});
$( "#save" ).click(function() {
var geom=vectorSource.getFeatures();
console.log(geom);
var writer=new ol.format.GeoJSON();
var geoJsonStr = writer.writeFeatures(geom);
console.log (geom.proj.transform('EPSG:3857', 'EPSG:4326'));
/* console.log(geoJsonStr) */
});
Uncommenting the code on the drawend event will correctly console.log the co-ordinates,as well as demonstrate polygon disappearing
To get a new geojson
var geom = [];
vectorSource.forEachFeature( function(feature) { geom.push(new ol.Feature(feature.getGeometry().clone().transform('EPSG:3857', 'EPSG:4326'))); } );
var writer = new ol.format.GeoJSON();
var geoJsonStr = writer.writeFeatures(geom);
console.log(geoJsonStr);
Openlayers 6, no need to loop on features
var format = new ol.format["GeoJSON"]();
var geoJsonStr = format.writeFeatures(vectorSource.getFeatures(), { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857'});

Remove all points from polygon one by one

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.

Heat map using openlayers

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.

Make Polyline Longer at runtime

I have a google map application where i am moving markers on a polyline. I am generating a new destination point(latlng coordinates). I would like to extend the polyline to this new destination point.
Can some one tell me how i can move the end point of a polyline to another point on the map.
I have used polyline[index].getPath() in here i can see all the latlng coordinate pairs that make up the route. How to add to this route to make it longer or shorter?
Simple. If you merely wanted to add an additional point to the existing array of points, this works:
var currentPath = polyline[index].getPath();
var newPoint = new google.maps.LatLng(40.781321,-73.965855);
currentPath.push(newPoint);
polyline[index].setPath(currentPath);
If you wanted however to change where the current last point is at, try this instead:
var currentPath = polyline[index].getPath();
var newPoint = new google.maps.LatLng(40.781321,-73.965855);
currentPath.setAt(currentPath.getLength()-1, newPoint);
polyline[index].setPath(currentPath);

OpenLayers LonLat transform

I want to use decimal Lon and Lat like Google Maps uses. But it seems I need to transform the LonLat object in OpenLayers, e.g.
var map, layer;
function init(){
map = new OpenLayers.Map('map');
layer = new OpenLayers.Layer.OSM( "Simple OSM Map");
map.addLayer(layer);
map.setCenter(
new OpenLayers.LonLat(-1.60400390625, 54.07228265560386).transform(
new OpenLayers.Projection("EPSG:4326"),
map.getProjectionObject()
), 6
);
var markers = new OpenLayers.Layer.Markers( "Markers" );
map.addLayer(markers);
var size = new OpenLayers.Size(21,25);
var offset = new OpenLayers.Pixel(0,0);
var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png', size, offset);
markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(-1.60400390625, 54.07228265560386).transform(new OpenLayers.Projection("EPSG:4326"),map.getProjectionObject()),icon));
}
Each time I place a marker the position needs to be transformed to EPSG:4326. Is there a way to tell the map to always use this projection?
Whether you can set the projection on a map or not, depends on which service you are using for the base layer. As far as I know, OSM only provides its rendered tiles in EPSG:900913, so there is no way around transforming your coordinates before adding them to the map. You could search for a service that provides its tiles in multiple projections, but I haven't seen one that is free to use so far. An alternative would be to render your own tiles in the needed projection and provide them through your own tile server.
Let's suppose you have such a map, you can change the projection using OpenLayers.Map.setOptions() like this:
map.setOptions({
projection: "EPSG:4326"
});
But you may also need to set some projection related properties, like maxExtent etc. See this question.

Categories

Resources