Given a point, say [-75.343, 39.984], how do I go about finding all features/markers within a 5km radius of it? I'm utilizing turf.js so I'll be using their circle() function to generate the circle about the point.
Would this work?
const center = [-75.343, 39.984];
const radius = 5;
const options = {steps: 10, units: 'kilometers', properties: {foo: 'bar'}};
const circle = turf.circle(center, radius, options);
}
const features = map.queryRenderedFeatures(
circle,
{ filter: {["within", circle] : true} }
);
I'm hoping to find all features within the circle and be able to store them in an array or in a database for further processing like accessing the feature's lat/lng, etc.
Thank you for the help!
Using queryRenderedFeatures you will be able to get the features that are actually in the viewport (visible). In case your source data is GeoJSON, you can use querySourceFeatures, so it will look to all your source features:
const filteredFeatures = map.querySourceFeatures('routes', {
filter: ['within', circle]
});
The examples shown in here show how to move an object along the path in Paperjs but how do I rotate them correctly along the path?
In the examples shown on the link above, people suggested by using a circle as an example. But once changed to a rectangle new Path.Rectangle(new Point(20,20), new Size(20,20)); you can see that it moves along the path but does not actually rotate in the direction of the path.
How do I calculate the rotation and set it to my object?
In order to calculate the rotation, you need to know the tangent vector to the path at the position of your rectangle.
This can be retrieved with path.getTangentAt(offset) method.
Then, an easy way to animate the rotation of an item is to set item.applyMatrix to false and then animate the item.rotation property on each frame.
Here is a sketch demonstrating the solution.
// Create the rectangle to animate along the path.
// Note that matrix is not applied, this will allow us to easily animate its
// rotation.
var rectangle = new Path.Rectangle({
point: view.center,
size: new Size(100, 200),
strokeColor: 'orange',
applyMatrix: false
});
// Create the path along which the rectangle will be animated.
var path = new Path.Circle({
center: view.center,
radius: 250,
strokeColor: 'blue'
});
// On each frame...
function onFrame(event) {
// ...calculate the time of the animation between 0 and 1...
var slowness = 400;
var time = event.count % slowness / slowness;
// ...and move the rectangle.
updateRectangle(time);
}
function updateRectangle(time) {
// Calculate the offset relatively to the path length.
var offset = time * path.length;
// Get point to position the rectangle.
var point = path.getPointAt(offset);
// Get tangent vector at this point.
var tangent = path.getTangentAt(offset);
// Move rectangle.
rectangle.position = point;
// Rotate rectangle.
rectangle.rotation = tangent.angle;
}
What I am trying to do is to replace or change the geometry of a feature after it has been drawn. e.g.: I draw a line and after it has been drawn I modify the geometry with Turf.js, to make a buffer around the drawn line and display the buffered line(polygon) instead of the line.
var draw = new ol.interaction.Draw({
source: vectorSource,
type: 'LineString'
});
draw.on('drawend', function(e) {
//Sending the LineString to a Turf function with a buffer value and getting a Polygon in return
var bfc = bufferedFeatureCollection(100, e.feature);
//Replacing the LineString geometry with a Polygon geometry
e.feature.setGeometry(bfc[0].getGeometry());
//Removes and terminates the draw action....
map.removeInteraction(this);
});
Now from console.log(), I can see that the feature.geometry has been changed from ol.geom.linestring to ol.geom.polygon. But on the map I still see a line being displayed.
What am I doing wrong?
Do these modifications after the feature is added to ol.source.Vector, so:
vectorSource.on('addfeature', function(evt){
//Sending the LineString to a Turf function with a buffer value and getting a Polygon in return
var bfc = bufferedFeatureCollection(100, evt.feature);
//Replacing the LineString geometry with a Polygon geometry
evt.feature.setGeometry(bfc[0].getGeometry());
//Removes and terminates the draw action....
map.removeInteraction(draw);
});
The mistake I made was that the buffer value was too low to be seen as a buffer hence I only saw a line(even do it was a polygon) I had to up the buffer value from 100 to 10000000...
So in both draw.on('drawend') and vectorSource.on('addfeature') it is possible to replace the geometry that has been drawn.
Edit:
For the completeness of the answer. The reason I had to change the buffer from 100 to 10000000 is that I forgot to transform the geometry into EPSG:4326, before passing it to the Turf function. Turf only works with EPSG:4326.
var draw = new ol.interaction.Draw({
source: vectorSource,
type: 'LineString'
});
draw.on('drawend', function(e) {
e.feature.getGeometry().transform('EPSG:3857', 'EPSG:4326');
var bfc = bufferedFeatureCollection(radius, e.feature);
bfc[0].getGeometry().transform('EPSG:4326', 'EPSG:3857');
e.feature.setGeometry(bfc[0].getGeometry());
//Removes and terminates the draw action....
map.removeInteraction(this);
});
I have a project which consist in visualizing the exchange of data between points on a map.
I'm using Leaflet to draw polylines from coordinates in a GeoJson file and Leaflet.polylineDecorator (https://github.com/bbecquet/Leaflet.PolylineDecorator) to put an animated arrow on the polyline.
The thing is that I need to visualize the stream in both directions. I started by adding to my Geojson file polylines in the other direction but the issue is when I zoom out, the two polylines are stacked.
So I found Leaflet.polylineOffset (https://github.com/bbecquet/Leaflet.PolylineOffset) which allows to create an another polyline just by setting the offset option.
I thought, i just had to do the same to put the animated arrow on it but when i'm doing it, the animation is affected to the original polyline. In fact, the offset polyline keeps the coordinates from the original one.
I wanted to know if there is a way to apply this animation to the offset polyline.
Here is my code:
d3.json("data/trajetsFibreDCSigma.json",function (data){ // getting polylines' data from a json file to add them on the map
L.geoJson(data, {
style: function(feature){return {color : feature.properties.stroke,opacity: 1};}, // setting the style of the polylines
onEachFeature: function(feature){
// getting the coordinates of the polyline from the json file
var latlng = feature.geometry.coordinates;
var size = feature.geometry.coordinates.length;
var buffer;
// reversing the order of latitude and longitude in the array because a L.latLng object needs the latitude first and I have the opposite in my json file
for (i=0;i<size;i++)
{
buffer = latlng[i][0];
latlng[i][0] = latlng[i][1];
latlng[i][1] = buffer;
}
var polylineOffset = L.polyline(latlng,{offset: 5,color: 'blue',opacity: 1}).addTo(map); // putting an offset to the polyline
addArrow(latlng,feature);
addArrow(polylineOffset,feature);
}
}).addTo(map);
});
function addArrow(polyline,feature){ // function to add an arrow on the map
var arrowHead = L.polylineDecorator(polyline).addTo(map); // creating an arrow which will be put on the polyline
var arrowOffset = 0;
window.setInterval(function() { // creating an animation for the arrow to cross the polyline
arrowHead.setPatterns([
{offset: arrowOffset+'%', repeat: 0, symbol: L.Symbol.arrowHead({pixelSize: 10, polygon: false,
pathOptions: {stroke: true,color: feature.properties.stroke,opacity: 1}})}
]);
if(++arrowOffset > 100)
arrowOffset = 0;
}, 100);
}
(If I'm just calling addArrow with the offset polyline, it will pop on the original one).
I found a solution to get the offset polyline's coordinates.
The PolylineOffset plugin has a function which returns the offset coordinates.
You can use it like this:
var pts = L.PolylineOffset.offsetLatLngs(latlng,10,map); // getting the coordinates from the offset polyline
where latlng is the array of the original coordinates
; 10 is the offset
; map is your leaflet map
I'd been trying to write a small library in Javascript mainly for Canvas drawImage() method.
The main purpose of the library is to pass array values instead of passing single values such as :
// srcPos=[0,0] , size=[90,90], dstPos=[50,50]
function draw_image(context, image, srcPos, size, dstPos, size) {
context.drawImage(image, srcPos[0], srcPos[1], size[0], size[1], dstPos[0], dstPos[1], size[0], size[1]);
}
but when i called this function jzz like this, I'm getting Uncaught ReferenceError :
var canvas = document.getElementById("display"),
frame = canvas.getContext("2d");
var shipInfo = { center:[45, 45], size:[90, 90], radius: 35, angle:45 },
shipImage = new Image(),
pos = [40, 70];
shipImage.src = "ship.png";
function draw() {
draw_image(frame, shipImage, shipInfo.size, pos, shipInfo.size);
}
window.onload = function() {
draw();
}
And Is it possible to implement a method overriding the default drawImage() like this:
frame.draw_image(shipImage, srcPos, shipInfo.size, dstPos, shipInfo.size);
If you want to add a function to the 2d context, javascript makes this easy thanks to the prototype inheritance : You can inject the Context2D object to add or change its function as you wish.
You might want to look at a few addings i made to the context in a small canvas lib i made here : https://github.com/gamealchemist/CanvasLib
Some will tell that injecting is evil, but unless you're on a huge boat i would just say : If you use some graphic library, respect the semantic of existing functions and everything should be fine. If you don't use libs : do whatever it takes !
So, to answer more specifically to your question, your shorter drawImage would give :
CanvasRenderingContext2D.prototype.draw_image = function ( image,
srcPos, size,
dstPos, size) {
this.drawImage(image, srcPos[0], srcPos[1], size[0], size[1],
dstPos[0], dstPos[1], size[0], size[1]);
};
Then you can use the new function on all your contexts :
var canvas = document.getElementById("display"),
frame = canvas.getContext("2d");
frame.draw_image( ... ) ;
Notice that you could use 'rect' objects, which would be arrays with 4 elements, x, y, w, h, and lead to an even shorter syntax.
Edit : i see in your lib that you want to rotate your rect.
First thing is that you don't want to reset the transform. Just save it then restore it.
I would try something closer to this :
var x = dstPos[0],
y = dstPos[1],
halfWidth = dstSize[0]*0.5, // !! not src use >>1 if you know it's an int.
halfHeight = dstSize[1]*0.5, // !! not src ...
angleInRads = angle * Math.PI / 180;
this.save();
this.translate(x+halfWidth,y+halfHeight);
this.rotate(angleInRads);
this.drawImage(image
, center[0], center[1], srcSize[0], srcSize[1]
, -halfWidth, -halfHeight, dstSize[0],dstSize[1]);
this.restore();
Your small image library would fit well inside a javascript object.
A Demo: http://jsfiddle.net/m1erickson/7pZJw/
A javascript object can hold information about your image:
the image itself
the image size (can be automatically calculated for you)
the image centerpoint (can be automatically calculated for you)
Example:
// create a new object
// fill it with the info about the image
var object={
image:shipImage,
width:shipImage.width,
height:shipImage.height,
centerOffsetX:shipImage.width/2,
centerOffsetY:shipImage.height/2,
radius:35,
angle:45,
};
A javascript object can also hold functions that draws the image (as you've done in your code)
Example:
// when you call object.draw the image will be drawn by this function
// which is added to the object itself
draw:function(context,atX,atY,newWidth,newHeight){
context.drawImage(
this.image,
0,0,this.width,this.height,
atX,atY,newWidth,newHeight);
},
A function to create your small image library inside a javascript object might look like this:
function createImageObject(image,radius,angle){
// create a new object
// fill it with the info about the image
var object={
image:image,
width:image.width,
height:image.height,
centerOffsetX:image.width/2,
centerOffsetY:image.height/2,
radius:radius,
angle:angle,
draw:function(context,atX,atY,newWidth,newHeight){
context.drawImage(
this.image,
0,0,this.width,this.height,
atX,atY,newWidth,newHeight);
},
};
return(object);
}
And you can use your ship object library like this:
// create a new ship object
var shipObject=createImageObject(img,35,45);
// draw the ship image using the ship object
// draw at 20,20 with size 75,75
shipObject.draw(frame,20,20,75,75);
BTW, I see you're using the version of drawImage that will scale/clip the source image.
If you just want to draw the full image at its original size you can do this shortcut:
// draw the image full-sized at x,y
context.drawImage(image,x,y);