void PageItem_Line::getBoundingRect(double *x1, double *y1, double *x2, double *y2) const { double minx = std::numeric_limits<double>::max(); double miny = std::numeric_limits<double>::max(); double maxx = -std::numeric_limits<double>::max(); double maxy = -std::numeric_limits<double>::max(); if (m_rotation != 0) { FPointArray pb; pb.resize(0); pb.addPoint(FPoint(0, -m_lineWidth / 2.0, m_xPos, m_yPos, m_rotation, 1.0, 1.0)); pb.addPoint(FPoint(m_width, -m_lineWidth / 2.0, m_xPos, m_yPos, m_rotation, 1.0, 1.0)); pb.addPoint(FPoint(m_width, +m_lineWidth / 2.0, m_xPos, m_yPos, m_rotation, 1.0, 1.0)); pb.addPoint(FPoint(0, +m_lineWidth / 2.0, m_xPos, m_yPos, m_rotation, 1.0, 1.0)); for (uint pc = 0; pc < 4; ++pc) { minx = qMin(minx, pb.point(pc).x()); miny = qMin(miny, pb.point(pc).y()); maxx = qMax(maxx, pb.point(pc).x()); maxy = qMax(maxy, pb.point(pc).y()); } *x1 = minx; *y1 = miny; *x2 = maxx; *y2 = maxy; } else { *x1 = m_xPos; *y1 = m_yPos - qMax(1.0, m_lineWidth) / 2.0; *x2 = m_xPos + m_width; *y2 = m_yPos + qMax(1.0, m_lineWidth) / 2.0; } QRectF totalRect = QRectF(QPointF(*x1, *y1), QPointF(*x2, *y2)); if (m_startArrowIndex != 0) { QTransform arrowTrans; FPointArray arrow = m_Doc->arrowStyles().at(m_startArrowIndex-1).points.copy(); arrowTrans.translate(m_xPos, m_yPos); arrowTrans.rotate(m_rotation); arrowTrans.translate(0, 0); arrowTrans.scale(m_startArrowScale / 100.0, m_startArrowScale / 100.0); if (NamedLStyle.isEmpty()) { if (m_lineWidth != 0.0) arrowTrans.scale(m_lineWidth, m_lineWidth); } else { multiLine ml = m_Doc->MLineStyles[NamedLStyle]; if (ml[ml.size()-1].Width != 0.0) arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width); } arrowTrans.scale(-1,1); arrow.map(arrowTrans); FPoint minAr = getMinClipF(&arrow); FPoint maxAr = getMaxClipF(&arrow); totalRect = totalRect.united(QRectF(QPointF(minAr.x(), minAr.y()), QPointF(maxAr.x(), maxAr.y()))); } if (m_endArrowIndex != 0) { QTransform arrowTrans; FPointArray arrow = m_Doc->arrowStyles().at(m_endArrowIndex-1).points.copy(); arrowTrans.translate(m_xPos, m_yPos); arrowTrans.rotate(m_rotation); arrowTrans.translate(m_width, 0); arrowTrans.scale(m_endArrowScale / 100.0, m_endArrowScale / 100.0); if (NamedLStyle.isEmpty()) { if (m_lineWidth != 0.0) arrowTrans.scale(m_lineWidth, m_lineWidth); } else { multiLine ml = m_Doc->MLineStyles[NamedLStyle]; if (ml[ml.size()-1].Width != 0.0) arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width); } arrow.map(arrowTrans); FPoint minAr = getMinClipF(&arrow); FPoint maxAr = getMaxClipF(&arrow); totalRect = totalRect.united(QRectF(QPointF(minAr.x(), minAr.y()), QPointF(maxAr.x(), maxAr.y()))); } totalRect.getCoords(x1, y1, x2, y2); }
bool AbstractCoordinateSystem::clipLineToRect(QLineF *line, const QRectF &rect, LineClipResult *clipResult) { //we usually clip on large rectangles, so we don't need high precision here -> round to one float digit //this prevents some subtle float rounding artefacts that lead to disappearance //of lines along the boundaries of the rect. (e.g. axis lines). qreal x1 = round(line->x1(), 1); qreal x2 = round(line->x2(), 1); qreal y1 = round(line->y1(), 1); qreal y2 = round(line->y2(), 1); qreal left; qreal right; qreal top; qreal bottom; rect.getCoords(&left, &top, &right, &bottom); if (clipResult) clipResult->reset(); enum { Left, Right, Top, Bottom }; // clip the lines, after cohen-sutherland, see e.g. http://www.nondot.org/~sabre/graphpro/line6.html int p1 = ((x1 < left) << Left) | ((x1 > right) << Right) | ((y1 < top) << Top) | ((y1 > bottom) << Bottom); int p2 = ((x2 < left) << Left) | ((x2 > right) << Right) | ((y2 < top) << Top) | ((y2 > bottom) << Bottom); if (p1 & p2) // completely outside return false; if (p1 | p2) { qreal dx = x2 - x1; qreal dy = y2 - y1; // clip x coordinates if (x1 < left) { y1 += dy/dx * (left - x1); x1 = left; if (clipResult) clipResult->xClippedLeft[0] = true; } else if (x1 > right) { y1 -= dy/dx * (x1 - right); x1 = right; if (clipResult) clipResult->xClippedRight[0] = true; } if (x2 < left) { y2 += dy/dx * (left - x2); x2 = left; if (clipResult) clipResult->xClippedLeft[1] = true; } else if (x2 > right) { y2 -= dy/dx * (x2 - right); x2 = right; if (clipResult) clipResult->xClippedRight[1] = true; } p1 = ((y1 < top) << Top) | ((y1 > bottom) << Bottom); p2 = ((y2 < top) << Top) | ((y2 > bottom) << Bottom); if (p1 & p2) return false; // clip y coordinates if (y1 < top) { x1 += dx/dy * (top - y1); y1 = top; if (clipResult) { clipResult->xClippedRight[0] = false; clipResult->xClippedLeft[0] = false; clipResult->yClippedTop[0] = true; } } else if (y1 > bottom) { x1 -= dx/dy * (y1 - bottom); y1 = bottom; if (clipResult) { clipResult->xClippedRight[0] = false; clipResult->xClippedLeft[0] = false; clipResult->yClippedBottom[0] = true; } } if (y2 < top) { x2 += dx/dy * (top - y2); y2 = top; if (clipResult) { clipResult->xClippedRight[1] = false; clipResult->xClippedLeft[1] = false; clipResult->yClippedTop[1] = true; } } else if (y2 > bottom) { x2 -= dx/dy * (y2 - bottom); y2 = bottom; if (clipResult) { clipResult->xClippedRight[1] = false; clipResult->xClippedLeft[1] = false; clipResult->yClippedBottom[1] = true; } } *line = QLineF(QPointF(x1, y1), QPointF(x2, y2)); } return true; }
void PageItem_Spiral::getBoundingRect(double *x1, double *y1, double *x2, double *y2) const { PageItem::getBoundingRect(x1, y1, x2, y2); QRectF totalRect = QRectF(QPointF(*x1, *y1), QPointF(*x2, *y2)); if (m_startArrowIndex != 0 && !PoLine.empty()) { QTransform arrowTrans; FPointArray arrow = m_Doc->arrowStyles().at(m_startArrowIndex-1).points.copy(); arrowTrans.translate(m_xPos, m_yPos); arrowTrans.rotate(m_rotation); FPoint Start = PoLine.point(0); for (int xx = 1; xx < PoLine.size(); xx += 2) { FPoint Vector = PoLine.point(xx); if ((Start.x() != Vector.x()) || (Start.y() != Vector.y())) { arrowTrans.translate(Start.x(), Start.y()); arrowTrans.rotate(atan2(Start.y()-Vector.y(),Start.x()-Vector.x())*(180.0/M_PI)); arrowTrans.scale(m_startArrowScale / 100.0, m_startArrowScale / 100.0); if (NamedLStyle.isEmpty()) { if (m_lineWidth != 0.0) arrowTrans.scale(m_lineWidth, m_lineWidth); } else { multiLine ml = m_Doc->MLineStyles[NamedLStyle]; if (ml[ml.size()-1].Width != 0.0) arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width); } arrow.map(arrowTrans); break; } } FPoint minAr = getMinClipF(&arrow); FPoint maxAr = getMaxClipF(&arrow); totalRect = totalRect.united(QRectF(QPointF(minAr.x(), minAr.y()), QPointF(maxAr.x(), maxAr.y()))); } if (m_endArrowIndex != 0 && PoLine.size() >= 2) { QTransform arrowTrans; FPointArray arrow = m_Doc->arrowStyles().at(m_endArrowIndex-1).points.copy(); arrowTrans.translate(m_xPos, m_yPos); arrowTrans.rotate(m_rotation); FPoint End = PoLine.point(PoLine.size()-2); for (uint xx = PoLine.size()-1; xx > 0; xx -= 2) { FPoint Vector = PoLine.point(xx); if ((End.x() != Vector.x()) || (End.y() != Vector.y())) { arrowTrans.translate(End.x(), End.y()); arrowTrans.rotate(atan2(End.y()-Vector.y(),End.x()-Vector.x())*(180.0/M_PI)); arrowTrans.scale(m_endArrowScale / 100.0, m_endArrowScale / 100.0); if (NamedLStyle.isEmpty()) { if (m_lineWidth != 0.0) arrowTrans.scale(m_lineWidth, m_lineWidth); } else { multiLine ml = m_Doc->MLineStyles[NamedLStyle]; if (ml[ml.size()-1].Width != 0.0) arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width); } arrow.map(arrowTrans); break; } } FPoint minAr = getMinClipF(&arrow); FPoint maxAr = getMaxClipF(&arrow); totalRect = totalRect.united(QRectF(QPointF(minAr.x(), minAr.y()), QPointF(maxAr.x(), maxAr.y()))); } totalRect.getCoords(x1, y1, x2, y2); }
void SourceWidget::mouseReleaseEvent(QMouseEvent *event) { // Once the user releases the mouse, the selection process is finished. We need to // extract the selection and update the glWidget if (event->button() == Qt::LeftButton) { // Draw the last line path.lineTo(event->pos()); path.connectPath(path); update(); // TODO: safety due to CGAL fail // if (path.length()<20) // return; QPolygonF selectionPoly = path.toFillPolygon(); QRectF boundingRect = selectionPoly.boundingRect(); // Don't pass bad selections on if (boundingRect.width()>20 && boundingRect.height()>20) ; else return; // adjusted - boundary value will be cut without it QImage sourcePatch = image.copy(boundingRect.toRect().adjusted(-1,-1,1,1)); // Pass source patch pixels to glWidet glWidget->setSourcePatch(sourcePatch); qreal x0,x1,y0,y1; boundingRect.getCoords(&x0,&y0,&x1,&y1); // Find a point on the boundary of the selection QPoint cPoint(-1,-1); for (int x=x0; x<=x1; x++) { for (int y=y0; y<=y1; y++) { if (selectionPoly.containsPoint(QPointF(x,y),Qt::WindingFill)) cPoint = QPoint(x,y); } } //assert(cPoint != QPoint(-1,-1)); //TODO: No violence please... if (cPoint == QPoint(-1,-1)){ qDebug() << "assert(cPoint != QPoint(-1,-1)) fails"; return; } // Track the boundary of the selection std::vector<Point> boundaryVector; // TODO: Why does it fail with dir=0 ??? int dir = 1; int x,y; int c=0; bool cont = true; do { x = cPoint.x(); y = cPoint.y(); cPoint = findStartingFromDir(selectionPoly ,x, y, dir); boundaryVector.push_back(Point((cPoint.x()-x0),((y1-y0) - (cPoint.y()-y0)))); if (boundaryVector.size()>3){ if(boundaryVector[0]==boundaryVector[c-1] && boundaryVector[1]==boundaryVector[c]){ boundaryVector.pop_back(); boundaryVector.pop_back(); cont = false; } } c++; } while (cont); if (boundaryVector.size()>8192) { path = QPainterPath(); update(); QMessageBox::warning(this, tr("Boundary Size"), tr("Largest supported boundary size is 8192")); return; } // // Subsample // std::vector<Point> boundaryVectorNew; // bool subs = false; // for(std::vector<Point>::const_iterator it = boundaryVector.begin(); it != boundaryVector.end(); ++it){ // if(subs) // boundaryVectorNew.push_back(Point((*it).x(),(*it).y())); // subs = 1-subs; // } // boundaryVector = boundaryVectorNew; // // Subsample // QPolygon selectionPolyNew; // int i = 0; // for(std::vector<Point>::const_iterator it = boundaryVector.begin(); it != boundaryVector.end(); ++it){ // selectionPolyNew.setPoint(i, (*it).x(), (*it).y()); // i++; // } // TODO: Since we didn't figure out the way yet to get from CGAL the information // about the whenever triangle inside the boundary, glWidget will do it with // the help of selectionPoly // QPolygon temp(boundaryVector); // selectionPoly = QPolygonF(temp); selectionPoly.translate(-x0,-y0); // boundingRect = selectionPoly.boundingRect(); // boundingRect.getCoords(&x0,&y0,&x1,&y1); glWidget->updateSelection(boundaryVector, selectionPoly); glWidget->update(); } }