Contents
A simple geometrical construction with 2D homogeneous coordinates
Our goal is to complete the drawing of the isometric projection http://en.wikipedia.org/wiki/Isometric_projection of a cuboid when the points corresponding to a vertex and to three vertices adjacent to it are given as input. The geometrical construction only requires to find lines parallel to other lines, find lines passing through two points, and intersect lines, which is easily achieved in homogeneous coordinates.
clear
close all
clc
Naming
We will name the vertices as in the following image
figure(1), imshow(imread('simplecube-letters.png'));
FNT_SZ = 28;
Data entering
the user should click on a vertex of the cuboid, then on the three adjacent vertices
figure(2), imshow(imread('buildingSmall.png')) % imshow(imread('cube.jpeg')) hold on; [x y]=getpts plot(x,y,'.w','MarkerSize',12, 'LineWidth', 3); % plots points clicked by user with red circles a=[x(1) y(1) 1]'; text(a(1), a(2), 'a', 'FontSize', FNT_SZ, 'Color', 'w') b=[x(2) y(2) 1]'; text(b(1), b(2), 'b', 'FontSize', FNT_SZ, 'Color', 'w') c=[x(3) y(3) 1]'; text(c(1), c(2), 'c', 'FontSize', FNT_SZ, 'Color', 'w') e=[x(4) y(4) 1]'; text(e(1), e(2), 'e', 'FontSize', FNT_SZ, 'Color', 'w')
x = 445.0000 352.0000 505.0000 447.0000 y = 567.0000 543.0000 476.0000 318.0000
Finding some lines
Now variables a, b, c and d are 3-vectors containing the homogeneous coordinates of the 2D points. We need to find the lines passing through couples of points, using the cross product
lab=cross(a,b) lac=cross(a,c) lae=cross(a,e)
lab = 1.0e+04 * 0.0024 -0.0093 4.2051 lac = 1.0e+04 * 0.0091 0.0060 -7.4515 lae = 1.0e+05 * 0.0025 0.0000 -1.1194
Check the incidence equation
lab, lac and lae now contain the homogeneous represenation of the three lines ab, ac and ae. We can easily check that the lines actually contain the points by using the incidence relation:
lab'*a lab'*b lac'*a lac'*c lae'*a lae'*e
ans = -1.4552e-11 ans = -1.4552e-11 ans = 0 ans = 0 ans = -1.4552e-11 ans = -1.4552e-11
Parallelism
We now need to compute the line parallel to ab and passing through c. In order to do this, we create the line at infinity:
linf=[0 0 1]';
then, we find the directions of segments by ab, ac and ae intersecting their lines with the line at infinity
dab=cross(lab,linf) dac=cross(lac,linf) dae=cross(lae,linf)
dab = -93.0000 -24.0000 0 dac = 60.0000 -91.0000 0 dae = 2.0000 -249.0000 0
dab, dac and dae are points at the infinity, which represent directions. All lines with a given direction pass through the corresponding point at the infinity. We can then find the lines containing segments bd and cd.
lbd=cross(b,dac); lcd=cross(c,dab);
point d is now found by just intersecting lbd and lcd
d=cross(lbd,lcd);
we normalize d's coordinates so that we can read its cartesian coordinates in d(1) and d(2). We plot the point with a blue circle.
d=d/d(3); plot(d(1),d(2),'.b','MarkerSize',12); text(d(1), d(2), 'd', 'FontSize', FNT_SZ, 'Color', 'w')
Finding remaining points
The rest of the procedure is straightforward, and follows exactly the same technique.
lbf=cross(b,dae); lcg=cross(c,dae); ldh=cross(d,dae); lef=cross(e,dab); leg=cross(e,dac); f=cross(lbf,lef); g=cross(lcg,leg); lfh=cross(f,dac); h=cross(lfh,ldh); f=f/f(3); g=g/g(3); h=h/h(3); plot(f(1), f(2),'.w','MarkerSize',12, 'LineWidth', 3); % plots points clicked by user with red circles text(f(1), f(2), 'f', 'FontSize', FNT_SZ, 'Color', 'w') plot(g(1), g(2),'.w','MarkerSize',12, 'LineWidth', 3); % plots points clicked by user with red circles text(g(1), g(2), 'g', 'FontSize', FNT_SZ, 'Color', 'w') plot(h(1), h(2),'.w','MarkerSize',12, 'LineWidth', 3); % plots points clicked by user with red circles text(h(1), h(2), 'h', 'FontSize', FNT_SZ, 'Color', 'w')
Drawing
we can now finally draw the cube.
myline=[a';b';d';c';a']; line(myline(:,1),myline(:,2),'LineWidth',5); myline=[e';f';h';g';e']; line(myline(:,1),myline(:,2),'LineWidth',5); myline=[a';e']; line(myline(:,1),myline(:,2),'LineWidth',5); myline=[b';f']; line(myline(:,1),myline(:,2),'LineWidth',5); myline=[c';g']; line(myline(:,1),myline(:,2),'LineWidth',5); myline=[d';h']; line(myline(:,1),myline(:,2),'LineWidth',5); hold off
Notes
which vertices you click is not important: the only requirement is that the first vertex is adjacent to the other three. also, note that the algorithm works, more generally, on parallelepipeds.