Reputation: 2517
The idea is to find the mid point of a bezeir curve. Following is the De Casteljau's algorithm for finding the midpoint of a curve with four points.
How can I implement such an algorithm in javascript using recursion?
Following is the four starting points. From here we start the algorithm and through recursion we arrive the tip of the tree.
(0, 0)
\
(1/2, 0) --> this node is calculated as follows [(x1 + x2)/2, (y1 + y2)/2]
/ \
(1, 0) (3/4, 1/4)
\ / \
(1, 1/2) (3/4, 1/2)
/ \ /
(1, 1) (3/4, 3/4)
\ /
(1/2, 1)
/
(0, 1)
for example the sample input of points will be like this
const points = [[0,2], [4,5], [6,7], [3,8]]
output = [3,5]
// so the output will be just an array of two numbers for eg: [3,5] (just a rough figure for demo) which represents the midpoint of the above four points obtained by the above algorithm.
This is what I've tried. But it is entirely wrong. Can someone help?
const mid = (array) => {
if (array.length === 1)
return array
else {
array.map(point => [point[0] + point[1] + point[2]])
}
}
UPDATE
Remember each node is calculated as follows [(x1 + x2)/2, (y1 + y2)/2]. i.e., by taking the average of similar coordinates of two adjacent points.= .
UPDATE
The second code suggested by Nina Scholz works fine.
But I want to extend it further. Ninas code returns the first midpoint. But I want to extend it to find more points as illustrated below.
Upvotes: 4
Views: 189
Reputation: 122047
You could do this with reduce
and map
which will work for the sub-arrays of any sizes assuming you they are of the same length.
const points = [[0,2], [4,5], [6,7], [3,8]]
function calc(data) {
if (data.length == 1) return data;
const points = data.reduce((r, e, i, a) => {
if (a[i + 1]) r.push(e.map((n, j) => (n + a[i + 1][j]) / e.length))
return r;
}, [])
return calc(points)
}
const result = calc(points);
console.log(result)
Upvotes: 1
Reputation: 11
Seems like a good use for the Reduce array method.
array.reduce((acc, cur) => {
return [(acc[0] + cur[0])/2, (acc[1] + cur[1])/2]
})
Upvotes: 0
Reputation: 386600
You could take a recursive approach and get a single pair.
This approach takes only integer values.
const
getB = array => {
if (array.length === 1) return array[0];
const result = [];
for (let i = 1; i < array.length; i++) {
result.push([Math.floor((array[i - 1][0] + array[i][0]) / 2), Math.floor((array[i - 1][1] + array[i][1]) / 2)]);
}
return getB(result);
},
points = [[0, 2], [4, 5], [6, 7], [3, 8]];
console.log(getB(points));
Same approach without using integer values.
const
getB = array => {
if (array.length === 1) return array[0];
const result = [];
for (let i = 1; i < array.length; i++) {
result.push([(array[i - 1][0] + array[i][0]) / 2, (array[i - 1][1] + array[i][1]) / 2]);
}
return getB(result);
},
points = [[0, 2], [4, 5], [6, 7], [3, 8]];
console.log(getB(points));
Upvotes: 2