paiza.ioでelixir その70

# 概要
paiza.ioでelixirやってみた。
Ray Tracerやってみた。

# 参考にしたページ

https://qiita.com/masatam81/items/eb638eee5a8a8c8589a4

# サンプルコード

```

defmodule Vector do
    defmodule Vec3 do
        defstruct x: 0.0, y: 0.0, z: 0.0
        alias Vector.Vec3, as: Vec3
        def vec3(list) when is_list(list) do
            [x | rest] = list
            [y | [z]] = rest
            %Vec3{x: x, y: y, z: z}
        end
        def ones() do
            %Vec3{x: 1.0, y: 1.0, z: 1.0}
        end
        def add(vec1, vec2) do
            %Vec3{x: vec1.x + vec2.x, y: vec1.y + vec2.y, z: vec1.z + vec2.z }
        end
        def dot(vec1, vec2) do
            vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z
        end
        def mult(vec1, vec2) do
            %Vec3{x: vec1.x * vec2.x, y: vec1.y * vec2.y, z: vec1.z * vec2.z }
        end
        def scale(vec, s) do
            %Vec3{x: vec.x * s, y: vec.y * s, z: vec.z * s }
        end
        def sub(vec1, vec2) when is_map vec2 do
            %Vec3{x: vec1.x - vec2.x, y: vec1.y - vec2.y, z: vec1.z - vec2.z }
        end
        def sub(vec, s) do
            %Vec3{x: vec.x - s, y: vec.y - s, z: vec.z - s}
        end
        def len(vec) do
            :math.sqrt(lengthSqr(vec))
        end
        def lengthSqr(vec) do
            vec.x * vec.x + vec.y * vec.y + vec.z * vec.z
        end
        def div(vec, scalar) do
            %Vec3{x: vec.x / scalar, y: vec.y / scalar, z: vec.z / scalar}
        end     
        def unit_vector(vec) do
            s = len(vec)
            Vec3.div(vec, s)
        end
        def cross(vec1, vec2) do
            x = vec1.y * vec2.z - vec1.z * vec2.y
            y = vec1.z * vec2.x - vec1.x * vec2.z
            z = vec1.x * vec2.y - vec1.y * vec2.x
            %Vec3{x: x, y: y, z: z}
        end
        def to_list(vec3) do
            [vec3.x, vec3.y, vec3.z]
        end
    end
end
defmodule Ray do
    alias Vector.Vec3, as: Vec3
    defstruct pos: %Vec3{}, dir: %Vec3{}
    def at(vec, t), do: Vec3.add(vec.pos, (Vec3.scale(vec.dir, t)))
end
IO.puts """
<!doctype html>
<html>
  <head>
    <link rel="stylesheet" href="lib/style.css">
  </head>
  <body>
    <canvas id="canvas" width="80" height="60"></canvas>
    <script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var img = ctx.createImageData(80, 60);
var data = img.data;
var v = [
"""
defmodule Main do
    require Vector
    require Ray
    alias Vector.Vec3, as: Vec3
    nx = 80
    ny = 60
    low_left = Vec3.vec3([-2.0, -1.0, -1.0])
    horizontal = Vec3.vec3([4.0, 0.0, 0.0])
    vertical = Vec3.vec3([0.0, 2.0, 0.0])
    origin = Vec3.vec3([0.0, 0.0, 0.0])
    for y <- ny - 1..0 do
        for x <- 0..nx - 1 do
            u = x / nx
            v = y / ny
            ray = %Ray{
                pos: origin, 
                dir: Vec3.scale(horizontal, u) 
                |> Vec3.add(Vec3.scale(vertical, v)) 
                |> Vec3.add(low_left)
            }   
            unit_vec = Vec3.unit_vector(ray.dir)
            t = 0.5 * (unit_vec.y + 1.0)
            color = Vec3.scale(Vec3.ones(), (1.0 - t))
                |> Vec3.add(Vec3.scale(Vec3.vec3([0.5, 0.7, 1.0]), t))
            [color.x, color.y, color.z] 
            |> Enum.map(fn n ->
                255 * n
                |> floor
                |> IO.write
                IO.write ","
		    end)
		    IO.write "255,"
        end
    end
end
IO.puts """

0];
for (var i = 0; i < 80 * 60 * 4; i++) 
{
	data[i] = v[i];
}
    ctx.putImageData(img, 0, 0);
//alert(v[2]);
    </script>
  </body>
</html>
"""


```

# 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/f669aee4-8d48-49ba-b1de-2b4e01c3b3a3.png)


# 成果物

https://paiza.io/projects/iswN0q8fOJJTX5zoJ26i5w?language=elixir


以上。