Random direction en 2D lua - random

I want to create a random direction for my sprite, in Lua 2D.
So, i've tried that :
Sprite.x = Sprite.x + vx
Sprite.y = Sprite.y + vy
Sprite.vx = math.random(-1,1)
Sprite.vy = math.random(-1,1)
So, i managed to create a random direction, but my problem is the speed of the sprite, is directly linked to the number of direction. For example if i want the speed to be 1, it can only have 4 direction. I made a sprite with a lot more, by setting the random speed between -3 and 3, but then it's faster than what i want.
What should i do?
I've seen a few posts talking about random direction, but the description wasn't about lua and i couldn't really understand it..
Thanks!

If I am understanding the problem correctly, you want to choose random directions for the velocity, but you don't want the speed to change. To do this you can choose random velocity components for the x- and y-directions, and then normalize this to a unit vector by dividing each component by the magnitude of the vector.
Also, math.random(-1, 1) will only give value of -1, 0, or 1. If you want more variety in the directions, use math.random() to get floating point values in the range [0, 1). You can randomly choose to make the components negative to get a full spectrum of directions.
Here is a little function that returns a pair of vx and vy velocity components:
function rand_v_dir ()
vx = math.random()
vy = math.random()
norm = math.sqrt(vx * vx + vy * vy)
vx = vx / norm
vy = vy / norm
if math.random(0, 1) == 0 then
vx = -vx
end
if math.random(0, 1) == 0 then
vy = -vy
end
return vx, vy
end
Here are ten random velocity vectors generated by the above function:
> for i = 1, 10 do
vx, vy = rand_v_dir()
print("Velocity: ", vx, vy)
print("Speed: ", math.sqrt(vx * vx + vy * vy))
end
Velocity: -0.70784982398251 0.70636295676368
Speed: 1.0
Velocity: -0.28169296961382 -0.95950459658625
Speed: 1.0
Velocity: 0.71839382297246 -0.69563662577168
Speed: 1.0
Velocity: 0.29007205509751 0.9570048081653
Speed: 1.0
Velocity: -0.40540707321421 0.91413626171807
Speed: 1.0
Velocity: -0.7236198731718 0.69019872439091
Speed: 1.0
Velocity: 0.31888322750977 0.94779401096069
Speed: 1.0
Velocity: -0.64427423170525 0.76479455696325
Speed: 1.0
Velocity: -0.66481241135881 0.74701034644996
Speed: 1.0
Velocity: -0.65843036923729 0.75264164704463
Speed: 1.0
We can do better than this, though. This approach gives directions that are biased towards the corners, as pointed out by #JoelCornett and #nobody in the comments. One improvement would be to select a random angle between 0 and 2π, and to take the velocity vector to be a unit vector. Then the cosine of the angle will be the velocity component in the x-direction, and the sine of the angle will be the component in the y-direction (measuring the angle with respect to the positive x-axis).
This approach also has the benefit of being simpler to code:
function rand_polar_dir ()
dir = 2 * math.pi * (math.random())
vx = math.cos(dir)
vy = math.sin(dir)
return vx, vy
end
Here are ten random velocity vectors generated with the second approach:
> for i = 1, 10 do
vx, vy = rand_polar_dir()
print("Velocity: ", vx, vy)
print("Speed: ", math.sqrt(vx * vx + vy * vy))
end
Velocity: 0.093304068605003 -0.99563766038743
Speed: 1.0
Velocity: -0.31453683190827 -0.9492452693446
Speed: 1.0
Velocity: 0.72403297094833 0.68976536371416
Speed: 1.0
Velocity: -0.39261186353618 -0.91970425931962
Speed: 1.0
Velocity: -0.74523744965918 0.66679917788303
Speed: 1.0
Velocity: 0.15192428057379 -0.98839213522374
Speed: 1.0
Velocity: 0.93666276755405 -0.35023257969239
Speed: 1.0
Velocity: 0.86478573695856 -0.50214104507902
Speed: 1.0
Velocity: 0.64665884247741 -0.7627793530542
Speed: 1.0
Velocity: 0.2877390096936 0.95770886092828
Speed: 1.0
For both of the above approaches, the magnitude of the velocity vector is 1. If you want to double the speed, just multiply the random vector by 2.

Related

using spherical coordinates in opengl

I am trying to plot points around a center point using spherical coordinates. I know this is by far not the most efficient way to plot a sphere in OpenGL but i want to do it as an excersive to understand spherical coordinates better.
I want to step through each point by a certain angle so for this i have a nested for loop itterating through theta 0 - 360 and phi 0-360 and i am attempting to get the Cartesian coordinates of each of these steps and display it as a single point.
so far i have this:
float r = 1.0;
for( float theta = 0.0; theta < 360.0; theta += 10.0){
for(float phi = 0.0; phi < 360.0; phi += 10.0){
float x = r * sin(theta) * cos(phi);
float y = r * sin(theta) * sin(phi);
float z = r * cos(theta);
}
}
i store these points a display them. the display function works fine as i have used it to display other point structure before but for some reason i can't get this to work.
I have also tried converting the angles from degrees to radians:
float rTheta = theta * M_PI * 180.0;
float rPhi = phi * M_PI * 18.0;
as sin() and cos() both use radians but it yields the same results.
Am i doing something wrong and badly misunderstanding something?
In the conversion from degrees to radians of angle x, the correct formula is x * M_PI / 180..

How to build my funny timeline?

Building my responsive website, I would like to build my funny timeline, but I cannot come up with a solution.
It would be a sprite such as a rocket or flying saucer taking off at the bottom of middle of the page and coming out with smoke.
Smoke would remain more or less and disclose my timeline.
Sketch
Is anyone does have an idea how to make that possible?
To simulate smoke, you have to use a particle system.
As you maybe know, WebGL is able to draw triangles, lines and points.
This last one is what we need. The smoke is made of hundreds of semi-transparent white disks of slighly different sizes. Each point is defined by 7 attributes :
x, y: starting position.
vx, vy: direction.
radius: maximal radius.
life: number of milliseconds before it disappears.
delay: Number of milliseconds to wait before its birth.
One trick is to create points along a vertical centered axis. The more you go up, the more the delay increases. The other trick is to make the point more more transparent as it reaches it end of live.
Here is how you create such vertices :
function createVertices() {
var x, y, vx, vy, radius, life, delay;
var vertices = [];
for( delay=0; delay<1; delay+=0.01 ) {
for( var loops=0; loops<5; loops++ ) {
// Going left.
x = rnd(0.01);
y = (2.2 * delay - 1) + rnd(-0.01, 0.01);
vx = -rnd(0, 1.5) * 0.0001;
vy = -rnd(0.001);
radius = rnd(0.1, 0.25) / 1000;
life = rnd(2000, 5000);
vertices.push( x, y, vx, vy, radius, life, delay );
// Going right.
x = -rnd(0.01);
y = (2.2 * delay - 1) + rnd(-0.01, 0.01);
vx = rnd(0, 1.5) * 0.0001;
vy = -rnd(0.001);
radius = rnd(0.1, 0.25) / 1000;
life = rnd(2000, 5000);
vertices.push( x, y, vx, vy, radius, life, delay );
}
}
var buff = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, buff );
gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW );
return Math.floor( vertices.length / 7 );
}
As you can see, I created points going right and points going left to get a growing fuzzy triangle.
Then you need a vertex shader controling the position and size of the points.
WebGL provide the output variable gl_PointSize which is the size (in pixels) of the square to draw for the current point.
uniform float uniWidth;
uniform float uniHeight;
uniform float uniTime;
attribute vec2 attCoords;
attribute vec2 attDirection;
attribute float attRadius;
attribute float attLife;
attribute float attDelay;
varying float varAlpha;
const float PERIOD = 10000.0;
const float TRAVEL_TIME = 2000.0;
void main() {
float time = mod( uniTime, PERIOD );
time -= TRAVEL_TIME * attDelay;
if( time < 0.0 || time > attLife) return;
vec2 pos = attCoords + time * attDirection;
gl_Position = vec4( pos.xy, 0, 1 );
gl_PointSize = time * attRadius * min(uniWidth, uniHeight);
varAlpha = 1.0 - (time / attLife);
}
Finally, the fragment shader will display a point in white. but the more you go far from the center, the more transparent the fragments become.
To know where you are in the square drawn for the current point, you can read the global WebGL variable gl_PointCoord.
precision mediump float;
varying float varAlpha;
void main() {
float x = gl_PointCoord.x - 0.5;
float y = gl_PointCoord.y - 0.5;
float radius = x * x + y * y;
if( radius > 0.25 ) discard;
float alpha = varAlpha * 0.8 * (0.25 - radius);
gl_FragColor = vec4(1, 1, 1, alpha);
}
Here is a live example : https://jsfiddle.net/m1a9qry6/1/

How to calculate the trajectory of an object with an initial velocity so that it stops at a given point

The subject comes from an old challenge on codingame.com.
The play area was a rectangle of 10000 x 8000 units.
I have an object with a position (objectX, objectY) and a velocity vector (speedX, speedY).
I have an object with a position (objectX, objectY) and a velocity vector (speedX, speedY).
To move this object, I have to display the coordinates (thrustX, thrustY) of the thrust destination followed by a thrust value (ranging from -100 to 100).
Friction: Each steps (ticks), previous speed vector is multiplied by 0.9 before applying thrust
I want to move and stop this objet at a point with coordinates targetX, targetY (with a given error rate).
How to calculate the list of targetX, targetY and thrustValue ?
Following example use these data:
initial objectX and objectY = 1000, 2500
initial speedX and speedY = -500, 1000
targetX, targetY = 8000, 3000
thrustX, thrustX = targetX, targetY
This table use these formulas:
objectX(step) = objectX(step-1) + speedX(step)
objectY(step) = objectY(step-1) + speedY(step)
speedX(step) = speedX(step-1)*0.9 + thrustX(step-1)
speedY(step) = speedY(step-1)*0.9 + thrustY(step-1)
angle(step) = degrees(atan2(targetX(step) - objectX(step); targetY(step) - objectY(step)))
thrustX(step) = cos(radians(angle(step))) * thrust(step)
thrustY(step) = sin(radians(angle(step))) * thrust(step)
I want to find the algorithm that would make me get directly to the target rather than turn around

Limit top speed of an object tracked by x and y when moving in a rotation-based direction

Let's imagine I have some character that can rotate in 360 degrees, and I am tracking its position as x and y.
I am using sin and cos to determine its movement:
x += speed * cos(rotation)
y += speed * sin(rotation)
This works fine, but I figure I want an acceleration based system instead. So rather than increasing speed, I increase acceleration which then increases speed:
x_velocity += speed * cos(rotation)
y_velocity += speed * sin(rotation)
x += x_velocity
y += y_velocity
However, I don't want this character to be able to accelerate indefinitely and therefore I want to limit its top speed. Now, I could do this:
if x_velocity > maxspeed then x_velocity = maxspeed
if y_velocity > maxspeed then y_velocity = maxspeed
but this is imperfect, as it means you can travel 44% faster if you move at a perfect diagonal than if you travel in a cardinal direction.
So I use the pythagorean theorem, but I immediately run into a problem.
if sqrt(x_velocity^2 + y_velocity^2) > maxspeed then ???
Is there a solution? I cannot simply define it equal to maxspeed like before, but I also cannot completely allocate all the velocity to one axis, since that would change the direction. How do I determine the velocity to limit it at?
Just use overall velocity
velocity = Min(max_velocity, velocity + speed) //really acceleration instead of speed
x_velocity = velocity * cos(rotation)
y_velocity = velocity * sin(rotation)
x += x_velocity
y += y_velocity
If you have to maintain x_velocity and y_velocity (by some strange reason), then you can limit overall velocity through it's components with direction preserving:
... update x_velocity, y_velocity
vel = sqrt(x_velocity^2 + y_velocity^2)
if vel > max_velocity then
x_velocity = x_velocity * max_velocity / vel
y_velocity = y_velocity * max_velocity / vel
DRAG
You want to add drag (friction) that will set a max speed (like freefall drag creates a terminal velocity)
To define movement
acceleration = 2.0; // the constant acceleration applied
vx = 0.0; // velocity x
vy = 0.0; // velocity y
x = 0.0; // current position
y = 0.0;
direction = 0.0; // direction of acceleration
drag = 0.01; // drag as a fraction of speed
To apply acceleration
vx += cos(direction) * acceleration ;
vy += sin(direction) * acceleration ;
To apply drag
vx *= 1 - drag;
vy *= 1 - drag;
To get current speed
speed = sqrt(vx * vx + vy * vy);
Calculate drag for max speed.
If you want to set the max speed in terms of drag.
maxSpeed = 100.0;
drag = accel / (maxSpeed + accel);
The just apply acceleration and drag (in that order) to the velocity and the character will never go above maxSpeed
An important note is that if the character changes direction when near maxSpeed there will be a drop in speed related to the amount of change in velocity. EG if direction changes 180 then the character will slow down at an amount equal to accel + speed * drag (drag is helping the deacceleration) until the velocity starts to increase again at which point acceleration is accel - speed * drag
The final solution to set a max speed in terms of drag,
acceleration = 2.0; // the constant acceleration applied
vx = 0.0; // velocity x
vy = 0.0; // velocity y
x = 0.0; // current position
y = 0.0;
direction = 0.0; // direction of acceleration
maxSpeed = 100.0;
// set drag to give a maxSpeed
drag = acceleration / (maxSpeed + acceleration);
The apply acceleration and drag as follows
vx += cos(direction) * acceleration ;
vy += sin(direction) * acceleration ;
vx *= 1 - drag;
vy *= 1 - drag;
x += vx;
y += vy;
Speed will never go over maxSpeed. But also speed will never reach max speed, it will just keep on getting closer, but never quite getting there, though we are talking insignificant fractions of a unit 0.00000000001 pixels per frame

Calculating new longitude, latitude from old + n meters

I want to create 2 new longitude and 2 new latitudes based on a coordinate and a distance in meters, I want to create a nice bounding box around a certain point. It is for a part of a city and max ±1500 meters. I therefore don't think the curvature of earth has to be taken into account.
So I have 50.0452345 (x) and 4.3242234 (y) and I want to know x + 500 meters, x - 500 meters, y - 500 meters, y + 500 meters
I found many algorithms but almost all seem to deal with the distance between points.
The number of kilometers per degree of longitude is approximately
(pi/180) * r_earth * cos(theta*pi/180)
where theta is the latitude in degrees and r_earth is approximately 6378 km.
The number of kilometers per degree of latitude is approximately the same at all locations, approx
(pi/180) * r_earth = 111 km / degree
So you can do:
new_latitude = latitude + (dy / r_earth) * (180 / pi);
new_longitude = longitude + (dx / r_earth) * (180 / pi) / cos(latitude * pi/180);
As long as dx and dy are small compared to the radius of the earth and you don't get too close to the poles.
The accepted answer is perfectly right and works. I made some tweaks and turned into this:
double meters = 50;
// number of km per degree = ~111km (111.32 in google maps, but range varies
// between 110.567km at the equator and 111.699km at the poles)
//
// 111.32km = 111320.0m (".0" is used to make sure the result of division is
// double even if the "meters" variable can't be explicitly declared as double)
double coef = meters / 111320.0;
double new_lat = my_lat + coef;
// pi / 180 ~= 0.01745
double new_long = my_long + coef / Math.cos(my_lat * 0.01745);
Hope this helps too.
For latitude do:
var earth = 6378.137, //radius of the earth in kilometer
pi = Math.PI,
m = (1 / ((2 * pi / 360) * earth)) / 1000; //1 meter in degree
var new_latitude = latitude + (your_meters * m);
For longitude do:
var earth = 6378.137, //radius of the earth in kilometer
pi = Math.PI,
cos = Math.cos,
m = (1 / ((2 * pi / 360) * earth)) / 1000; //1 meter in degree
var new_longitude = longitude + (your_meters * m) / cos(latitude * (pi / 180));
The variable your_meters can contain a positive or a negative value.
I had to spend about two hours to work out the solution by #nibot , I simply needed a method to create a boundary box given its center point and width/height (or radius) in kilometers:
I don't fully understand the solution mathematically/ geographically.
I tweaked the solution (by trial and error) to get the four coordinates. Distances in km, given the current position and distance we shift to the new position in the four coordinates:
North:
private static Position ToNorthPosition(Position center, double northDistance)
{
double r_earth = 6378;
var pi = Math.PI;
var new_latitude = center.Lat + (northDistance / r_earth) * (180 / pi);
return new Position(new_latitude, center.Long);
}
East:
private static Position ToEastPosition(Position center, double eastDistance)
{
double r_earth = 6378;
var pi = Math.PI;
var new_longitude = center.Long + (eastDistance / r_earth) * (180 / pi) / Math.Cos(center.Lat * pi / 180);
return new Position(center.Lat, new_longitude);
}
South:
private static Position ToSouthPosition(Position center, double southDistance)
{
double r_earth = 6378;
var pi = Math.PI;
var new_latitude = center.Lat - (southDistance / r_earth) * (180 / pi);
return new Position(new_latitude, center.Long);
}
West:
private static Position ToWestPosition(Position center, double westDistance)
{
double r_earth = 6378;
var pi = Math.PI;
var new_longitude = center.Long - (westDistance / r_earth) * (180 / pi) / Math.Cos(center.Lat * pi / 180);
return new Position(center.Lat, new_longitude);
}
Have you checked out: How do I find the lat/long that is x km north of a given lat/long ?
These calculations are annoying at best, I've done many of them. The haversine formula will be your friend.
Some reference: http://www.movable-type.co.uk/scripts/latlong.html
Posting this method for sake of completeness.
Use this method "as it is" to:
Move any (lat,long) point by given meters in either axis.
Python method to move any point by defined meters.
def translate_latlong(lat,long,lat_translation_meters,long_translation_meters):
''' method to move any lat,long point by provided meters in lat and long direction.
params :
lat,long: lattitude and longitude in degrees as decimal values, e.g. 37.43609517497065, -122.17226450150885
lat_translation_meters: movement of point in meters in lattitude direction.
positive value: up move, negative value: down move
long_translation_meters: movement of point in meters in longitude direction.
positive value: left move, negative value: right move
'''
earth_radius = 6378.137
#Calculate top, which is lat_translation_meters above
m_lat = (1 / ((2 * math.pi / 360) * earth_radius)) / 1000;
lat_new = lat + (lat_translation_meters * m_lat)
#Calculate right, which is long_translation_meters right
m_long = (1 / ((2 * math.pi / 360) * earth_radius)) / 1000; # 1 meter in degree
long_new = long + (long_translation_meters * m_long) / math.cos(lat * (math.pi / 180));
return lat_new,long_new
Working Python code to offset coordinates by 10 metres.
def add_blur(lat, long):
meters = 10
blur_factor = meters * 0.000006279
new_lat = lat + blur_factor
new_long = long + blur_factor / math.cos(lat * 0.018)
return new_lat, new_long
if you don't have to be very exact then: each 10000 meters is about 0.1 for latitude and longitude.
for example I want to load locations 3000 meters around point_A from my database:
double newMeter = 3000 * 0.1 / 10000;
double lat1 = point_A.latitude - newMeter;
double lat2 = point_A.latitude + newMeter;
double lon1 = point_A.longitude - newMeter;
double lon1 = point_A.longitude + newMeter;
Cursor c = mDb.rawQuery("select * from TABLE1 where lat >= " + lat1 + " and lat <= " + lat2 + " and lon >= " + lon1 + " and lon <= " + lon2 + " order by id", null);
public double MeterToDegree(double meters, double latitude)
{
return meters / (111.32 * 1000 * Math.Cos(latitude * (Math.PI / 180)));
}
var meters = 50;
var coef = meters * 0.0000089;
var new_lat = map.getCenter().lat.apply() + coef;
var new_long = map.getCenter().lng.apply() + coef / Math.cos(new_lat * 0.018);
map.setCenter({lat:new_lat, lng:new_long});
See from Official Google Maps Documentation (link below) as they solve on easy/simple maps the problems with distance by countries :)
I recommended this solution to easy/simply solve issue with boundaries that you can know which area you're solving the problem with boundaries (not recommended globally)
Note:
Latitude lines run west-east and mark the position south-north of a point. Lines of latitude are called parallels and in total there are 180 degrees of latitude. The distance between each degree of latitude is about 69 miles (110 kilometers).
The distance between longitudes narrows the further away from the equator. The distance between longitudes at the equator is the same as latitude, roughly 69 miles (110 kilometers) . At 45 degrees north or south, the distance between is about 49 miles (79 kilometers). The distance between longitudes reaches zero at the poles as the lines of meridian converge at that point.
Original source 1
Original source 2
Official Google Maps Documentation: Code Example: Autocomplete Restricted to Multiple Countries
See the part of their code how they solve problem with distance center + 10 kilometers by +/- 0.1 degree
function initMap(): void {
const map = new google.maps.Map(
document.getElementById("map") as HTMLElement,
{
center: { lat: 50.064192, lng: -130.605469 },
zoom: 3,
}
);
const card = document.getElementById("pac-card") as HTMLElement;
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);
const center = { lat: 50.064192, lng: -130.605469 };
// Create a bounding box with sides ~10km away from the center point
const defaultBounds = {
north: center.lat + 0.1,
south: center.lat - 0.1,
east: center.lng + 0.1,
west: center.lng - 0.1,
};
const input = document.getElementById("pac-input") as HTMLInputElement;
const options = {
bounds: defaultBounds,
componentRestrictions: { country: "us" },
fields: ["address_components", "geometry", "icon", "name"],
origin: center,
strictBounds: false,
types: ["establishment"],
};
This is what I did in VBA that seems to be working for me. Calculation is in feet not meters though
Public Function CalcLong(OrigLong As Double, OrigLat As Double, DirLong As String, DirLat As String, DistLong As Double, DistLat As Double)
Dim FT As Double
Dim NewLong, NewLat As Double
FT = 1 / ((2 * WorksheetFunction.Pi / 360) * 20902230.971129)
If DirLong = "W" Then
NewLat = CalcLat(OrigLong, OrigLat, DirLong, DirLat, DistLong, DistLat)
NewLong = OrigLong - ((FT * DistLong) / Cos(NewLat * (WorksheetFunction.Pi / 180)))
CalcLong = NewLong
Else
NewLong = OrigLong + ((FT * DistLong) / Math.Cos(CalcLat(OrigLong, OrigLat, DirLong, DirLat, DistLong, DistLat) * (WorksheetFunction.Pi / 180)))
CalcLong = NewLong
End If
End Function
Public Function CalcLat(OrigLong As Double, OrigLat As Double, DirLong As String, DirLat As String, DistLong As Double, DistLat As Double) As Double
Dim FT As Double
Dim NewLat As Double
FT = 1 / ((2 * WorksheetFunction.Pi / 360) * 20902230.971129)
If DirLat = "S" Then
NewLat = (OrigLat - (FT * DistLat))
CalcLat = NewLat
Else
NewLat = (OrigLat + (FT * DistLat))
CalcLat = NewLat
End If
End Function
Original poster said:
"So I have 50.0452345 (x) and 4.3242234 (y) and I want to know x + 500 meters..."
I will assume the units of the x and y values he gave there were in meters (and not degrees Longitude, Latitude). If so then he is stating measurements to 0.1 micrometer, so I will assume he needs similar accuracy for the translated output. I also will assume by "+500 meters" etc. he meant
the direction to be due North-South and due East-West.
He refers to a reference point:
"2 new latitudes based on a coordinate";
but he did not give the Longitude and Latitude,
so to explain the procedure concretely I will give
the Latitudes and Longitudes for the corners of the
500 meter box he requested around the point
[30 degrees Longitude,30 degrees Latitude].
The exact solution on the surface of the GRS80 Ellipsoid is
given with the following set of functions
(I wrote these for the free-open-source-mac-pc math program called "PARI"
which allows any number of digits precision to be setup):
\\=======Arc lengths along Latitude and Longitude and the respective scales:
dms(u)=[truncate(u),truncate((u-truncate(u))*60),((u-truncate(u))*60-truncate((u-truncate(u))*60))*60];
SpinEarthRadiansPerSec=7.292115e-5;\
GMearth=3986005e8;\
J2earth=108263e-8;\
re=6378137;\
ecc=solve(ecc=.0001,.9999,eccp=ecc/sqrt(1-ecc^2);qecc=(1+3/eccp^2)*atan(eccp)-3/eccp;ecc^2-(3*J2earth+4/15*SpinEarthRadiansPerSec^2*re^3/GMearth*ecc^3/qecc));\
e2=ecc^2;\
b2=1-e2;\
b=sqrt(b2);\
fl=1-b;\
rfl=1/fl;\
U0=GMearth/ecc/re*atan(eccp)+1/3*SpinEarthRadiansPerSec^2*re^2;\
HeightAboveEllipsoid=0;\
reh=re+HeightAboveEllipsoid;\
longscale(lat)=reh*Pi/648000/sqrt(1+b2*(tan(lat))^2);
latscale(lat)=reh*b*Pi/648000/(1-e2*(sin(lat))^2)^(3/2);
longarc(lat,long1,long2)=longscale(lat)*648000/Pi*(long2-long1);
latarc(lat1,lat2)=(intnum(th=lat1,lat2,sqrt(1-e2*(sin(th))^2))+e2/2*sin(2*lat1)/sqrt(1-e2*(sin(lat1))^2)-e2/2*sin(2*lat2)/sqrt(1-e2*(sin(lat2))^2))*reh;
\\=======
I then plugged the reference point [30,30]
into those functions at the PARI command prompt
and had PARI solve for the point +/- 500 meters away
from it, giving the two new Longitudes and
two new Latitudes that the original poster asked for.
Here is the input and output showing that:
? dms(solve(x=29,31,longarc(30*Pi/180,30*Pi/180,x*Pi/180)+500))
cpu time = 1 ms, real time = 1 ms.
%1172 = [29, 59, 41.3444979398934670450280297216509190843055]
? dms(solve(x=29,31,longarc(30*Pi/180,30*Pi/180,x*Pi/180)-500))
cpu time = 1 ms, real time = 1 ms.
%1173 = [30, 0, 18.6555020601065329549719702783490809156945]
? dms(solve(x=29,31,latarc(30*Pi/180,x*Pi/180)+500))
cpu time = 1,357 ms, real time = 1,358 ms.
%1174 = [29, 59, 43.7621925447500548285775757329518579545513]
? dms(solve(x=29,31,latarc(30*Pi/180,x*Pi/180)-500))
cpu time = 1,365 ms, real time = 1,368 ms.
%1175 = [30, 0, 16.2377963202802863245716034907838199823349]
?

Resources