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

#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);
}
}
}
}