Vectors

There are two data structures to represent a vector in two-dimensional space, of components \((x, y)\):

digraph Vector2D {
Vector2D -> "CVector2D*"
"CVector2D*" -> x
"CVector2D*" -> y
"CVector2D*" [fillcolor=gray,style="rounded,filled"]
x [fillcolor=gray,style="rounded,filled"]
y [fillcolor=gray,style="rounded,filled"]
}

CVector2D C structure

A CVector2D has just two members, to store its components:

CVector2D
double x
double y
In [2]:
%%cython

from libc.stdio cimport printf
cimport geomalgo as ga

cdef:
    ga.CVector2D u

u.x = 1
u.y = 2

printf('u: (%.1f, %.1f)\n', u.x, u.y)
u: (1.0, 2.0)

CVector2D can be allocated and destroyed with these functions:

CVector2D* new_vector2d()
void del_vector2d(CVector2D* V)

Note

This functions are rarely used, as C structure in GeomAlgo are usually stack-allocated.

In [5]:
%%cython

from libc.stdio cimport printf
cimport geomalgo as ga

cdef:
    ga.CVector2D* u

u = ga.new_vector2d()

u.x = 1
u.y = 2

printf('u: (%.1f, %.1f)\n', u.x, u.y)

ga.del_vector2d(u)
u: (1.0, 2.0)

Vector2D Python extension

A Vector2D take components as arguments.

class Vector2D(x, y)

Attributes:

cvector2d: CVector2D*
In [6]:
u = ga.Vector2D(1, 2)
print(u)
<Vector2D(1.0,2.0>

The wrapped C structure Vector2D.cvector2d is accessible only using Cython.

In [8]:
%%cython

from libc.stdio cimport printf
cimport geomalgo as ga

cdef:
    ga.Vector2D u
    ga.CVector2D* ptr

u = ga.Vector2D(1, 2)

ptr = u.cvector2d
printf("(%.1f, %.1f)\n", ptr.x, ptr.y)
(1.0, 2.0)

Get and set components

CVector2D members are accessed directly to get and set coordinates:

In [9]:
%%cython

from libc.stdio cimport printf
cimport geomalgo as ga

cdef:
    ga.CVector2D u

u.x, u.y = 1, 2
printf("u: (%.1f, %.1f)\n", u.x, u.y)

u.x, u.y = 4, -5
printf("u: (%.1f, %.1f)\n", u.x, u.y)
u: (1.0, 2.0)
u: (4.0, -5.0)

Vector2D as two properties x and y to get/set coordinates from/to its underlying cvector2d attribute:

Vector2D.x
Vector2D.y
In [10]:
u = ga.Vector2D(1, 2)
print(u)

u.x, u.y = 4, -5
print(u)
<Vector2D(1.0,2.0>
<Vector2D(4.0,-5.0>

Vector operators

Vectors addition

Compute the vector \(\mathbf{AC} = \mathbf{AB} + \mathbf{BC}\)

Vector2D.__add__(self, other)
In [16]:
AB = ga.Vector2D(0, 1)
BC = ga.Vector2D(1, 1)

AC = AB + BC
print(AC)
<Vector2D(1.0,2.0>
void add_vector2d(CVector2D *AC, CVector2D *AB, CVector2D *BC)

AC must be already allocated.

In [18]:
%%cython

from libc.stdio cimport printf
cimport geomalgo as ga

cdef:
    ga.CVector2D AB, BC, AC

AB.x, AB.y = 0, 1
BC.x, BC.y = 1, 1

ga.add_vector2d(&AC, &AB, &BC)
printf("(%.1f, %.1f)\n", AC.x, AC.y)
(1.0, 2.0)

Vectors substraction

Compute the vector \(\mathbf{AB} = \mathbf{AC} - \mathbf{BC}\)

Vector2D.__sub__(self, other)
In [21]:
AC = ga.Vector2D(1, 2)
BC = ga.Vector2D(1, 1)

AB = AC - BC
print(AB)
<Vector2D(0.0,1.0>
void subtract_vector2d(CVector2D *AB, CVector2D *AC, CVector2D *BC)

AB must be already allocated.

In [22]:
%%cython

from libc.stdio cimport printf
cimport geomalgo as ga

cdef:
    ga.CVector2D AB, BC, AC

AC.x, AC.y = 1, 2
BC.x, BC.y = 1, 1

ga.subtract_vector2d(&AB, &AC, &BC)
printf("(%.1f, %.1f)\n", AB.x, AB.y)
(0.0, 1.0)

Vector multiplication

Compute the vector \(\mathbf{t} = \alpha \mathbf{u}\)

Point2D.__mul__(self, alpha)
In [24]:
u = ga.Vector2D(1, 2)
t = u*2
print(t)
<Vector2D(2.0,4.0>
void vector2d_times_scalar(CVector2D *t, double alpha, CVector2D *u)

t must be already allocated.

In [26]:
%%cython

from libc.stdio cimport printf
cimport geomalgo as ga

cdef:
    ga.CVector2D u, t

u.x, u.y = 1, 2
ga.vector2d_times_scalar(&t, 2., &u)
printf("(%.1f, %.1f)", t.x, t.y)
(2.0, 4.0)

Vectors dot product

Compute the dot product \(u_x v_x + u_y v_y\) between vectors \(\mathbf{u}\) and \(\mathbf{v}\).

Point2D.dot(self, other)
In [29]:
u = ga.Vector2D(1, 2)
v = ga.Vector2D(3, 4)
u.dot(v)
Out[29]:
11.0
double dot_product2d(CVector2D *u, CVector2D *v)
In [32]:
%%cython

from libc.stdio cimport printf
cimport geomalgo as ga

cdef:
    ga.CVector2D u, v

u.x, u.y = 1, 2
v.x, v.y = 3, 4

printf("%.1f\n", ga.dot_product2d(&u, &v))
11.0

Vectors cross product

Compute the cross product \(u_x v_y - u_y v_x\) between vectors \(\mathbf{u}\) and \(\mathbf{v}\).

Point2D.__xor__(self, other)
In [33]:
u = ga.Vector2D(1, 2)
v = ga.Vector2D(3, 4)
u^v
Out[33]:
-2.0
double cross_product2d(CVector2D *u, CVector2D *v)
In [34]:
%%cython

from libc.stdio cimport printf
cimport geomalgo as ga

cdef:
    ga.CVector2D u, v

u.x, u.y = 1, 2
v.x, v.y = 3, 4

printf("%.1f\n", ga.cross_product2d(&u, &v))
-2.0

Norms

Compute the norm \(|\mathbf{u}| = \sqrt{u_x^2 + u_y^2}\).

Vector2D.norm
In [11]:
u = ga.Vector2D(3, 4)
u.norm
Out[11]:
5.0
double compute_norm2d(CVector2D *u)
In [13]:
%%cython

from libc.stdio cimport printf
cimport geomalgo as ga

cdef:
    ga.CVector2D u

u.x, u.y = 3, 4
printf("%.1f\n", ga.compute_norm2d(&u))
5.0

Normalize vector \(\mathbf{u}\) so that its norm \(|\mathbf{u}|\) is 1.

Point2D.normalize(self)
In [14]:
u = ga.Vector2D(3, 4)
u.normalize()
print(u)
print(u.norm)
<Vector2D(0.6,0.8>
1.0
void normalize_vector2d(CVector2D *u)
In [15]:
%%cython

from libc.stdio cimport printf
cimport geomalgo as ga

cdef:
    ga.CVector2D u

u.x, u.y = 3, 4
ga.normalize_vector2d(&u)
printf("(%.1f, %.1f)\n", u.x, u.y)
printf("%.1f\n", ga.compute_norm2d(&u))
(0.6, 0.8)
1.0

Normals

Compute the unitary (\(|\mathbf{u}=1|\) ) normal \(\mathbf{u}\) of vector \(\mathbf{u}\).

Point2D.normal

(property)

In [42]:
u = ga.Vector2D(0, 1)
print(u.normal)
<Vector2D(1.0,-0.0>
void compute_normal2d(CVector2D *n, CVector2D *u, double norm)

norm argument can be previously obtained with compute_norm2d()

n must be already allocated.

In [48]:
%%cython

from libc.stdio cimport printf
cimport geomalgo as ga

cdef:
    ga.CVector2D u, n
    double norm

u.x, u.y = 0, 1

norm = ga.compute_norm2d(&u)
ga.compute_normal2d(&n, &u, norm)
printf("(%.1f, %.1f)\n", n.x, n.y)
(1.0, -0.0)
In [ ]: