| |
| |
| #include "tcenterlinevectP.h" |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| namespace |
| { |
| VectorizerCoreGlobals *globals; |
| std::vector<unsigned int> contourFamilyOfOrganized; |
| JointSequenceGraph *currJSGraph; |
| ContourFamily *currContourFamily; |
| }; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| typedef std::map<UINT, UINT, std::less<UINT>> uintMap; |
| |
| |
| void organizeGraphs(SkeletonList *skeleton, VectorizerCoreGlobals &g) |
| { |
| globals = &g; |
| |
| SkeletonList::iterator currGraphPtr; |
| Sequence currSequence; |
| uintMap jointsMap; |
| UINT i, j; |
| |
| UINT counter = 0; |
| |
| |
| contourFamilyOfOrganized.clear(); |
| |
| for (currGraphPtr = skeleton->begin(); currGraphPtr != skeleton->end(); ++currGraphPtr) { |
| SkeletonGraph &currGraph = **currGraphPtr; |
| currSequence.m_graphHolder = &currGraph; |
| |
| |
| if (currGraph.getNodesCount() == 1) { |
| globals->singlePoints.push_back(*currGraph.getNode(0)); |
| ++counter; |
| continue; |
| } |
| |
| |
| bool has1DegreePoint = 0; |
| for (i = 0; i < currGraph.getNodesCount(); ++i) |
| if (currGraph.getNode(i).degree() != 2) |
| if (currGraph.getNode(i).degree() == 1) |
| has1DegreePoint = 1; |
| else |
| goto _graph; |
| |
| if (has1DegreePoint) |
| goto _two_endpoint; |
| else |
| goto _circulars; |
| |
| _two_endpoint : { |
| |
| for (i = 0; currGraph.getNode(i).degree() != 1; ++i) |
| ; |
| |
| currSequence.m_head = i; |
| currSequence.m_headLink = 0; |
| |
| |
| for (++i; i < currGraph.getNodesCount() && |
| currGraph.getNode(i).degree() == 2; |
| ++i) |
| ; |
| currSequence.m_tail = i; |
| currSequence.m_tailLink = 0; |
| |
| globals->singleSequences.push_back(currSequence); |
| |
| ++counter; |
| continue; |
| } |
| |
| _graph : { |
| |
| globals->organizedGraphs.push_back(JointSequenceGraph()); |
| JointSequenceGraph &JSGraph = globals->organizedGraphs.back(); |
| contourFamilyOfOrganized.push_back(counter); |
| |
| jointsMap.clear(); |
| |
| |
| for (i = 0; i < currGraph.getNodesCount(); ++i) { |
| if (currGraph.getNode(i).degree() != 2) { |
| j = JSGraph.newNode(i); |
| |
| jointsMap.insert(uintMap::value_type(i, j)); |
| } |
| } |
| |
| |
| for (i = 0; i < JSGraph.getNodesCount(); ++i) { |
| UINT joint = *JSGraph.getNode(i); |
| for (j = 0; j < currGraph.getNode(joint).getLinksCount(); ++j) { |
| currSequence.m_head = joint; |
| currSequence.m_headLink = j; |
| |
| |
| UINT oldNode = joint, thisNode = currGraph.getNode(joint).getLink(j).getNext(); |
| while (currGraph.getNode(thisNode).degree() == 2) { |
| currGraph.node(thisNode).setAttribute(ORGANIZEGRAPHS_SIGN); |
| currSequence.advance(oldNode, thisNode); |
| } |
| |
| currSequence.m_tail = thisNode; |
| currSequence.m_tailLink = currGraph.getNode(thisNode).linkOfNode(oldNode); |
| |
| JSGraph.newLink(i, jointsMap.find(thisNode)->second, currSequence); |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| _circulars : { |
| |
| |
| for (i = 0; i < currGraph.getNodesCount(); ++i) { |
| if (!currGraph.getNode(i).hasAttribute(ORGANIZEGRAPHS_SIGN) && currGraph.getNode(i).degree() == 2) { |
| |
| unsigned int curr = i, currLink = 0; |
| currSequence.next(curr, currLink); |
| |
| for (; curr != i; currSequence.next(curr, currLink)) |
| currGraph.node(curr).setAttribute(ORGANIZEGRAPHS_SIGN); |
| |
| |
| currSequence.m_head = currSequence.m_tail = i; |
| currSequence.m_headLink = 0; |
| currSequence.m_tailLink = 1; |
| |
| globals->singleSequences.push_back(currSequence); |
| } |
| } |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| namespace |
| { |
| const double roadsMaxSlope = 0.3; |
| const double shapeDistMul = 1; |
| const double hDiffMul = 0.3; |
| const double lineDistMul = 1; |
| const double pullBackMul = 0.2; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| inline void findRoads(const Sequence &s) |
| { |
| |
| unsigned int curr, currLink, next; |
| unsigned int roadStart, roadStartLink; |
| double d, hMax, length; |
| bool lowSlope, roadOn = 0; |
| |
| curr = s.m_head; |
| currLink = s.m_headLink; |
| for (; curr != s.m_tail; s.next(curr, currLink)) { |
| next = s.m_graphHolder->getNode(curr).getLink(currLink).getNext(); |
| |
| d = planeDistance(*s.m_graphHolder->getNode(curr), *s.m_graphHolder->getNode(next)); |
| lowSlope = fabs(s.m_graphHolder->getNode(curr).getLink(currLink)->getSlope()) < roadsMaxSlope ? 1 : 0; |
| |
| |
| if (!roadOn && lowSlope) { |
| length = 0; |
| hMax = s.m_graphHolder->getNode(curr)->z; |
| roadStart = curr; |
| roadStartLink = currLink; |
| } |
| |
| |
| else if (roadOn && !lowSlope && (length > hMax)) |
| |
| for (; roadStart != curr; s.next(roadStart, roadStartLink)) |
| s.m_graphHolder->node(roadStart).link(roadStartLink)->setAttribute(SkeletonArc::ROAD); |
| |
| |
| if (lowSlope) { |
| length += d; |
| if (hMax < s.m_graphHolder->getNode(next)->z) |
| hMax = s.m_graphHolder->getNode(next)->z; |
| } |
| |
| roadOn = lowSlope; |
| } |
| |
| |
| if (roadOn && (length > hMax)) |
| for (; roadStart != curr; s.next(roadStart, roadStartLink)) |
| s.m_graphHolder->node(roadStart).link(roadStartLink)->setAttribute(SkeletonArc::ROAD); |
| } |
| |
| |
| |
| |
| void findRoads(const JointSequenceGraph &JSGraph) |
| { |
| unsigned int i, j; |
| |
| |
| for (i = 0; i < JSGraph.getNodesCount(); ++i) { |
| for (j = 0; j < JSGraph.getNode(i).getLinksCount(); ++j) |
| |
| findRoads(*JSGraph.getNode(i).getLink(j)); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| class EnteringSequence : public Sequence |
| { |
| public: |
| TPointD m_direction; |
| double m_height; |
| |
| |
| unsigned int m_initialJoint; |
| unsigned int m_outerLink; |
| |
| EnteringSequence() {} |
| EnteringSequence(const Sequence &s) : Sequence(s) {} |
| }; |
| |
| |
| |
| class JunctionArea |
| { |
| public: |
| vector<EnteringSequence> m_enteringSequences; |
| vector<unsigned int> m_jointsAbsorbed; |
| TPointD m_newJointPosition; |
| |
| JunctionArea() {} |
| |
| |
| void expandArea(unsigned int initial); |
| |
| |
| bool checkShape(); |
| bool solveJunctionPosition(); |
| bool makeHeights(); |
| bool calculateReconstruction(); |
| |
| |
| bool sequencesPullBack(); |
| void apply(); |
| }; |
| |
| |
| |
| |
| |
| |
| |
| |
| inline void JunctionArea::expandArea(unsigned int initial) |
| { |
| unsigned int a; |
| unsigned int curr, currLink; |
| unsigned int i, iLink, iNext; |
| |
| m_jointsAbsorbed.push_back(initial); |
| currJSGraph->node(initial).setAttribute(JointSequenceGraph::REACHED); |
| |
| for (a = 0; a < m_jointsAbsorbed.size(); ++a) { |
| |
| curr = m_jointsAbsorbed[a]; |
| |
| for (currLink = 0; currLink < currJSGraph->getNode(curr).getLinksCount(); ++currLink) { |
| Sequence &s = *currJSGraph->node(curr).link(currLink); |
| if (s.m_graphHolder->getNode(s.m_head).getLink(s.m_headLink).getAccess()) { |
| |
| i = s.m_head; |
| iLink = s.m_headLink; |
| for (; i != s.m_tail && !s.m_graphHolder->getNode(i).getLink(iLink)->hasAttribute(SkeletonArc::ROAD); |
| s.next(i, iLink)) |
| ; |
| |
| |
| |
| if (i == s.m_tail) { |
| iNext = currJSGraph->getNode(curr).getLink(currLink).getNext(); |
| if (!currJSGraph->node(iNext).hasAttribute(JointSequenceGraph::REACHED)) { |
| currJSGraph->node(iNext).setAttribute(JointSequenceGraph::REACHED); |
| m_jointsAbsorbed.push_back(iNext); |
| } |
| |
| s.m_graphHolder->node(s.m_tail).link(s.m_tailLink).setAccess(0); |
| s.m_graphHolder->node(s.m_head).link(s.m_headLink).setAccess(0); |
| } else { |
| |
| m_enteringSequences.push_back(EnteringSequence(s)); |
| m_enteringSequences.back().m_head = i; |
| m_enteringSequences.back().m_headLink = iLink; |
| |
| |
| iNext = s.m_graphHolder->getNode(i).getLink(iLink).getNext(); |
| m_enteringSequences.back().m_direction = |
| planeProjection(*s.m_graphHolder->getNode(i) - *s.m_graphHolder->getNode(iNext)); |
| m_enteringSequences.back().m_direction = |
| m_enteringSequences.back().m_direction * (1 / norm(m_enteringSequences.back().m_direction)); |
| |
| |
| m_enteringSequences.back().m_height = s.m_graphHolder->getNode(i)->z; |
| |
| |
| m_enteringSequences.back().m_initialJoint = curr; |
| m_enteringSequences.back().m_outerLink = currLink; |
| } |
| } |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| inline bool JunctionArea::checkShape() |
| { |
| std::vector<EnteringSequence>::iterator a, b; |
| unsigned int node, contour, first, last, n; |
| TPointD A, A1, B, B1, P, P1; |
| bool result = 1; |
| |
| |
| |
| for (a = m_enteringSequences.begin(); a != m_enteringSequences.end(); ++a) { |
| node = a->m_graphHolder->getNode(a->m_head).getLink(a->m_headLink)->getLeftGenerator(); |
| contour = a->m_graphHolder->getNode(a->m_head).getLink(a->m_headLink)->getLeftContour(); |
| |
| (*currContourFamily)[contour][node].setAttribute(ContourNode::JR_RESERVED); |
| } |
| |
| |
| for (a = m_enteringSequences.begin(), b = m_enteringSequences.end() - 1; |
| a != m_enteringSequences.end(); b = a, ++a) { |
| |
| first = a->m_graphHolder->getNode(a->m_head).getLink(a->m_headLink)->getRightGenerator(); |
| |
| |
| contour = a->m_graphHolder->getNode(a->m_head).getLink(a->m_headLink)->getRightContour(); |
| n = (*currContourFamily)[contour].size(); |
| |
| |
| unsigned int numChecked = 0; |
| for (last = first; !(*currContourFamily)[contour][last].hasAttribute(ContourNode::JR_RESERVED) && numChecked < n; last = (last + 1) % n, ++numChecked) |
| ; |
| |
| |
| if (numChecked == n) |
| return 0; |
| |
| A = planeProjection((*currContourFamily)[contour][first].m_position); |
| A1 = planeProjection((*currContourFamily)[contour][(first + 1) % n].m_position); |
| B = planeProjection((*currContourFamily)[contour][last].m_position); |
| B1 = planeProjection((*currContourFamily)[contour][(last + 1) % n].m_position); |
| |
| for (node = first; !(*currContourFamily)[contour][node].hasAttribute(ContourNode::JR_RESERVED); |
| node = (node + 1) % n) { |
| P = planeProjection((*currContourFamily)[contour][node].m_position); |
| P1 = planeProjection((*currContourFamily)[contour][(node + 1) % n].m_position); |
| |
| |
| |
| result &= |
| (fabs(cross(P - A, normalize(A1 - A))) < a->m_height * shapeDistMul && |
| fabs(cross(P1 - A, normalize(A1 - A))) < a->m_height * shapeDistMul) |
| |
| || |
| |
| (fabs(cross(P - B, normalize(B1 - B))) < b->m_height * shapeDistMul && |
| fabs(cross(P1 - B, normalize(B1 - B))) < b->m_height * shapeDistMul); |
| } |
| } |
| |
| |
| for (a = m_enteringSequences.begin(); a != m_enteringSequences.end(); ++a) { |
| node = a->m_graphHolder->getNode(a->m_head).getLink(a->m_headLink)->getLeftGenerator(); |
| contour = a->m_graphHolder->getNode(a->m_head).getLink(a->m_headLink)->getLeftContour(); |
| |
| (*currContourFamily)[contour][node].clearAttribute(ContourNode::JR_RESERVED); |
| } |
| |
| return result; |
| } |
| |
| |
| |
| |
| |
| |
| |
| inline bool JunctionArea::solveJunctionPosition() |
| { |
| std::vector<EnteringSequence>::iterator a; |
| double Sx2 = 0, Sy2 = 0, Sxy = 0; |
| TPointD P, v, b; |
| double h; |
| |
| |
| for (a = m_enteringSequences.begin(); a != m_enteringSequences.end(); ++a) { |
| h = a->m_height; |
| v = a->m_direction; |
| P = planeProjection(*a->m_graphHolder->getNode(a->m_head)); |
| |
| |
| Sx2 += sq(v.x) * h; |
| Sy2 += sq(v.y) * h; |
| Sxy += v.x * v.y * h; |
| b.x += h * (sq(v.y) * P.x - (v.x * v.y * P.y)); |
| b.y += h * (sq(v.x) * P.y - (v.x * v.y * P.x)); |
| } |
| |
| |
| double det = Sx2 * Sy2 - sq(Sxy); |
| if (fabs(det) < 0.1) |
| return 0; |
| |
| |
| TAffine M(Sx2 / det, Sxy / det, 0, Sxy / det, Sy2 / det, 0); |
| |
| m_newJointPosition = M * b; |
| |
| |
| |
| for (a = m_enteringSequences.begin(); a != m_enteringSequences.end(); ++a) { |
| P = planeProjection(*a->m_graphHolder->getNode(a->m_head)); |
| if (tdistance(m_newJointPosition, a->m_direction, P) > a->m_height * lineDistMul) |
| return 0; |
| } |
| |
| return 1; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| namespace |
| { |
| const std::vector<EnteringSequence> *currEnterings; |
| const std::vector<unsigned int> *heightIndicesPtr; |
| |
| std::vector<double> *optHeights; |
| double optMeanError; |
| double hMax; |
| } |
| |
| |
| |
| inline bool checkCircles(std::vector<double> &heights) |
| { |
| unsigned int i, j; |
| double cos, sin, frac; |
| TPointD vi, vj; |
| |
| |
| for (j = 0, i = currEnterings->size() - 1; j < currEnterings->size(); i = j, ++j) { |
| vi = (*currEnterings)[i].m_direction; |
| vj = (*currEnterings)[j].m_direction; |
| |
| sin = cross(vi, vj); |
| |
| if (heights[i] == heights[j]) |
| goto test_against_max_height; |
| |
| frac = heights[i] / heights[j]; |
| if (sin < 0) |
| return 0; |
| cos = vi * vj; |
| |
| if (cos < 0 && (frac < -cos || frac > (-1 / cos))) |
| return 0; |
| |
| test_against_max_height: |
| |
| cos = (sin < 0.1) ? tmax(heights[i], heights[j]) : norm((vi * (heights[j] / sin)) + (vj * (heights[i] / sin))); |
| if (cos < hMax) |
| return 0; |
| } |
| |
| return 1; |
| } |
| |
| |
| |
| inline void tryConfiguration(const std::vector<unsigned int> &bounds) |
| { |
| std::vector<double> currHeights(currEnterings->size()); |
| double mean, currMeanError = 0; |
| unsigned int i, j, first, end; |
| |
| for (i = 0, first = 0; i <= bounds.size(); first = end, ++i) { |
| |
| end = i < bounds.size() ? end = bounds[i] + 1 : currEnterings->size(); |
| |
| |
| for (j = first, mean = 0; j < end; ++j) |
| mean += (*currEnterings)[(*heightIndicesPtr)[j]].m_height; |
| |
| mean /= end - first; |
| |
| |
| if (tmax((*currEnterings)[(*heightIndicesPtr)[end - 1]].m_height - mean, |
| mean - (*currEnterings)[(*heightIndicesPtr)[first]].m_height) > hDiffMul * mean) |
| return; |
| |
| |
| for (j = first; j < end; ++j) |
| currMeanError += |
| sq((*currEnterings)[(*heightIndicesPtr)[j]].m_height - mean); |
| |
| |
| for (j = first; j < end; ++j) |
| currHeights[(*heightIndicesPtr)[j]] = mean; |
| } |
| |
| |
| hMax = mean; |
| |
| |
| if (optHeights->empty() || currMeanError < optMeanError) { |
| if (checkCircles(currHeights)) { |
| (*optHeights) = currHeights; |
| optMeanError = currMeanError; |
| } |
| } |
| } |
| |
| |
| |
| class hLess |
| { |
| public: |
| std::vector<EnteringSequence> &m_entSequences; |
| |
| hLess(std::vector<EnteringSequence> &v) : m_entSequences(v) {} |
| |
| inline bool operator()(unsigned int a, unsigned int b) |
| { |
| return m_entSequences[a].m_height < m_entSequences[b].m_height; |
| } |
| }; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| inline bool JunctionArea::makeHeights() |
| { |
| std::vector<unsigned int> heightOrderedIndices; |
| std::vector<unsigned int> rightIntervalBounds; |
| std::vector<double> optimalHeights; |
| |
| unsigned int i, n, m; |
| |
| |
| heightOrderedIndices.resize(m_enteringSequences.size()); |
| for (i = 0; i < m_enteringSequences.size(); ++i) |
| heightOrderedIndices[i] = i; |
| sort(heightOrderedIndices.begin(), heightOrderedIndices.end(), |
| hLess(m_enteringSequences)); |
| |
| |
| currEnterings = &m_enteringSequences; |
| heightIndicesPtr = &heightOrderedIndices; |
| |
| optMeanError = 0; |
| optHeights = &optimalHeights; |
| |
| |
| n = m_enteringSequences.size(); |
| |
| |
| rightIntervalBounds.resize(0); |
| tryConfiguration(rightIntervalBounds); |
| for (m = 1; m < n && optimalHeights.empty(); ++m) { |
| |
| rightIntervalBounds.resize(1); |
| rightIntervalBounds[0] = 0; |
| |
| while (!rightIntervalBounds.empty()) { |
| |
| while (rightIntervalBounds.size() < m) |
| rightIntervalBounds.push_back(rightIntervalBounds.back() + 1); |
| |
| tryConfiguration(rightIntervalBounds); |
| |
| |
| |
| |
| while ((++rightIntervalBounds.back(), |
| rightIntervalBounds.back() < n - 1 - (m - rightIntervalBounds.size()) ? 0 : (rightIntervalBounds.pop_back(), |
| !rightIntervalBounds.empty()))) |
| ; |
| } |
| } |
| |
| if (!optimalHeights.empty()) { |
| for (i = 0; i < n; ++i) |
| m_enteringSequences[i].m_height = optimalHeights[i]; |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| |
| |
| |
| |
| class EntSequenceLess |
| { |
| public: |
| EntSequenceLess() {} |
| |
| inline bool operator()(const EnteringSequence &a, const EnteringSequence &b) |
| { |
| |
| return a.m_direction.y >= 0 ? b.m_direction.y >= 0 ? a.m_direction.x > b.m_direction.x : 1 : b.m_direction.y < 0 ? a.m_direction.x < b.m_direction.x : 0; |
| } |
| }; |
| |
| |
| |
| bool JunctionArea::calculateReconstruction() |
| { |
| unsigned int i; |
| |
| if (m_enteringSequences.size() == 0) |
| return 0; |
| |
| |
| |
| |
| for (i = 0; i < m_jointsAbsorbed.size(); ++i) |
| if (currJSGraph->getNode(m_jointsAbsorbed[i]).degree() == 1) |
| return 0; |
| |
| |
| |
| sort(m_enteringSequences.begin(), m_enteringSequences.end(), |
| EntSequenceLess()); |
| |
| if (!checkShape()) |
| return 0; |
| |
| |
| if (!solveJunctionPosition()) |
| return 0; |
| |
| |
| if (!makeHeights()) |
| return 0; |
| |
| return 1; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| inline bool JunctionArea::sequencesPullBack() |
| { |
| std::vector<EnteringSequence>::iterator a; |
| double alongLinePosition, distanceFromLine; |
| unsigned int i, iLink, tail; |
| TPointD P; |
| |
| for (a = m_enteringSequences.begin(); a != m_enteringSequences.end(); ++a) { |
| i = a->m_head; |
| iLink = a->m_headLink; |
| |
| |
| tail = currJSGraph->getNode(a->m_initialJoint).getLink(a->m_outerLink)->m_tail; |
| P = planeProjection(*a->m_graphHolder->getNode(a->m_head)); |
| |
| while (i != tail) { |
| alongLinePosition = a->m_direction * (m_newJointPosition - P); |
| distanceFromLine = tdistance(m_newJointPosition, a->m_direction, P); |
| |
| if (alongLinePosition >= 0 && (distanceFromLine / alongLinePosition) <= 0.5) |
| goto found_pull_back; |
| |
| |
| |
| if (!a->m_graphHolder->getNode(i).getLink(iLink)->hasAttribute(SkeletonArc::ROAD)) |
| return 0; |
| |
| a->next(i, iLink); |
| |
| P = planeProjection(*a->m_graphHolder->getNode(i)); |
| if (tdistance(P, a->m_direction, m_newJointPosition) > |
| tmax(pullBackMul * a->m_height, 1.0)) |
| return 0; |
| } |
| |
| |
| if (alongLinePosition < 0 || (distanceFromLine / alongLinePosition) > 0.5) |
| return 0; |
| |
| found_pull_back: |
| |
| a->m_head = i; |
| a->m_headLink = iLink; |
| } |
| |
| return 1; |
| } |
| |
| |
| |
| |
| |
| |
| |
| void JunctionArea::apply() |
| { |
| std::vector<EnteringSequence>::iterator a; |
| unsigned int newJoint, newSkeletonNode; |
| unsigned int head, headLink, tail, tailLink; |
| unsigned int outerJoint, outerLink; |
| unsigned int i, next, nextLink; |
| |
| |
| if (!sequencesPullBack()) |
| return; |
| |
| |
| |
| for (i = 0; i < m_jointsAbsorbed.size(); ++i) |
| currJSGraph->node(m_jointsAbsorbed[i]).setAttribute(JointSequenceGraph::ELIMINATED); |
| |
| newJoint = currJSGraph->newNode(); |
| |
| for (a = m_enteringSequences.begin(); a != m_enteringSequences.end(); ++a) { |
| |
| newSkeletonNode = a->m_graphHolder |
| ->newNode(T3DPointD(m_newJointPosition, a->m_height)); |
| |
| |
| |
| |
| const JointSequenceGraph::Link &tempLink = |
| currJSGraph->getNode(a->m_initialJoint).getLink(a->m_outerLink); |
| |
| head = tempLink->m_head; |
| headLink = tempLink->m_headLink; |
| tail = tempLink->m_tail; |
| tailLink = tempLink->m_tailLink; |
| |
| outerJoint = tempLink.getNext(); |
| |
| |
| for (i = 0; (currJSGraph->getNode(outerJoint).getLink(i)->m_tail != head) || |
| (currJSGraph->getNode(outerJoint).getLink(i)->m_tailLink != headLink); |
| ++i) |
| ; |
| outerLink = i; |
| |
| |
| |
| |
| |
| |
| |
| if (a->m_graphHolder->getNode(a->m_head).degree() == 2) { |
| a->m_graphHolder->newLink(newSkeletonNode, a->m_head); |
| |
| a->m_graphHolder->node(a->m_head).link(!a->m_headLink).setNext(newSkeletonNode); |
| a->m_graphHolder->node(a->m_head).link(!a->m_headLink)->setAttribute(SkeletonArc::ROAD); |
| |
| } else if (a->m_head == tail) { |
| a->m_graphHolder->newLink(newSkeletonNode, tail); |
| |
| a->m_graphHolder->node(tail).link(tailLink).setNext(newSkeletonNode); |
| a->m_graphHolder->node(tail).link(tailLink)->setAttribute(SkeletonArc::ROAD); |
| } else |
| { |
| |
| unsigned int newHead = a->m_graphHolder |
| ->newNode(T3DPointD(*a->m_graphHolder->getNode(a->m_head))); |
| |
| a->m_graphHolder->newLink(newSkeletonNode, newHead); |
| a->m_graphHolder->newLink(newHead, newSkeletonNode); |
| |
| |
| next = a->m_graphHolder |
| ->getNode(head) |
| .getLink(headLink) |
| .getNext(); |
| nextLink = a->m_graphHolder->getNode(next).linkOfNode(head); |
| |
| a->m_graphHolder->newLink(newHead, next); |
| a->m_graphHolder->node(next).link(nextLink).setNext(newHead); |
| } |
| |
| |
| Sequence newSequence; |
| |
| newSequence.m_graphHolder = a->m_graphHolder; |
| newSequence.m_head = newSkeletonNode; |
| newSequence.m_headLink = 0; |
| newSequence.m_tail = tail; |
| newSequence.m_tailLink = tailLink; |
| |
| currJSGraph->node(outerJoint).link(outerLink).setNext(newJoint); |
| currJSGraph->node(outerJoint).link(outerLink)->m_tail = newSkeletonNode; |
| currJSGraph->node(outerJoint).link(outerLink)->m_tailLink = 0; |
| |
| currJSGraph->newLink(newJoint, outerJoint, newSequence); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| void junctionRecovery(Contours *polygons, VectorizerCoreGlobals &g) |
| { |
| globals = &g; |
| |
| unsigned int i, j; |
| std::vector<JunctionArea> junctionAreasList; |
| |
| |
| |
| for (i = 0; i < globals->organizedGraphs.size(); ++i) { |
| currJSGraph = &globals->organizedGraphs[i]; |
| currContourFamily = &(*polygons)[contourFamilyOfOrganized[i]]; |
| junctionAreasList.clear(); |
| |
| |
| findRoads(*currJSGraph); |
| |
| |
| for (j = 0; j < currJSGraph->getNodesCount(); ++j) |
| if (!currJSGraph->getNode(j).hasAttribute(JointSequenceGraph::REACHED)) { |
| junctionAreasList.push_back(JunctionArea()); |
| junctionAreasList.back().expandArea(j); |
| if (!junctionAreasList.back().calculateReconstruction()) |
| junctionAreasList.pop_back(); |
| } |
| |
| |
| for (j = 0; j < junctionAreasList.size(); ++j) |
| junctionAreasList[j].apply(); |
| } |
| } |
| |