#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (c) 2012, tamanegi (tamanegi@users.sourceforge.jp)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

import math

# my 3D Vector class

# p0 and p1 must be Vector3D
def getMinVector3D( p0, p1 ):
  ret = Vector3D( p0.x, p0.y, p0.z )
  if p1.x < p0.x:
    ret.x = p1.x
  if p1.y < p0.y:
    ret.y = p1.y
  if p1.z < p0.z:
    ret.z = p1.z
  return ret

def getMaxVector3D( p0, p1 ):
  ret = Vector3D( p0.x, p0.y, p0.z )
  if p1.x > p0.x:
    ret.x = p1.x
  if p1.y > p0.y:
    ret.y = p1.y
  if p1.z > p0.z:
    ret.z = p1.z
  return ret

class Vector3D:
  def __init__( self, x = 0.0, y = 0.0, z = 0.0 ):
    self.x = x
    self.y = y
    self.z = z

  def __add__( self, v ):
    if isinstance( v, Vector3D ):
      ret = Vector3D()
      ret.x = self.x + v.x
      ret.y = self.y + v.y
      ret.z = self.z + v.z
      return( ret )
    elif isinstance( v, float ) or isinstance( v, int ):
      ret = Vector3D()
      ret.x = self.x + v
      ret.y = self.y + v
      ret.z = self.z + v
      return( ret )
    else:
      raise NotImplementedError

  def __sub__( self, v ):
    if isinstance( v, Vector3D ):
      ret = Vector3D()
      ret.x = self.x - v.x
      ret.y = self.y - v.y
      ret.z = self.z - v.z
      return( ret )
    elif isinstance( v, float ) or isinstance( v, int ):
      ret = Vector3D()
      ret.x = self.x - v
      ret.y = self.y - v
      ret.z = self.z - v
      return( ret )
    else:
      raise NotImplementedError

  def __mul__( self, v ):
    if isinstance( v, Vector3D ):
      return( self.x * v.x + self.y * v.y + self.z * v.z )
    elif isinstance( v, float ) or isinstance( v, int ):
      ret = Vector3D()
      ret.x = self.x * v
      ret.y = self.y * v
      ret.z = self.z * v
      return( ret )
    else:
      raise NotImplementedError

  def __div__( self, v ):
    if isinstance( v, float ) or isinstance( v, int ):
      ret = Vector3D()
      ret.x = self.x / v
      ret.y = self.y / v
      ret.z = self.z / v
      return( ret )
    else:
      raise NotImplementedError

  def __str__( self ):
    if isinstance( self.x, int ):
      return( str(self.x).strip() + " " + str(self.y).strip() + " " + str(self.z).strip() )
    elif isinstance( self.x, float ):
      return( ( '%8.3f' % self.x ).strip() + " " + ( '%8.3f' % self.y ).strip() + " " + ( '%8.3f' % self.z ).strip() )
    return ""

  def dot( self, v ):
    return( self * v )

  def cross( self, v ):
    if isinstance( v, Vector3D ):
      ret = Vector3D()
      ret.x = self.y * v.z - self.z * v.y
      ret.y = self.z * v.x - self.x * v.z
      ret.z = self.x * v.y - self.y * v.x
      return( ret )
    else:
      raise NotImplementedError

  def square( self ):
    return( self.x * self.x + self.y * self.y + self.z * self.z )

  def norm( self ):
    return( math.sqrt( self.square() ) )

  def normalize( self ):
    norm = self.norm()
    ret = Vector3D()
    ret.x = self.x / norm
    ret.y = self.y / norm
    ret.z = self.z / norm
    return( ret )

  def clear( self ):
    self.x = 0.0
    self.y = 0.0
    self.z = 0.0
