#include "pch.h" // use stdafx.h in Visual Studio 2017 and earlier #include "BasicChannel.h" // 仅仅根据卡箍的相对位置创建近似的通道 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 BasicChannel::getBranchPointAndClip(vector cv, int offset) { vector 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> &partClip = resClip[i]; vector &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信息按格式要求打印出来 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< 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); } } } }