/*

 ----------------------------------------------------------------
 Copyright (C) 2005 Ricard Marxer Piñón
 
 email (at) ricardmarxer.com
 http://www.ricardmarxer.com/
 ----------------------------------------------------------------
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 ----------------------------------------------------------------
 Built with Processing (Beta) v098
 uses Geomerative (Alpha) v004
 ----------------------------------------------------------------
 
 Created 14 November 2006
 
 ----------------------------------------------------------------
 lettree
 ----------------------------------------------------------------
 
 */

import processing.core.*;
import geomerative.*;

public class Serif{
  public RPoint startp;
  public RPoint endp;
  
  public Letter parent;

  public Serif connected;
  public int state = EMPTY;
  
  public final static int EMPTY = 0;
  public final static int CHILD = 1;
  public final static int PARENT = 2;
  
  public Serif(Letter l, RPoint sp, RPoint ep){
    parent = l;
    startp = sp;
    endp = ep;
  }
 
  public Serif(Letter l, Serif s){
    parent = l;
    startp = new RPoint(s.startp);
    endp = new RPoint(s.endp);
  }
 
  public boolean isEmpty(){
    return (state==EMPTY);
  }
  
  public boolean isChild(){
    return (state==CHILD);
  }
  
  public void attatchSerif(Serif srf){
    RMatrix mtx = calculateTransformFor(srf);
    srf.parent.transform(mtx);
    
    this.connected = srf;
    this.state = CHILD;
    
    srf.connected = this;
    srf.state = PARENT;
  }
  
  public RMatrix calculateTransformFor(Serif srf){
    float scaling = (float)dist(this.startp.x, this.startp.y, this.endp.x, this.endp.y) / (float)dist(srf.startp.x, srf.startp.y, srf.endp.x, srf.endp.y);
    float rotation = (float)Math.PI + atan2(srf.endp.x - srf.startp.x, srf.endp.y - srf.startp.y) - atan2(this.endp.x - this.startp.x, this.endp.y - this.startp.y);
    
    RPoint pointStart = new RPoint((srf.startp.x + srf.endp.x) / 2,(srf.startp.y + srf.endp.y) / 2);
    RPoint pointEnd = new RPoint((this.startp.x + this.endp.x) / 2,(this.startp.y + this.endp.y) / 2);
    RPoint translation = new RPoint(pointEnd.x - pointStart.x, pointEnd.y - pointStart.y);

    RMatrix mtx = new RMatrix();
    mtx.translate(translation);
    mtx.scale(scaling, pointStart);
    mtx.rotate(rotation, pointStart);
    
    return mtx;
  }

  public void draw(PGraphics g){
      float px = (startp.x + endp.x)/2;
      float py = (startp.y + endp.y)/2;
      float angle = atan2(endp.x-startp.x,endp.y-startp.y)+(float)Math.PI;
      
      // Draw bounds
      g.stroke(0,0,255);
      g.line(startp.x,startp.y,startp.x-10F*(float)Math.cos(angle),startp.y+10F*(float)Math.sin(angle));
      g.line(endp.x,endp.y,endp.x-10F*(float)Math.cos(angle),endp.y+10F*(float)Math.sin(angle));

      // Draw center
      g.stroke(255,0,0);
      g.line(px,py,px-10F*(float)Math.cos(angle),py+10F*(float)Math.sin(angle));
  }
  
  private static float dist(float x1, float y1, float x2, float y2){
	float difx = x2-x1;
	float dify = y2-y1;
	return (float)Math.sqrt(difx*difx + dify*dify);
  }

  private static float atan2(float x, float y){
	return (float)Math.atan2(x,y);
  }

  private static float random(float min, float max){
	return (float)((max-min)*Math.random()+min);
  }

  private static float round(float a){
	return (float)Math.round(a);
  }
}
