```python
from decodes.core import *
from decodes.io.jupyter_out import JupyterOut
out = JupyterOut.unit_square( )
```

# Vectors in Cartesian Space

A vector in Cartesian three-dimensional space, denoted by $\mathbb{R}^3$, can be described by a collection of three numbers $(x,y,z)$. As this construction is identical to that of a Cartesian point, it is not surprising that a vector and a point are closely related. In fact, we say that a point in Cartesian space is identified by its corresponding vector. By convention, we will denote a point by a capital letter, such as $P$, and a vector whose head is at that point using the same letter in lower case with an arrow on top, $\vec{p}$ . Notice that this notational convention holds even when operations are applied; for instance, the head of vector $\vec{p}_{1} + \vec{p}_{2}$ is the point $P_{1} + P_{2}$.



In specifying vectors in Cartesian three-dimensional space, we are able to move from a purely diagrammatic representation of a vector to a numerical representation. The operations previously represented geometrically can then be expressed algebraically, and then in code.

## Vec Objects in Decod.es



In the Decod.es library, a Vec is an object with three members - `vec.x`, `vec.y`, and `vec.z` - each of which is assigned a numeric value, typically the Python primitive type Float.

<table style="width:600px">
    
<tr>
    <th colspan="3" style="text-align:left">*Vec Members*</th>
</tr>

<tr>
    <td style="width:10%">`vec.x`<br>`vec.y`<br>`vec.z`</td>
    <td style="width:10%">Float</td>
    <td style="width:80%">Numeric values that determine the x,y and z coordinates of the head of the vector.</td>
</tr>

</table>

### Vec Initialization

A vector in $\mathbb{R}^3$ could be initialized simply by requesting values for its three coordinates, and assigning these to its three numeric members.




```python
"""
Vector Initialization from Coordinates
"""
class Vec(Geometry):   
    
    def __init__(self, a, b, c=0):
        self.x = a
        self.y = b
        self.z = c
```

Alternatively, it is often convenient in practice to initialize a vector by two points, by its tail at a given “start point” and its head at a given “end point”.


```python
"""
Vector Initialization from Points
"""
class Vec(Geometry):   
    
    def __init__(self, a, b):
        self.x = b.x - a.x
        self.y = b.y - a.y
        self.z = b.z - a.z    
```


```python
"""
Vector Construction 
"""
# construction by coordinates
vec_a = Vec(0,1,1)

# construction by points
vec_b = Vec(pt_a,pt_b)
```

### Elemental Vec Methods
Each of the elemental vector operations presented diagrammatically may also be defined algebraically using component-wise arithmetic, and thereby implemented in code. This is the basis for some of the most important methods of the Vec class. For example, the addition of two vectors $\vec{v_{1}} = (x_{1},y_{1},z_{1})$ and $\vec{v_{2}} = (x_{2},y_{2},z_{2})$ is given by:

\begin{align}
\vec{v_{1}} + \vec{v_{2}} = (x_{1}+x_{2} , y_{1}+y_{2} , z_{1}+z_{2})
\end{align}

An implementation in code immediately follows:


```python
"""
Vector Addition
"""
def vec_plus_vec(vec_a, vec_b):
    return Vec(vec_a.x+vec_b.x , vec_a.y+vec_b.y, vec_a.z+vec_b.z)

vec_c = vec_a + vec_b
```


```python
"""
Vector Scalar Multiplication
"""
def vec_times_scalar(vec,scl):
    return Vec(vec.x * scl, vec.y * scl, vec.z * scl)

vec_b = vec_a * 2.0
```


```python
"""
Vector Subtraction
"""
def vec_minus_vec(vec_a, vec_b):
    return Vec(vec_a.x-vec_b.x , vec_a.y-vec_b.y, vec_a.z-vec_b.z)

vec_c = vec_a - vec_b
```

The above methods are so common, they have each been defined as a special method that relates them to a corresponding operator.

Besides these operations, the Decod.es Vec object packages a number of other routines as instance methods, static methods, and properties

### Other Vec Methods

The `vec.inverted()` method is a typical instance method, and offers us a straightforward example of some of the issues involved in structuring a geometric routine as a method of a class. Even in a simple case such as this, questions surrounding implementation arise. 

For example, the Decod.es Vec class might have defined an inversion method that modifies an existing vector in place. In such a case, no return value would need to be specified:


```python
"""
Vector Inversion in Place
The given vector is modified, and nothing is returned
"""
def invert(self):
    self.x = -self.x
    self.y = -self.y
    self.z = -self.z
```

Alternatively, we might define a method that constructs an entirely new Vec based upon a vector on which we are operating, but leaving the latter completely unaltered.


```python
"""
Vector Inversion by Construction
Rather than inverting the vector in place, 
a new vector is constructed and returned
"""
def inverted(self):
    return Vec(-self.x,-self.y,-self.z)
```

The Vec class defines a host of instance methods in a manner similar to the `Vec.inverted()` method.




<table style="width:600px">
    
<tr>
    <th colspan="3" style="text-align:left">*Selected Vec Methods*</th>
</tr>

<tr>
    <td style="width:20%">`vec.dot(other)`</td>
    <td style="width:20%">Float</td>
    <td style="width:60%">Computes the dot product of self and other.</td>
</tr>

<tr>
    <td style="width:20%">`vec.cross(other)`</td>
    <td style="width:20%">Vec</td>
    <td style="width:60%">Returns a new vector that lies at right angles to self and other.</td>
</tr>

<tr>
    <td style="width:20%">`vec.normalized(length)`</td>
    <td style="width:20%">Vec</td>
    <td style="width:60%">Returns a new vector that lies in the same direction as self, but at a given length.</td>
</tr>

<tr>
    <td style="width:20%">`vec.projected(other)`</td>
    <td style="width:20%">Vec</td>
    <td style="width:60%">Returns a new vector that results from projecting self onto other.
</td>
</tr>

<tr>
    <td style="width:20%">`vec.inverted()`</td>
    <td style="width:20%">Vec</td>
    <td style="width:60%">Returns a new vector that lies in the opposite direction as self.</td>
</tr>

<tr>
    <td style="width:20%">`vec.angle(other)`</td>
    <td style="width:20%">Float</td>
    <td style="width:60%">Returns the angle in radians between self and other.</td>
</tr>

</table>

### Vec Properties

We may recall that a property is a derivative trait of an object that requires calculation but does not require any external information.

Of the properties of a Vec, the `vec.tup` property is typical. This routine fits the mandate of a property: while derivative of more elemental members, this trait is fairly intrinsic to the nature of a Vec, requires only modest amount of computation to produce, and does not require any external information.


```python
"""
The Tup Property of a Vec
Returns a list of three numeric values representing the x, y, 
and z coordinates of this vector
"""
@property
def tup(self):
    return self._x,self._y,self._z
```



<table style="width:600px">
    
<tr>
    <th colspan="3" style="text-align:left">*Selected Vec Properties*</th>
</tr>

<tr>
    <td style="width:20%">`vec.tup`</td>
    <td style="width:20%">(Float,Float,Float)</td>
    <td style="width:60%">The three coordinates of this vector described simply as a Tuple of three numbers.</td>
</tr>

<tr>
    <td style="width:20%">`vec.length2`</td>
    <td style="width:20%">Float</td>
    <td style="width:60%">The squared length of this vector. Due to the nature of the distance formula, this property is cheaper to calculate than `vec.length`.</td>
</tr>

<tr>
    <td style="width:20%">`vec.length`</td>
    <td style="width:20%">Float</td>
    <td style="width:60%">The length of this vector.</td>
</tr>


</table>

### Vec Static Methods

There are situations in which we want to define a function that is not associated with any one particular member of the class, but is so closely related that it deserves to be *“bundled”* within the class definition. Such functions are termed **static methods**.

A good example of a static method is the interpolation function.

Mathematically, vector interpolation may be thought of as a kind of weighted average of two vectors. The result of this process is a third vector at some location between the heads of the two given vectors, as determined by a given factor `t`. Since there is no hierarchical distinction between the two input vectors, it is logical that this function belongs to neither of them, but rather acts as a stand-alone function which takes both as arguments:







```python
"""
Vector Interpolation
Calculates and returns the vector that results from an interpolation 
between two given vectors at parameter t.
"""
@staticmethod
def interpolate(vec_a,vec_b,t=0.5):
    x = (1-t) * vec_a.x + t * vec_b.x
    y = (1-t) * vec_a.y + t * vec_b.y
    z = (1-t) * vec_a.z + t * vec_b.z
    return Vec(x,y,z)
```

Note the `@staticmethod` expression that precedes this function definition, which marks it as a static method belonging to the class rather than an instance method belonging to individual objects of this class.

We can treat static methods like any other function, and recognize them in code as a call not on Vec objects, but on the Vec class itself.


```python
"""
Calling a Static Method
The static interpolate method of the Vec class may be evoked as seen here
"""
Vec.interpolate(some_vector, another_vector, 0.25)
```

<table style="width:600px">
    
<tr>
    <th colspan="3" style="text-align:left">*Vec Static Methods*</th>
</tr>

<tr>
    <td style="width:20%">`vec.interpolate(vec_a, vec_b, t)`</td>
    <td style="width:20%">Vec</td>
    <td style="width:60%">Returns the weighted average of two given vectors.</td>
</tr>

</table>

## Point Objects in Decod.es

A Point is described as a special kind of Vec, such that anything that a Vec can do, so can a Point. This relationship is termed **inheritance**. A majority of the behavior and regular usage of Point objects is colored by this relationship to the Vec class.

Point inherits the structure of Vec, storing three members - `pt.x`,
`pt.y`, and `pt.z`



Mathematically, we say that a point is identified by the vector whose head lies at that position. From an object-oriented design point of view, a Point and Vec can be represented by an object that stores and manages three numeric coordinates as members.

<table style="width:600px">
    
<tr>
    <th colspan="3" style="text-align:left">*Point Members*</th>
</tr>

<tr>
    <td style="width:10%">`pt.x`<br>`pt.y`<br>`pt.z`</td>
    <td style="width:10%">Float</td>
    <td style="width:80%">Numeric values that determine the x,y and z coordinates of the head of the point.</td>
</tr>

</table>

For example, the calculation of the centroid of a set of points is mathematically equivalent to computing the average of the corresponding set of vectors. The implementation of the static `Point.centroid()` method can simply wrap the `Vec.average()` method, converting the return value so that a Point is produced.


```python
"""
The Centroid of a Set of Points
Since the centroid of a set of points is equivalent to the average 
of the corresponding set of vectors, the Point class may evoke the 
corresponding method of the Vec class.
"""
@staticmethod
def centroid(points):
    return Point( Vec.average(points) )
```

The trade-off to this approach of having a point inherit the behavior of a vector is that some strangeness can occur. This is evident when we consider that one is permitted to “invert” a Point. A call to the `Vec.inverted()` method from a Point object results in a location mirrored about the origin. Furthermore, the `vec.inverted()` method returns a new Vec, so the result of calling `pt.inverted()` will also be a Vec, not a Point.


```python
"""
The Strange Case of Point Inversion
Just like a Vec, a Point may be "inverted". Strangely, and due to 
the nature of inheritance, this operation results in a Vec
"""
# results in a Vec at (0,-1)
vec_a = Vec(0,1).inverted()

# also results in a Vec at (0,-1)
vec_b = Point(0,1).inverted()
```

At times such behavior is harmless, and at other times unacceptable. 

For `pt.projected()`, for example, we expect to get the point that results from projecting onto the given vector. Since Point inherits this method from Vec, without intervention, the result would be a Vec. In such a case, we must adjust the superclass method such that the result is cast into the type we desire, a technique termed **method overriding**.


```python
"""
Overriding the Projected Method
Points inherit the projected method from the Vec superclass, and 
override it so that a Point is returned rather than a Vec
"""
def projected(self, other):
    return Point( Vec(self.x,self.y,self.z).projected(other) )
    
# results in a Point projected on the given vector    
pt_a.projected(vec_a)
```

Most of the routines used by Points are already implimented in Vec. Among the few exceptions are procedures that are unique to points, such as finding nearest neighbors, via the `Point.near()` method shown below.


```python
"""
Nearest Point Method
Returns a point from the given list of points which is nearest to 
the given source point.
"""
@staticmethod
def near(pt, pts):
    # a syntax called 'list comprehension', see Chapter Four
    dists = [pt.distance2(p) for p in pts]
    near_index = dists.index(min(dists))
    return pts[near_index]

```

287b22dac92d7cbe70034dbfde58900aac1b0acb
ipynb
Jupyter Notebook
103 - Points, Vectors, and Coordinate Systems/076 - Vectors in Cartesian Space.ipynb
ksteinfe/decodes_ipynb
2e4bb6b398472fc61ef8b88dad7babbdeb2a5754
MIT
2018-05-15T14:31:23.000Z
2018-05-15T14:31:23.000Z
103 - Points, Vectors, and Coordinate Systems/076 - Vectors in Cartesian Space.ipynb
ksteinfe/decodes_ipynb
2e4bb6b398472fc61ef8b88dad7babbdeb2a5754
MIT
103 - Points, Vectors, and Coordinate Systems/076 - Vectors in Cartesian Space.ipynb
ksteinfe/decodes_ipynb
2e4bb6b398472fc61ef8b88dad7babbdeb2a5754
MIT
2020-05-19T05:40:18.000Z
2020-06-28T02:18:08.000Z
Qwen/Qwen-72B
1. YES
2. YES