Reputation: 1170
Ok, I have two positions in 3d space:
var fromX = 1,
fromY = 2,
fromZ = 3,
toX = 15,
toY = 16,
toZ = 17;
Then I need to calculate the current position, when someone/something is moving in a straight line from the from-coordinates, to the to-coordinates. I know the distance left is 2, what would be the formula for calculating the current position?
I guess this is more of a math question than a javascript question, but it is for a javascript application, so I'm hoping that is not a problem.
Upvotes: 0
Views: 1702
Reputation: 7824
You need to use 3D Pythagoras to find the distance between two points. If x1,y1,z1 and x2,y2,z2 are your points then the distance is sqrt((x1-x2)^2+(y1-y2)^2+(z1-z2)^2)
. There are several ways of finding the desired point. We can find the distance from the starting point to the ending point and then calculate the proportion of that distance which will give 2 as a result using linear interpolation.
var fromX = 1,
fromY = 2,
fromZ = 3,
toX = 15,
toY = 16,
toZ = 17;
// find the difference
var dx = toX-fromX, dy = toY-fromY, dz=toZ-fromZ;
// find the total length
var dist = Math.hypot(dx,dy,dz);
// find the proportion of this length
var lambda = (dist-2.0) / dist;
// do the linear interpolation
var x = fromX + lambda * dx,
y = fromY + lambda * dy,
z = fromZ + lambda * dz;
console.log(x,y,z);
// Just to check
var dx2 = toX-x, dy2 = toY-y, dz2=toZ-z;
var dist2 = Math.hypot(dx2,dy2,dz2);
console.log(dist2);
We get the result 13.845299461620748 14.845299461620748 15.845299461620748 and the final distance is 2.0000000000000013.
Note I've uses Math.hypot this is a new feature which works in Chrome/firefox/opera but not in IE. There is a work-around to enable it in other browsers if needed. You just use Math.sqrt(dx*dx+dy*dy+dz*dz)
instead.
Upvotes: 1
Reputation: 147403
There are already 2 answers with the correct algorithm, this one's no different, just a bit neater.
// Distance between two points is the square root of the sum
// of the squares of the differences
function get3dDistance(startCoords, endCoords) {
var dx = Math.pow((startCoords[0] - endCoords[0]), 2);
var dy = Math.pow((startCoords[1] - endCoords[1]), 2);
var dz = Math.pow((startCoords[2] - endCoords[2]), 2);
return Math.sqrt(dx + dy + dz);
}
// The coordinates of a point some distance from the end is
// proportional to the distance left and total distance.
function getCoordsFromDistanceLeft(startCoords, endCoords, distanceLeft) {
var distance = get3dDistance(startCoords, endCoords);
var f = (distance - distanceLeft)/distance;
return [startCoords[0] + f*(endCoords[0] - startCoords[0]),
startCoords[1] + f*(endCoords[1] - startCoords[1]),
startCoords[2] + f*(endCoords[2] - startCoords[2])];
}
// Test case
var start = [1,2,3];
var end = [15,16,17];
var distanceLeft = 2;
// Distance between the two points
var dist = get3dDistance(start, end)
document.write('distance: ' + dist + '<br>');
// distance: 24.24871130596428
// Get the coords
var x = getCoordsFromDistanceLeft(start, end, distanceLeft);
document.write('x: ' + x + ' is ' + distanceLeft + ' to end<br>');
// x: 13.845299461620748,14.845299461620748,15.845299461620748 is 2 to end
document.write('From x to end: ' + get3dDistance(x, end) + '<br>');
// From x to end: 2.0000000000000013
Salix alba has introduced Math.hypot, which is interesting but since it's a new feature in ECMAScript 2015 it would be wise to include a polyfill.
Upvotes: 1
Reputation: 50057
Given two points, fromPt
and toPt
, the distance between two points can easily be calculated:
distanceX = Math.pow(fromPt.x - toPt.x, 2)
distanceY = Math.pow(fromPt.y - toPt.y, 2)
distanceZ = Math.pow(fromPt.z - toPt.z, 2)
total_distance = Math.sqrt(distanceX + distanceY + distanceZ)
and now finding the correct point along the line is just a case of correct interpolation :)
newPt = {}
newPt.x = fromPt.x + ((toPt.x - fromPt.x) * (wantedDistance / total_distance))
newPt.y = fromPt.y + ((toPt.y - fromPt.y) * (wantedDistance / total_distance))
newPt.z = fromPt.z + ((toPt.z - fromPt.z) * (wantedDistance / total_distance))
Upvotes: 2