Studio Matrx Monthly · Volume 1 · Issue 3 · August 2026
Amogh N P
 In loving memory of Amogh N P — Architect · Designer · Visionary 
Coordinates and PointsLesson 5.1
PSD for Architecture, Planning & Urban Design/Module 5 · Geometry & Math for Design

Lesson 5.1 · Geometry & Math for Design

Coordinates and Points

The atom of all geometry: a point is just a few numbers, and everything you model is built from them

12 min Interactive lessonFree · open lessonByAmogh N P· Architect & interior designer
The hook

Zoom into any model far enough and the walls, curves and columns all dissolve into the same thing: points, each one just a couple of numbers.

Geometry can feel like the intimidating end of scripting - the place where the maths lives. It is not, and the reason is simple: the whole of it is built from one tiny idea, the point, and a point is nothing more than a few numbers that say where something is. Master that, and curves, surfaces and whole buildings are just organised collections of it.

This lesson stays deliberately close to the ground. We set up the Cartesian grid every CAD tool secretly runs on, store a point in Python three different ways, measure the distance between two of them, and then use a loop to spread hundreds of points into a grid. No trigonometry yet, no matrices - only the atom, handled until it feels obvious.

Point = (x, y) or (x, y, z). Distance = hypot(dx, dy). Grid = loop x loop.

The Cartesian grid every CAD tool runs on

Open Rhino, Revit, AutoCAD or SketchUp and, underneath the drawing, they all agree on the same quiet convention: a Cartesian coordinate system. There is an origin - the point (0, 0) - and from it you measure two directions, x running across and y running up. Any location on the plane is then fixed by two numbers: how far across, and how far up. The point (5, 3) means start at the origin, go 5 along x, then 3 along y. That is the entire idea, and it is the same one you used with graph paper in school.

The convention matters because it makes location computable. Once a place is two numbers instead of a spot you point at with a mouse, a program can store it, compare it, move it and measure it. A drawing becomes data. Everything else in this module - vectors, curves, meshes, the geometry algorithms - is built on this one agreement about what a location is.

One detail worth fixing early: in mathematics and in most CAD, y increases upward and angles turn anticlockwise. Some screen and image systems flip y so it grows downward, which is why a shape can appear upside-down when you move between contexts. It is not a mistake in your maths - just a different convention about which way is up. Knowing the axis directions of the tool you are targeting saves a lot of confused debugging later.

Designers already think this way without naming it. A setting-out drawing gives dimensions from a reference corner; a survey gives eastings and northings; a façade panel is placed so many millimetres over and so many up from a datum. Each is a Cartesian coordinate in disguise. When you script geometry you are simply making that habit explicit and handing it to the computer, which is tireless about the arithmetic you would rather not do by hand.

THE CARTESIAN GRIDxy0503(5, 3)A point is an address: go 5 across, then 3 up. Two numbers fix it exactly.
Zoom
The Cartesian grid underneath every CAD tool: an origin at (0, 0), an x axis across and a y axis up. The point (5, 3) is simply the instruction go 5 across, then 3 up - two numbers that fix a location exactly and make it something a computer can store and measure.

A point is an address: (x, y) = go across x, then up y, from the origin (0, 0).

A point is just a few numbers

In Python a point is not a special object you have to import - it is just numbers held together in one of the containers you already met in Module 2. The three natural choices are a tuple, a list, and a dictionary, and the difference between them is really a difference of intent.

python
p_tuple = (5, 3)          # fixed: a point that will not change
p_list  = [5, 3]          # editable: same idea, but mutable
p_dict  = {"x": 5, "y": 3}  # labelled: clear names instead of positions

print(p_tuple[0], p_tuple[1])   # 5 3
print(p_dict["y"])              # 3

Most geometry code uses tuples for points, for two good reasons. A tuple is immutable - once made it will not change by accident, which is exactly what you want for a fixed location - and its shape reads clearly: (x, y) in 2D, (x, y, z) in 3D. You reach into it by position, so p[0] is x and p[1] is y.

A dict is worth it when the labels earn their keep - a point that also carries data, say {"x": 5, "y": 3, "level": "ground", "tag": "C4"} for a column. Then names beat remembering that index 3 was the tag. There is no single right container; there is only the one that makes your particular script clearest. A quick habit that pays off: unpack a point into named variables the moment you use it, so the maths reads plainly.

python
point = (5, 3)
x, y = point          # unpack into names
print(x + y)          # 8
ONE POINT, THREE CONTAINERStuple (fixed)(5, 3)order carries meaninglist (editable)[5, 3]same idea, can changedict (labelled){x: 5, y: 3}names, not positionsThe same point (5, 3). A tuple when it is fixed, a list to edit, a dict when clear labels help.
Zoom
The same point (5, 3) stored three ways in Python. A tuple when the location is fixed, a list when you need to edit it, a dict when clear labels help - especially if the point carries extra data. Most geometry code uses tuples; the difference is one of intent, not of correctness.

Distance between two points

The first genuinely useful thing you can compute from points is the distance between them - the straight-line length from one to the other. It comes straight from Pythagoras: the distance is the square root of the horizontal gap squared plus the vertical gap squared. In code you never write the square root by hand, because the standard library has math.hypot, which does exactly this and handles the awkward numeric edge cases for you.

python
import math

a = (2, 3)
b = (7, 15)
dx = b[0] - a[0]        # horizontal gap: 5
dy = b[1] - a[1]        # vertical gap: 12
dist = math.hypot(dx, dy)   # sqrt(5*5 + 12*12) = 13.0
print(round(dist, 2))       # 13.0

Because you will want this again and again, wrap it in a small function. This is the single most reused piece of geometry code you will write, and giving it a name makes every later script read better.

python
import math

def distance(a, b):
    return math.hypot(b[0] - a[0], b[1] - a[1])

print(distance((0, 0), (3, 4)))     # 5.0
print(distance((1, 1), (1, 6)))     # 5.0

With distance in hand you can already answer real questions: is this door within reach of that socket, which of these trees is nearest the boundary, how long is a setting-out line. Notice too that the function does not care about units - if your coordinates are in metres it returns metres, in millimetres it returns millimetres. Keeping your whole script in one unit is a discipline worth adopting early; mixing them is one of the most common sources of silently wrong geometry.

There is one performance habit worth knowing even now. When you only need to compare distances - to find which point is nearest, say - you can skip the square root entirely and compare the squared distances (dx*dx + dy*dy), because whichever is smaller squared is also smaller un-squared. The square root is a small cost, but in a loop over thousands of points that saving adds up, and it is a trick you will see in real geometry libraries. For everyday scripts, reach for the clear distance function first; keep the squared shortcut in your back pocket for when speed genuinely matters.

distance = math.hypot(dx, dy). Never square-root by hand.

A grid of points, built with a loop

One point is an address. The power arrives when you generate many points from a rule - and a rule repeated is exactly what a loop is for. A regular grid is the simplest and most useful example: think of column positions, a setting-out grid, paving units, or sample points across a site. Two nested loops - one for rows, one for columns - place every point.

python
points = []
for row in range(3):
    for col in range(4):
        points.append((col * 2.0, row * 2.0))

print(len(points))          # 12
print(points[0], points[-1])  # (0.0, 0.0) (6.0, 4.0)

The outer loop steps down the rows; for each row the inner loop walks across the columns, and at every stop it appends one point. Multiply the spacing (2.0 here) and you change the grid module; change the range values and you change how many bays. The same six lines produce a 3x4 grid or a 30x40 grid - that is the leverage from Lesson 0.1, now aimed at geometry.

A more Pythonic way to write the same thing is a list comprehension, which many computational designers prefer once the shape is familiar:

python
grid = [(col * 2.0, row * 2.0)
        for row in range(3)
        for col in range(4)]
print(len(grid))   # 12

Either form gives you a list of points you can now transform, measure or draw. In Rhino or Grasshopper (Module 6) this exact list becomes real geometry with one more call; here the point is that the thinking - a rule, repeated over a range - is already complete, and it is pure Python.

The grid is only the beginning of rule-driven placement. Swap the arithmetic inside the loop and the same structure gives you a diagonal, a staggered brick-bond pattern, or points along a circle - anything you can express as a formula of the loop counters. That is the real lesson hiding in a humble nested loop: once positions come from a rule rather than from clicking, changing the design means changing one number, and the hundreds of points update themselves.

THE CARTESIAN GRIDxy0503(5, 3)A point is an address: go 5 across, then 3 up. Two numbers fix it exactly.
Zoom
The Cartesian grid underneath every CAD tool: an origin at (0, 0), an x axis across and a y axis up. The point (5, 3) is simply the instruction go 5 across, then 3 up - two numbers that fix a location exactly and make it something a computer can store and measure.

3D is the same idea, one number more

Everything so far was 2D, but stepping into three dimensions costs almost nothing conceptually: you add a third number, z, for height. A point becomes (x, y, z), the origin is (0, 0, 0), and distance gains one more squared term - which math.hypot handles happily, since it accepts any number of arguments.

python
import math

def distance3d(a, b):
    return math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2])

floor = (0, 0, 0)
light = (3, 4, 12)
print(distance3d(floor, light))   # 13.0

The habit of unpacking still works - x, y, z = point - and a grid of points in 3D is just one more nested loop for the levels. This is why the atom matters so much: learn to handle a point cleanly and 2D versus 3D stops being a wall and becomes a single extra coordinate.

It is worth being honest about where the maths does get heavier later. Rotating in 3D, orienting a panel to a surface, or projecting a point onto a plane brings in trigonometry and matrices, which the next lesson opens gently. But a surprising amount of real design scripting - schedules of positions, nearest-neighbour checks, setting-out, simple layouts - never needs more than points, distance and a loop. Get comfortable here and you already have a genuinely useful geometric toolkit, before a single sine or cosine appears.

One last habit to build from the very start: give your coordinates meaning through good names and small helper functions. A tuple (5, 3) says nothing on its own, but a well-named variable - door_hinge, corner_ne, sample_points - turns a wall of numbers into readable geometry. The computer does not care, but the designer reading the script in three months certainly will, and that designer is usually you.

Tools & terms you'll meet in this lesson

tuple

The default container for a fixed point, (x, y) or (x, y, z)

Immutable and clearly shaped, so it will not change by accident. Reach in by position: p[0] is x, p[1] is y.

math.hypot

Straight-line distance from horizontal and vertical gaps

Does the Pythagoras square root for you and accepts 2D or 3D. The single most reused geometry call in this course.

nested for loop

Rows-by-columns iteration to place a grid of points

Outer loop for rows, inner for columns; append one point at each stop. The engine that turns one rule into many positions.

list comprehension

A compact one-line way to build the same list of points

[(c*2, r*2) for r in range(3) for c in range(4)] - idiomatic once the shape is familiar, but a plain loop is just as correct.

Hands-on workshop

Workshop — a setting-out grid you can measure

Build a small grid of points with a loop, then measure it - the two moves this lesson is really about. No CAD needed; plain Python and print statements are enough to see it working.

Python 3 and the standard-library `math` module. No CAD or extra installs. A Jupyter notebook or any editor is fine.

Given & goal
Goal: generate a grid of points and measure distances within it
Inputs: a chosen bay spacing and number of bays
Time: ~30 minutes
  1. 1Write a distance(a, b) function using math.hypot, and test it on (0, 0) and (3, 4) - you should get 5.0.
  2. 2With two nested loops, build a list of grid points for a 4x5 grid at 3.0-unit spacing. Print how many points you made and the first and last one.
  3. 3Compute the diagonal of the whole grid by calling distance on points[0] and points[-1], and print it.
  4. 4Loop over every point and find the one nearest to a target you choose, say (6, 6) - keep the point with the smallest distance seen so far.
  5. 5Rewrite the grid using a list comprehension and confirm it produces an identical list (compare with ==). Then, as a stretch, add a z value and turn it into a 3D grid over two levels.

You’ll walk away with
A short script that builds a grid of points with a loop, reports its size and diagonal, finds the point nearest a chosen target, and reproduces the grid as a list comprehension.

The worked example

Three altitudes on the same idea

Read the band that fits you — or all three.

For the architectAutomate busywork & build custom tools

Setting-out and coordination live and die on coordinates. A column grid, a survey of levels, a cloud of panel-fixing points - all are lists of (x, y, z) tuples you can generate, measure and check with a loop and distance. Before you ever touch Rhino scripting, plain-Python points let you verify spacings, find the nearest gridline, or export a setting-out schedule that matches the drawing exactly.

For the interior designerScripts for data, schedules & layouts

Layout is coordinate work in disguise. Furniture positions, socket and switch locations, the spacing of pendants over an island, a paving or tile grid - each is a point, and a rule-driven grid of them is a short loop. Even without a 3D engine you can script a clean list of positions with their labels as dicts, then feed it straight into a schedule with the pandas skills from Module 4.

For the studentA hireable computational skill

This is the lesson that makes computational geometry stop being scary. Every parametric exercise, every Grasshopper definition, every generative studio project rests on points and distance. Get fluent here - tuples for points, math.hypot for distance, nested loops for grids - and Modules 6 and 9, and the Computational Design course in this Academy, will feel like variations on ideas you already own rather than new mountains to climb.

Misconception check

Geometry in code means heavy maths - trigonometry and matrices - from the very start.

It does not, and believing so keeps designers away from the most useful, most approachable part. The foundation of all model geometry is the point, which is just two or three numbers, and the operations you reach for most - storing positions, measuring distance, generating grids, checking nearest neighbours - need only arithmetic and a loop. Trigonometry and matrices do appear when you rotate or orient geometry in space, and the next lesson introduces them gently and visually. But a great deal of genuinely valuable design scripting never goes beyond (x, y), math.hypot and a for loop. Start with the atom, get it fluent, and add the heavier maths only when a specific task actually demands it.
Try it

Do it yourself

Reason these through, then check with a quick print.

  1. 1What two (or three) numbers define a point, and what does the origin mean?
  2. 2Why do most geometry scripts use a tuple for a point rather than a list?
  3. 3Write the one line that gives the distance between (1, 2) and (4, 6).
  4. 4How many points does a nested loop over range(5) and range(6) create?
  5. 5What is the only change needed to take distance from 2D to 3D?
Take this with you

The one line to carry out

A point is just a few numbers on the Cartesian grid, and from that atom - stored in a tuple, measured with `math.hypot`, multiplied by a loop - the whole of geometry is built. Get the atom fluent and 2D, 3D, grids and distances all become easy.
Take it further
References & further reading

Peer-reviewed journals & authoritative standards

  1. 01Cartesian coordinate systemWikipedia, 2026.
  2. 02TupleWikipedia, 2026.
  3. 03The Python Standard LibraryPython Software Foundation, 2026.
  4. 04Computational geometryWikipedia, 2026.
Related lessons
Recap
Every CAD tool runs on a Cartesian system: an origin and coordinates that fix a location as two or three numbers. In Python a point is just those numbers in a tuple (usually), a list, or a labelled dict. Distance comes from math.hypot, and a loop turns one placement rule into a whole grid of points. Moving from 2D to 3D costs only one extra coordinate.
Carry forward →

Points tell you where things are. Next we learn to _move_ them - vectors give geometry a direction and a length, and translate, rotate and scale let you copy and transform whole shapes with arithmetic.

A

The author

Amogh N P

Architect, interior designer, and creative polymath. Studio Matrx began in his notebooks — his vision of design made honest, useful, and open to everyone. Its Academy is written and taught in his memory, and free, forever.

More about Amogh →