Today I want to give some information on the dot-product and provide it’s implementation for out Vector-type in F# (this will be trivial).

The dot-product will be very important for our Raytracer-project because of it’s many uses in analytic-geometry. You can for example decide very easy (see below) if two vectors are perpendicular, you can project vectors on others, give a nice representation of affine-subspaces (planes in 3D space) and a lot more with it.

Indeed if you only remember it’s basic-properties you can easily derive all mentioned above by yourself in case you forgot.

But before looking at those we have to give the definition: The dot-product of two vectors will be a scalar-value (a float-value). You compute it by summing the product of coordinates:

For vectors and we will define the dot-product to be

this translate directly to the following F#-operation for our Vector3-struct:

static member (<*>) (a : Vector3, b : Vector3) = a.X*b.X + a.Y*b.Y + a.Z*b.Z

## Basic properties of the dot-product

### 1 – it’s Commutative

this just states that for vectors and we have

#### Proof

There is not much to say – both multiplication and addition (for real numbers) are commutative so the sum of the products will be too.

#### Test case

[< Test >] member test.``dot-product is symmetric``() = // ARRANGE let a = Vector.Create (-3.22, 2.25, -0.13) let b = Vector.Create (0.0, -6.7, 10.0) // ACT let prod1 = a <*> b let prod2 = b <*> a // ASSERT prod1 |> should equal prod2

### 2 – it’s linear in the first factor

For vectors , and and a scalar this says that

#### Remark:

Because of the first property the same is true for the second component – so we can call it bilinear.

#### Proof:

A simple exercise in “algebra”:

#### Test case

[< Test >] member test.``dot-product is linear for the first factor``() = // ARRANGE let a = Vector.Create (-3.22, 2.25, -0.13) let b = Vector.Create (0.0, -6.7, 10.0) let c = Vector.Create (12.4, -1.7, 3.15) let r = 0.22 // ACT let prod1 = a <*> (r*b + c) let prod2 = r * (a <*> b) + (a <*> c) // ASSERT prod1 |> should equal prod2

## Some Corollaries

### Is one of the factors zero will the dot-product be zero

So is a vector then (note: the zeroes left and right are vectors – the zero in the middle is a scalar )

#### Test case

[< Test >] member test.``dot-product by a zero-vector will always be 0``() = // ARRANGE let v = Vector.Create (-3.22, 2.25, -0.13) let zero = Vector.Zero // ACT let prod1 = v <*> zero let prod2 = zero <*> v // ASSERT prod1 |> should equal 0.0 prod2 |> should equal 0.0

#### Proof

Is almost to easy to bother writing down if we use the definition:

but it follows from the properties above as well (I will put the arrows on top of vectors for now to make it more clear):

As we have: by the second property – using the first we see that this holds for zero as the first factor as well.

### The dot-product of different base-vectors is zero

As a proof just use the definition of the dot-product

#### Test case

[< Test >] member test.``dot-product of different base-vectors is zero``() = // Helper let pairs ls = let rec pairs' ls acc = let pairOne l ls = ls |> List.map (fun l' -> (l, l')) match ls with | [] -> acc | l::ls' -> let acc' = acc@(pairOne l ls') pairs' ls' acc' pairs' ls [] // ARRANGE let baseV = [Vector.E1; Vector.E2; Vector.E3] // ACT let pairProds = baseV |> pairs |> List.map (fun (a,b) -> a <*> b) // ASSERT let check v = v |> should equal 0.0 pairProds |> List.iter check

### The Dot-product of a Vector with itself is the square of it’s length

#### Proof

for proof just use the definition (very easy) or

and using the bilinearity and the fact just seen

as (using the definition again) the dot-product of a base-vector with itself is just 1 this yields the result.

#### Test case

[< Test >] member test.``dot-product of a vector by itself is the square of it's length``() = // ARRANGE let v = Vector.Create (-3.22, 2.25, -0.13) let len2 = Vector.Len2 v // ACT let prod = v <*> v // ASSERT prod |> should equal len2

### Two vectors are perpendicular iFF their dot-product is zero

Ok – this only holds if none of the vectors is zero so please note this!

Test case

[< Test >] member test.``dot-product of perpendicular vectors is zero``() = // ARRANGE let a = Vector.Create (2.0, 1.0, 4.0) let b = Vector.Create (1.0, -1.0, -0.25) // ACT let prod1 = a <*> b let prod2 = b <*> a // ASSERT prod1 |> should equal 0.0 prod2 |> should equal 0.0

#### Proof

Depending on what you take as given this is hard or rather easy. I will take the same approach as the Wikipedia article and invoke the power of the law of cosines – of course you should know why this holds. Well I aside from the proofs mentioned in the wiki-article I immediate think of one using complex analysis (well it’s getting worse ) and one using the dot-product (doh – this one would use just what we want to proof) – so be beware of this.

You can get away with our approach if you look at the geometric definition of perpendicular and use the fact that the base-vectors are. Then you can find similar vectors on the axis (for which the dot-product will be zero) and you can use the fact that there is a matrix transforming your vectors to those similar. Using the definition of matrix-multiplication by forming the dot-product of it’s columns with your vector as the components of the final result will finally yield a proof that does not need the law of cosines but a lot of linear algebra …)

Having vectors and we are interested in the angle between them. Together with the vector those form a triangle like this:

The law of cosines states that (using the square of length law we’ve seen right now):

.

As the left side is and cosine-law reduces to

Now as both vectors have length greater 0 the left side will be zero IFF the cosine on the right is zero and this holds IFF the angle is 90° or 270° so the vectors are perpendicular.

Nice one huh?

Ok I think this is enough for now – next time we will start etching out a very simple ray-tracer by explaining the algorithm and rendering the shape of a 3D-sphere…

Pingback: FunTracer: hitting a sphere | getting #er()

Pingback: FunTracer: the first simple tracer | getting #er()