Reputation: 2216
I am working on a [specialized] graphics editor. It is used to draw simple vector graphics elements including arcs/curves.
We support a shape that mixes straight lines and curves. It gets drawn as a bunch of straight sections. At a later point, a designer can convert a straight segment into a curve. It looks like the below:
We persist this object as an array of dots. Each dot has coordinates x
and y
as well as optional angles r1
and r2
. I draw the shape on canvas using the below:
const parts = [
...,
{x: 359, y: 187, r1: 0.4, r2: 0},
{x: 214, y: 184, r1: 0, r2: 0.5}
...
];
for (let j = 0, len = parts.length; j < len; j++) {
const p1 = parts[j];
const p2 = parts[j < len - 1 ? j + 1 : 0];
if ('r1' in p && p.r1 > 0 && 'r2' in p2 && p2.r2 > 0) {
console.log('point:', p1);
console.log('next point:', p2);
console.log('draw arc, angle:', p1['r1']);
console.log('next vertex angle:', p2['r2']);
ctx[j ? 'quadraticCurveTo' : 'moveTo'](p1.x + 50, p1.y + 50, p1.x, p1.y);
} else {
ctx[j ? 'lineTo' : 'moveTo'](p1.x, p1.y);
}
}
It works, I get straight lines and curves when I need them.
However, my control point is off. I temporarily coded it as p1.x + 50, p1.y + 50
and this is not right. Knowing p1
and p2
, including coordinates and angles, how do I calculate the control point?
Upvotes: 0
Views: 254
Reputation: 80187
You need to calculate intersection point of two rays. Using parametric representation:
first ray second ray
x = p1.x + t * cos(r1) = p2.x + u * cos(r2)
y = p1.y + t * sin(r1) = p1.y + u * sin(r2)
Solve this equation system (shortening variable names as p1.x=x1, cos(r2)=c2 etx )
x1 + t * c1 = x2 + u * c2
y1 + t * s1 = y2 + u * s2
t = (x2 - x1 + u * c2) / c1
y1 + (x2 - x1 + u * c2) / c1 * s1 = y2 + u * s2
u * (c2 / c1 * s1 - s2) = (y2 - y1) - (x2 - x1) / c1 * s1
u * (c2 * s1 - s2 * c1 ) = (y2 - y1) * c1 - (x2 - x1) * s1
u = ((y2 - y1) * c1 - (x2 - x1) * s1) / (c2 * s1 - s2 * c1 )
substitute this value into the first equations and get x,y of intersection
x = x2 + u * c2
y = y2 + u * s2
Zero value of denominator (c2 * s1 - s2 * c1)
occurs for parallel vectors. Negative value of parameter u
- for case of non-intersecting vectors when angle is too large. These cases are impossible when non-degenerate point sequence is used as input.
Upvotes: 2