Basic Geometry
Analytical geometry treats each point r as the vector from the origin to that point. We stop distinguishing “point” from “vector” and build everything from a few linear operations.
This lesson follows CP-Algorithms — Basic Geometry.
Linear operations
2D and 3D points form a vector space: you can add points and scale by a scalar. Coordinate type ftype is usually int, long long, or double.
using ftype = double;
struct point2d {
ftype x, y;
point2d() {}
point2d(ftype x, ftype y): x(x), y(y) {}
point2d& operator+=(const point2d &t) {
x += t.x; y += t.y; return *this;
}
point2d& operator-=(const point2d &t) {
x -= t.x; y -= t.y; return *this;
}
point2d& operator*=(ftype t) {
x *= t; y *= t; return *this;
}
point2d& operator/=(ftype t) {
x /= t; y /= t; return *this;
}
point2d operator+(const point2d &t) const { return point2d(*this) += t; }
point2d operator-(const point2d &t) const { return point2d(*this) -= t; }
point2d operator*(ftype t) const { return point2d(*this) *= t; }
point2d operator/(ftype t) const { return point2d(*this) /= t; }
};
point2d operator*(ftype a, point2d b) { return b * a; }
3D is the same idea with a z coordinate:
struct point3d {
ftype x, y, z;
point3d() {}
point3d(ftype x, ftype y, ftype z): x(x), y(y), z(z) {}
point3d& operator+=(const point3d &t) {
x += t.x; y += t.y; z += t.z; return *this;
}
point3d& operator-=(const point3d &t) {
x -= t.x; y -= t.y; z -= t.z; return *this;
}
point3d& operator*=(ftype t) {
x *= t; y *= t; z *= t; return *this;
}
point3d& operator/=(ftype t) {
x /= t; y /= t; z /= t; return *this;
}
point3d operator+(const point3d &t) const { return point3d(*this) += t; }
point3d operator-(const point3d &t) const { return point3d(*this) -= t; }
point3d operator*(ftype t) const { return point3d(*this) *= t; }
point3d operator/(ftype t) const { return point3d(*this) /= t; }
};
point3d operator*(ftype a, point3d b) { return b * a; }
🧪 Point arithmetic in C++
Dot product
Definition
The dot (scalar) product a · b has two matching stories:
- Geometry:
|a| · |b| · cos θ— length of a times the signed projection of b onto a. - Algebra: for a =
(x₁, y₁, z₁)and b =(x₂, y₂, z₂),
a · b = x₁x₂ + y₁y₂ + z₁z₂
It is commutative and linear in each argument.
ftype dot(point2d a, point2d b) {
return a.x * b.x + a.y * b.y;
}
ftype dot(point3d a, point3d b) {
return a.x * b.x + a.y * b.y + a.z * b.z;
}
Compute with the algebraic formula; reason with the geometric one.
🧪 Dot product: angle & projection
Properties
| Idea | Formula |
|---|---|
| Squared length (norm) | |a|² = a · a |
| Length | |a| = √(a · a) |
| Projection of a onto b | (a · b) / |b| |
| Angle | acos((a · b) / (|a| |b|)) |
| Sign | > 0 acute, = 0 orthogonal, < 0 obtuse |
ftype norm(point2d a) { return dot(a, a); }
double abs(point2d a) { return sqrt(norm(a)); }
double proj(point2d a, point2d b) { return dot(a, b) / abs(b); }
double angle(point2d a, point2d b) {
return acos(dot(a, b) / abs(a) / abs(b));
}
The level set { r | r · a = C } is a line in 2D (a plane in 3D) orthogonal to a. So a 2D line can be written r · n = C or (r − r₀) · n = 0 with normal n.
Interactive: see the products
Drag nothing — pick presets. Dot mode draws the projection of b onto a. Cross mode shades the parallelogram whose signed area is the 2D cross product.
Check: dot product
Dot product
1 / 4a · b equals zero when…
Pick an answer to see if you are right.
Cross product
3D cross and triple product
b × c is the vector orthogonal to both b and c, with length equal to the parallelogram area they span, oriented so that the turn from b to c looks counter-clockwise when viewed along b × c.
The triple product |a · (b × c)| is the parallelepiped volume. Coordinate form:
a × b = (a.y b.z − a.z b.y,
a.z b.x − a.x b.z,
a.x b.y − a.y b.x)
Notable facts:
a × b = −(b × a)(anti-commutative)|a × b| = |a| |b| sin θa × b = 0⇔ a and b are collineara · (b × c) = 0⇔ a, b, c are coplanar
point3d cross(point3d a, point3d b) {
return point3d(a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.x * b.y - a.y * b.x);
}
ftype triple(point3d a, point3d b, point3d c) {
return dot(a, cross(b, c));
}
2D pseudo-scalar (oriented area)
In 2D we keep only the z-component of the 3D cross:
cross(a, b) = a.x * b.y − a.y * b.x
This equals |a| |b| sin θ with θ measured counter-clockwise from a to b. Sign:
> 0→ turn a → b is counter-clockwise (LEFT)< 0→ clockwise (RIGHT)= 0→ collinear (TOUCH)
ftype cross(point2d a, point2d b) {
return a.x * b.y - a.y * b.x;
}
Same primitive checks orientation of three points A → B → C:
cross(B − A, C − A)
🧪 Orientation & line intersection
Lines and planes
| Object | Equation |
|---|---|
Line through r₀ with direction d | (r − r₀) × d = 0 |
Line through a and b | (r − a) × (b − a) = 0 |
Plane through a,b,c | (r − a) · ((b − a) × (c − a)) = 0 |
Line & plane intersection
Two lines in 2D
Parametrize the first line: r = a₁ + t · d₁. Require the second-line condition (r − a₂) × d₂ = 0:
t = cross(a₂ − a₁, d₂) / cross(d₁, d₂)
point2d intersect(point2d a1, point2d d1, point2d a2, point2d d2) {
return a1 + cross(a2 - a1, d2) / cross(d1, d2) * d1;
}
(Parallel lines → denominator 0; handle separately.)
Three planes in 3D
Planes r · nᵢ = aᵢ · nᵢ. Solve with Cramer’s rule; the triple product is the determinant of the columns:
point3d intersect(point3d a1, point3d n1,
point3d a2, point3d n2,
point3d a3, point3d n3) {
point3d x(n1.x, n2.x, n3.x);
point3d y(n1.y, n2.y, n3.y);
point3d z(n1.z, n2.z, n3.z);
point3d d(dot(a1, n1), dot(a2, n2), dot(a3, n3));
return point3d(triple(d, y, z),
triple(x, d, z),
triple(x, y, d)) / triple(n1, n2, n3);
}
Check: cross product & orientation
Cross product
1 / 5In 2D, cross(a, b) = a.x*b.y − a.y*b.x is…
Pick an answer to see if you are right.
Practice drills
Implement the primitives. Starters compile but fail the tests until the formulas are correct.
dot(ax, ay, bx, by) returns the 2D scalar product. Print one integer.
Contest problems
Apply orientation and cross products on a real judge.
Point Location Test
Judge: CSES — Point Location Test
A directed line through p1 → p2. For each query point p3, print whether it is LEFT, RIGHT, or TOUCH.
Up to 10⁵ tests with coordinates up to 10⁹ — use 64-bit integers for the cross product.
Sample
Input
3
1 1 5 3 2 3
1 1 5 3 4 1
1 1 5 3 3 2
Output
LEFT
RIGHT
TOUCH
Exactly the orientation drill: sign(cross(p2 − p1, p3 − p1)).
When to reach for which product
| Question | Tool |
|---|---|
| Length, angle, orthogonality, projection | Dot |
| Oriented turn, parallelogram / polygon area | 2D cross |
| Normal to a plane, parallelepiped volume | 3D cross / triple |
| Line as “through point + direction” | Cross equation |
| Line as “normal + offset” | Dot equation |
Previous: 0-1 BFS
Source: CP-Algorithms — Basic Geometry