/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package geomExtension;

import java.awt.geom.*;
import util.*;

public class Vector2D {
    double x; 
    double y;
    //static final double eps12=1.0e-12;
    //static final double eps5=1.0e-5;
    
    public Vector2D(){}
    public Vector2D(double x, double y){
        this.x=x;
        this.y=y;
    }
    
    public Vector2D(Point2D point){
        this.x=point.getX();
        this.y=point.getY();
    }
    
    public double getX(){
        return this.x;
    }
    
    public double getY(){
        return this.y;
    } 
    
    public void setX(double x){
        this.x=x;
    }
    
    public void setY(double y){
        this.y=y;
    }
    
    public String toString(){
        String str="Vector2D";
        str+=" ("+Util.Num(this.x)+","+Util.Num(this.y)+")";
        return str;
    }
    
    public Object clone(){
        return (new Vector2D(this.x, this.y));
    }
    
    public static Vector2D add(Vector2D vec1, Vector2D vec2){
        Vector2D newVec=new Vector2D(vec1.getX()+vec2.getX(), vec1.getY()+vec2.getY());
        return newVec;
    }
    
    public static Vector2D sub(Vector2D vec1, Vector2D vec2){
        Vector2D newVec=new Vector2D(vec1.getX()-vec2.getX(), vec1.getY()-vec2.getY());
        return newVec;
    }
    public static Vector2D sub(Point2D p1, Point2D p2){
        Vector2D vec1=new Vector2D(p1);
        Vector2D vec2=new Vector2D(p2);
        return Vector2D.sub(vec1, vec2);
    }
    
    public static Vector2D multiply(double scalar, Vector2D vec){
        Vector2D newVec=new Vector2D(scalar*vec.getX(), scalar*vec.getY());
        return newVec;
    }
    
    public static Vector2D mult(double scalar, Vector2D vec){
        Vector2D newVec=new Vector2D(scalar*vec.getX(), scalar*vec.getY());
        return newVec;
    }
    
     public static double sproduct(Vector2D vec1, Vector2D vec2){
        double sprod=vec1.getX()*vec2.getX()+vec1.getY()*vec2.getY();
        return sprod;
    }
     
     public static double vproduct(Vector2D vec1, Vector2D vec2){
        double vprod=vec1.getX()*vec2.getY()-vec1.getY()*vec2.getX();
        return vprod;
    }
     
     public static boolean isSameDirection(Vector2D vec1, Vector2D vec2, double tolerance){
        double vprod=vec1.getX()*vec2.getY()-vec1.getY()*vec2.getX();
        double len1=Vector2D.length(vec1);
        double len2=Vector2D.length(vec2);
        if(len1<1.0e-8||len2<1.0e-8) return false;
        double sin=vprod/(len1*len2);
        double deg=Math.asin(sin)*180/Math.PI;
        boolean same=false;
        if(Math.abs(deg)<tolerance) same=true;
        return same;
    }
     
     public static Vector2D unitVector(Vector2D vec){
        double eps=1e-12;
        double norm=Math.sqrt(vec.getX()*vec.getX()+vec.getY()*vec.getY());
        Vector2D newVec=new Vector2D(0d,0d);
        if(norm>eps) newVec=Vector2D.multiply(1d/norm, vec);
        return newVec;
    }
     
     public static Vector2D normalVector(Vector2D vec){
        Vector2D newVec=new Vector2D(-vec.getY(),vec.getX());
        return newVec;
    }
     
     public static Vector2D unitNormalVector(Vector2D vec){
        Vector2D newVec=new Vector2D(-vec.getY(),vec.getX());
        newVec=Vector2D.unitVector(newVec);
        return newVec;
    }
     
     public static Vector2D project(Vector2D vec1, Vector2D vec2){
        Vector2D unitVec=Vector2D.unitVector(vec2);
        double sprod=Vector2D.sproduct(vec1, unitVec);
        Vector2D newVec=Vector2D.multiply(sprod, unitVec);
        return newVec;
    }
	public static double abs(Vector2D vec) {
		double sprod = Vector2D.sproduct(vec, vec);
		Math.sqrt(sprod);
		return Math.sqrt(sprod);
	}
	
    public static double length(Vector2D vec){
        double sprod=Vector2D.sproduct(vec, vec);
        Math.sqrt(sprod);
        return Math.sqrt(sprod);
    }
     
     public static double dist(Vector2D vec1, Vector2D vec2){
        double dist=Vector2D.length(Vector2D.sub(vec2, vec1));
        return dist;
     }
     
     public static double dist(Point2D p1, Point2D p2){
        Vector2D vec1=new Vector2D(p1);
        Vector2D vec2=new Vector2D(p2);
        double dist=Vector2D.length(Vector2D.sub(vec2, vec1));
        return dist;
     }
/*
    public static Vector2D discreteVector(Vector2D vec, double initAngle, double anglePitch){
        double pai=Math.PI;
        int num=(int)(360/anglePitch);
        Vector2D[] baseVec=new Vector2D[num];
        for(int i=0;i<num;i++){
            double teta=(initAngle+anglePitch*i)/180*pai;
            baseVec[i]=new Vector2D(Math.cos(teta), Math.sin(teta));
        }
        double sprodMax=0.0;
        double sprodSave=0.0;
        int isave=0;
        for(int i=0;i<num;i++){
            double sprod=Vector2D.sproduct(vec, baseVec[i]);
            if(Math.abs(sprod)>sprodMax) {
                sprodMax=Math.abs(sprod);
                sprodSave=sprod;
                isave=i;
            }
        }
        Vector2D newVec=Vector2D.multiply(sprodSave, baseVec[isave]);
        return newVec;
    }
*/
    public static CrossCurvePT crossPoint(Point2D p1s, Point2D p1e, Point2D p2s, Point2D p2e){
        Vector2D tvec1=Vector2D.sub(p1e,p1s);
        Vector2D tvec2=Vector2D.sub(p2e,p2s);
        tvec2=Vector2D.multiply(-1d, tvec2);
        Vector2D p1=new Vector2D(p1s);
        Vector2D p2=new Vector2D(p2s);
        Vector2D subVec=Vector2D.sub(p2,p1);
        double det=tvec1.getX()*tvec2.getY()-tvec1.getY()*tvec2.getX();
        if(Math.abs(det)<Curve2DUtil.eps4) return null;
        double t1=(subVec.getX()*tvec2.getY()-subVec.getY()*tvec2.getX())/det;
        double t2=(tvec1.getX()*subVec.getY()-tvec1.getY()*subVec.getX())/det;
        CrossCurvePT curvePT=null;
        Vector2D crossVec=Vector2D.add(p1, Vector2D.multiply(t1, tvec1));
        Point2D crossP=new Point2D.Double(crossVec.getX(), crossVec.getY());
        curvePT=new CrossCurvePT(t1, t2, crossP, crossP);
        return curvePT;
    }

    public static CrossCurvePT crossPoint(Vector2D p1s, Vector2D p1e, Vector2D p2s, Vector2D p2e){
        Point2D P1S=new Point2D.Double(p1s.getX(), p1s.getY());
        Point2D P1E=new Point2D.Double(p1e.getX(), p1e.getY());
        Point2D P2S=new Point2D.Double(p2s.getX(), p2s.getY());
        Point2D P2E=new Point2D.Double(p2e.getX(), p2e.getY());
        CrossCurvePT curvePT=Vector2D.crossPoint(P1S, P1E, P2S, P2E);
        return curvePT;
    }
}
