Linking to Blines - Equations
From Synfig
WARNING: This text is under HEAVY development. Please be patient.
Contents |
[edit] Main equations
- (x1,y1),(x2,y2) - vertices, defining bline segment
- (x,y) - current bline point
- (xt1,yt1),(xt2,yt2) - tangent points defining bline segment
- (xt,yt) - tangent coordinates for current bline point
- u - Amount of current segment, [0,1]
- (x,y) = (1 − u)3(x1,y1) + 3u(1 − u)2(xt1,yt1) + 3u2(1 − u)(xt2,yt2) + u3(x2,y2) - bline point
[edit] Relative tangents
O'kay, I know, the (xt1,yt1),(xt2,yt2) defining absolute position of tangents, but in synfig we have their coordinates relative to vertex. Moreover, coordinates of yellow tangent are inverted.
Let's say:
- (Δxt1,Δyt1) and (Δxt2,Δyt2) - relative coordinates of tangents
Then:
- (xt1,yt1) = (x,y) + (Δxt1,Δyt1)
- (xt2,yt2) = (x,y) − (Δxt2,Δyt2)
Make substitution:
- Bline point: (x,y) = (1 − (3u2 − 2u3))(x1,y1) + 3u(1 − u)2(Δxt1,Δyt1) − 3u2(1 − u)(Δxt2,Δyt2) + (3u2 − 2u3)(x2,y2)
[edit] Tangent coordinates
<dooglus> look at etl/_calculus.h <dooglus> class derivative<hermite<T> > <dooglus> T a = func[0], b = func[1], c = func[2], d = func[3]; <dooglus> typename hermite<T>::argument_type y(1-x); <dooglus> return ((b-a)*y*y + (c-b)*x*y*2 + (d-c)*x*x) * 3;
- Can't understand, why *3? --Zelgadis 05:31, 8 March 2008 (EST)
For x:
- Δxt = (1 − u)2Δxt1 + 2u(1 − u)((x2 − Δxt2) − (x1 + Δxt1)) + u2Δxt2 = = − 2u(1 − u)x1 + (1 − u)(1 − 3u)Δxt1 + (3u2 − 2u)Δxt2 + 2u(1 − u)x2
[edit] Checking formulas
Well, I really wasn't sure if this formulas correct, that's why I did a little research and made some graphics and calculations. They are available here.
As result I got some final corrections to formulas (for x only):
- Bline point: x = (1 − (3u2 − 2u3))x1 + u(1 − u)2Δxt1 − u2(1 − u)Δxt2 + (3u2 − 2u3)x2
- Bline tangent: Δxt = − 6u(1 − u)x1 + (1 − u)(1 − 3u)Δxt1 + (3u2 − 2u)Δxt2 + 6u(1 − u)x2
[edit] Zelgadis, you wrong!
O'kay I understand what equations above could be wrong. But no one will argue what equations for bline point and tangents generally have form:
- (x,y) = c1(u)(x1,y1) + c2(u)(xt1,yt1) + c3(u)(xt2,yt2) + c4(u)(x2,y2)
- (Δxt,Δyt) = ct1(u)(x1,y1) + ct2(u)(Δxt1,Δyt1) + ct3(Δxt2,Δyt2) + ct4(u)(x2,y2)
where ci(u) - some function from 'u' argument
So I will use this notation further.
For now we assume what:
- c1(u) = 1 − (3u2 − 2u3)
- c2(u) = u(1 − u)2
- c3(u) = − u2(1 − u)
- c4(u) = 3u2 − 2u3
- ct1(u) = − 6u(1 − u)
- ct2(u) = (1 − u)(1 − 3u)
- ct3(u) = 3u2 − 2u
- ct4(u) = 6u(1 − u)
[edit] General model
The problem: see Linking_to_Blines#Creating_loops
So we need to determine position of vertex engaged in loop if she attachet ot some position of other bline.
- NOTICE: We need such recalculation only for cases when in loop included only 1 segment from each bline. Like this:
- We don't need to do recalculation for cases like those:
So, we have N blines (N bline segments) engaged in a loop.
To determine the x coordinate of vertex what finalizes the loop we need to solve matrix equation having form
(A − B) * α = β
- NOTE: Solution formulas for y coordinate will be the same.
- A,B - matrices 4N x 4N
- α,β - 4N column vectors
- α - is unknown quantity
Each line in matrix or column vector corresponding to particular vertex or it's tangent.
After solving system we will find column vector α which have form:
where
- point j of bline [i] and
tangent of point j of bline i. From this vector we could retrieve x coordinate of desired vertex or tangent.
So:
- the first line of each matrix or column vector corresponding to first vertex of first bline,
- second line - corresponding to tangent of first vertex of first bline,
- third line - to tangent of second vertex of first bline,
- fourth - second vertex of first bline,
- fifth - first vertex of second bline,
- sixth - tangent of first vertex of second bline,
- ...and so on...
- NOTE: Talking about bline we are talking about single (!) segment of bline which engaged in loop. That's why I not specify which tangent (yellow or red) we using - it's always tangent for current segment.
Column vector β have following structure. If position of vertex/tangent corresponding to vector element is "static" (i.e. it's not linked any other bline segment of the loop) then vector element is βi where βi is current x coordinate of this vector/tangent. If vertex/tangent is not "static" then corresponding vector element is zero.
- NOTE: When we calling vertex position "static" it's not means what vertex not linked to anything. The vertex could be linked to bline and still considered as "static" if that bline is not engaged into loop what we processing.
B matrix is zero-filled 4Nx4N matrix which we modifying in folowing way (rows and columns in matrix are numbered from 1):
- if first vertex of bline [i] is linked to bline [j] then element at ( (i-1)*4+1 , (i-1)*4+1 ) = 1
- if tangent of first vertex of bline [i] is linked to bline [j] then element at ( (i-1)*4+2 , (i-1)*4+2 ) = 1
- if tangent of second vertex of bline [i] is linked to bline [j] then element at ( (i-1)*4+3 , (i-1)*4+3 ) = 1
- if second vertex of bline [i] is linked to bline [j] then element at ( (i-1)*4+4 , (i-1)*4+4 ) = 1
A matrix is modified E matrix.
It is modified in such way:
- if first vertex of bline [i] is linked to bline [j] then element at position ( (i-1)*4+1, (i-1)*4+1 ) replaced with zero and elements in line (i-1)*4+1 at positions (j-1)*4+1, (j-1)*4+2, (j-1)*4+3, (j-1)*4+4 are replaced with
- if tangent of first vertex of bline [i] is linked to bline [j] then element at position ( (i-1)*4+2, (i-1)*4+2 ) replaced with zero and elements in line (i-1)*4+2 at positions (j-1)*4+1, (j-1)*4+2, (j-1)*4+3, (j-1)*4+4 are replaced with
- if tangent of second vertex of bline [i] is linked to bline [j] then element at position ( (i-1)*4+3, (i-1)*4+3 ) replaced with zero and elements in line (i-1)*4+3 at positions (j-1)*4+1, (j-1)*4+2, (j-1)*4+3, (j-1)*4+4 are replaced with
- if second vertex of bline [i] is linked to bline [j] then element at position ( (i-1)*4+4, (i-1)*4+4 ) replaced with zero and elements in line (i-1)*4+4 at positions (j-1)*4+1, (j-1)*4+2, (j-1)*4+3, (j-1)*4+4 are replaced with
where
is a position of vertex/tangent k of bline [i] on bline which it's linked to.
[edit] Examples
Ok, I sure you guys are wondering how is this work. (I personally wondering IF this works or not :D). Let's view some examples.
[edit] One spline
Case 1: Given Bline [1]. Vertex 2 of bline [1] linked to bline [1].
For x coordinates we have following system of equations:
-
-
-
-
- because
belongs to bline [1]
is a constant value of
and
is a constant value of
.
is a position of vertex 2 of bline [1] on the bline which it's linked to (i.e. bline [1]).
Transform:
So, we must solve the 4x4 matrix equation:
dooglus, can you check how this formula works in code? Something like:
- Create bline with 2 points - 1 and 2
- Select point 2, right click on bline -> "Link to bline"
- Place (not link!) point 2 at the position calculated by this formula. If we'll have point 2 on bline after that then it's ok for now, if not - something wrong.
Case 2: Given Bline [1]. Vertex 2 of bline [1] linked to bline [1] with it's tangent.
For x coordinates we have following system of equations:
-
-
-
- because tangent
linked to bline [1]
-
- because
belongs to bline [1]
is a constant value of
and
is a constant value of
.
is a position of vertex 2 of bline [1] on the bline which it's linked to (i.e. bline [1]).
Transform:
So, we must solve the 4x4 matrix equation:
[edit] Two splines
Case 1: Given Blines [1] and [2].
Vertex 1 of bline [1] linked to bline [2].
Vertex 2 of bline [2] linked to bline [1].
For x coordinates we have following system of equations:
-
- because
belongs to bline [2]
-
-
-
-
-
-
-
- because
belongs to bline [1]
is a constant value of
and
is a constant value of
.
is a position of vertex 2 of bline [2] on the bline which it's linked to (i.e. bline [1]).
is a position of vertex 1 of bline [1] on the bline which it's linked to (i.e. bline [2]).
Transform:
-
- because
belongs to bline [2]
-
-
-
-
-
-
-
- because
belongs to bline [1]
So, we must solve the 8x8 matrix equation:
[edit] Conclusion
Maybe formulas are not correct, but I think you've got the idea: For N Bline segments in loop we have 4N equations. If vertex is linked then we got appropriate equation, depending on what is linked. If vertex is not linked - just assigning constants.
