/** * Update text distribution between edges */ void GuiEdge::updateLabels() { float sum_len = 0; QPoint end_sequence; bool first_run = full_label.length() == 0; for (GuiEdge* i = this;; i->succ()->firstSucc() && (i = addGui (i->succ()->firstSucc()))) { sum_len += i->length(); if (first_run) full_label += i->edgeLabel(); if (i->succ() && i->succ()->real()) { end_sequence = addAux(i->succ())->coor(); break; } } float n_letters = 0; float last_round_up = 0; int full_len = full_label.length(); QPoint delta = end_sequence - edge_start_point_priv.toPoint(); reverse = -delta.x() > delta.y(); QString buf = full_label; for (GuiEdge* i = this;; i->succ()->firstSucc() && (i = addGui (i->succ()->firstSucc()))) { i->reverse = reverse; n_letters = full_len*i->length()/sum_len + last_round_up; //give an appropriate substring last_round_up = n_letters - (int)n_letters; if (i->succ() && i->succ()->real())//take the last character n_letters ++; if (reverse) { i->setEdgeLabel (buf.right (n_letters)); buf.remove (buf.length() + 1 - n_letters, n_letters); } else { i->setEdgeLabel (buf.left (n_letters)); buf.remove (0, n_letters); } if (i->succ() && i->succ()->real()) break; } }
int addAux(LinkedList & lsum, Node * nptr1, Node * nptr2) { if (nptr1 && nptr2) { int carry = addAux(lsum, nptr1->next, nptr2->next); int sum = carry + nptr1->getVal() + nptr2->getVal(); lsum.prepend(new Node('0' + sum % 10)); return sum / 10; } if (!nptr1 && !nptr2) { return 0; } else { assert(false); // For now } }
/** * Draws a label near the edge */ void GuiEdge::drawText (QPainter * painter) const { int len = edgeLabel().length(); float k = 0.8f; float start = 0.1f; if (Edge::pred() && !addAux (Edge::pred())->real())//press letters to the virtual nodes { k += start; start = 0; } if (Edge::succ() && !addAux (Edge::succ())->real())//press letters to the virtual nodes { k = 1 - start; } if (reverse) { k = -k; start = 1 - start; } QPointF delta = edge_end_point_priv - edge_start_point_priv; float letter_size = 1.3*edge_curve_priv.length()/len; if (letter_size > 25) letter_size = 25; if (letter_size > 8 && !cycle()) { for (int i = 0; i < len; ++i) { float slope = edge_curve_priv.slopeAtPercent (start + k*float(i)/len); float ang = atan(slope); QPointF pos = edge_curve_priv.pointAtPercent(start + k*float(i)/len); pos += QPointF (cos (Pi/2 + ang), sin(Pi/2 + ang))*letter_size; QFont curf = painter->font(); curf.setPixelSize (letter_size); painter->setFont (curf); painter->drawText (pos, QString(edgeLabel().at(i))); } } }
int main() { srand(time(0)); std::cout << "--- Test lists when digits are in increasing magnitude\n"; for (int k = 0; k < NUM_ITERATIONS; ++k) { int NUM_DIGITS1 = (rand() % NUM_DIGITS_MAX) + 1; int NUM_DIGITS2 = (rand() % NUM_DIGITS_MAX) + 1; LinkedList l1, l2; // Leading zeroes are handled like any other number for simple testing for (int i = 0; i < NUM_DIGITS1; ++i) { l1.append(new Node(rand() % 10 + '0')); } for (int i = 0; i < NUM_DIGITS2; ++i) { l2.append(new Node(rand() % 10 + '0')); } LinkedList lsum; Node * n1, * n2; n1 = l1.root; n2 = l2.root; int carry = 0; while (n1 && n2) { int sum = n1->getVal() + n2->getVal() + carry; lsum.append(new Node('0' + sum % 10)); carry = sum / 10; n1 = n1->next; n2 = n2->next; } if (n1 || n2) { // One # was longer than the other Node * n = n1 ? n1 : n2; while (n) { int sum = n->getVal() + carry; lsum.append(new Node('0' + sum % 10)); carry = sum / 10; n = n->next; } } if (carry) { lsum.append(new Node('0' + carry)); } std::cout << l1.toNum(1) << " + " << l2.toNum(1) << " = " << lsum.toNum(1) << std::endl; assert(l1.toNum(1) + l2.toNum(1) == lsum.toNum(1)); } std::cout << "--- Test lists when digits are in decreasing magnitude\n"; for (int k = 0; k < NUM_ITERATIONS; ++k) { int NUM_DIGITS1 = (rand() % NUM_DIGITS_MAX) + 1; int NUM_DIGITS2 = (rand() % NUM_DIGITS_MAX) + 1; LinkedList l1, l2, lsum; for (int i = 0; i < NUM_DIGITS1; ++i) { l1.append(new Node(rand() % 10 + '0')); } for (int i = 0; i < NUM_DIGITS2; ++i) { l2.append(new Node(rand() % 10 + '0')); } // Add filler digits to generalize to the case where lists are same size while (l1.size < l2.size) { l1.prepend(new Node('0')); } while (l2.size < l1.size) { l2.prepend(new Node('0')); } int carry = addAux(lsum, l1.root, l2.root); if (carry) { lsum.prepend(new Node('0' + carry)); } std::cout << l1.toNum(0) << " + " << l2.toNum(0) << " = " << lsum.toNum(0) << std::endl; assert(l1.toNum(0) + l2.toNum(0) == lsum.toNum(0)); } return 0; }
/** * Update position the edge */ void GuiEdge::updatePosition (bool original_run) { GuiNode* pre = addGui (pred()); GuiNode* suc = addGui (succ()); edge_start_point_priv = mapFromItem( pre, pre->width()/2, pre->height()/2); edge_end_point_priv = mapFromItem( suc, suc->width()/2, suc->height()/2);//!!!rarely it not work if (pre == suc)//mesh edge { QPointF heigh (0, 2*pre->height()); QPointF middle (pre->pos().x() - 10, pre->pos().y() + pre->height()/2); QPointF middleDirUp = middle + heigh; QPointF middleDirDown = middle - heigh; edge_start_dir_priv = edge_start_point_priv + heigh; edge_end_dir_priv = edge_end_point_priv - heigh; QPolygonF polygon = suc->polygon(); polygon.translate (suc->pos()); getIntersection (QLineF (edge_start_point_priv, edge_start_dir_priv), polygon, &edge_start_point_priv); getIntersection (QLineF (edge_end_point_priv, edge_end_dir_priv), polygon, &edge_end_point_priv); QPainterPath path; path.moveTo (edge_start_point_priv); path.cubicTo (edge_start_dir_priv, middleDirUp, middle); path.cubicTo (middleDirDown, edge_end_dir_priv, edge_end_point_priv); edge_curve_priv = path; } else { edge_valid_priv = true; QPolygonF headPolygon = suc->polygon(); headPolygon.translate (suc->pos()); QPolygonF tailPolygon = pre->polygon(); tailPolygon.translate (pre->pos()); if (suc->real()) edge_valid_priv = edge_valid_priv && getIntersection (QLineF (edge_start_point_priv, edge_end_point_priv), headPolygon, &edge_end_point_priv) == QLineF::BoundedIntersection; if (pre->real()) edge_valid_priv = edge_valid_priv && getIntersection (QLineF (edge_start_point_priv, edge_end_point_priv), tailPolygon, &edge_start_point_priv) == QLineF::BoundedIntersection; QPointF delta = edge_start_point_priv - edge_end_point_priv; delta.setX(0); if (pre->real()) edge_start_dir_priv = (edge_start_point_priv + edge_end_point_priv)/2; else { if (pre->firstPred() != 0) edge_start_dir_priv = (suc->coor() - pre->firstPred()->pred()->coor())/8 + pre->coor(); else edge_start_dir_priv = edge_start_point_priv - delta/2; } if (suc->real()) edge_end_dir_priv = (edge_start_point_priv + edge_end_point_priv)/2; else if (suc->firstSucc() != 0) edge_end_dir_priv = (pre->coor() - suc->firstSucc()->succ()->coor())/8 + suc->coor(); else edge_end_dir_priv = edge_end_point_priv + delta/2; QPainterPath path; path.moveTo (edge_start_point_priv); path.cubicTo (edge_start_dir_priv, edge_end_dir_priv, edge_end_point_priv); if (edge_valid_priv) edge_curve_priv = path; } edge_top_left_priv.setX( min< qreal>( edge_start_point_priv.x(), edge_end_point_priv.x())); edge_top_left_priv.setY( min< qreal>( edge_start_point_priv.y(), edge_end_point_priv.y())); edge_bottom_right_priv.setX( max< qreal>( edge_start_point_priv.x(), edge_end_point_priv.x())); edge_bottom_right_priv.setY( max< qreal>( edge_start_point_priv.y(), edge_end_point_priv.y())); if (original_run) { if (Edge::succ() && !addAux (Edge::succ())->real() && Edge::succ()->firstSucc()) addGui (Edge::succ()->firstSucc())->updatePosition (false);//avoidance sharp corners if (Edge::pred() && !addAux (Edge::pred())->real() && Edge::pred()->firstPred()) addGui (Edge::pred()->firstPred())->updatePosition (false);//avoidance sharp corners GuiEdge* i = this; for (i; !i->startEdge(); i->pred()->firstPred() && (i = addGui (i->pred()->firstPred()))); i->updateLabels(); } prepareGeometryChange(); }
/** * Return if this edge first in a sequence */ bool GuiEdge::startEdge() const {// pred exists and, it real or it is a root return Edge::pred() && (addAux (Edge::pred())->real() || addAux (Edge::pred())->isRoot()); }