double tdistance(const TSegment &segment, const TPointD &point) { TPointD v1 = segment.getP1() - segment.getP0(); TPointD v2 = point - segment.getP0(); TPointD v3 = point - segment.getP1(); if (v2 * v1 <= 0) return tdistance(point, segment.getP0()); else if (v3 * v1 >= 0) return tdistance(point, segment.getP1()); return fabs(v2 * rotate90(normalize(v1))); }
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; // NOTE: updated tails are stored this way, *DONT* look in a->m_tail // because these typically store old infos 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; // We then take the next arc and check it if (!a->m_graphHolder->getNode(i).getLink(iLink)->hasAttribute( SkeletonArc::ROAD)) return 0; // Pull back failed a->next(i, iLink); P = planeProjection(*a->m_graphHolder->getNode(i)); if (tdistance(P, a->m_direction, m_newJointPosition) > std::max(pullBackMul * a->m_height, 1.0)) return 0; // Pull back failed } // Now checking opposite sequence extremity if (alongLinePosition < 0 || (distanceFromLine / alongLinePosition) > 0.5) return 0; found_pull_back: a->m_head = i; a->m_headLink = iLink; } return 1; }
void MyInbetweener::stabilizeSegments(TStroke *stroke) { for (int j = 0; j + 4 < stroke->getControlPointCount(); j += 4) { TThickPoint q0 = stroke->getControlPoint(j); TThickPoint q4 = stroke->getControlPoint(j + 4); TPointD p0 = convert(q0); TPointD p1 = convert(stroke->getControlPoint(j + 1)); TPointD p2 = convert(stroke->getControlPoint(j + 2)); TPointD p3 = convert(stroke->getControlPoint(j + 3)); TPointD p4 = convert(q4); TPointD v = normalize(p4 - p0); TPointD u = rotate90(v); double eps = tdistance(p0, p4) * 0.1; if (fabs(u * (p2 - p0)) < eps && fabs(u * (p1 - p0)) < eps && fabs(u * (p3 - p0)) < eps) { double e = 0.001; double d2 = norm2(p4 - p0); if (e * e * 6 * 6 > d2) e = sqrt(d2) / 6; TThickPoint q1(p0 + v * e, q0.thick); TThickPoint q3(p4 - v * e, q4.thick); stroke->setControlPoint(j + 1, q1); stroke->setControlPoint(j + 3, q3); } } }
inline bool JunctionArea::solveJunctionPosition() { std::vector<EnteringSequence>::iterator a; double Sx2 = 0, Sy2 = 0, Sxy = 0; TPointD P, v, b; double h; //Build preliminary sums for the linear system 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)); //Height-weighted problem 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)); } //First check problem determinant double det = Sx2 * Sy2 - sq(Sxy); if (fabs(det) < 0.1) return 0; //Now construct linear system TAffine M(Sx2 / det, Sxy / det, 0, Sxy / det, Sy2 / det, 0); m_newJointPosition = M * b; //Finally, check if J is too far from the line extensions of the entering //sequences 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; }
void renormalizeImage(TVectorImage *vi) { int i, j; int n = vi->getStrokeCount(); std::vector<ControlPoint> points; points.reserve(n * 2); for (i = 0; i < n; i++) { TStroke *stroke = vi->getStroke(i); int m = stroke->getControlPointCount(); if (m > 0) { if (m == 1) points.push_back(ControlPoint(stroke, 0)); else { points.push_back(ControlPoint(stroke, 0)); points.push_back(ControlPoint(stroke, m - 1)); } } } int count = points.size(); for (i = 0; i < count; i++) { ControlPoint &pi = points[i]; TPointD posi = pi.getPoint(); TPointD center = posi; std::vector<int> neighbours; neighbours.push_back(i); for (j = i + 1; j < count; j++) { TPointD posj = points[j].getPoint(); double d = tdistance(posj, posi); if (d < 0.01) { neighbours.push_back(j); center += posj; } } int m = neighbours.size(); if (m == 1) continue; center = center * (1.0 / m); for (j = 0; j < m; j++) points[neighbours[j]].setPoint(center); } }