/* 
 
Copyright 2006 Rene Grothmann, modified by Eric Hakenholz

This file is part of C.a.R. software.

    C.a.R. is a 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, version 3 of the License.

    C.a.R. 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, see <http://www.gnu.org/licenses/>.
 
 */
 
 
 package rene.zirkel.objects;

import rene.zirkel.construction.Construction;
import rene.zirkel.structures.Coordinates;

// file: IntersectionObject.java

public class LineIntersectionObject extends IntersectionObject {
	public LineIntersectionObject(final Construction c,
			final PrimitiveLineObject P1, final PrimitiveLineObject P2) {
		super(c, P1, P2);
		validate();
	}

	@Override
	public void updateCircleDep() {
		((PrimitiveLineObject) P1).addDep(this);
		((PrimitiveLineObject) P2).addDep(this);
	}

	@Override
	public void validate() {
		if(!P1.valid() || !P2.valid()) {
                    Valid = false;
                } else {
                    Valid = true;
                }
                
		if(!Valid) {
                    return;
                }
                
		final Coordinates coord = PrimitiveLineObject.intersect((PrimitiveLineObject) P1, (PrimitiveLineObject) P2);
                
		if(coord == null) {
                    Valid = false;
                    return;
		}
                
		setXY(coord.X, coord.Y);
		if(Restricted) {
                    if (!((PrimitiveLineObject) P1).contains(X, Y))
                    Valid = false;
                    else if(!((PrimitiveLineObject) P2).contains(X, Y)) {
                        Valid = false;
                    }
		}
                
                /**
                 * En 3D
                 * 
                 * On veut résoudre le système : (dans le membre de gauche l'équation de P1, dans celui de droite, l'équation de P2)
                 * x1 + a1s = x2 + a2t
                 * y1 + b1s = y2 + b2t
                 * z1 + c1s = z2 + c2t
                 * 
                 * où (x1;y1;z1) est un point de P1 et (x2;y2;z2) un point de P2
                 * et (a1;b1;c1) est un vd de P1 et (a2;b2;c2) est un vd de P2
                 * 
                 * Ce système est équivalent à :
                 * a1s - a2t = x2 - x1 (L1)
                 * b1s - b2t = y2 - y1 (L2)
                 * c1s - c2t = z2 - z1 (L3)
                 */
                
                try {
                    if(((PrimitiveLineObject) P1).getP1().is3D() && ((PrimitiveLineObject) P2).getP1().is3D()) {
                        double x1 = ((PrimitiveLineObject) P1).getP1().getX3D();
                        double y1 = ((PrimitiveLineObject) P1).getP1().getY3D();
                        double z1 = ((PrimitiveLineObject) P1).getP1().getZ3D();
                        
                        double x2 = ((PrimitiveLineObject) P2).getP1().getX3D();
                        double y2 = ((PrimitiveLineObject) P2).getP1().getY3D();
                        double z2 = ((PrimitiveLineObject) P2).getP1().getZ3D();
                        
                        /**
                        * Si P2 ou P2 sont des parallèles, la méthode Pi.getP2() ne renvoie rien.
                        * Pour connaitre un vecteur directeur de P1, il suffit de connaitre
                        * sa parallèle, instance de TwoPointLineObject
                        */
                        ConstructionObject p1 = P1;
                        if(p1 instanceof ParallelObject) {
                            do{
                                p1 = ((ParallelObject) p1).getL();
                            } while(!(p1 instanceof TwoPointLineObject));
                        }
                        double a1 = ((TwoPointLineObject) p1).getP2().getX3D() - ((TwoPointLineObject) p1).getP1().getX3D();
                        double b1 = ((TwoPointLineObject) p1).getP2().getY3D() - ((TwoPointLineObject) p1).getP1().getY3D();
                        double c1 = ((TwoPointLineObject) p1).getP2().getZ3D() - ((TwoPointLineObject) p1).getP1().getZ3D();
                        
                        ConstructionObject p2 = P2;
                        if(p2 instanceof ParallelObject) {
                            do{
                                p2 = ((ParallelObject) p2).getL();
                            } while(!(p2 instanceof TwoPointLineObject));
                        }
                        double a2 = ((TwoPointLineObject) p2).getP2().getX3D() - ((TwoPointLineObject) p2).getP1().getX3D();
                        double b2 = ((TwoPointLineObject) p2).getP2().getY3D() - ((TwoPointLineObject) p2).getP1().getY3D();
                        double c2 = ((TwoPointLineObject) p2).getP2().getZ3D() - ((TwoPointLineObject) p2).getP1().getZ3D();
                        
                        //(L1) et (L2)
                        double det = -a1*b2 + b1*a2;
                        double dets = -(x2-x1)*b2 + (y2-y1)*a2;
                        double dett = a1*(y2-y1) - b1*(x2-x1);
                        int choice = 1;
                        
                        if(Math.abs(det)<1e-12) { //(L1) et (L3)
                            det = -a1*c2 + c1*a2;
                            dets = -(x2-x1)*c2 + (z2-z1)*a2;
                            dett = a1*(z2-z1) - c1*(x2-x1);
                            choice = 2;
                        }
                        if(Math.abs(det)<1e-12) { //(L2) et (L3)
                            det = -b1*c2 + c1*b2;
                            dets = -(y2-y1)*c2 + (z2-z1)*b2;
                            dett = b1*(z2-z1) - c1*(y2-y1);
                            choice = 3;
                        }
                        
                        double s = dets/det, t = dett/det;
                        
                        if (    (choice==1 && Math.abs(c1*s-c2*t-z2+z1)<1e-12)
                                || (choice==2 && Math.abs(b1*s-b2*t-y2+y1)<1e-12)
                                || (choice==3 && Math.abs(a1*s-a2*t-x2+x1)<1e-12)) {
                            setX3D(x1+a1*s);
                            setY3D(y1+b1*s);
                            setZ3D(z1+c1*s);
                            setIs3D(true);
                            //System.out.println(x1+a1*s);
                            //System.out.println(y1+b1*s);
                            //System.out.println(z1+c1*s);
                            //System.out.println("-------");
                            setSuperHidden(false);
                        } else {
                            setSuperHidden(true);
                        }
                    }
                } catch(final Exception ex){}
                
                
                
                /*
		if(    (P1 instanceof TwoPointLineObject && ((TwoPointLineObject) P1).getP1().is3D())
                        || (P1 instanceof TwoPointLineObject && ((TwoPointLineObject) P1).getP2().is3D())
                        || (P2 instanceof TwoPointLineObject && ((TwoPointLineObject) P2).getP1().is3D())
                        || (P2 instanceof TwoPointLineObject && ((TwoPointLineObject) P2).getP2().is3D())) {
                    try {	// Dibs intersection 3D
                        double a1=((TwoPointLineObject) P1).getP1().getX3D();
                        double b1=((TwoPointLineObject) P1).getP1().getY3D();
                        double c1=((TwoPointLineObject) P1).getP1().getZ3D();
                        double a2=((TwoPointLineObject) P1).getP2().getX3D();
                        double b2=((TwoPointLineObject) P1).getP2().getY3D();
                        double c2=((TwoPointLineObject) P1).getP2().getZ3D();
                        
                        double a3=((TwoPointLineObject) P2).getP1().getX3D();
                        double b3=((TwoPointLineObject) P2).getP1().getY3D();
                        double c3=((TwoPointLineObject) P2).getP1().getZ3D();
                        double a4=((TwoPointLineObject) P2).getP2().getX3D();
                        double b4=((TwoPointLineObject) P2).getP2().getY3D();
                        double c4=((TwoPointLineObject) P2).getP2().getZ3D();
                        
                        double det =(a2-a1)*(b3-b4)+(b2-b1)*(a4-a3);
                        double dets=(b3-b1)*(a4-a3)-(a3-a1)*(b4-b3);
                        double dett=(a2-a1)*(b3-b1)-(b2-b1)*(a3-a1);
                        int choice = 1;
                        
                        if(Math.abs(det)<1e-12) {
                            det =(b2-b1)*(c3-c4)+(c2-c1)*(b4-b3);
                            dets=(c3-c1)*(b4-b3)-(b3-b1)*(c4-c3);
                            dett=(b2-b1)*(c3-c1)-(c2-c1)*(b3-b1);
                            choice = 2;
                        }
                        if(Math.abs(det)<1e-12) {
                            det =(a2-a1)*(c3-c4)+(c2-c1)*(a4-a3); 
                            dets=(a3-a1)*(c3-c4)+(c3-c1)*(a4-a3);
                            dett=(a2-a1)*(c3-c1)-(c2-c1)*(a3-a1);
                            choice = 3;
                        }
                        
                        double s, t;
                        s=dets/det;
                        t=dett/det;
                        
                        if (    (choice==1 && Math.abs((c2-c1)*s-(c4-c3)*t-c3+c1)<1e-12)
                                || (choice==2 && Math.abs((b2-b1)*s-(b4-b3)*t-b3+b1)<1e-12)
                                || (choice==3 && Math.abs((a2-a1)*s-(a4-a3)*t-a3+a1)<1e-12)) {
                            setX3D(a1+s*(a2-a1));
                            setY3D(b1+s*(b2-b1));
                            setZ3D(c1+s*(c2-c1));
                            setIs3D(true);
                            setSuperHidden(false);
                        } else {
                            setSuperHidden(true);
                        }
                    } catch (final Exception ex) {
                        //System.err.println("Error : "+ex);
                    }	
                }
                */
	}
}