Zalgorithm

Drawing a point from the parametric representation of a line

This is not a math tutorial. See Why am I writing about math?

Related to notes / Drawing a point from the slope of two points in the Cartesian plane.

The goal is to create a new point that’s exactly some distance along a line that’s been defined by two points.

My intuition is that the sine of an angle that’s formed where a line intersects the horizontal axis of a plane is the length of the opposite side over the length of the hypotenuse: the SOH in SOH CAH TOA (sin = opposite/hypotenuse). The cosine of the angle is the length of the adjacent side over the length of the hypotenuse: the CAH in SOH CAH TOA (cosine = adjacent/hypotenuse).

The SOH CAH TOA mnemonic isn’t the best mnemonic for me (the word that sounds like “soh” could also be written as “soa”). What works is to remember that cosine is associated with the x component of a point, which is its horizontal position; sine is associated with the y component of a point, which its vertical position.

From public school (and construction work) “‘a’ squared plus ‘b’ squared equals ‘c’ squared” (the Pythagorean theorem) is locked in my brain. It’s the basis of how you square a wall with two tape measures.

Given the points (x1, y1), (x2, y2) the rise is y2 - y1, the run is x2 - x1. The hypotenuse is sqrt(rise*rise + run*run).

With that in hand, theta can be defined as the angle that’s formed where the line (x1, y1, x2, y2) intersects a horizontal line on a 2D plane.

The sine of theta is rise/hypotenuse; the cosine of theta is run/hypotenuse.

It seems that formally, the use that the relationships rise/hypotenuse and run/hypotenuse are being put to here means that they shouldn’t really be referred to as sine and cosine. Sine and cosine are the “outputs of applying trig functions to an angle.” I’m using them here as direction vectors.1 So the code below uses the variable names dirX and dirY to refer to what’s mathematically equivalent to sin(theta) and cos(theta).

It would be technically more correct, but computationally less efficient, to use the terms sin and cos in the code if I approached it like this:

float theta = atan2(rise, run);
float cosTheta = cos(theta);  // equivalent to dirX in the code below
float sinTheta = sin(theta);  // equivalent to dirY in the code below

How does this relate to the parametric form of a line?

The parametric form of the line defined in the code is:

x(t)=x1+t(dirX)y(t)=y1+t(dirY) x(t) = x_1 + t\cdot(\text{dirX}) \\ y(t) = y_1 + t\cdot(\text{dirY})

Where tt is some distance from the point (x1,y1)(x_1, y_1).

Given dirX (or cosTheta), and dirY (or sinTheta), the x component of new point some distance from x1 is x1 + some_distance * dirX, the y component is y1 + some_distance * dirY:

size(400, 400);
textSize(8);
background(235);
fill(25);

translate(width/2, height/2);
scale(1, -1);

int x1 = -123;
int y1 = -44;
int x2 = 157;
int y2 = 99;

float rise = y2 - y1;
float run = x2 - x1;
float hypotenuse = sqrt(rise*rise + run*run);
float slope = rise/run;
float dirX = run/hypotenuse;
float dirY = rise/hypotenuse;


strokeWeight(8);
stroke(158, 41, 28);
point(x1, y1);

stroke(46, 28, 158);
point(x2, y2);

float oneThird = hypotenuse/3;

float newX = x1 + oneThird * dirX;
float newY = y1 + oneThird * dirY;

stroke(28, 158, 65);
point(newX, newY);

strokeWeight(1);
pushMatrix();
stroke(122);
scale(1, -1);
text("slope: " + str(slope), -width/2 + 8, -height/2 + 8);
text("hypotenuse: " + str(hypotenuse), -width/2 + 8, -height/2 + 20);
text("one-third hypotenuse: " + str(oneThird), -width/2 + 8, -height/2 + 32);
text("calculated distance: " + str(dist(x1, y1, newX, newY)), -width/2 + 8, -height/2 + 44);
popMatrix();

// visually confirm
stroke(175);
line(x1, y1, x2, y2);

Allow the second point to be moved with the mouse

The same idea as in the above code, but the point (x2, y2) is moved on mouseDrag() events. The calculated point is always half way between points (x1, y1) and (x2, y2):

float x2 = 0;
float y2 = 0;

void setup() {
  size(400, 400);
  textSize(8);
  background(235);
  fill(25);
}

void draw() {
  translate(width/2, height/2);
  scale(1, -1);

  background(235);

  float x1 = -173;
  float y1 = -184;

  float rise = y2 - y1;
  float run = x2 - x1;
  float slope = rise/run;
  float hypotenuse = sqrt(rise*rise + run*run);
  float dirX = run/hypotenuse;
  float dirY = rise/hypotenuse;

  strokeWeight(8);
  stroke(158, 41, 28);
  point(x1, y1);

  stroke(46, 28, 158);
  point(x2, y2);

  float halfway = hypotenuse/2;

  float xHalf = x1 + halfway * dirX;
  float yHalf = y1 + halfway * dirY;

  stroke(28, 158, 65);
  point(xHalf, yHalf);
  strokeWeight(1);
  pushMatrix();
  stroke(122);
  scale(1, -1);
  text("slope: " + str(slope), -width/2 + 8, -height/2 + 8);
  text("hypotenuse: " + str(hypotenuse), -width/2 + 8, -height/2 + 20);
  text("half hypotenuse: " + str(halfway), -width/2 + 8, -height/2 + 32);
  text("calculated distance: " + str(dist(x1, y1, xHalf, yHalf)), -width/2 + 8, -height/2 + 44);
  popMatrix();
}

void mouseDragged() {
  x2 = mouseX - width/2;
  y2 = -1 * (mouseY - height/2);
}

Parametric point
Parametric point

References

Wikipedia contributors. “Parametric equation.” Accessed on: January 20, 2026. https://en.wikipedia.org/wiki/Parametric_equation .


  1. Claude. ↩︎