Programmazione/Progetti/Architettura3D/Stesura III

Da WikiDsy.
  //ROYV
  
  import java.util.Hashtable;
  
  // CLASSI di Figura3D ////////////////////////////////////////////////////////
  
  
  class Cilindro extends Figura3D {
  
    private double r, h;
  
    public Cilindro(double r, double h) {
  
      if (r <= 0 || h <= 0)
        throw new Figura3DException(this.getClass().getName() +  ": Parametro errato!");
      else {
        this.r = r;
        this.h = h;
      }
    }
  
    public void setParametri(double[] param) {
  
      if (param == null || param.length < 2 || (param[0] <= 0 || param[1] <= 0))
        throw new Figura3DException(this.getClass().getName() +  ": Parametro errato!");
      else {
        this.r = param[0];
        this.h = param[1];
      }
    }
  
    public double[] getParametri() {
      return new double[] {r, h};
    }
  
    public double getVolume() {
      return Math.PI * r * r * h;
    }
  
    public double getSuperficie() {
      return 2 * Math.PI * r * h;
    }
  
    public boolean equals(Object o) {
      /* Confronto l' istanza attuale con l' istanza dell' oggeto.
         Permettendo un confronto più specifico, nel caso il metodo venga utilizzato
         da un eventuale sottoclasse.
       */
      //return (o instanceof Cilindro) ? equals((Cilindro)o) : false;
      return (this.getClass().isInstance(o))? equals((Cilindro)o) : false;
    }
  
    public boolean equals(Cilindro c) {
      //test sui parametri dimensionali.
      return this.r == c.r && this.h == c.h;
    }
  
    public String toString() {
      return this.getClass().getName() + ": raggio = " + r + ", altezza = " + h;
    }
  }
  
  
  class Sfera extends Cilindro {
  
    public Sfera(double r) {
      super(r, r);
    }
  
    public void setParametri(double[] param) {
  
      if (param == null || param.length < 1)
        throw new Figura3DException(this.getClass().getName() +  ": Parametro errato!");
      else
        //crea una lista di due elementi costituiti dallo stesso valore.
        super.setParametri(new double[] {param[0], param[0]});
    }
  
    public double[] getParametri() {
      return new double[] {super.getParametri()[0]};
    }
  
    public double getVolume() {
      //divisione tra valori double, 4/3 * volume del Cilindro.
      return (4 * super.getVolume()) / 3;
    }
  
    public double getSuperficie() {
      // 2 * (2PIhr)
      return 2 * super.getSuperficie();
    }
  
    public String toString() {
      return this.getClass().getName() + ": raggio = " + getParametri()[0];
    }
  }
  
  class Parallelepipedo extends Figura3D {
  
    private double a, b, h;
  
    public Parallelepipedo(double a, double b, double h) {
  
      if (a <= 0 || b <= 0 || h <= 0)
        throw new Figura3DException(this.getClass().getName() + ": Parametro errato!");
      else {
        this.a = a;
        this.b = b;
        this.h = h;
      }
    }
  
    public void setParametri(double[] param) {
  
      if (param == null || param.length < 3 || (param[0] <= 0 || param[1] <= 0 || param[2] <= 0))
        throw new Figura3DException(this.getClass().getName() + "Parametri non validi");
      else {
        this.a = param[0];
        this.b = param[1];
        this.h = param[2];
      }
    }
  
    public double[] getParametri() {
      return new double[] {a, b, h};
    }
  
    public double getVolume() {
      return a * b * h;
    }
  
    public double getSuperficie() {
      return 2 * (h * (a + b) + a * b);
    }
  
    public boolean equals(Object o) {
      //stessa logica applicato sul metodo del Cilindro.
      return (this.getClass().isInstance(o))? equals((Parallelepipedo)o) : false;
    }
  
    public boolean equals(Parallelepipedo p) {
      return this.a == p.a && this.b == p.b && this.h == p.h;
    }
  
    public String toString() {
      return this.getClass().getName() + ": latoA = " + a + ", latoB = " + b + ", altezza = " + h;
    }
  }
  
  
  class Cubo extends Parallelepipedo {
  
    public Cubo(double l) {
      super(l, l, l);
    }
  
    public void setParametri(double[] param) {
  
      if (param == null || param.length < 1)
        throw new Figura3DException(this.getClass().getName() + ": Parametro errato!");
      else
        super.setParametri(new double[] {param[0], param[0], param[0]});
    }
  
    public double[] getParametri() {
      return new double[] {super.getParametri()[0]} ;
    }
  
    public String toString() {
      //lato -> raggio per confronto con i file di prova
      return this.getClass().getName() + ": raggio = " + super.getParametri()[0];
    }
  }
  
  
  class TroncoDiCono extends Figura3D {
  
    private double rh, rs, h;
  
    public TroncoDiCono(double rh, double rs, double h) {
  
      if (rh <= 0 || rs < 0 || h <= 0)
        throw new Figura3DException(this.getClass().getName() + ": Parametro errato!");
      else {
        this.rh = rh;
        this.rs = rs;
        this.h = h;
      }
    }
  
    public void setParametri(double[] param) {
  
      if (param == null || param.length < 3 || (param[0] <= 0 || param[1] < 0 || param[2] <= 0))
        throw new Figura3DException(this.getClass().getName() + "Parametri non validi");
      else {
        this.rh = param[0];
        this.rs = param[1];
        this.h = param[2];
      }
    }
  
    public double[] getParametri() {
      return new double[] {rh, rs, h};
    }
  
    public double getVolume() {
      return Math.PI / 3 * (rh * rs + rh * rh + rs * rs) * h;
    }
  
    public double getSuperficie() {
      return Math.PI * (rh + rs) * Math.sqrt((rh - rs) * (rh - rs) + h * h);
    }
  
    public boolean equals(Object o) {
      //return (o instanceof TroncoDiCono) ? equals( (TroncoDiCono) o) : false;
      return (this.getClass().isInstance(o))? equals((TroncoDiCono)o) : false;
    }
  
    public boolean equals(TroncoDiCono t) {
      return this.rh == t.rh && this.rs == t.rs && this.h == t.h;
    }
  
    public String toString() {
      //return this.getClass().getName() +  ": raggio grande = " + rh + ", raggio piccolo = " + rs + ", altezza = " + h;
      return "Tronco di cono: raggio grande = " + rh + ", raggio piccolo = " + rs + ", altezza = " + h;
    }
  }
  
  
  class Cono extends TroncoDiCono {
  
    public Cono(double r, double h) {
      super(r, 0, h);
    }
  
    public void setParametri(double[] param) {
  
      if (param == null || param.length < 2)
        throw new Figura3DException(this.getClass().getName() + ": Parametro errato!");
      else
        super.setParametri(new double[] {param[0], 0, param[1]});
    }
  
    public double[] getParametri() {
      //utilizzo i parametri di TroncoDiCono Raggio Grande -> 0 e Altezza -> 2
      double[] p = super.getParametri();
      return new double[] {p[0], p[2]};
    }
  
    public String toString() {
      double[] p = getParametri();
      return this.getClass().getName() + ": raggio = " + p[0] + ", altezza = " + p[1];
    }
  }
  
  class Figura3DException extends RuntimeException {
    public Figura3DException(String msg) {
      super(msg);
    }
  }
  
  
  class TipoNonPrevistoException extends Exception {
    public TipoNonPrevistoException(String msg) {
      super(msg);
    }
  }
  
  /////////////////////////////////////////////////////////////////////
  
  class Architettura3D {
  
    private Hashtable paramList;
    private SequenzaFigure3D lista = null;
    //identifica il tipo + generico di figura.
    private static final String BASE_CLASS = "Figura3D";
  
    public Architettura3D() {
      lista = new SequenzaFigure3D();
      inizializeParamList();
    }
  
    public void addFigura3D(Figura3D figura) {
      lista.add(figura);
    }
  
    public Figura3D[] getFigure3D() {
     return lista.toArray();
    }
  
    public double getVolume(String tipoFigura) throws TipoNonPrevistoException {
      return lista.getSommaVolume(getBaseClass(tipoFigura));
    }
  
    public double getSuperficie(String tipoFigura) throws TipoNonPrevistoException {
      return lista.getSommaSuperficie(getBaseClass(tipoFigura));
    }
  
    public double getVolumeMedio() {
      return lista.getSommaVolume(BASE_CLASS) / lista.getSize();
    }
  
    public double getSuperficieMedia() {
      return lista.getSommaSuperficie(BASE_CLASS) / lista.getSize();
    }
  
    public Figura3D trova(Figura3D fig) {
     return lista.find(fig);
    }
  
    private String getBaseClass(String tipof)  throws TipoNonPrevistoException {
  
     String s;
     if (tipof == null)
       throw new TipoNonPrevistoException("Nessun parametro passato!");
     else if ((s =  (String)paramList.get(tipof)) == null)
       throw new TipoNonPrevistoException("Il tipo " + tipof + " non è previsto!");
     else
      return s;
  
    }
  
    private void inizializeParamList() {
  
      paramList = new Hashtable();
  
      paramList.put("SC", "Cilindro");
      paramList.put("PC", "Parallelepipedo");
      paramList.put("TC", "TroncoDiCono");
      paramList.put("TUTTE", BASE_CLASS);
    }
  }
  
  // LISTA CONCATENATA
  class SequenzaFigure3D {
  
    //puntatore al primo nodo inizio della lista.
    private NodoFigura inizio;
    //puntatore all' ultimo nodo inizio della lista.
    private NodoFigura fine;
    //contatore degli elementi della lista.
    private int nelem;
  
    public SequenzaFigure3D() {
      inizio = null;
      fine = null;
      nelem = 0;
    }
  
    private static class NodoFigura {
      Figura3D figura;
      NodoFigura pros;
    }
  
    public void add(Figura3D f) {
  
      if (f == null)
        throw new SequenzaFigure3DException("Parametro non valido!");
      else {
        NodoFigura n = new NodoFigura();
        n.figura = f;
        n.pros = null;
  
        if (inizio == null)
          inizio = n;
        else
          fine.pros = n;
  
        fine = n;
        nelem++;
      }
    }
  
    public boolean remove(Figura3D f) {
  
      if (f == null)
        throw new SequenzaFigure3DException("Parametro non valido!");
      else {
        NodoFigura p = inizio, q = null;
        //creazione del riferimento di sinistra e di destra della fig. da ricercare.
        while (p != null && !f.equals(p.figura)) {
          q = p;
          p = p.pros;
        }
        //verifica della ricerca e gestione della posizione iniziale.
        if (p != null && f.equals(p.figura)) {
          if (q == null)
            inizio = inizio.pros;
          else
            //eliminando l' unico riferimento l' oggetto verrà cancellato dal GC.
            q.pros = p.pros;
  
          nelem--;
          return true;
        }
        return false;
      }
    }
  
    public Figura3D find(Figura3D f) {
  
      if (f == null)
        throw new SequenzaFigure3DException("Parametro non valido!");
      else {
        NodoFigura nf = inizio;
        //for(NodoFigura n = inizio.pros; n != null; n = n.pros)
        //controllo delle figure dall' inizio della sequenza.
        for (int i = 0; i < nelem; i++)
          if (nf != null && f.equals(nf.figura))
            return nf.figura;
          else
            nf = nf.pros;
  
        return null;
      }
    }
  
    public Figura3D[] toArray() {
  
      NodoFigura nf = inizio;
      Figura3D[] ls = new Figura3D[nelem];
      for(int i = 0; i < nelem; i++) {
        ls[i] = nf.figura;
        nf = nf.pros;
      }
      return ls;
    }
  
    public boolean isEmpty() {
      return inizio == null;
    }
  
    public int getSize() {
      return nelem;
    }
  
    public double getSommaVolume(String tipoFigura) {
     return sommaDati(inizio, tipoFigura, 'V');
    }
  
    public double getSommaSuperficie(String tipoFigura) {
      return sommaDati(inizio, tipoFigura, 'S');
    }
  
    private double sommaDati(NodoFigura n, String filter, char c) {
  
      /*
       metodo basato sulla ricorsione.
       caso base :
       - nessun riferimento al nodo.
       casi ricorsivi :
       - Controllo istanze per tipo figura e in caso la figura corrente non
         è della "categoria - filter" da utilizzare si rimanda al prossimo oggetto.
       - Calcolo della proprietà "metodo da eseguire" e somma del risultato con
         il calcolo applicato sulla prossima figura.
       */
  
      double d = 0;
  
      try {
  
        if (n == null)
          return 0;
        //controllo dinamico sui tipi delle istanze.
        else if (!Class.forName(filter).isInstance(n.figura))
          return sommaDati(n.pros, filter, c);
        else {
  
          switch (c) {
            case 'V':
              d = n.figura.getVolume();
              break;
            case 'S':
              d = n.figura.getSuperficie();
              break;
            default:
              break;
          }
  
          return d + sommaDati(n.pros, filter, c);
  
        }
      }
      //Gestione classe controllata.
      catch (ClassNotFoundException e) {
        throw new SequenzaFigure3DException("Tipo classe " + filter + " non trovata");
      }
    }
  
    public String toString() {
      return this.toString(" ");
    }
  
    public String toString(String sep) {
      if (inizio == null)
        return "";
      else {
        String s = inizio.figura.toString();
        for(NodoFigura n = inizio.pros; n != null; n = n.pros)
          s = s + sep + n.figura.toString();
  
        return s;
      }
    }
  }
  
  class SequenzaFigure3DException extends RuntimeException {
    public SequenzaFigure3DException(String msg) {
      super(msg);
    }
  }