/*! \file  ElementSegment.cpp
 */

#include "./MeshProfileIntersectionx.h"

void ElementSegment(DataSet* segments_dataset,int el,double* xnodes,double* ynodes,double* xsegment,double* ysegment){

	/*We have a tria element (xnodes,ynodes) and a segment (xsegment,ysegment). Find whether they intersect. 
	 * If they do, create a Segment object with the intersection, and add to segments_dataset dataset: */

	double alpha1,alpha2;
	double beta1,beta2;
	double gamma1,gamma2;

	int    edge1,edge2,edge3;

	double xel[2],yel[2];
	double coord1,coord2;
	double xfinal[2],yfinal[2];

	/*edge 1: */
	xel[0]=xnodes[0];  yel[0]=ynodes[0]; xel[1]=xnodes[1];  yel[1]=ynodes[1];
	edge1=SegmentIntersect(&alpha1,&alpha2, xel,yel,xsegment,ysegment); //alpha1: segment coordinate of intersection. alpha2: same thing for second interesection if it exists (colinear edges)

	/*edge 2: */
	xel[0]=xnodes[1];  yel[0]=ynodes[1]; xel[1]=xnodes[2];  yel[1]=ynodes[2];
	edge2=SegmentIntersect(&beta1,&beta2, xel,yel,xsegment,ysegment);

	/*edge 3: */
	xel[0]=xnodes[2];  yel[0]=ynodes[2]; xel[1]=xnodes[0];  yel[1]=ynodes[0];
	edge3=SegmentIntersect(&gamma1,&gamma2, xel,yel,xsegment,ysegment);

	/*edge can be either IntersectEnum (one iand only one intersection between the edge and the segment), ColinearEnum (edge and segment are collinear) and SeparateEnum (no intersection): */

	if(    (edge1==IntersectEnum) && (edge2==IntersectEnum) && (edge3==IntersectEnum)   ){
		/*This case is impossible: */
		_error_("error: a line cannot go through 3 different vertices!");
	}
	else if(    ((edge1==IntersectEnum) && (edge2==IntersectEnum)) || ((edge2==IntersectEnum) && (edge3==IntersectEnum)) || ((edge3==IntersectEnum) && (edge1==IntersectEnum))   ){

		/*segment interscts 2 opposite edges of our triangle, at 2 segment coordinates, pick up the lowest (coord1) and highest (coord2): */
		if((edge1==IntersectEnum) && (edge2==IntersectEnum)) {coord1=min(alpha1,beta1); coord2=max(alpha1,beta1);}
		if((edge2==IntersectEnum) && (edge3==IntersectEnum)) {coord1=min(beta1,gamma1); coord2=max(beta1,gamma1);}
		if((edge3==IntersectEnum) && (edge1==IntersectEnum)) {coord1=min(gamma1,alpha1); coord2=max(gamma1,alpha1);}

		/*check this segment did not intersect at a vertex of the tria: */
		if(coord1!=coord2){

			xfinal[0]=xsegment[0]+coord1*(xsegment[1]-xsegment[0]);
			xfinal[1]=xsegment[0]+coord2*(xsegment[1]-xsegment[0]);
			yfinal[0]=ysegment[0]+coord1*(ysegment[1]-ysegment[0]);
			yfinal[1]=ysegment[0]+coord2*(ysegment[1]-ysegment[0]);

			segments_dataset->AddObject(new  Segment<double>(el+1,xfinal[0],yfinal[0],xfinal[1],yfinal[1]));
		}
		else{
			/*the segment intersected at the vertex, do not bother with this "0" length segment!:*/
		}
	}
	else if(  (edge1==IntersectEnum) || (edge2==IntersectEnum) || (edge3==IntersectEnum)   ){

		/*segment intersect only 1 edge. Figure out where the first point in the segment is, inside or outside the element, 
		 * this will decide the coordinate: */
		if (NodeInElement(xnodes,ynodes,xsegment[0],ysegment[0])){
			coord1=0;
			if(edge1==IntersectEnum){coord2=alpha1;}
			if(edge2==IntersectEnum){coord2=beta1;}
			if(edge3==IntersectEnum){coord2=gamma1;}
		}
		else{
			if(edge1==IntersectEnum){coord1=alpha1;}
			if(edge2==IntersectEnum){coord1=beta1;}
			if(edge3==IntersectEnum){coord1=gamma1;}
			coord2=1.0;
		}

		xfinal[0]=xsegment[0]+coord1*(xsegment[1]-xsegment[0]);
		xfinal[1]=xsegment[0]+coord2*(xsegment[1]-xsegment[0]);
		yfinal[0]=ysegment[0]+coord1*(ysegment[1]-ysegment[0]);
		yfinal[1]=ysegment[0]+coord2*(ysegment[1]-ysegment[0]);

		segments_dataset->AddObject(new  Segment<double>(el+1,xfinal[0],yfinal[0],xfinal[1],yfinal[1]));
	}
	else{
		/*No interesections, but the segment might be entirely inside this triangle!: */
		if ( (NodeInElement(xnodes,ynodes,xsegment[0],ysegment[0])) && (NodeInElement(xnodes,ynodes,xsegment[1],ysegment[1])) ){
			segments_dataset->AddObject(new  Segment<double>(el+1,xsegment[0],ysegment[0],xsegment[1],ysegment[1]));
		}
	}
}
