import java.applet.*; 
import java.awt.*; 
import java.awt.image.*; 
import java.awt.event.*; 
import java.io.*; 
import java.net.*; 
import java.text.*; 
import java.util.*; 
import java.util.zip.*; 

public class _3Dprimitive_1a extends BApplet {
/*A study on 3d primitives. It's still a work in progress.
  I used some samples of code by Fry and Reas, in particulary the Handler Class that I modify in a rather rough way.
  Xnumbers, Ynumbers draw the profile, var q determinates the number of  the sides
  by Alessandro Capozzo
  11 August 03
*/

float ymag,xmag=0;
float  newYmag,newXmag=0;
int[] Xnumbers = { 100,15,15, 10, 10 , 20, 10, 70, 80, 150 }; 
int[] Ynumbers = { -190,-170,-50, -20, 0, 20, 60, 100, 120, 190};
int q=8;

int Sx,Sx1,Sy,Sy1;
Handle[] handles;
int num;
void setup() 
{
  size(600, 400);
 colorMode(RGB, 255);
  background(230, 230, 230);
    num = Xnumbers.length;
  handles = new Handle[num];
  int hsize = 10;
  for(int i=0; i<num; i++) {
    handles[i] = new Handle(width-Xnumbers[i],height/2- Ynumbers[i], 50-hsize/2, 10, handles,0,width-10,0,height-10);
     
  }
}
void loop(){

     for(int i=0; i<num; i++) {
     
    handles[i].update();
    handles[i].display();
    Xnumbers[i]=width-handles[i].getX();
    Ynumbers[i]=height/2- handles[i].getY();
    
       if(i<(num-1)){
   
    line( handles[i].getX()+5 ,handles[i].getY()+5 ,handles[i+1].getX()+5 ,handles[i+1].getY()+5 );
    
    }
  }
   /////////////////////////
  
  translate(width/2, height/2,-200);

  newXmag = mouseX/(float)(width) * TWO_PI;
  newYmag = mouseY/(float)(height) * TWO_PI;
  
  float diff = xmag-newXmag;
  if (abs(diff) >  0.01f) { 
    xmag -= diff/4.0f; 
  }
  
  diff = ymag-newYmag;
  if (abs(diff) >  0.01f) {
    ymag -= diff/4.0f;
  }
  
  
  push();
  
  rotateX(ymag);
  rotateY(xmag);

   
  float d= 0.0f;
  
  
  while(d < TWO_PI) { 
    
   rotateY(TWO_PI/q);
   
  push();
   
    int arraycont=Xnumbers.length-1;
    int i;
    for (i=0;i<arraycont;i++){
    Sy1=Ynumbers[i+1];
    Sy=Ynumbers[i];
    Sx=Xnumbers[i];
   Sx1=Xnumbers[i+1];
   push();
   translate(0,-Sy1,Sx1);
    int prova1=(int)(Sx1*tan(PI/q));
    int prova=(int)(Sx*tan(PI/q));
    int highProj=Sy1-Sy;
    float beta1=atan2(Sx1-Sx,Sy1-Sy);
    int high=(int)(sqrt((highProj*highProj)+(Sx1-Sx)*(Sx1-Sx)));
    rotateX(-beta1);
      
    quad(prova1,0,-prova1,0,-prova,high,prova,high);
    pop();
    }
   pop();
   d +=TWO_PI/q; 
  
   } 
 pop();

}
void mouseReleased() 
{
  for(int i=0; i<num; i++) {
    handles[i].release();
  }
}

class Handle
{
  int x, y;
  int boxx, boxy;
  int length;
  int size;
  int getX=boxx;
  int getY=boxy;
  int xlimit1,xlimit2,ylimit1,ylimit2;
  boolean over;
  boolean press;
  boolean locked = false;
  boolean otherslocked = false;
  boolean checkMouse;
  Handle[] others;
  
  Handle(int _x, int _y, int _l, int _s, Handle[] o, int _xlimit1, int _xlimit2, int _ylimit1, int _ylimit2)
  {
    x = _x;
    y = _y;
    length = _l;
    
    size = _s;
    boxx = x;
    boxy = y ;
    others = o;
    xlimit1=_xlimit1;
    xlimit2=_xlimit2;
    ylimit1=_ylimit1;
    ylimit2=_ylimit2;
  }
  
  void update() {
     
    
    
    for(int i=0; i<others.length; i++) {
      if(others[i].locked == true) {
        otherslocked = true;
        break;
      } else {
        otherslocked = false;
      }  
    }
    
    if(otherslocked == false) {
      over();
      press();
    }
    
    if(press) {
    if(checkMouse()){
    boxx=mouseX;
    boxy=mouseY;
    
         
    }
  }
  }
  
  void over()
  {
    if(overRect(boxx, boxy, size, size)) {
      over = true;
    } else {
      over = false;
    }
  }
  
  void press()
  {
    if(over && mousePressed || locked) {
      press = true;
      locked = true;
    } else {
      press = false;
    }
  }
  
  void release()
  {
    locked = false;
  }
  
  void display() 
  {
   
    fill(255);
    stroke(0);
    rect(boxx, boxy, size, size);


  }
  boolean checkMouse (){
   if (mouseX < xlimit2 && mouseX > xlimit1 && mouseY < ylimit2 && mouseY >ylimit1 ){
     return  true;
   } else {
   return  false;
   }
  }
  int getX(){
  return boxx;
  
  }
    int getY(){
  return boxy;
  }
}

boolean overRect(int x, int y, int width, int height) 
{
  if (mouseX >= x && mouseX <= x+width && 
      mouseY >= y && mouseY <= y+height) {
    return true;
  } else {
    return false;
  }
}
int lock(int val, int minv, int maxv) 
{ 
  return  min(max(val, minv), maxv); 
}
void keyReleased()
{ 
  if((key=='a'|| key=='A') && q<64){
  q++;
  } else if ((key=='z'|| key=='Z') && q>3) {
  q--;
  }

  
}

}