function getDistance({y: y1, x:x1}, {y:y2, x:x2}){
return Math.sqrt(Math.pow(y2-y1, 2) + Math.pow(x2-x1, 2))
}
function interpolate(a, b, frac){
return {
x: a.x+(b.x-a.x)*frac,
y: a.y+(b.y-a.y)*frac,
};
}
//generate N point in a line
function generateOnLineEveryDistance(a, b, n, distance){
let res = [];
for(let i = 0; i < n ; i++){
// add a point interpolating on a line after (i + 1) * distance from the beginning point (i+1 to avoid the starting point 0,0)
res.push(interpolate(a, b, (i + 1) * distance))
}
return res;
}
function generate(points, n){
// calculate total distance to find out how distant we have to place the points
let totalDistance = 0;
for(let i = 1; i < points.length; i++){
totalDistance += getDistance(points[i - 1], points[i])
}
// distance to place the points
const pointDistance = totalDistance / (n - 1);
// the first point is always included
let res = [points[0]];
// now, we will consider a segment as point[i - 1] & point[i], and we will consider only the piece where we can fit point:
// eg. in a segment long 10 ([x:0, y:0], [x:0, y:10]), and a pointDistance of 4, we will consider only [x:0, y:0], [x:0, y:8]
// and the remainder is 2... this remainder will be used in the next segment, "appending it at the beginning"
// let's say the second segment is [x:0, y:10], [x:0, y:20], with the remainder it will be [x:0, y:8], [x:0, y:20]
let remainder = 0;
for(let i = 1; i < points.length ; i++){
// add the remainder if exists at the beginning of the current segment (point[i-1], point[i])
// source https://stackoverflow.com/questions/7740507/extend-a-line-segment-a-specific-distance
if(remainder > 0){
let a = points[i];
let b = points[i - 1];
let lengthAB = Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2))
points[i - 1].x = b.x + (b.x - a.x) / lengthAB * remainder;
points[i - 1].y = b.y + (b.y - a.y) / lengthAB * remainder;
}
// points we need to generate
let nPoints = Math.floor(getDistance(points[i - 1], points[i]) / pointDistance)
// remainder to add to the next iteration
remainder = getDistance(points[i - 1], points[i]) - nPoints * pointDistance;
// add to the result the points
res = [
...res, // previous result
...generateOnLineEveryDistance( // new points
points[i - 1], // first point to consider
points[i], // second point to consider
nPoints, // number of points to generate
pointDistance / getDistance(points[i - 1], points[i]) // the ratio we want to use to generate them
)
]
}
// small fix in case of .333333 decimals that will "miss" the last point because it's .9999 and not 1.00000
if(res.length < n){
res = [...res, points[points.length - 1]]
}
return res;
}
const points = [
{
x: 0,
y: 0
} , {
x: 0,
y: 10
} , {
x: 0,
y: 20
}
]
console.log(generate(points, 4))