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.
650 lines
14 KiB
650 lines
14 KiB
#include "pch.h" // use stdafx.h in Visual Studio 2017 and earlier
|
|
#include "BasicChannel.h"
|
|
|
|
BasicChannel basicChannel;
|
|
|
|
// 仅仅根据卡箍的相对位置创建近似的通道
|
|
void BasicChannel::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);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 创建所有分支点
|
|
void BasicChannel::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;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 根据卡箍标号获取其所属的通道节点指针
|
|
BundleNode *BasicChannel::getClipBundleNodePointer(int cid)
|
|
{
|
|
assert(clipSet.c[cid].bundleNodeID != 0);
|
|
return &bdNode[clipSet.c[cid].bundleNodeID];
|
|
}
|
|
|
|
// 获取卡箍属于的通道id
|
|
int BasicChannel::getClipBundleID(Clip *pc)
|
|
{
|
|
BundleNode *pbn = &bdNode[pc->bundleNodeID];
|
|
return pbn->bundleID;
|
|
}
|
|
int BasicChannel::getClipBundleID(int cid)
|
|
{
|
|
BundleNode *pbn = &bdNode[clipSet.c[cid].bundleNodeID];
|
|
return pbn->bundleID;
|
|
}
|
|
|
|
// 根据点获取其属于的bundleNode,不包括分支点,如果不存在就新创建一个
|
|
BundleNode *BasicChannel::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;
|
|
}
|
|
}
|
|
|
|
// 获取卡箍在通道里的正方向
|
|
int BasicChannel::getClipInOut(int cid)
|
|
{
|
|
BundleNode *pbn = &bdNode[clipSet.c[cid].bundleNodeID];
|
|
return pbn->inOut;
|
|
}
|
|
|
|
// 返回卡箍类型,0为孤立卡箍,1为断头卡箍,2为中间卡箍
|
|
int BasicChannel::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;
|
|
}
|
|
|
|
// 获取断头卡箍的进入通道方向
|
|
int BasicChannel::getEXTClipInDir(Clip *pc)
|
|
{
|
|
BundleNode *pbn = &bdNode[pc->bundleNodeID];
|
|
if (pbn->pre == NULL)
|
|
return pbn->inOut;
|
|
else
|
|
return (pbn->inOut) ^ 1;
|
|
}
|
|
int BasicChannel::getEXTClipInDir(int cid)
|
|
{
|
|
BundleNode *pbn = &bdNode[clipSet.c[cid].bundleNodeID];
|
|
if (pbn->pre == NULL)
|
|
return pbn->inOut;
|
|
else
|
|
return (pbn->inOut) ^ 1;
|
|
}
|
|
|
|
// 获取中间卡箍在通道里的方向
|
|
int BasicChannel::getMIDClipDir(int cid)
|
|
{
|
|
BundleNode *pbn = &bdNode[clipSet.c[cid].bundleNodeID];
|
|
return pbn->inOut;
|
|
}
|
|
|
|
/*判断一个分支点是否在通道中连接到一个卡箍
|
|
如果不连接返回-1
|
|
如果连接上返回由分支点连接到卡箍的方向
|
|
*/
|
|
int BasicChannel::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的方向
|
|
*/
|
|
int BasicChannel::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;
|
|
}
|
|
|
|
// 根据一个卡箍的集合返回附近所有卡箍和分支点的集合
|
|
vector<int> BasicChannel::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
|
|
*/
|
|
int BasicChannel::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;
|
|
}
|
|
}
|
|
|
|
// 加入一条路径来更新通道数据
|
|
void BasicChannel::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 = nullptr; // 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;
|
|
}
|
|
|
|
void BasicChannel::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();
|
|
//------------------------mark------------------------
|
|
ofs << tp.x << " " << tp.y << " " << tp.z << " ";
|
|
ofs << tp.dx << " " << tp.dy << " " << tp.dz << endl;
|
|
// for blender input
|
|
// ofs << tp.x * 100 << " " << tp.y * 100 << " " << tp.z * 100 << " ";
|
|
// ofs << tp.dx * 100 << " " << tp.dy * 100 << " " << tp.dz * 100 << 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信息按格式要求打印出来
|
|
void BasicChannel::printBundle(string resultfile, bool basic)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|