#include "pch.h" // use stdafx.h in Visual Studio 2017 and earlier
#include "BranchPoint.h"

void BranchPoint::init(){
	l=0;r=1;
	pc1=pc2=NULL;
	pb1=pb2=NULL;
	t=0.5;Dis=0;
	fixed=false;
	position=0;
	id=0;
	bundleNodeID=0;
	used=0;
}

//初始化
BranchPoint::BranchPoint(){
	init();
}

//按两个卡箍初始化
BranchPoint::BranchPoint(Clip *c1,Clip *c2){
	init();
	pc1=c1;pc2=c2;
	Dis=distan1(c1->coord,c2->coord);
	double ratio=MinClipToBranchPointDistance/Dis;
	l=max(l,ratio);r=min(r,1-ratio);
	t=(l+r)/2;
	////cout<<"BranchPoint2: ratio:"<<ratio<<" l:"<<l<<" r:"<<r<<" t:"<<t<<endl;
	coord=(c1->coord)*(1-t)+(c2->coord)*t;
}


//按卡箍和范围初始化
BranchPoint::BranchPoint(Clip *c1,Clip *c2,double L,double R){
	init();
	pc1=c1;pc2=c2;
	Dis=distan1(c1->coord,c2->coord);
	double ratio=MinClipToBranchPointDistance/Dis;
	l=max(L,ratio);r=min(R,1-ratio);
	t=(l+r)/2;
	cout<<"BranchPoint L+R: ratio:"<<ratio<<" l:"<<l<<" r:"<<r<<" t:"<<t<<endl;
	coord=(c1->coord)*(1-t)+(c2->coord)*t;
}

//添加左边的分支点
void BranchPoint::addL(BranchPoint b){
	pb1=&b;
}

//添加右边的分支点
void BranchPoint::addR(BranchPoint b){
	pb2=&b;
}
	
//把左边界向右边推d距离
void BranchPoint::pushL(double d){
	if(d<=0)return;
	l+=d/Dis;
}

//把右边界向左边推d距离
void BranchPoint::pushR(double d){
	if(d<=0)return;
	r-=d/Dis;
}

	//固定分支点位置
void BranchPoint::fix(){
	if(fixed==true)return;
	fixed=true;
	t=tempt[mode];
	cout<<"***********";
	if(!Equal(t,l)&&!Equal(t,r))cout<<"-------";
	cout<<endl;
	referClip=pc1->name;
	position=t*Dis;
	assert(position<=Dis);
}

//通道方向反向,分支点也改变其表示形式
void BranchPoint::reverse(){
	referClip=pc2->name;
	position=Dis-position;
}

//返回分支点在分支上可以连接到的下一个点
//offSet代表分支点坐标的偏差值
vector<int> BranchPoint::getNext(int offSet) {
	vector<int> rc = branchPointsInSameSegment;
	for (int i = 0; i < rc.size(); i++)rc[i] += offSet;
	rc.push_back(pc1->id);
	rc.push_back(pc2->id);
	return rc;
}

/*计算分支点到卡箍点的权值
	reverse=0代表从分支点到p
	reverse=1代表从p到分支点
*/
double BranchPoint::computeWeight(P& p, int inOut, bool reverse) {
	if (l >= r)return 1e9;

	if (fixed == false) {
		double X1 = pc1->coord.x, Y1 = pc1->coord.y, Z1 = pc1->coord.z;
		double X2 = pc2->coord.x, Y2 = pc2->coord.y, Z2 = pc2->coord.z;

		double X0 = p.x, Y0 = p.y, Z0 = p.z;

		double FZ = (X1 - X0) * (X1 - X2) + (Y1 - Y0) * (Y1 - Y2) + (Z1 - Z0) * (Z1 - Z2);
		double FM = 2 * Dis * Dis;

		t = FZ / FM; //公式法求t极小值点

		t = max(t, l); t = min(t, r);
	}

	//if(!Equal(t,l)&&!Equal(t,r))cout<<"-------"<<endl;
	coord = pc1->coord * (1 - t) + pc2->coord * t;

	coord.type = 1;

	if (reverse)return distan(p, coord, inOut, 0);
	return distan(coord, p, 0, inOut);

}


//记录分支点最优位置
void BranchPoint::recordPos(int mode){
	tempt[mode]=t;
}

void BranchPoint::check(int i){
}
	
BranchPointSet::BranchPointSet(){
	branchPointNum=0;
}

//添加一个分支点,并返回指向它的指针
BranchPoint* BranchPointSet::addBranchPoint(Clip* pc1,Clip* pc2,int bundleNodeID){
	branchPointNum++;
	b[branchPointNum]=BranchPoint(pc1,pc2);
	b[branchPointNum].bundleNodeID=bundleNodeID;
	b[branchPointNum].id=branchPointNum;
	b[branchPointNum].coord.type=1;
	b[branchPointNum].coord.ref=branchPointNum;
	return &b[branchPointNum];
}

	//获取指向编号为id的分支点的指针
BranchPoint * BranchPointSet::getBranchPointPointer(int id){
	assert(id>=1&&id<=branchPointNum);
	return &b[id];
}