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

import math

# my 3D Vector class

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 ):
    return( self.x.__str__() + " " + self.y.__str__() + " " + self.z.__str__() )

  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
