Initializing 3D Canvas...

Vectors And Tangents

2 min read1 page

In polygon modeling, a line is just two points connected by a straight edge. But in CAD and Differential Geometry, curves are Parametric Equations. They are continuous mathematical functions.

The 't' Parameter:

1. A parametric curve is evaluated using a parameter usually called t. 2. You can think of t as "Time" or "Percentage". 3. If t = 0.0, the math function returns the Start Point of the curve. 4. If t = 1.0, the math function returns the End Point of the curve. 5. If t = 0.5, the function returns the exact midpoint of the curve.
python
1# Evaluating a Parametric Line
2def evaluate_line(start_pt, end_pt, t):
3 """Finds the exact XYZ coordinate at a specific percentage (t)."""
4
5 # Ensure t is between 0.0 (start) and 1.0 (end)
6 t = max(0.0, min(1.0, t))
7
8 # Linear Interpolation (Lerp)
9 x = start_pt.x + (end_pt.x - start_pt.x) * t
10 y = start_pt.y + (end_pt.y - start_pt.y) * t
11 z = start_pt.z + (end_pt.z - start_pt.z) * t
12
13 return Point3d(x, y, z)
Parameter t (0.0 - 1.0)
0.00
2 min read1 page

Straight lines are boring. How does CAD math generate smooth curves? It uses Control Pointsand recursively applies the simple linear interpolation formula we just learned! This is called De Casteljau's Algorithm.

Curve Generation:

1. Given 3 Control Points, draw 2 straight lines connecting them. 2. Pick a parameter t = 0.5. 3. Find the midpoint of line 1, and the midpoint of line 2. 4. Connect those two midpoints with a new, temporary line. 5. Find the midpoint of THAT temporary line. This final point is exactly on the smooth curve!
python
1# Quadratic Bezier Evaluation
2def evaluate_bezier(p0, p1, p2, t):
3 """Evaluates a smooth curve using 3 control points."""
4
5 # 1. Find the point at 't' on the first segment (p0 to p1)
6 a = evaluate_line(p0, p1, t)
7
8 # 2. Find the point at 't' on the second segment (p1 to p2)
9 b = evaluate_line(p1, p2, t)
10
11 # 3. Find the point at 't' on the segment connecting those two new points!
12 c = evaluate_line(a, b, t)
13
14 # c is the final point on our smooth curve.
15 return c
Parameter t (0.0 - 1.0)
0.00
2 min read1 page

Now that we can evaluate a point on the curve, we want to know what direction the curve is pointing at that exact spot. This direction is called the Tangent Vector.

Mathematical Slopes:

1. If we take the mathematical formula for the Bezier curve and calculate its First Derivative (Calculus), we get a new equation. 2. If we plug our parameter t into this new Derivative equation, it outputs a Vector (a 3D arrow). 3. This arrow points exactly parallel to the curve at that specific location. 4. The Tangent vector represents the "velocity" or "direction of travel" along the curve.
python
1# Calculating the Derivative (Tangent Vector)
2def get_tangent(p0, p1, p2, t):
3 """Calculates the exact direction the curve is pointing at 't'."""
4
5 # 1. Take the mathematical derivative of the Bezier formula
6 # For a Quadratic Bezier, the derivative formula is:
7 # 2 * (1-t) * (p1 - p0) + 2 * t * (p2 - p1)
8
9 vec1 = (p1 - p0) * (2 * (1.0 - t))
10 vec2 = (p2 - p1) * (2 * t)
11
12 tangent_vector = vec1 + vec2
13
14 return tangent_vector
Parameter t (0.0 - 1.0)
0.50
2 min read1 page

The raw First Derivative formula gives us a vector that points in the right direction, but its Length (Magnitude) changes wildly depending on how the curve was drawn. Often, we only care about the Direction, not the length.

Unit Vectors:

1. A vector with a length of exactly 1.0 is called a Unit Vector (or Normalized Vector). 2. To Normalize a vector, you calculate its current length using the Pythagorean theorem, and then divide its X, Y, and Z components by that length. 3. Unit Vectors are essential for 3D graphics. When you tell a character to "walk forward", you multiply their Unit Forward Vector by their walking speed!
python
1# Vector Normalization
2def get_unit_tangent(tangent_vector):
3 """Forces the tangent vector to have a length of exactly 1.0."""
4
5 # 1. Calculate the current length using Pythagoras
6 x, y, z = tangent_vector
7 length = math.sqrt(x*x + y*y + z*z)
8
9 # 2. Divide every component by the length
10 unit_x = x / length
11 unit_y = y / length
12 unit_z = z / length
13
14 return Vector3d(unit_x, unit_y, unit_z)
Vector Mode (Raw / Normalized)
0.00
2 min read1 page

A single point and a single arrow are useful, but for complex tasks (like sweeping a pipe along a curve), we need a full 3D Coordinate System (X, Y, Z axes) that rides along the curve like a rollercoaster cart.

The Frenet Frame:

1. The Tangent vector acts as the local "Forward" (Z axis). 2. If we take the Second Derivative, we get the Normal vector. It always points towards the "inside" of the turn, acting as the local "Up" (Y axis). 3. If we cross-multiply the Tangent and the Normal, we get the Binormal vector, which acts as the local "Right" (X axis). 4. This moving coordinate system is called a Frenet-Serret Frame.
python
1# Parameter Coordinate System
2def evaluate_frenet_frame(curve, t):
3 """Calculates a local 3D coordinate system at point 't'."""
4
5 # 1. Evaluate position
6 origin = curve.evaluate_position(t)
7
8 # 2. Tangent (Forward direction)
9 tangent = curve.evaluate_derivative(t).normalize()
10
11 # 3. Normal (Up direction, pointing towards center of curvature)
12 second_derivative = curve.evaluate_second_derivative(t)
13 normal = second_derivative.normalize()
14
15 # 4. Binormal (Right direction)
16 binormal = tangent.cross(normal).normalize()
17
18 return origin, tangent, normal, binormal
Parameter t (0.0 - 1.0)
0.20
2 min read1 page

We mentioned that the length of the raw Tangent Vector represents "Velocity". But what does that actually mean? It means that the parameter t does not move at a constant physical speed along the curve!

Parametric Speed:

1. If you place control points far apart, the curve is "stretched" tightly between them. 2. A stretched segment has a high velocity: moving t from 0.1 to 0.2 covers a massive physical distance. 3. If you place control points close together, the curve "bunches up". 4. A bunched segment has a low velocity: moving t from 0.8 to 0.9 barely moves the physical point at all.
python
1# Mapping Velocity
2def analyze_curve_speed(curve, sample_count=50):
3 """Visualizes how fast 't' moves along the physical curve."""
4
5 velocity_data = []
6
7 for i in range(sample_count):
8 t = i / (sample_count - 1)
9
10 # Get the un-normalized tangent vector
11 raw_tangent = curve.evaluate_derivative(t)
12
13 # The Length of the Tangent IS the Velocity!
14 speed = raw_tangent.length()
15
16 # We can map this speed to a color (e.g., Red = Fast, Blue = Slow)
17 color = map_speed_to_color(speed)
18 velocity_data.append((t, color))
19
20 return velocity_data
View (Curve / Velocity Map)
0.00
2 min read1 page

Because t does not move at a constant physical speed, animating an object by simply increasing tby 0.01 every frame creates a very interesting effect. The object will physically speed up and slow down!

Natural Easing:

1. Animators love Bezier curves exactly because of this variable velocity. 2. If they want an object to start moving slowly, they bunch control points together at the start. 3. If they want it to whip quickly through the middle, they stretch the control points far apart. 4. This creates natural "Ease-In" and "Ease-Out" animations purely through the curve's mathematical shape, without writing complex physics code!
python
1# Animating along a curve
2def animate_object(curve, t_value):
3 """Moves an object along a path."""
4
5 # Notice that we just increase 't' at a constant rate!
6 # t += 0.01 per frame
7
8 # We get the position
9 position = curve.evaluate_position(t_value)
10
11 # We get the direction it should face
12 forward = curve.evaluate_derivative(t_value).normalize()
13
14 return position, forward
Play Animation
1.00
Show Velocity Map
1.00