The function http://help.arcgis.com/en/webapi/javascript/arcgis/jsapi/#namespace_geometry/esri.geometry.getLength should calculate distances between points.
When I am trying to calculate distance between points having 100 meters between them
p1=new esri.geometry.Point(3997030.6690969253, 7444299.320646087, new esri.SpatialReference({ wkid: 102113 }));
Object
p2=new esri.geometry.Point(3996951.455397143, 7444142.154020177, new esri.SpatialReference({ wkid: 102113 }));
Object
esri.geometry.getLength(p1, p2)
176.00045037719127
I am getting 176 which is wrong. Projection is Web Mercator (WKID 102113).
It looks like it's just calculating the simple euclidean map distance between the two points (3997030,7444299) and (3996951, 7444142).
a^2 + b^2 = c^2
where a = (3997031 - 3996951) and b = (7444299 - 7444142)
c = 176
So 176 is the map distance, what you want is the real world ground distance. You'll probably have to use a GeometryService to accomplish this, I don't think the Javascript can do it on it's own. Here's ESRI's sample of it: https://developers.arcgis.com/javascript/jssamples/util_distance.html
Related
I want to store a Javascript object as a polygon in a Mysql database.
I can define start and end points of x and y to give me four corners:
var polygon = [
xstart +' '+ ystart,
xend +' '+ ystart,
xend +' '+ yend,
xstart +' '+ yend,
xstart +' '+ ystart
];
I can format this object as a string
polygon = "ST_GeomFromText('POLYGON(("+ polygon.toString() +"))'";
When I insert this into a Mysql database
INSERT INTO `caption` (`caption_id`, `caption_area`) VALUES (NULL, '\'POLYGON((0.28 0.33,0.35 0.33,0.35 0.45,0.28 0.45,0.28 0.33))\'')
the query fails
#1416 - Cannot get geometry object from data you send to the GEOMETRY field
How can I format the Javascript object, or the query, to correctly insert a polygon in to a database?
in mysql you must use ST_GeomFromText
polygon = "ST_GeomFromText('POLYGON("+ polygon.toString() +")')";
I am unsure what you need the number 0 at the end.
POLYGON is a Spatial Data Type from MySQL spatial extension defined in the Open Geospatial Consortium OpenGIS.
You can define a Spatial Data Type in MySQL for your four polygon. The following is an example using LINESTRING:
LINESTRING(0.28540775806607094 0.3356063323928521, 0.35407728596306665 0.3356063323928521, 0.35407728596306665 0.45764498813705906, 0.28540775806607094 0.45764498813705906, 0.28540775806607094 0.3356063323928521)
So, it stores caption_area as TEXT using:
SET #g = 'LINESTRING(0.28540775806607094 0.3356063323928521, 0.35407728596306665 0.3356063323928521, 0.35407728596306665 0.45764498813705906, 0.28540775806607094 0.45764498813705906, 0.28540775806607094 0.3356063323928521)';
INTO `caption` (`caption_id`, `caption_area`) VALUES (NULL,ST_AsText(ST_GeomFromText(#g)));
Also, an example with POLYGON:
SET #g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))';
INTO `caption` (`caption_id`, `caption_area`)
VALUES (NULL,ST_AsText(ST_GeomFromText(#g)));
I am looking for a way to find the distance between two coordinates that have elevation data as well, but I want the solution to take under account the TERRAIN between the two points i.e the shortest way between them on the ground and not "as the crow flies".
I have found and used the Haversine formula for the distance "in the air" but obviously it will not yield the real distance that a man would walk on the ground as in between the two points there might be a slope that goes up and / or down. The larger the distance between the points the bigger the error margin.
I have sampled a real .gpx file and converted its data into JSON format. it looks like this:
let jsonSample = [{
"lat": "57.107297", // 0
"lon": "-5.334734",
"ele": "957.00"
}, // distance between 0 and 1 => 169.1849929515954 m (as the crow flies) elevation difference: 50.210000000000036
{
"lat": "57.106590", // 1
"lon": "-5.332253",
"ele": "1007.21"
}, // distance between 1 and 2 => 162.49601252670058 m (as the crow flies) elevation difference: 23.789999999999964
{
"lat": "57.105537", // 2 (summit)
"lon": "-5.330387",
"ele": "1031.00"
}, // distance between 2 and 3 => 32.45395539826568 m (as the crow flies) elevation difference: -13
{
"lat": "57.105284", // 3
"lon": "-5.330119",
"ele": "1018.00"
}];
Real distances should be longer than the ones calculated with Haversine formula. But how do I calculate it?
Googling "haversine formula elevation" found me this Math.SE question and answer.
Heeding the comments, so long as the distances you're measuring aren't too far apart, using the Pythagorean Theorem, you can add the elevation deltas in.
I'd use Pythagoras: let d the Haversine distance and dh the difference in altitudes, D=sqrt(d**2+dh**2).
Something like
function haversineWithAltitude(lat1, lon1, alt1, lat2, lon2, alt2) {
const groundDistanceInMeters = haversine(lat1, lon1, lat2, lon2);
const elevationDifferenceMeters = Math.abs(alt1 - alt2);
return Math.sqrt(groundDistanceInMeters * groundDistanceInMeters + elevationDifferenceInMeters * elevationDifferenceInMeters);
}
should thus work – but as said, this will inevitably become more inaccurate if the length between the points is very long. (At that point, I'd, not being a mathematician and not knowing better, segment the long leg and calculate each distance piecewise.)
I began with a set of coordinates, which I then approximated a function to represent them (Fourier series). The function produced is a sum of sin and cos waves:
0.3sin(2x) + 1.7(sin5x) + 1.8(sin43x)...
I would like to take this new function that I generated and produce a new set of coordinates. How can I generate points for every [INTEGER X Value] say from 0-400?
Note: I have 2 complex (2D) functions.
GOAL: Take a function --> Generate Points from this function for every whole integer.
This uses a function handle and (:) to force a column vector ((:).' forces a row vector).
The code simply uses the given equation (summing sines and cosines) to calculate a corresponding y coordinate for each given x coordinate.
% MATLAB R2018b
X = 0:400; % x = 0, 1, 2, ..., 400
fh = #(x) 0.3*sin(2*x) + 1.7*sin(5*x) + 1.8*sin(43*x);
Y = fh(X);
P = [X(:) Y(:)];
Note that size(P) returns 401 x 2. You'll see Y takes on whatever size X is, which is a row vector. X can be declared as as column vector with X = (0:400).' using .' which performs a transpose.
Recommend taking a look at MATLAB's documentation, specifically the Getting Started and Language Fundamentals.
Relevant MATLAB functions: sin, cos.
Matlab Code
X = 0:400;
fh = #(x) 0.3*sin(2*x) + 1.7*sin(5*x) + 1.8*sin(43*x);
Y = fh(X);
P = [X, Y]
So I got a 3d system and some coordinates:
Start coordinates (x, y, z) of a rocket (on the ground)
Target coordinates (x, y, z) of the rockets target (also on the ground)
I got some initialize values like:
maximum_velocityZ = 0.5
maximum_resVelocityXY = 0.3
gravity factor = 9.81
How can I calculate the flight velocitys (velocityX, velocityY and velocityZ) for every update frame?
let maximum_velocityZ = 0.5
let maximum_resVelocityXY = 0.3
let gravity_factor = 9.81
let rocketPosition = {
x: 3,
y: 0,
z: 2
}
let rocketTarget = {
x: 7,
y: 5,
z: 8
}
let rocketVelocity = {
x: 0,
y: 0,
z: 0
}
let update = function() {
rocketPosition.x += rocketVelocity.x
rocketPosition.y += rocketVelocity.y
rocketPosition.z += rocketVelocity.z
let distanceX = (rocketTarget.x - rocketPosition.x)
let distanceY = (rocketTarget.y - rocketPosition.y)
let distanceZ = (rocketTarget.z - rocketPosition.z)
let factorXY = Math.abs(distanceX / distanceY)
rocketVelocity.x = maximum_resVelocityXY / Math.sqrt((1 / factorXY ** 2) + 1) * (distanceX > 0 ? 1 : -1)
rocketVelocity.y = maximum_resVelocityXY / Math.sqrt((factorXY ** 2) + 1) * (distanceY > 0 ? 1 : -1)
rocketVelocity.z = maximum_velocityZ * distanceZ;
rocketVelocity.z /= gravity_factor;
console.log("x:", Math.round(rocketPosition.x), "y:", Math.round(rocketPosition.y), "z:", Math.round(rocketPosition.z))
}
setInterval(update, 300)
This code is what I've developed so far. I'm sure I'm on the right track. X and Y seem to be more or less right. Only the Velocity Z can't be calculated the way I tried. In 3D space the trajectory doesn't really look realistic. So by "not really" I mean "not realistic at all"...
I would be happy for help. Thanks and a happy new year - matching to the rocket - of course!
I do not know what is you coordinate system
plane
sphere
ellipsoid like WGS84
My guess is your ground is planar (induced from your constants however your positions suggest something else)... so I will stick with that for now... You got 2 problems:
Newton/D'Alembert physics
Yours is weird as you got no dt multiplication so it works only if your update is 1 Hz. take a look at this:
Can't flip direction of ball without messing up gravity
you do not need speed limiter as air friction will do it for you and you should drive with accelerations ... or Force if you want to account for mass changes too.
However as you are working with ground/ground then I assume atmospheric flight instead of Newtonian so in such case you need to handle the heading control not by acceleration but by turning the integrated velocity. The main thruster should still be handled as acceleration.
The collisions are not necessary in your case (unless your ground is not planar or have obstacles along the way).
Rocket guiding system
I suggest to use 3 state (Markovov model) rocket control.
launch
Rise the rocket to safe altitude first to avoid obstacles, conserve fuel and maximize speed
cruise
Travel to the target area (while still keep its altitude). Simply compute heading projected on the ground plane and apply correction to the heading of the rocket to match it (still going parallel to ground).
hit
Hit the target while descending. Almost the same as #2 but this time you need to change altitude too...
On top of these you can add strategies to avoid detection/destruction or obstacles etc ... You can also make a fake approach from different heading to keep the launch position hidden ...
Here a simple C++ example of this approach:
//---------------------------------------------------------------------------
void vector_one(double *c,double *a)
{
double l=sqrt((a[0]*a[0])+(a[1]*a[1])+(a[2]*a[2]));
if (l>1e-10) l=1.0/l; else l=0.0;
c[0]=a[0]*l;
c[1]=a[1]*l;
c[2]=a[2]*l;
}
//---------------------------------------------------------------------------
// Z=0 plane is ground, Z+ is up
const double g=9.81; // [m/s^2] Earth's gravity
const double acc0=20.0; // [m/s^2] rocket main thruster acceleration
const double kv2 =0.002; // [-] rocket air friction coeff (speed limiter)
const double alt0=50.0; // [m] rocket safe altitude
const double dis0=100.0; // [m] rocket safe distance to target
const double dis1= 10.0; // [m] rocket explosion distance to target
const double dang0=375.0*M_PI/180.0;// [rad/s] rocket turn speed per yaw/roll/pitch
// Rocket
double dst[3]={+90.0,-50.0,0.0}; // [m] target position
double pos[3]={-100.0,200.0,0.0}; // [m] rocket position
double vel[3]={ 0.0, 0.0,0.0}; // [m/s] rocket velocity
double acc[3]={ 0.0, 0.0,0.0}; // [m/s^2] rocket acceleration
enum{
_state_none=0,
_state_launch, // rise to alt0
_state_cruise, // get near target but maintain alt0
_state_hit, // descend and hit
};
int state=_state_launch;
void update(double dt) // update rocket after dt [sec] has passed
{
int i;
double v,a,hdg[3],tar[3];
// guiding system
if (state==_state_none)
{
for (i=0;i<3;i++) vel[i]=0.0;
for (i=0;i<3;i++) acc[i]=0.0;
return;
}
if (state==_state_launch)
{
// init heading to Up
for (i=0;i<3;i++) hdg[i]=0.0; hdg[2]=1.0;
if (pos[2]>=alt0) state=_state_cruise;
}
v=sqrt((vel[0]*vel[0])+(vel[1]*vel[1])+(vel[2]*vel[2]));// |vel|
if ((state==_state_cruise)||(state==_state_hit))
{
vector_one(hdg,vel); // heading
for (i=0;i<3;i++) tar[i]=dst[i]-pos[i]; // to target
a=sqrt((tar[0]*tar[0])+(tar[1]*tar[1])+(tar[2]*tar[2])); // distance to target
if (state==_state_cruise)
{
tar[2]=0; // no altitude change
if (a<=dis0) state=_state_hit;
}
else{
if (a<=dis1) state=_state_none; // here you shoul add exlosion code
}
vector_one(tar,tar);
// a = angle between hdg and tar [rad]
for (a=0.0,i=0;i<3;i++) a+=hdg[i]*tar[i];
a=fabs(acos(a));
// approximate turn up to dang0
if (a>1e-10) a=dt*dang0/a; else a=0.0;
for (i=0;i<3;i++) hdg[i]=hdg[i]+a*(tar[i]-hdg[i]);
vector_one(hdg,hdg); // new heading
for (i=0;i<3;i++) vel[i]=v*hdg[i]; // new vel
}
// physics
for (i=0;i<3;i++) acc[i] =-kv2*vel[i]*v; // air friction (k*|vel|^2)
for (i=0;i<3;i++) acc[i]+=hdg[i]*acc0; // rocket thrust
acc[2]-=g; // gravity
// Newton/D'Alembert simulation
for (i=0;i<3;i++) vel[i]+=acc[i]*dt;
for (i=0;i<3;i++) pos[i]+=vel[i]*dt;
}
//---------------------------------------------------------------------------
You might need to tweak the constants a bit to match your sizes and game needs. As you can see you can customize the rocket quite a lot which is ideal for game (tech upgrades).
The physics is straight forward Newton/D'Alembert (apart the vel turning due to wings) and the guiding system works as described above. In first state the rocket just rise to alt0 then it try to turn towards target with dang0 turn speed while maintaining altitude and when closer than dis0 it start also descending. If closer than dis1 the rocket should explode ...
Here preview (top view):
The white line is line from ground to verify the altitude of rocket ... Rocket is Blue and target is Red.
The turning math is like this:
so I just scaled tar-hdg to approximately match dang0*dt and add that to original hdg. now the new heading is turned towards target by up to dang0*dt so just I normalize it back to unit size and recompute velocity to this new direction (as wings are turning velocity instead of accelerating)
Beware of the units
All the units used must be compatible I am using SI. Your 9.81 constant suggest the same but your position and target values makes no sense if in meters ... Why shoot rocket if target is just few meters away? Also the values suggest your coordinates are either not cartessian or ground is not planar/flat. Also the values suggest integers hope you have floats/doubles instead...
The trajectory will be a parabola. The basic equations of which are explained quite well here: https://courses.lumenlearning.com/boundless-physics/chapter/projectile-motion/
The 3D problem (x, y, z) can be easily be transformed to a 2D (single plane) problem (horizontal, vertical), for the equations then back to 3D for the problem.
It's been a while since my math classes so here's the question, any help is appreciated.
I'll be implementing the function in javascript also.
I have an X range of 0-100 and a set max Y of 10000 (which may change).
This is an exponential function and the closer X is to 100, the closer it gets to Y max and x=100 is y=10000. So my question is, what is the function that can handle this? Ideally I'd like to have something to control the steepness of the curve as well.
What I have in mind :
graph
Thanks.
The formula would be a variant of y = a * exp(b * x), where you can play around with a and b to get the curve / endpoints you want. For 100/100.000, you could use:
y = 5 * exp(0.0990348754944493 * x). In Javascript that would look something like:
function getExponent(x) {
return 5 * Math.pow(0.0990348754944493*x);
}
or if you want a and b to be variables:
function getExponent(x,a,b) {
return a * Math.pow(b*x);
}