/// Evolver Copyright 2000, Morgan McGuire
/// matrix@alum.mit.edu   http://graphics3d.com/matrix
/**
 * A 3 vector.
 * <PRE>
 *   ELVector := ELScalar x ELScalar x ELScalar
 * </PRE>
 */
public class ELVector extends AbstractELExpression implements ELExpression
{
  float red;
  float grn;
  float blu;

  public ELVector()
  {
    red = 0.0f;
    grn = 0.0f;
    blu = 0.0f;
  }

  public ELVector(double r, double g, double b)
  {
    red = (float)Math.max(-1.0, Math.min(1.0, r));
    grn = (float)Math.max(-1.0, Math.min(1.0, g));
    blu = (float)Math.max(-1.0, Math.min(1.0, b));
  }

  public ELExpression geneticClone(ELCall parent, GeneticParameters gp)
  {
    if (gp.mutationOccurs(parent)) {
      while (true) {

        int mutation = gp.randomMutationType();
        switch (mutation) {
        case GeneticParameters.ENCLOSE_IN_NEW_CALL_MUTATION:
          return encloseInNewCallMutation(gp);
        
        case GeneticParameters.NEW_EXPRESSION_MUTATION:
          return gp.randomExpression();
        
        case GeneticParameters.CLONE_SIBLING_MUTATION:
          if (parent != null) {
            return cloneSiblingMutation(parent, gp);
          } else {
            // Not appropriate; no siblings.
            break;
          }
        
        case GeneticParameters.VECTOR_CONSTANT_MUTATION:
          double r = Math.random() * 2.0 - 1.0;
          double g = Math.random() * 2.0 - 1.0;
          double b = Math.random() * 2.0 - 1.0;
          return new ELVector(red + r * gp.vectorDisturbance,
                              grn + g * gp.vectorDisturbance,
                              blu + b * gp.vectorDisturbance);
          
        default:
          // not an appropriate mutation; keep cycling.
        }
      }
      
    } else {
      return cloneWithChildMutations(gp);
    }
  }

  public Object clone()
  {
    return new ELVector(red, grn, blu);
  }

  public String unparse()
  {
    return "{" + red + ", " + grn + ", " + blu + "}";
  }

  public String toString()
  {
    return "ELVector(" + red + ", " + grn + ", " + blu + ")";
  }

  public void evaluate(ELMatrix out, ELEnvironment environment, ParameterList pl)
  {
    out.setAll(red, grn, blu);
  }

}
