Set Tangnet of Spline
-
Hi everyone!
I have recently been learning some basics of linear algebra.
In order to verify my learning results, I created a Bezier spline Generator with Python Generator.
But when I set the tangents of the spline, something confused me.
When I moved the point of the spline, the left and right handles of the tangent would switch positions, or would they flip 180 degrees? I don't quite understand what's going on here.And there is my test code and Scene file:
import c4d import math def main() -> c4d.BaseObject: null = c4d.BaseObject(c4d.Onull) a = op.GetDown() b = a.GetNext() c = b.GetNext() obj = b.GetClone(0) obj[c4d.NULLOBJECT_RADIUS] = 5 obj[c4d.ID_BASEOBJECT_USECOLOR] = 2 obj[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(1,0,0) obj2 = obj.GetClone(0) obj2[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(0,1,0) a_pos_local = ~b.GetMg() * a.GetMg().off a_polar_angle = math.atan2(a_pos_local.y, a_pos_local.x) a_length = a_pos_local.GetLength() b_pos_local = ~b.GetMg() * c.GetMg().off b_polar_angle = math.atan2(b_pos_local.y, b_pos_local.x) b_length = b_pos_local.GetLength() polar = (a_polar_angle + b_polar_angle)/2 + (math.pi / 2) leng = (a_length + b_length)/2 x = leng * math.cos(polar) y = leng * math.sin(polar) vec = c4d.Vector(x,y) move_vec1 = vec.GetNormalized() * op[c4d.ID_USERDATA,1] m1 = ~op.GetMg() * b.GetMg() * c4d.utils.MatrixMove(move_vec1) m2 = ~op.GetMg() * b.GetMg() * c4d.utils.MatrixMove(-move_vec1) obj.SetMg(m1) obj2.SetMg(m2) obj.InsertUnder(null) obj2.InsertUnder(null) spline = c4d.SplineObject(3, c4d.SPLINETYPE_BEZIER) spline.SetPoint(0, a.GetMg().off) spline.SetPoint(1, b.GetMg().off) spline.SetPoint(2, c.GetMg().off) vl = ~b.GetMg() * obj.GetMg().off vr = ~b.GetMg() * obj2.GetMg().off spline.SetTangent(1, vl, vr) spline.InsertUnder(null) return null
-
Hey @gheyret,
thank you for reaching out to us. Please note that both questions about mathematical concepts and debugging user code are out of scope of support, as declared in our Support Procedures.
Linear algebra is a mathematical subject which is famous for being overloaded with other subjects, probably because it has become so popular. So, people can mean a lot when they say "linear algebra", a popular misnaming is for example to treat it as synonymous with statistics, a.k.a., machine learning, because it is there being used a lot. But at its heart linear algebra is just the sub-section of vector/matrix algebra which limits itself to the name giving linear combinations, sometimes also labeled as linear transforms. A linear combination is just the sum of an arbitrary set of vectors, each multiplied by a scalar (basically a fancy word for a number), e.g.,
4x + 9y + -2.2z
or22x + z
are both examples of linear combinations, wherex
,y
, andz
are vectors.In computer graphics linear combinations/algebra are popular because among other things they are very useful to express a transform, a bundle of an offset, an orientation and a scale. A 'matrix/transform' does nothing other than encoding the linear combination
M(p)=off + p.x*x + p.y*y + p.z*z
for a matrixM
transforming the pointP
and the framex
,y
,z
of that matrixM
. Linear algebra then usually also means writing that linear combinationoff + p.x*x + p.y*y + p.z*z
in a matrix form which is more convenient for multiple reasons.Your code is mostly about trigonometry, the subject of mathematics which is all about the relation of the right triangle to the circle. Which then manifest as the central trigonometric identities sine, cosine, and tangent which due to their intimate relation with the circle are also called circle functions. This has nothing to do with linear algebra, but you need trigonometry to construct the basis (or as I prefer to say: frame) of a vector space. This is then sometimes called a rotation matrix, but that is a bit misleading since all transforms/linear combinations also encode an orientation/rotation. It is just that some transforms encode uninteresting oreintations such as (0°, 0°, 0°) . But the point of transforms is exactly not to do this, as trigonometry although somewhat simple school math can prove tricky in detail, and more important on the computer: computing the sine and cosine of things is very slow while using a (linear) transform which encodes that rotation is very fast. So, I do not want to stop your appetite for coding adventures, I am all for it, go ahead and explore! But you should be aware that what you are doing there is mostly trigonometry.
About your problem at hand
Due to the fact that the sum of the angles of a triangle is 180° (at least in Euclidean space), the angle/circle measuring/describing capabilities of the scircle functions sine, cosine, etc. is limited to 180°. After that value they just flip over, so 181° is just 1° for them (π radians is 180°, after that you need a multiple of π to express an angle in degree). You can exhibit this indirectly when you print out your
a_polar_angle
andb_polar_angle
, as they simply flip over at certain points, suddenly go from the positive into the negative due that limit (at least I think that is what is happening there in your code).-2.995054571067229 0.5746922011297894 -2.995054571067229 0.5746922011297894 -3.0671200894559045 0.5746922011297894 -3.117816186863078 0.5746922011297894 # The value flips here suddenly, your output is not continuous anymore, because π did 'overflow' 3.129067398903298 0.5746922011297894 3.0422583006849884 0.5746922011297894 2.9745193433216155 0.5746922011297894 2.939439875027449 0.5746922011297894 2.9082912851108667 0.5746922011297894
In the end I cannot debug all your code for you as this is out of scope of support and I do not truly understand what you are doing there exactly (one of the reasons why such things are out of scope of support). In general I would advise against doing the trigonometry yourself (use something like
sine
,cosine
, ortan
in your code). It is slow and even when somewhat comfortable with the math behind it, it is easy to make mistakes. Transforms (a.k.a linear combinations/transforms) as expressed in API such asc4d
exist exactly so that you do not have to touch the trigonometry yourself.As I said, I do not truly understand what you are trying to do here in the first place. If you just want to place the two tangent handles in relation to your two input objects
a
andc
, you can just do this:n: c4d.Vector = ~(c - a) # Get the normalized vector pointing from a to b. t0: c4d.Vector = b + (n * -tangentLength) # The position of the left tangent. t1: c4d.Vector = b + (n * tangentLength) # The position of the right tangent.
But your code does something different with a non-linear rotation behavior, where for small angles (e.g.,
a ° b <= 15°
) the relation above holds true, but for larger angles (e.g.,a ° b >= 90°
) not anymore. I am not sure if that is intentional. If you just want to align the tangent handles of a spline, you can look at this thread, I once showed there what I would consider a clean algebraic solution to the problem (no angle measuring required at all).Cheers,
Ferdinand -
Hi @ferdinand !
Sorry for late reply, and thank you very much for your detailed and thorough explanation, and for taking the time to explain the relationship between linear algebra and trigonometry in the context of computer graphics and transformations.
As a beginner, all I want to do here is to practice as much as I can with the knowledge I've learned, and I apologize if I didn't explain clearly.
Yes, in the code I want to implement is placing two tangent handle relative to the two input objects a and c.
Compared to calculating with trigonometric functions, your suggestion seems more straightforward and clear, and I never would have thought to use vectors to achieve this, I need to keep practicing.
I will take the time to review the thread you mentioned.
Thank you again for your support and guidance. Thank you very much for your insights!