I have some code with points which draws a polygon.
Here is the code:
app.pts = [
[33.644631, -70.610453],
[33.637884, -70.608253],
[33.637566, -70.608704],
[33.638933, -70.610935],
[33.641044, -70.614036],
[33.641386, -70.614176]
];
app.map = L.map('map').setView(app.pt, 15);
app.polygon = L.polygon(app.pts, {
color: '#00ff00',
opacity: 0.6,
fillOpacity: 0.2
});
What I would like is a circle instead, so my question is:
How do I modify this code so I can draw a Circle instead of a polygon?
The circle would be 50 meters radius and centered on 33.644631, -70.610453
Per the documentation
app.circle = L.circle([33.644631, -70.610453], {radius: 50});
Related
I have a paper.js layer where users can draw different paths (circles, line, etc). This layer can be panned or zoomed using mouse scrolling or dragging. I use affine matrix transformation to zoom/pan paths in this layer. This works rather well.
What i'm looking for is to create a circle (Path.Circle object) that can be panned and zoomed using matrix, just its radius has to be always fixed (5px for example). So basically matrix transformation needs to be applied only to position of circle, but not to outline of it.
Below is sample of a circle with radius 20px transformedPath, that is zoomed to 2x. Questions is how to keep radius of circle transformedPath fixed (radius = 20px), while applying the matrix transformation.
var transformedPath = new paper.Path.Circle(100,100,20);
transformedPath.strokeColor = 'black';
paper.project.activeLayer.matrix = new paper.Matrix(
2, 0,
0, 2,
0, 0
);
UPDATE. Here's a more general sketch (code below) that is based on solution suggested by sasensi. In this sample blue circle radius stays fixed (this is correct), but problem is that blue circle also stays on the same place instead.
The desired outcome is that both circles move to new position, but blue circle radius stays fixed.
// draw a normal circle
var normalCircle = new Path.Circle({
center: new Point(100,100),
radius: 50,
fillColor: 'orange',
});
// draw another circle that will have scale transformation reversed
var notScalingCircle = new Path.Circle({
center: new Point(100,100),
radius: 30,
fillColor: 'blue',
});
// draw instructions
new PointText({
content: 'press mouse button down to zoom in and see that blue circle size does not change',
point: view.center + [0, -80],
justification: 'center'
});
function transformLayer(matrix) {
// scale layer
// project.activeLayer.applyMatrix = false;
project.activeLayer.matrix = matrix;
// scale item with inverted amount to make it display like if it was not scaled with the layer
notScalingCircle.matrix = matrix.clone().invert();
}
var matrix = new paper.Matrix(
2,0,
0,1.5,
50,30
);
// on mouse down...
function onMouseDown() {
// ...scale up
transformLayer(matrix);
}
// on mouse up...
function onMouseUp() {
// ...scale down
transformLayer(matrix.clone().invert());
}
I think that the best way do that is, when you scale your layer with a given amount, to scale your circle with the inverted amount.
That will make your circle look like if it was not scaled.
Here is a sketch demonstrating the solution:
// draw a normal circle
var normalCircle = new Path.Circle({
center: view.center,
radius: 50,
fillColor: 'orange'
});
// draw another circle that will have scale transformation reversed
var notScalingCircle = new Path.Circle({
center: view.center,
radius: 30,
fillColor: 'blue'
});
// draw instructions
new PointText({
content: 'press mouse button down to zoom in and see that blue circle size does not change',
point: view.center + [0, -80],
justification: 'center'
});
function scaleLayer(amount) {
// scale layer
project.activeLayer.scale(amount, view.center);
// scale item with inverted amount to make it display like if it was not scaled with the layer
notScalingCircle.scale(1 / amount);
}
// on mouse down...
function onMouseDown() {
// ...scale up
scaleLayer(3);
}
// on mouse up...
function onMouseUp() {
// ...scale down
scaleLayer(1 / 3);
}
Edit
In response to the new example, you just have to invert the scaling transformation on the item and not all the matrix (which also include translation and rotation).
Here is the corrected sketch:
// draw a normal circle
var normalCircle = new Path.Circle({
center: new Point(100, 100),
radius: 50,
fillColor: 'orange'
});
// draw another circle that will have scale transformation reversed
var notScalingCircle = new Path.Circle({
center: new Point(100, 100),
radius: 30,
fillColor: 'blue'
});
// draw instructions
new PointText({
content: 'press mouse button down to zoom in and see that blue circle size does not change',
point: view.center + [0, -80],
justification: 'center'
});
function transformLayer(matrix) {
// scale layer
// project.activeLayer.applyMatrix = false;
project.activeLayer.matrix = matrix;
// just invert the scale and not all matrix
notScalingCircle.scale(1 / matrix.scaling.x, 1 / matrix.scaling.y);
}
var matrix = new paper.Matrix(
2, 0,
0, 1.5,
50, 30
);
// on mouse down...
function onMouseDown() {
// ...scale up
transformLayer(matrix);
}
// on mouse up...
function onMouseUp() {
// ...scale down
transformLayer(matrix.clone().invert());
}
I make map using Leaflet with one circle.
index code:
<div id="mapid" style="height: 500px;"></div>
<script type="text/javascript">
var mymap = L.map('mapid').setView([52.233333, 19.016667], 6);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap',
minZoom: 6,
}).addTo(mymap);
var x = 52.233333;
var y = 19.016667;
showCircle(x,y);
</script>
ShowCircle :
function showCircle(x,y)
{
var circle = L.circle([x,y], 1900, {
color: 'blue',
fillColor: '#f03',
fillOpacity: 0.5
}).addTo(mymap);
}
The problem is : the circle always have the same size.
I want to get: if i zoomout map the circle is bigger, when i zoomin the circle is smaller. (zoomin, zoomout is from scroll)
How to get this effect?
There are two kinds of circles in Leaflet: L.Circle and L.CircleMarker. L.Circle has a radius specified in meters, and L.CircleMarker has a radius specified in pixels.
Your question is not fully clear (what do you mean by "always have the same size"? Meters or pixels?); but I guess that you want to use L.CircleMarker instead of L.Circle.
Try the following , and tweak it as per your requirement :
var radiusQuantifier=100;
map.on('zoomend',function (e) {
circle.setRadius(map.getZoom()*radiusQuantifier);
});
This will change the radius of the circle on zoomend event.You can combine it with zoomstart event to get the desired result.
Note : Increase/Decrease the value of radiusQuantifier as it seems fit.
On Leaflet I can create a new circle easily given the centre and the radius:
// Circle
var radius = 500; // [metres]
var circleLocation = new L.LatLng(centreLat, centreLon);
var circleOptions = {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5
};
var circle = new L.Circle(circleLocation, radius, circleOptions);
map.addLayer(circle);
The circle above is created and drawn without problems, so it is all.
However, if I wanted now to create and draw a rectangle that which bounds the circle, it does not work. Here is what I did:
// Rectangle
var halfside = radius; // It was 500 metres as reported above
// convert from latlng to a point (<-- I think the problem is here!)
var centre_point = map.latLngToContainerPoint([newCentreLat, newCentreLon]);
// Compute SouthWest and NorthEast points
var sw_point = L.point([centre_point.x - halfside, centre_point.y - halfside]);
var ne_point = L.point([centre_point.x + halfside, centre_point.y + halfside]);
// Convert the obtained points to latlng
var sw_LatLng = map.containerPointToLatLng(sw_point);
var ne_LatLng = map.containerPointToLatLng(ne_point);
// Create bound
var bounds = [sw_LatLng, ne_LatLng];
var rectangleOptions = {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5
};
var rectangle = L.rectangle(bounds, rectangleOptions);
map.addLayer(rectangle);
The size of the rectangle that I obtain has nothing to do with 500 metres. Also, it looks like the size of the rectangle depends on the zoom level the map is. None of these problems arose for the circle.
I suspect the way I transform the latitude/longitude to point and viceversa is wrong.
Just use the getBounds method that L.Circle inherits from L.Path:
Returns the LatLngBounds of the path.
http://leafletjs.com/reference.html#path-getbounds
var circle = new L.Circle([0,0], 500).addTo(map);
var rectangle = new L.Rectangle(circle.getBounds()).addTo(map);
Working example on Plunker: http://plnkr.co/edit/n55xLOIohNMY6sVA3GLT?p=preview
I was getting "Cannot read property 'layerPointToLatLng' of undefined" error, So I made some changes to iH8's answer.
var grp=L.featureGroup().addTo(map);
var circle=L.circle([0,0],{radius:<circle radius>}).addTo(grp);
L.rectangle(circle.getBounds()).addTo(this.bufferMap);
map.removeLayer(grp);
I am working on an application using Openlayers3. On the map there are a couple of line segments and text labels. Each line has a color and an associated label.
For the map, I would like to have the text label anchored at a point of a line segment that is drawn on the map. So if I move the map or zoom in or out, that the label sticks to the point. However, if I zoom in or out the labels move (a lot). Dragging the map does not have this effect. Somehow I would like them to stick at a point on the line rather than move around.
Does anyone has some clever advice or links where to look? Googling for terms like 'anchor' or 'fixed point' and trying some of the recommendations did not solve the issue for me. Any help would be very much appreciated!
maybe you can be inspered by the "arrow" example wich use a style function that use geometry segments:
http://jsfiddle.net/davidhequet/7asg74Lc/
var styleFunction = function(feature, resolution) {
var geometry = feature.getGeometry();
var styles = [
// linestring
new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
})
})
];
geometry.forEachSegment(function(start, end) {
var dx = end[0] - start[0];
var dy = end[1] - start[1];
var rotation = Math.atan2(dy, dx);
// arrows
styles.push(new ol.style.Style({
geometry: new ol.geom.Point(end),
text: new ol.style.Text({
textAlign: 'left',
textBaseline: 'bottom',
font: 'Arial',
text: 'test text',
fill: new ol.style.Fill({color: 'red'}),
stroke: new ol.style.Stroke({color: 'white', width: '2'}),
offsetX: 0,
offsetY: 0,
rotation: 0
})
}));
});
return styles;
};
Does anyone have any examples or source for letting users draw curved maps from point a to point b?
Thanks,
Alex
You can draw Bezier curves this way:
var GmapsCubicBezier = function(lat1, long1, lat2, long2, lat3, long3, lat4, long4, resolution, map){
var points = [];
for(it = 0; it <= 1; it += resolution) {
points.push(this.getBezier({x:lat1, y:long1},{x:lat2, y:long2},{x:lat3, y:long3},{x:lat4, y:long4}, it));
}
for(var i = 0; i < points.length - 1; i++) {
var Line = new google.maps.Polyline({
path: [new google.maps.LatLng(points[i].x, points[i].y), new google.maps.LatLng(points[i+1].x, points[i+1].y)],
geodesic: true,
strokeOpacity: 0,
strokeColor: 'yellow',
icons: [{
icon: {
path: 'M 0,-2 0,2',
strokeColor: 'violet',
strokeOpacity: 1,
strokeWeight: 4
},
repeat: '36px'
},{
icon: {
path: 'M -1,-2 -1,2',
strokeColor: 'black',
strokeOpacity: 1,
strokeWeight: 2
},
repeat: '36px'
}]
});
Line.setMap(map);
}
};
GmapsCubicBezier.prototype = {
B1 : function (t) { return t*t*t; },
B2 : function (t) { return 3*t*t*(1-t); },
B3 : function (t) { return 3*t*(1-t)*(1-t); },
B4 : function (t) { return (1-t)*(1-t)*(1-t); },
getBezier : function (C1,C2,C3,C4, percent) {
var pos = {};
pos.x = C1.x*this.B1(percent) + C2.x*this.B2(percent) + C3.x*this.B3(percent) + C4.x*this.B4(percent);
pos.y = C1.y*this.B1(percent) + C2.y*this.B2(percent) + C3.y*this.B3(percent) + C4.y*this.B4(percent);
return pos;
}
};
You can modify the code, to provide differents strategies to draw the lines. The one implemented is pointed with "shadow".
The usage is pretty easy:
var curvedLine = new GmapsCubicBezier(initLat, initLong, control1Lat, control1Long, control2Lat, control2Long, endLat, endLong, 0.1, map);
you might have to use some sort of layer on top of google map. I know there's a cloud app that allows you to scrabble on a google map, but it uses flash to embed the google map scribblemaps.com/… i don't think it's possible to use two points to create a curve perhaps more than two points.
If i understand your application correctly, based on your website, the goal that you wish to achieve is to let users to "blaze a trail"? If that is the case maybe you can create a form where the users can submit Lat Lng coordinates of the "trials" that they've "blazed," and then use Polyline to draw the curve line similar to this google map draw curved line.
However, if users just want to know how to hike from point a to point b and etc, then you can use DirectionService and DirectionRenderer, and set the DirectionsTravelMode to google.maps.DirectionsTravelMode.WALKING and render the direction on the map that way so the user would know how to hike a route with directions drawn on the map + actual direction instructions.