I have (lat, lon) for the center of a circle.
I have a radius R in km.
My code
for (var i = 0; i < steps; i++) {
let degrees = (i/steps)*360
let radians = (Math.PI/180)*degrees
let x = lat + radius * Math.cos(radians)
let y = lon + radius * Math.sin(radians)
coordinates.push([x,y])
}
returns an oval shape because of the latitude and variable radius is not in km, but in coordinates.
How can I adapt this code in order to generate a perfect circle?
For not very large circle radius you can correct longitude dimension using division by cos(latitude), because meridian/parallel ratio depends on this value.
Related
I need to position a dot on a coordinate system based on its bearing and radius.
Using the following code i can position a dot at the correct distance from the center, but this only works horizontally.
What i need is both top & left position of the dot based on bearing & radius
setTimeout(function() {
var km2show = 100;
var testDistance = 50;
var width = $('#radar').width(); // Width & height of radar
var center = width/2; // Radar center
var px2km = center/km2show; // Pixels per km
var radius = radius2coor((px2km*testDistance),center);
var bearing = 45;
// Set height of radar based on the width
$('#radar').height(width);
// Set dot in center of radar
$('#centerDot').css({top: center, left: center});
$('#container').append("<div style='position:absolute;top:0px;left:"+radius+"px;color:white;'>*</div>");
},100);
function radius2coor(radius,center) {
var res = radius-center;
return res;
}
Please see
jsFiddle
So how would i go about getting bot top and left position of the dot ?
The end result should position the dot at the red marker having a bearing of 45 degrees:
The main issue you were encountering was that the angle wasn't in radians so first thing we want is to convert the 45 degrees to pi/4.
Also, when going from regular angular coordinates to x,y coordinates you multiply the radius by sine of the angle to find y coordinate and you multiply the radius by the cosine of the angle to get the x coordinate. Just think about the unit circle and it will make sense.
var bearing = parseInt(prompt("enter angle in degrees", "0"));
if(!isNaN(bearing)){
setTimeout(function() {
var km2show = 100;
var testDistance = 50;
var width = $('#radar').width(); // Width & height of radar
var center = width/2; // Radar center
var px2km = center/km2show; // Pixels per k
//not sure what this is doing so I set a random radius
//(called it distanceFromCenter). If you need this to be
//the distance between two cartesian points then you can
//just implement the distance formula.
//var radius = radius2coor((px2km*testDistance),center);
var radius = 100;
var radianBearing = (bearing/180)*Math.PI
// Set height of radar based on the width
$('#radar').height(width);
// Set dot in center of radar
$('#centerDot').css({top: center, left: center});
//the main issue you were encountering was that the angle wasn't in radians so I converted it.
positionDot(radius, radianBearing);
},100);
}
function positionDot(distanceFromCenter, bearing, width)
{
//when going from regular angular coordinates to x,y coordinates you multiply the radius by sine of the angle to find y coordinate and you multiply the radius by the cosine of the angle to get the x coordinate.
$('#container').append("<div style='position:absolute;top:"+(-distanceFromCenter*Math.sin(bearing)).toString()+"px;left:"+distanceFromCenter*Math.cos(bearing)+"px;color:white;'>*</div>");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id='radar' style='width:100%;max-width:400px;height:400px;border:1px black solid;border-radius:400px;background-color:#3c3c3c;position:relative;'>
<div id='centerDot' style='position:absolute;color:white;'>
<div style='position:relative;' id='container'></div>
<b>*</b>
</div>
</div>
To get both coordinates, you need coordinates of center, radius and bearing.
Note that trigonometric functions usually work with argument in radians, not degrees (don't know about javascript math library)
P.X = Center.X + Radius * Math.Cos(bearing)
P.Y = Center.Y + Radius * Math.Sin(bearing)
You can get it with:
x = center + radius * cos(bearing)
y = center + radius * sin(bearing)
and as MBo said, you have to convert bearing into radians
rad = deg * PI / 180
https://upload.wikimedia.org/wikipedia/sr/8/85/Trig-funkcije1.gif
I am working on an application where I have the center of a circle and the radius and I am plotting the circle with the help of Leaflet.
I placed a marker on the north most end of the circumference and made it draggable.
var circle = L.circle(coords, radius).addTo(map);
convertRadiusToLatitude = parseInt(response.radius)/111111;
var coordsOnRadius = [parseFloat(response.lat) + convertRadiusToLatitude, parseFloat(response.long)];
var markerOnRadius = L.marker(coordsOnRadius, {draggable: true}).addTo(map);
Now, this adds the marker to the circumference and now I wanted it to be draggable only on the circumference itself for which I used the parametric equation.
Parametric equation
x = Xc + R * cos(theta)
y = Yc + R * sin(theta)
Code for dragging
markerOnRadius.on('drag', function(e){
bearing = marker.getLatLng().bearingTo(markerOnRadius.getLatLng());
var markerOnRadiusX = parseFloat(response.lat) + ((0.000009 * parseFloat(response.radius)) * Math.cos( toRad(bearing) ));
var markerOnRadiusY = parseFloat(response.long) + ((0.000009 * parseFloat(response.radius)) * Math.sin( toRad(bearing) ));
markerOnRadius.setLatLng([markerOnRadiusX, markerOnRadiusY]);
});
The bearingTo method:
L.LatLng.prototype.bearingTo = function(other) {
var d2r = L.LatLng.DEG_TO_RAD;
var r2d = L.LatLng.RAD_TO_DEG;
var lat1 = this.lat * d2r;
var lat2 = other.lat * d2r;
var dLon = (other.lng-this.lng) * d2r;
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
var brng = Math.atan2(y, x);
brng = parseInt( brng * r2d );
brng = (brng + 360) % 360;
return brng;
};
Issue
When I start dragging the marker, this code is working fine and brings it back to the circumference at the bearing at which the marker is dragged to. But there is one problem, the coords on the circumference are slightly off and in terms of longitude. When the bearing is 0 (north), the coords are perfect, but when it is 90 (east), the longitude is slightly less that it should for the marker to be at the circumference.
Again at 180 (south), coords are perfect, but at 270 (west), the longitude calculated is slightly less and the marker tends towards the radius again.
So basically if you visualize the marker being dragged, it starts perfectly on the north end and starts coming inside the circle slightly increasing with the bearing till it reacher 90 and then starts going towards the circumference again till 180 when it is perfect again.
It forms more like a ellipse if you get the gist of it.
Could anyone tell me why is longitude coming a little off and why the marker moves in an elliptical path. Has it something to do with the world coordinates and window coordinates. Or are my equations slightly off somewhere?
It does look like a projection issue. In your dragging code you are basically doing
lat = a + r cos(baring)
long = b + r sin(baring)
giving a circle in the Lat-Long coordinates. This would work fine if you were at the equator with Mercator projection. You will get more distortion as you move further towards the polls.
Assume you are using the defaults for Leaflet reference doc You have the EPSG3857 Web Mercator coordinates.
If you want to ensure you have a exact circle it will be better to work using screen coordinates. You can get these using methods on the ICRS objects. First get the coordinate system L.CRS.EPSG3857 and use the latLngToPoint and pointToLatLng methods.
var crs = L.CRS.EPSG3857;
var zoom = ...; // how you calculate your zoom factor
markerOnRadius.on('drag', function(e){
var markerLL = marker.getLatLng()
var morLL = markerOnRadius.getLatLng();
var markerP = crs.latLngToPoint(markerLL,zoom);
var morP = crs.latLngToPoint(morLL,zoom);
// get the distance between the two points
var dist = markerP.distanceTo(morP);
// Get the vector from center to point
var A = morP.subtract(markerP);
// scale so its of the desired length
var B = A. multiplyBy( factor / dist);
// Add on the center
var C = markerP.add(B);
// Convert back to LatLong
var D = crs.pointToLatLng(C,zoom);
markerOnRadius.setLatLong(D);
});
I need use mercator projection to point the places by latitude and logitude in my svg application.I have serached a lot and i got these links,
http://en.wikipedia.org/wiki/Mercator_projection
Covert latitude/longitude point to a pixels (x,y) on mercator projection
CODE
//this lat and long is for chicago
var latitude = 41.850033; // (φ)
var longitude = -87.65005229999997; // (λ)
var PI = 3.14;
var mapWidth = 750;
var mapHeight = 380;
// get x value
var x = (mapWidth * (180+longitude) / 360) % mapWidth + (mapWidth / 2);
// convert from degrees to radians
var latRad = latitude * PI / 180;
// get y value
var mercN = Math.log(Math.tan((PI / 4) + (latRad / 2)));
var y = (mapHeight / 2) - (mapWidth * mercN / (2 * PI));
I've used this code in my application, but it doesn't work for me.
Please help to get x and y position from the latitude and longitude.
Any Suggestions should be appreciated.
You forgot the top left and bottom right corner of the map and the factor to multiply the x,y coordinates to give the correct map projection. You can use a fixed map coordinate, i.e. a factor or you can compute the bounding box:Convert lat/lon to pixel coordinate? and then compute the world width and height that fits the map's width and height.
I have a lat/long coordinate point and I'm drawing a polygon (hexagon) around it on a Google map. Here's my code to calculate the hexagon coordinates:
for (var i = 0; i < 6; i++) {
x = lat + r * Math.sin(i * 2 * Math.PI / 6);
y = lng + r * Math.cos(i * 2 * Math.PI / 6);
}
This calculates all coordinates in a regular hexagon and I can draw it on the map without a problem if its center is near (0 lat, 0 long). The problem is when I want to draw it far from (0, 0) this gets into an elongated shape. I'm guessing it's because the earth is not flat and Google maps takes that into account. So I probably need to change the radius in my calculation to reflect this, has anyone any idea how it is done?
Examples of various regular polygons far from (0,0)
Is there a way to translate into javascript a piece of code that will allow me to show map pins around a point taking in consideration a radius ?
var data=[
{long:3,lat:2},
{long:5,lat:2},
{long:2,lat:3}
];
aCoord={long:1,lat:2};
for(var i=0;i<data.length;i++){
if (data[i] is 30 kms far from aCoord)
myMap.addPin(data[i]);
}
myMap.autozoom();
Thank you,
Regards
I came up with this example so you have an idea on how to calculate the points. You'll need to figure out how to do any necessary conversions for lat/lon.
/**
* Returns coordinates for N points around a circle with a given radius from
* the center.
*
* center: array [x, y]
* radius: int
* num_points: int
*/
function get_points_on_circle(center, radius, num_points) {
if (!num_points) num_points = 10;
var interval = Math.PI * 2 / num_points;
points = [];
i = -1;
while (++i < num_points) {
var theta = interval * i,
point = [Math.cos(theta) * radius + center[0], Math.sin(theta) * radius + center[1]];
points.push(point);
}
return points;
}
// Sample usage
var center = [250, 250],
radius = 100,
num_points = 10;
var points = get_points_on_circle(center, radius, num_points);
Test it out (uses Raphael for plotting)
If you are interested in learning a little about the logic:
A radian is a unit of measure for angles. There are a total of 2*PI radians in a circle. Using that fact, you can calculate the angle interval of any number of points on a circle by performing 2*PI/num_points.
When you know the angle interval, you can calculate the angle (theta) of a point on a circle. Once you have theta (the angle), you have polar coordinates (radius,angle). For that to be of any use to us in this problem, you need to convert the polar coordinates into Cartesian coordinates (x,y). You can do that by using the following formulas:
x = cos(theta) * radius
y = sin(theta) * radius
That's pretty much it in a nutshell.