You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

586 lines
13 KiB

#include "stdafx.h"
#include "Bundle.h"
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<iostream>
#include<fstream>
#include<sstream>
using namespace std;
//根据卡箍相对位置估计基本的通道,并维护与此相关的分支点信息
struct BasicChannel {
Bundle bundles[N]; //所有通道
int bundleNum; //所有通道数量
int basicChannelNum;//基本通道数量
map<int,BundleNode *> PointConnectedTobranchPoint[MAXPointNum];//连接到分支点的点
//仅仅根据卡箍的相对位置创建近似的通道
inline void createChannel(){
Clip *c = clipSet.c;
int clipNum=clipSet.clipnum;
for(int i=1;i<=clipNum;i++){
if(c[i].bundleNodeID!=0)continue;
int cnt=0;
for(int j=0;j<c[i].channelEdge.size();j++){
int cid=c[i].channelEdge[j];
if(clipSet.bothConnect(i,cid))cnt++;
}
if(cnt==1){
Path path;
path.dia=5;
int lastCid=0;
int cid=i;
while(cid){
bool flag=true;
path.points.push_back(c[cid].coord);
for(int j=0;j<c[cid].channelEdge.size();j++){
int cid2=c[cid].channelEdge[j];
if(cid2==lastCid)continue;
if(clipSet.bothConnect(cid,cid2)){
lastCid=cid;
cid=cid2;
flag=false;
break;
}
}
if(flag)break;
}
path.processDir();
bundleNum++;
basicChannelNum++;
bundles[bundleNum]=Bundle(path,bundleNum);
}
}
}
//创建所有分支点
inline void createBranchPoint(){
for(int i=1;i<=bundleNum;i++){
BranchPoint * ppb=NULL;
BundleNode * pbn=bundles[i].head;
while(pbn!=NULL&&pbn->next!=NULL){
BranchPoint* pb=branchPointSet.addBranchPoint(pbn->pc,pbn->next->pc,pbn->id);
pbn->vb.push_back(pb->id);
if(ppb!=NULL){
ppb->pb2=pb;
pb->pb1=ppb;
}
ppb=pb;
pbn=pbn->next;
}
}
}
//根据卡箍标号获取其所属的通道节点指针
inline BundleNode* getClipBundleNodePointer(int cid){
assert(clipSet.c[cid].bundleNodeID!=0);
return &bdNode[clipSet.c[cid].bundleNodeID];
}
//获取卡箍属于的通道id
inline int getClipBundleID(Clip * pc){
BundleNode *pbn=&bdNode[pc->bundleNodeID];
return pbn->bundleID;
}
inline int getClipBundleID(int cid){
BundleNode *pbn=&bdNode[clipSet.c[cid].bundleNodeID];
return pbn->bundleID;
}
//根据点获取其属于的bundleNode,不包括分支点,如果不存在就新创建一个
inline BundleNode * getBundleNodeByPoint(P& p,int inOut,int bundleID){
assert(p.type==0||p.type==3);
if(p.type==0){
int cid=p.ref;
int bnid=clipSet.c[cid].bundleNodeID;
if(bnid==0)return Bundle::createBundleNode(p,inOut,bundleID);
BundleNode *pbn=&bdNode[bnid];
return pbn;
}
else {
int cnid=p.ref;
int bnid=connectors[cnid].bundleNodeID;
if(bnid==0)return Bundle::createBundleNode(p,inOut,bundleID);
cout<<"---"<<bnid<<endl;
BundleNode *pbn=&bdNode[bnid];
return pbn;
}
}
//获取卡箍在通道里的正方向
inline int getClipInOut(int cid){
BundleNode *pbn=&bdNode[clipSet.c[cid].bundleNodeID];
return pbn->inOut;
}
//返回卡箍类型,0为孤立卡箍,1为断头卡箍,2为中间卡箍
inline int clipType(int cid){
int bundleNodeID=clipSet.c[cid].bundleNodeID;
if(bundleNodeID==0)return 0;
BundleNode *pbn=&bdNode[bundleNodeID];
if(pbn->pre==NULL&&pbn->next==NULL)return 0;
if(pbn->pre==NULL||pbn->next==NULL)return 1;
return 2;
}
//获取断头卡箍的进入通道方向
inline int getEXTClipInDir(Clip * pc){
BundleNode *pbn=&bdNode[pc->bundleNodeID];
if(pbn->pre==NULL)return pbn->inOut;
else return (pbn->inOut)^1;
}
inline int getEXTClipInDir(int cid){
BundleNode *pbn=&bdNode[clipSet.c[cid].bundleNodeID];
if(pbn->pre==NULL)return pbn->inOut;
else return (pbn->inOut)^1;
}
//获取中间卡箍在通道里的方向
inline int getMIDClipDir(int cid){
BundleNode *pbn=&bdNode[clipSet.c[cid].bundleNodeID];
return pbn->inOut;
}
/*判断一个分支点是否在通道中连接到一个卡箍
如果不连接返回-1
如果连接上返回由分支点连接到卡箍的方向
*/
inline int isBranchPointConnectedToClip(int bid,int cid){
BundleNode *pbn=&bdNode[clipSet.c[cid].bundleNodeID];
if(pbn->next!=NULL&&
pbn->next->type==1&&
pbn->next->pb->id==bid)return getMIDClipDir(cid)^1;
if(pbn->pre!=NULL&&
pbn->pre->type==1&&
pbn->pre->pb->id==bid)return getMIDClipDir(cid);
return -1;
}
/*判断一个卡箍是否在通道中连接到一个卡箍
如果不连接返回-1
如果连接上返回由卡箍1连接到卡箍2的方向
*/
inline int isClipConnectedToClip(int cid1,int cid2){
BundleNode *pbn=&bdNode[clipSet.c[cid1].bundleNodeID];
if(pbn->next!=NULL&&
pbn->next->type==0&&
pbn->next->pc->id==cid2)return getMIDClipDir(cid2);
if(pbn->pre!=NULL&&
pbn->pre->type==0&&
pbn->pre->pc->id==cid2)return getMIDClipDir(cid2)^1;
return -1;
}
//根据一个卡箍的集合返回附近所有卡箍和分支点的集合
inline vector<int> getBranchPointAndClip(vector<int> cv,int offset){
vector<int>res;
for(int i=0;i<cv.size();i++){
int cid=cv[i];
res.push_back(cid);
int bundleNodeID=clipSet.c[cid].bundleNodeID;
if(bundleNodeID==0)continue;
BundleNode *pbn=&bdNode[bundleNodeID];
for(int j=0;j<pbn->vb.size();j++){
res.push_back(pbn->vb[j]);
}
}
return res;
}
/*合并两个bundle,短的并入长的
左边的bundle用指针pbd表示
右边的bundle用id表示
rev1,rev2分别代表左右两个bundle与path方向的关系
返回合并后的bundle与path的位置关系
pbd会指向合并后的bundle
*/
inline int mergeBundle(Bundle*& pbd,int bdid,int rev1,int rev2){
Bundle * pbd2=&bundles[bdid];
if(pbd->length<pbd2->length){
pbd->abandoned=true;
pbd2->length+=pbd->length;
BundleNode* pbn=pbd->head;
while(pbn!=NULL){
pbn->bundleID=bdid;
BundleNode* nt=pbn->next;
if(rev1!=rev2){
(pbn->inOut)^=1;
(pbn->rev)^=1;
swap(pbn->pre,pbn->next);
}
pbn=nt;
}
if(rev1!=rev2){
swap(pbd->head,pbd->tail);
}
if(rev2==0){
pbd->tail->next=pbd2->head;
pbd2->head->pre=pbd->tail;
pbd2->head=pbd->head;
}
else {
pbd->head->pre=pbd2->tail;
pbd2->tail->next=pbd->head;
pbd2->tail=pbd->tail;
}
if(pbd->id==this->bundleNum+1)delete pbd;
pbd=pbd2;
return rev2;
}
else{
pbd2->abandoned=true;
pbd->length+=pbd2->length;
BundleNode* pbn=pbd2->head;
while(pbn!=NULL){
pbn->bundleID=pbd->id;
BundleNode* nt=pbn->next;
if(rev1!=rev2){
pbn->inOut^=1;
pbn->rev^=1;
swap(pbn->pre,pbn->next);
}
pbn=nt;
}
if(rev1!=rev2){
swap(pbd2->head,pbd2->tail);
}
if(rev1==0){
pbd->tail->next=pbd2->head;
pbd2->head->pre=pbd->tail;
pbd->tail=pbd2->tail;
}
else {
pbd->head->pre=pbd2->tail;
pbd2->tail->next=pbd->head;
pbd->head=pbd2->head;
}
return rev1;
}
}
//加入一条路径来更新通道数据
inline void addPath(Path path){
Bundle *pbd=new Bundle();
pbd->id=bundleNum+1; //pdb代表当前通道
int reverse=0;//reverse=1代表path和bundle反向
BundleNode *pre=NULL;
for(int i=0;i<path.size();i++){
P p=path.points[i];
int inOut=path.inOut[i];
BundleNode *pbn; //pbn代表当前通道节点
//非分支点
if(p.type==0||p.type==3){
pbn=this->getBundleNodeByPoint(p,inOut^reverse,pbd->id);
//存在则返回,没有则新建
//起始连接器
if(i==0){
if(pbn->bundleID==pbd->id){ //起始连接器未加入通道
pbd->head=pbn;
pbd->tail=pbn;
pbd->length=1;
reverse=0;
}
else { //起始连接器已加入通道
delete pbd;
pbd=&this->bundles[pbn->bundleID];
reverse=(pbd->tail==pbn);
}
}
else { //非起始连接器
int rev2=(pbn->inOut!=inOut);
if(pbn->bundleID!=pbd->id) //新节点已经属于别的通道
reverse=this->mergeBundle(pbd,pbn->bundleID,reverse,rev2);
//短的通道向长的通道合并,方向以长通道为准
else if(pbn->pre==NULL&&pbn->next==NULL){//新节点还没有属于任何通道
if(reverse)pbd->head=pbn;
else pbd->tail=pbn;
pbd->length++;
}
//和前一个通道节点链接
if(pre!=NULL){
if(!reverse){
pre->next=pbn;
pbn->pre=pre;
}
else {
pre->pre=pbn;
pbn->next=pre;
}
}
if(i==path.size()-1){ //终止连接器
//创建新的通道
if(pbd->id==this->bundleNum+1){
this->bundleNum++;
this->bundles[pbd->id]=*pbd;
delete pbd;
}
}
}
if(pbn->id==146){
;
int TTT=1;
TTT++;
;
}
}
else { //分支点
int bid=p.ref;
BranchPoint* pb=branchPointSet.getBranchPointPointer(bid);
int cid1=pb->pc1->id,cid2=pb->pc2->id;
//分支点作为上一个通道的结尾
P& tp=path.points[i-1];
int id=tp.ref;
//同段分支点
if(tp.type==0&&(id==cid1||id==cid2)){
;
}
else{ //异段分支点
if(tp.type==0)id*=3;
else if(tp.type==3)id=id*3+1;
else id=id*3+2;
//给卡箍id*3,连接器id*3+1,分支点id*3+2,把他们区分开
//找到分支点对应通道节点,或新建一个
pbn=this->PointConnectedTobranchPoint[bid][id];
if(pbn==NULL){
pbn=Bundle::createBundleNode(p,inOut,pbd->id);
this->PointConnectedTobranchPoint[bid][id]=pbn;
//更新通道信息
pbd->length++;
if(reverse)pbd->head=pbn;
else pbd->tail=pbn;
}
//和前一个通道节点链接
if(pre!=NULL){
if(!reverse){
pre->next=pbn;
pbn->pre=pre;
}
else {
pre->pre=pbn;
pbn->next=pre;
}
}
}
//创建新的通道
if(pbd->id==this->bundleNum+1){
this->bundleNum++;
this->bundles[pbd->id]=*pbd;
delete pbd;
}
//分支点作为下一个通道的开头
if(i!=path.size()-1){
//创建临时新通道
pbd= new Bundle();
pbd->id=this->bundleNum+1;
P& tp=path.points[i+1];
int id=tp.ref;
//同段分支点
if(tp.type==0&&(id==cid1||id==cid2)){
delete pbd;
int bundleID=this->getClipBundleID(cid1);
pbd=&this->bundles[bundleID];
pbn=this->getClipBundleNodePointer(cid1);
BundleNode *pbn2=this->getClipBundleNodePointer(cid2);
if(id==cid2){
if(pbn->next==pbn2)reverse=0;
else {
assert(pbn->pre==pbn2);
reverse=1;
}
}
else {
assert(id==cid1);
if(pbn2->next==pbn)reverse=0;
else {
assert(pbn2->pre==pbn);
reverse=1;
}
pbn=pbn2;
}
}
else{ //异段分支点
if(tp.type==0)id*=3;
else if(tp.type==3)id=id*3+1;
else id=id*3+2;
//给卡箍id*3,连接器id*3+1,分支点id*3+2,把他们区分开
//找到分支点对应通道节点,或新建一个
pbn=this->PointConnectedTobranchPoint[bid][id];
if(pbn==NULL){
pbn=Bundle::createBundleNode(p,inOut,pbd->id);
this->PointConnectedTobranchPoint[bid][id]=pbn;
//更新通道信息
pbd->length++;
pbd->head=pbn;
pbd->tail=pbn;
reverse=0;
}
else {
delete pbd;
pbd=&bundles[pbn->bundleID];
if(pbd->head==pbn)reverse=0;
else{
assert(pbd->tail==pbn);
reverse=1;
}
}
}
}
}
pre=pbn;
}
return;
}
vector<vector<pair<int,int> > > resClip;
vector<vector<int> > resBranchPoint;
vector<int> startBranchPoint;
vector<int> endBranchPoint;
vector<int> BundleConnectedToBranchPoint[MAXPointNum]; //连接到分支点的通道
int Out[N];
void printSingleBundle(int i,ofstream &ofs){
vector< pair<int,int> >& partClip=resClip[i];
vector<int>& partBranchPoint=resBranchPoint[i];
ofs<<partClip.size()<<" "<<1<<
" "<<startBranchPoint[i]<<" "<<endBranchPoint[i]<<endl;
for(int j=0;j<partClip.size();j++){
int id=partClip[j].first;
int inOut=partClip[j].second;
P tp;
if(inOut==-1){
ofs<<connectors[id].name<<" "<<0<<endl;
tp=connectors[id].coord;
}
else {
ofs<<clipSet.c[id].name<<" "<<(inOut^1)<<endl;
tp=clipSet.c[id].coord;
}
if(inOut!=0)tp.reverse();
ofs<<tp.x<<" "<<tp.y<<" "<<tp.z<<" ";
ofs<<tp.dx<<" "<<tp.dy<<" "<<tp.dz<<endl;
}
ofs<<partBranchPoint.size()<<endl;
for(int j=0;j<partBranchPoint.size();j++){
int bid=partBranchPoint[j];
BranchPoint *pb=branchPointSet.getBranchPointPointer(bid);
int bnid=pb->bundleNodeID;
if(bid==150)cout<<(pb->Dis)<<" "<<(pb->position)<<" "<<(pb->pc2->name)<<endl;
assert((pb->position)<(pb->Dis));
if(bdNode[bnid].rev==1){
cout<<"reverse"<<endl;
pb->reverse();
}
ofs<<bid<<" "<<pb->referClip<<" "<<pb->position<<endl;
}
}
//把bundle信息按格式要求打印出来
inline void printBundle(string resultfile,bool basic=false){
ofstream ofs;
ofs.open(resultfile.c_str(), ios::out);
cout<<"bundleNum: "<<bundleNum<<endl;
for(int i=1;i<=bundleNum;i++)
if(!bundles[i].abandoned||basic)
bundles[i].updateOutput(resClip,resBranchPoint,
startBranchPoint,endBranchPoint,basic);
cout<<"resClip.size()= "<<resClip.size()<<endl;
ofs<<resClip.size()<<endl;
//ofs<<76<<endl;
queue<int>q;
for(int i=0;i<resClip.size();i++)Out[i]=0;
for(int i=0;i<resClip.size();i++){
if(startBranchPoint[i]!=0){
Out[i]++;
this->BundleConnectedToBranchPoint[this->startBranchPoint[i]].push_back(i);
}
if(this->endBranchPoint[i]!=0){
Out[i]++;
this->BundleConnectedToBranchPoint[this->endBranchPoint[i]].push_back(i);
}
if(Out[i]==0)q.push(i);
}
while(!q.empty()){
int x=q.front();q.pop();
this->printSingleBundle(x,ofs);
for(int i=0;i<this->resBranchPoint[x].size();i++){
int bid=this->resBranchPoint[x][i];
for(int j=0;j<this->BundleConnectedToBranchPoint[bid].size();j++){
int bdid=this->BundleConnectedToBranchPoint[bid][j];
Out[bdid]--;
if(Out[bdid]==0)q.push(bdid);
}
}
}
}
}basicChannel;