# -*- coding: iso-8859-1 -*-

from math import *

#------------------------------------------------------------------------------
class shape(object):
  """
  Classe de base.
  """

#------------------------------------------------------------------------------
class circle(shape):
  """
  circle(r), circle(d=...), circle(r=...)

  Implémentation d'un cercle.
  Un cercle peut être définit soit par son rayon, soit par son diamètre.
  Si les deux paramètres sont définis, le rayon est utilisé.

  Attributs disponibles :
  rayon : radius, r
  diamètre : diameter, d
  surface : area, a
  périmètre : circumference, c, perimeter, r
  """

  def __init__(self, r=None, d=None):
    if r==None:
      r = abs(d/2.0)
    self.radius = abs(r)
    self.r = self.radius
    self.diameter = self.d = 2*self.r
    self.area = self.a = pi * self.r**2
    self.circumference = self.c = self.perimeter = self.p = 2 * pi * self.r

  def __name__(self):
    return 'circle'

#------------------------------------------------------------------------------
class sphere(shape):
  """
  sphere(r), sphere(d=...), sphere(r=...)

  Implémentation d'une sphère.
  Une sphère peut être définie soit par son rayon, soit par son diamètre.
  Si les deux paramètres sont définis, le rayon est utilisé.

  Attributs disponibles :
  rayon : radius, r
  diamètre : diameter, d
  surface : surface, s
  volume : volume, v
  """

  def __init__(self, r=None, d=None):
    if r==None:
      r = abs(d/2.0)
    self.radius = abs(r)
    self.r = self.radius
    self.diameter = self.d = 2*self.r
    self.surface = self.s = 4 * pi * self.r**2
    self.volume = self.v = 4.0/3 * pi * self.r**3

  def __name__(self):
    return 'sphere'

#------------------------------------------------------------------------------
class cylinder(shape):
  """
  cylinder(r, h)

  Implémentation d'un cylindre (droit).
  Un cylindre est définit par sa hauteur et le rayon de sa base.

  Attributs disponibles :
  rayon : radius, r
  hauteur : height, h
  base (surface) : basearea, base, b
  surface : surface, s
  volume : volume, v
  périmètre : circumference, c, perimeter, r
  """

  def __init__(self, r, h):
    self.r = self.radius = abs(r)
    self.h = self.height = abs(h)
    self.b = self.basearea = self.base = circle(r=self.r).a
    self.volume = self.v = self.b * self.h
    self.surface = self.s = circle(r=self.r).c * self.h
    self.circumference = self.c = self.perimeter = self.p = 2 * pi * self.r

  def __name__(self):
    return 'cylinder'

#------------------------------------------------------------------------------
class rectangle(shape):
  """
  rectangle(x, y)

  Implémentation d'un rectangle.
  Un rectangle est définit par ses deux cotés.

  Attributs disponibles :
  longeur : x
  largeur : y
  surface : area, a
  périmètre : perimeter, p
  diagonale : diag, d
  moment quadratique par rapport à Y : Iyy, iyy
  moment quadratique par rapport à Z : Izz, izz
  """

  def __init__(self, x, y):
    self.x, self.y = abs(x), abs(y)
    self.area = self.a = x*y
    self.perimeter = self.p = 2*(x + y)
    self.Iyy = self.iyy = 1.0/12 * x * y**3
    self.Izz = self.izz = 1.0/12 * y * x**3
    self.diag = self.d = sqrt(x**2 + y**2)

  def __name__(self):
    return 'rectangle'

#------------------------------------------------------------------------------
class square(rectangle):
  """
  square(x)

  Implémentation d'un carré.
  Un carré est définit par son coté.
  Cette classe surcharge la classe rectangle.

  Attributs disponibles :
  longeur : x, y
  surface : area, a
  périmètre : perimeter, p
  diagonale : diag, d
  : Iyy, iyy, secmon
  : Izz, izz
  """

  def __init__(self, x):
    rectangle.__init__(self, x, x)

  def __name__(self):
    return 'square'

#------------------------------------------------------------------------------
class triangle(shape):
  """
  triangle(x, h), triangle(a, b, c)

  Implémentation d'un triangle quelconque.
  Un triangle est définit par sa base et sa hauteur ou par ses trois cotés.

  Attributs disponibles :
  longeur (base) : x
  hauteur : h
  surface : surface, s
  rayon du cercle circonscrit : rc
  rauon du cercle inscrit : ri
  """

  def __init__(self, x, h, c=None):
    if c == None:
      self.x, self.h = abs(x), abs(h)
      self.surface = self.s = 1.0/2 * self.x * self.h
      self.a = self.b = self.c = None
      self.perimeter = self.p = None
      self.rc = self.ri = None
    else:
      self.a, self.b, self.c = abs(x), abs(h), abs(c)
      self.perimeter = self.p = self.a + self.b + self.c
      hp = self.p / 2.0
      self.surface = self.s = sqrt(hp * abs(hp - self.a) * abs(hp - self.b) * abs(hp - self.c) )
      self.rc = (self.a * self.b * self.c) / (4.0 * self.s)
      self.ri = (2.0 * self.s) / (self.a + self.b + self.c)
      self.x = self.h = None

  def __name__(self):
    return 'triangle'

#------------------------------------------------------------------------------
class cube(shape):
  """
  cube(x)

  Implémentation d'un cube.
  Un cube est définit par son coté.

  longeur : x
  surface : surface, s
  volume : volume, v
  sommet : sommet
  face : face
  arete : arete
  perimetre developpe : perimeter, p
  """

  def __init__(self, x):
    self.x = abs(x)
    self.sommet = 8
    self.face = 6
    self.arete = 12
    self.surface = self.s = self.face * square(self.x).area
    self.volume = self.v = self.x ** 3
    self.perimeter = self.p = self.x * 14

  def __name__(self):
    return 'cube'

#------------------------------------------------------------------------------
class pyramid(shape):
  """
  pyramid(x, y, h), pyramid(b, h)

  Implémentation d'une pyramide.
  Une pyramide est définie par :
   - la surface de sa base et sa hauteur
   - la longueur et la largeur de sa base et sa hauteur

  Attributs disponibles :
  base (surface) : basearea, base, b
  longeur : x
  largeur : y
  hauteur : height, h
  volume : volume, v
  """

  def __init__(self, x, y, h=None):
    if h == None :
      self.b = self.basearea = self.base = abs(x)
      self.h = self.height = abs(y)
      self.volume = self.v = 1.0/3 * self.b * self.h
      self.x = self.y = None
    else :
      self.x, self.y = x, y
      self.b = self.basearea = self.base = abs(x) * abs(y)
      self.h = self.height = abs(h)
      self.volume = self.v = 1.0/3 * self.b * self.h

  def __name__(self):
    return 'pyramid'

#------------------------------------------------------------------------------
class cone(shape):
  """
  cone(r, h)

  Implémentation d'un cone circulaire.
  Un cône est définit par le rayon de sa base et sa hauteur.

  Attributs disponibles :
  rayon : radius, r
  diametre : diameter, d
  hauteur : height, h
  base (surface) : basearea, base, b
  surface : surface, s
  volume : volume, v
  """

  def __init__(self, r, h):
    self.r = self.radius = abs(r)
    self.h = self.height = abs(h)
    self.diameter = self.d = 2*self.r
    self.b = self.basearea = self.base = circle(r=self.r).a
    self.volume = self.v = 1.0/3 * self.b * self.h
    self.surface = self.s = pi * self.r * hypot(self.h, self.r)

  def __name__(self):
    return 'cone'

#------------------------------------------------------------------------------
class prism(shape):
  """
  prism(x, y, h), prism(b, h)

  Implémentation d'un prisme droit rectangulaire.
  Un  prisme droit est définit par :
   - la surface de sa base et sa hauteur
   - la longueur et la largeur de sa base et sa hauteur

  Attributs disponibles :
  base (surface) : basearea, base, b
  longeur : x
  largeur : y
  hauteur : height, h
  volume : volume, v
  """

  def __init__(self, x, y, h=None):
    if h == None :
      self.b = self.basearea = self.base = abs(x)
      self.h = self.height = abs(y)
      self.volume = self.v = self.b * self.h
      self.x = self.y = None
    else :
      self.x, self.y = x, y
      self.b = self.basearea = self.base = abs(x) * abs(y)
      self.h = self.height = abs(h)
      self.volume = self.v = self.b * self.h

  def __name__(self):
    return 'prism'

#------------------------------------------------------------------------------
class polyhedron(shape):
  """
  polyhedron(a, n)

  Implémentation d'un polyhèdre régulier.
  Un polyhèdre régulier est définit par la mesure d'un coté a et le nombre de faces n.

  Tetraèdre :
    sommet = 4
    coté = 3
    arête = 6
    surface = 1.73 * a ** 2
    volume = 0.12 * a ** 3

  Hexaèdre :
    sommet = 8
    coté = 4
    arête = 12
    surface = 6 * a ** 2
    volume = a ** 3

  Octaèdre :
    sommet = 6
    coté = 3
    arête = 12
    surface = 3.46 * a ** 2
    volume = 0.47 * a ** 3

  Dodécaèdre :
    sommet = 20
    coté = 5
    arête = 30
    surface = 20.6 * a ** 2
    volume = 7.66 * a ** 3

  Icosaèdre :
    sommet = 12
    coté = 3
    arête = 30
    surface = 8.66 * a ** 2
    volume = 2.18 * a ** 3

  Attributs disponibles :
  faces : face
  cotés (par face) : cote
  sommets : sommet
  arêtes : arete
  surface : area
  volume : volume
  """

  def __init__(self, a, n):
    self.face = n
    if n == 4:
      self.sommet = 4
      self.cote = 3
      self.arete = 6
      self.area = 1.73 * a ** 2
      self.volume = 0.12 * a ** 3
    elif n == 6:
      self.sommet = 8
      self.cote = 4
      self.arete = 12
      self.area = 6 * a ** 2
      self.volume = a ** 3
    elif n == 8:
      self.sommet = 6
      self.cote = 3
      self.arete = 12
      self.area = 3.46 * a ** 2
      self.volume = 0.47 * a ** 3
    elif n == 12:
      self.sommet = 20
      self.cote = 5
      self.arete = 30
      self.area = 20.6 * a ** 2
      self.volume = 7.66 * a ** 3
    elif n == 20:
      self.sommet = 12
      self.cote = 3
      self.arete = 30
      self.area = 8.66 * a ** 2
      self.volume = 2.18 * a ** 3
    else:
      self.sommet = self.cote = self.arete = self.area = self.volume = 0

  def __name__(self):
    return 'polyhedron'
