# -*- coding: utf-8 -*-

#  Copyright © 2013  B. Clausius <barcc@gmx.de>
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.

import math
import numpy


class vec3 (numpy.ndarray):
    def __new__(cls, x=0., y=0., z=0.):
        buf = numpy.array([x, y, z], dtype='f')
        return numpy.ndarray.__new__(cls, (3,), dtype='f', buffer=buf)
        
    def _seti(self, i, value):
        self[i] = value
        return value
    x = property(lambda self: self[0], lambda self, value: self._seti(0, value))
    y = property(lambda self: self[1], lambda self, value: self._seti(1, value))
    z = property(lambda self: self[2], lambda self, value: self._seti(2, value))
    
    
class vec4 (numpy.ndarray):
    def __new__(cls, x=0., y=0., z=0., w=1.):
        buf = numpy.array([x, y, z, w], dtype='f')
        return numpy.ndarray.__new__(cls, (4,), dtype='f', buffer=buf)
        
    def _seti(self, i, value):
        self[i] = value
        return value
    x = property(lambda self: self[0], lambda self, value: self._seti(0, value))
    y = property(lambda self: self[1], lambda self, value: self._seti(1, value))
    z = property(lambda self: self[2], lambda self, value: self._seti(2, value))
    w = property(lambda self: self[3], lambda self, value: self._seti(3, value))
    
    
class mat4(numpy.ndarray):
    def __new__(cls, diag=1.):
        buf = numpy.array([[diag, 0., 0., 0.],
                           [0., diag, 0., 0.],
                           [0., 0., diag, 0.],
                           [0., 0., 0., 1.]], dtype='f')
        return numpy.ndarray.__new__(cls, (4,4), dtype='f', buffer=buf)
        
        
def rotate(angle, vect):
    result = mat4()
    x = vect[0]
    y = vect[1]
    z = vect[2]
    c = math.cos(angle)
    s = math.sin(angle)
    result[0][0] = x*x*(1-c) + c
    result[0][1] = x*y*(1-c) - z*s
    result[0][2] = x*z*(1-c) + y*s
    result[1][0] = y*x*(1-c) + z*s
    result[1][1] = y*y*(1-c) + c
    result[1][2] = y*z*(1-c) - x*s
    result[2][0] = x*z*(1-c) - y*s
    result[2][1] = y*z*(1-c) + x*s
    result[2][2] = z*z*(1-c) + c
    return result
    
