1.1 Working with Coordinates



Part I - Cartesian Coordinates

The creation of geometry presupposes the positioning of elements in space, expressed in terms of coordinates. Probably the most common and known coordinate system is the Cartesian System where the position of a point p in space is described as (x,y,z), i.e., using a tuple of three coordinates – coordinate X (abscissa), coordinate Y (ordinate) and coordinate Z (applicate). This sequence of coordinates is shown in Figure 1.



FIGURE 1 | The Cartesian Coordinate System

In Rosetta this coordinate system is implemented using the function XYZ. Go ahead and launch DrRacket if you haven’t done so and let’s try this out in the Interpreter:

> (xyz 1 2 3)
# <xyz 1 2 3>
> (xyz (* 2 3) (+ 4 1) (- 6 2))
# <xyz 6 5 4>

We can see the evaluation of an expression such as (xyz 1 2 3) is a value that represents a position in space and that you can also easily use algebraic operations with the xyz function. Keep in mind you are not creating a point in space. We are merely specifying a location in space with so side effects in the CAD. If we actually want to see something happening in our CAD application we could use the function point and feed it the coordinates we want:

> (point (xyz 0 0 0))
(point (xyz 10 0 0))
(point (xyz 10 10 0))
(point (xyz 0 10 0))
#<point 0>
#<point 1>
#<point 2>
#<point 3>

FIGURE 2 | A series of points

Once we know how to specify positions in space we can start playing around with some useful functions in Rosetta that take coordinates as arguments. One such useful operation is being able to select a specific coordinate from a tuple of three coordinates. By using the functions cx , cy and cz we can easily retrieve the x, y and z coordinates respectively:

> (cx (xyz 1 2 3))
1
> (cy (xyz 0 6 3))
6
> (cz (xyz 7 2 3))
3

We can also build a new point with the coordinates of other points:

> (xyz (cx (xyz 1 2 3))
     (cy (xyz 0 6 3))
     (cz (xyz 7 2 3)))
#<xyz:1 6 3>

Another example would be the function distance which computes the distance between two points.

> (distance (xyz 0 0 0)
            (xyz 0 0 5))
5
> (distance (xyz 4 1 0)
            (xyz 3 5 11))
11.74734012447073

Let’s consider now that we want to apply a translation to a specific location, i.e., we what to define a new location in space in terms of another. By using the function +xyz we can specify a starting point and the respective increments in x, y and z as is shown in Figure 3.



FIGURE 3 | Applying a translation to a position

The functions xyz and +xyz need to receive the values as arguments, one for each coordinate. But consider that the positions in space we want to specify is only on the XY or XZ plane, or the translation we want to compute is only along the x or y axis? Naturally Rosetta also provides more particular functions for these operations. For defining positions in space Rosetta provides the functions xyz and the variants x , y , z , xy , xz and yz :

> (x 5)
#<xyz:5 0 0>
> (y 3)
#<xyz:0 3 0>
> (z 11)
#<xyz:0 0 11>
> (xy 4 2)
#<xyz:4 2 0>
> (xz 9 5)
#<xyz:9 0 5>
> (yz 1 5)
#<xyz:0 1 5>

And for computing translation Rosetta provides the functions +xyz and the variants +x , +y , +z for horizontal and vertical translations, and +xy , +xz , +yz for diagonal translations:

> (+x (xyz 0 0 0) 5)
#<xyz:5 0 0>
> (+y (xyz 0 0 0) 7)
#<xyz:0 7 0>
> (+z (xyz 0 0 0) 2)
#<xyz:0 0 2>
> (+xy (xyz 0 0 0) 2 5)
#<xyz:2 5 0>
> (+xz (xyz 0 0 0) 11 4)
#<xyz:11 0 4>
> (+yz (xyz 0 0 0) 3 9)
#<xyz:0 3 9>

These are just some basic contractors and selectors provided by Rosetta and we can put them to good use to define new functions. For example, if we want to define a function for calculating the midpoint between two points, given by the formula:

$$M=\left (\frac{x_1 + x_2}{2}, \frac{y_1 + y_2}{2}, \frac{z_1 + z_2}{2}\right )$$

We can easily define this function in Racket:

(define (midpoint p1 p2)
  (xyz (/ (+ (cx p1) (cx p2)) 2)
       (/ (+ (cy p1) (cy p2)) 2)
       (/ (+ (cz p1) (cz p2)) 2)))

> (midpoint (xyz 1 2 0) (xyz 3 5 9))
#<xyz:2 3 1/2 4 1/2>

Notice that we first use the constructor xyz since we want result to be a point and then we use the selectors cx , cy and cz to select specific coordinates from the two points p1 and p2.

Or if we want to define the function that computes the minimum distance between a point and a line given by the formula:

$$d = \frac{\left | (x_2-x_1)(y_1-y_0)-(x_1-x_0)(y_2-y_1) \right |}{\sqrt{(x_2-x_1)^2+(y_2-y_1)^2}}$$

This function needs to take as arguments three points: the point p0 to calculate the distance to, and the two line extremities p1 and p2:

(define (pt-line-distance p0 p1 p2)
  (/ (abs (- (* (- (cx p2) (cx p1)) (- (cy p1) (cy p0)))
             (* (- (cx p1) (cx p0)) (- (cy p2) (cy p1)))))
     (sqrt (+ (sqr (- (cx p2) (cx p1)))
              (sqr (- (cy p2) (cy p1)))))))

> (pt-line-distance (xyz 2 0 8) (xyz 0 0 0) (xyz 2 4 10))
1.7888543819998317

Or perhaps a more architectural useful function, a function that calculates the minimum number of steps in a stair needed to cover a determined height. Considering that each riser cannot be more than 0.18cm high we know that all we need to do is divide the total rise distance, i.e., the z coordinate of point p1, by that distance. That distance can be calculated by subtracting the z coordinate of p1 to the z coordinate of p0:

(define (minimum-steps p0 p1)
  (floor (/ (- (cz p1) (cz p0)) 0.18)))

> (minimum-steps (xyz 0 0 0) (xyz 10 20 10))
66.0

We included a floor form in this definition because we want round the final value down.



Part II - Polar Coordinates

For most cases Cartesian coordinates are enough for what we want to achieve but in certain occasions it might prove more useful to make use of other coordinate systems. If for example we want to determine locations in space that are equally spaced from an origin point. Understanding that these points would fall within a circle then it would be much more useful to specify those locations in terms of a radius and an angle. In Figure 4 we see a sketch of this idea.



FIGURE 4 | A set of locations equally spaced from an origin point

For such cases Rosetta provides the coordinate constructor pol which builds polar coordinates. Once more we can use the function point to see the results:

> (point (pol 5 0))
(point (pol 5 pi/4))
(point (pol 5 pi/2))
(point (pol 5 (* 3 pi/4)))
(point (pol 5 pi))
#<point 0>
#<point 1>
#<point 2>
#<point 3>
#<point 4>

Rosetta also provides the respective selectors for polar coordinates. Using the function pol-rho we can select the polar axis and using the function pol-phi we can select the polar angle. For computing translations we can use the functions +pol , +rho and +phi :

> (+pol (xy 1 2) (sqrt 2) (/ pi 4))
#<xyz 2.0 3.0 0>
> (+pol (xy 1 2) 1 0)
#<xyz 2 2 0>
> (+pol (xy 1 2) 1 (/ pi 2))
#<xyz 1.0 3.0 0>



Part III - Cylindrical Coordinates

Besides Cartesian and polar coordinates we can also specify a position in Cylindrical coordinates, in which the position is expressed in terms of a radius, an angle with the X axis and height.



FIGURE 5 | Cylindrical coordinates

For using cylindrical coordinates Rosetta provides the operator cyl and +cyl for applying a translation vector specified by its intensity, direction and height :

> (cyl 10 pi/4 5)
#<xyz:7.0710678118654755 7.071067811865475 5>
> (cyl 2.5 pi 8.2)
#<xyz:-2.5 3.061616997868383e-016 8.2>
> (cyl 2 0 8)
#<xyz:2 0 8>

> (+cyl (pol 2 pi/3) 4 pi/3 5)
#<xyz:3.000000000000001 5.196152422706632 5>
> (+cyl (xyz 0 3 0) 2 -pi/2 8)
#<xyz:1.2246467991473532e-016 1.0 8>
> (+cyl (cyl 3.2 0 4) 1.5 pi/4 3)
#<xyz:4.260660171779822 1.0606601717798212 7>

A good example where cylindrical coordinates can be very useful is when we want to model a spiral staircase. Simplifying the process and thinking merely in terms of structure, we can think of a step as a line of which the outer endpoint is specified in cylindrical coordinates:

(line (z  0) (cyl 10 0   0))
(line (z  2) (cyl 10 0.5 2))
(line (z  4) (cyl 10 1   4))
(line (z  6) (cyl 10 1.5 6))
(line (z  8) (cyl 10 2   8))
(line (z 10) (cyl 10 2.5 10))
(line (z 12) (cyl 10 3   12))
(line (z 14) (cyl 10 3.5 14))
(line (z 16) (cyl 10 4   16))
(line (z 18) (cyl 10 4.5 18))
(line (z 20) (cyl 10 5   20))
(line (z  0) (xyz 0 0 20))



FIGURE 6 | Sketch of a spiral staircase



Part IV - Spherical Coordinates

Lastly we can also specify a position using spherical coordinates. A point in spherical coordinates is specified in terms of a radius, the azimuth and zenith by using the operator sph . We also have the operator +sph for applying a translation vector to a given position specified by its intensity, longitudinal direction and polar direction.



FIGURE 7 | Spherical coordinates



Part V - Vectors

So far we have been looking at coordinates as mere positions in space but in certain situations it might also prove useful to look at coordinates as vectors. In this perspective a coordinate can be seen as the extremity of a vector positioned at the origin, as shown in Figure 5.



FIGURE 5 | Vector perspective of the concept of coordinates

The great advantage in working with vectors is that it provides us with a new algebra for working with them. Some of those operations provided by Rosetta are the sum between two vectors +c , the subtraction between two vectors –c , the scalar multiplication *c and finally the scalar division /c :

> (+c (xyz 1 1 1) (xyz 2 2 2))
#<xyz:3 3 3>
> (-c (xyz 1 1 1) (xyz 2 2 2))
#<xyz:-1 -1 -1>
> (*c (xyz 1 1 1) 2)
#<xyz:2 2 2>
> (-c (xyz 1 1 1) (xyz 2 2 2))
#<xyz:-1 -1 -1>

These operations become very useful if we want to use a specific orientation for our models. In 1.9 Modelling Classic Doric Temples we will see a direct application of these functions.

If all we wish to do is specify a direction parallel to the orthogonal axes then we can apply the concept of unit vector, i.e., a vector of length 1. For that Rosetta provides the functions ux , uy and uz as well as their inverse equivalents –ux , –uy and –uz , which define a unit vector parallel to the x, y and z axes respectively. We can also use u0 to define an origin point.

> (u0)
#<xyz:0 0 0>
> (ux)
#<xyz:1 0 0>
> (-ux)
#<xyz:-1 0 0>
> (uy)
#<xyz:0 1 0>
> (-uy)
#<xyz:0 -1 0>
> (uz)
#<xyz:0 0 1>
> (-uz)
#<xyz:0 0 -1>



In this tutorial we had a look at how to define locations in space using two different coordinate systems. We also saw how we can select specific coordinates and how to apply translations to predetermined positions. The choice of which coordinate system to use is obviously up to the user and they all wield the same result but understanding which coordinate system is more convenient to the situation at hand is a great step towards assuring our programs aren’t overly complicated with unnecessary calculations. Take some time to get the hang of these functions and once you’re ready move on to the next tutorial where we will see how to use them to create linear geometry.

Top