/** * Find the line of \a poly with the smallest or largest value (controlled by \a seek) * along the axis controlled by \a axis. * In case \a axis is X, do not consider lines whose Y values lie outside the Y values * defined by \a boundingRect. * In case \a axis is Y, do not consider lines whose X values lie outside the X values * defined by \a boundingRect. */ QLineF findLine(const QPolygonF& poly, Axis_Type axis, Comparison_Type seek, const QRectF& boundingRect) { const int lastIndex = poly.size() - 1 - (int)poly.isClosed(); QPointF prev = poly.at(lastIndex), curr; QPointF p1(seek == Smallest ? QPointF(1.0e6, 1.0e6) : QPointF(-1.0e6, -1.0e6)); QPointF p2; for (int i = 0; i <= lastIndex; i++) { curr = poly.at(i); // uDebug() << " poly[" << i << "] = " << curr; if (axis == X) { if (fmin(prev.y(), curr.y()) > boundingRect.y() + boundingRect.height() || fmax(prev.y(), curr.y()) < boundingRect.y()) { // line is outside Y-axis range defined by boundingRect } else if ((seek == Smallest && curr.x() <= p1.x()) || (seek == Largest && curr.x() >= p1.x())) { p1 = curr; p2 = prev; } } else { if (fmin(prev.x(), curr.x()) > boundingRect.x() + boundingRect.width() || fmax(prev.x(), curr.x()) < boundingRect.x()) { // line is outside X-axis range defined by boundingRect } else if ((seek == Smallest && curr.y() <= p1.y()) || (seek == Largest && curr.y() >= p1.y())) { p1 = curr; p2 = prev; } } prev = curr; } return QLineF(p1, p2); }
/** * Return the point in \a poly which follows the point at index \a index. * If \a index is the last index then return the first (or, if * \a poly.isClosed() is true, the second) point. */ QPointF nextPoint(int index, const QPolygonF& poly) { if (poly.size() < 3 || index >= poly.size()) return QPoint(); if (index == poly.size() - 1) return poly.at((int)poly.isClosed()); return poly.at(index + 1); }
/** * Return the point in \a poly which precedes the point at index \a index. * If \a index is 0 then return the last (or, if \a poly.isClosed() is * true, the second to last) point. */ QPointF prevPoint(int index, const QPolygonF& poly) { if (poly.size() < 3 || index >= poly.size()) return QPoint(); if (index == 0) return poly.at(poly.size() - 1 - (int)poly.isClosed()); return poly.at(index - 1); }
QPointF Meshing::addMiddlePoint(int id) { QPointF point(0,0); QPolygonF poly = mesh_.at(id); if(poly.isEmpty()) return point; if(!poly.isClosed()) poly << poly.at(0); mesh_.removeAt(id); for(int i=0;i<poly.size()-1;i++) point += poly.at(i); point /= (double)(poly.size()-1); /*while(!poly.containsPoint(point,Qt::WindingFill)){ point += QPointF(-50+rand()%100,-50+rand()%100); }*/ for(int i=0;i<poly.size()-1;i++){ QPolygonF p; p << poly.at(i) << poly.at(i+1) << point << poly.at(i); mesh_.push_back(p); } return point; }
QPolygonF Segmenter::makeSegmentFromDivs(const QPolygonF &start, const QPolygonF &end) const { QPolygonF area; area << start[0]; area += end; for (int i = start.size() - 1; i > -1 ; i--) area << start[i]; Q_ASSERT_X(area.isClosed(), "makeSegmentFromDivs", "area is not closed"); return area; }
QString QTikzPicturePrivate::toTikzPath(const QPolygonF & polygon) const { if (polygon.isEmpty()) return QString(); const int end = polygon.size() - polygon.isClosed() ? 1 : 0; QString path; for (int i = 0; i < end; ++i) { if (i == 0) { path = toCoord(polygon[i]); } else if (i == end - 1) { path += " -- cycle"; } else { path += " -- " + toCoord(polygon[i]); } } return path; }
/** * Determine the approximate closest points of two polygons. * @param self First QPolygonF. * @param other Second QPolygonF. * @return QLineF::p1() returns point of \a self; * QLineF::p2() returns point of \a other. */ QLineF closestPoints(const QPolygonF& self, const QPolygonF& other) { const QRectF& selfRect = self.boundingRect(); const QRectF& otherRect = other.boundingRect(); Uml::Region::Enum region = findRegion(selfRect, otherRect); if (region == Uml::Region::Center) return QLineF(); if (self.size() < 3 || other.size() < 3) return QLineF(); QLineF result; const int selfLastIndex = self.size() - 1 - (int)self.isClosed(); const int otherLastIndex = other.size() - 1 - (int)other.isClosed(); QPointF selfPoint(self.at(selfLastIndex)); QPointF otherPoint(other.at(otherLastIndex)); QLineF selfLine, otherLine; int i; switch (region) { case Uml::Region::North: // Find other's line with largest Y values otherLine = findLine(other, Y, Largest, selfRect); // Find own line with smallest Y values selfLine = findLine(self, Y, Smallest, otherRect); // Use the middle value of the X values result.setLine(middle(selfLine.p2().x(), selfLine.p1().x()), selfLine.p1().y(), middle(otherLine.p2().x(), otherLine.p1().x()), otherLine.p1().y()); break; case Uml::Region::South: // Find other's line with smallest Y values otherLine = findLine(other, Y, Smallest, selfRect); // Find own line with largest Y values selfLine = findLine(self, Y, Largest, otherRect); // Use the middle value of the X values result.setLine(middle(selfLine.p2().x(), selfLine.p1().x()), selfLine.p1().y(), middle(otherLine.p2().x(), otherLine.p1().x()), otherLine.p1().y()); break; case Uml::Region::West: // Find other's line with largest X values otherLine = findLine(other, X, Largest, selfRect); // Find own line with smallest X values selfLine = findLine(self, X, Smallest, otherRect); // Use the middle value of the Y values result.setLine(selfLine.p1().x(), middle(selfLine.p2().y(), selfLine.p1().y()), otherLine.p1().x(), middle(otherLine.p2().y(), otherLine.p1().y())); break; case Uml::Region::East: // Find other's line with smallest X values otherLine = findLine(other, X, Smallest, selfRect); // Find own line with largest X values selfLine = findLine(self, X, Largest, otherRect); // Use the middle value of the Y values result.setLine(selfLine.p1().x(), middle(selfLine.p2().y(), selfLine.p1().y()), otherLine.p1().x(), middle(otherLine.p2().y(), otherLine.p1().y())); break; case Uml::Region::NorthWest: // Find other's point with largest X and largest Y value for (i = 0; i < otherLastIndex; ++i) { QPointF current(other.at(i)); if (current.x() + current.y() >= otherPoint.x() + otherPoint.y()) { otherPoint = current; } } // Find own point with smallest X and smallest Y value for (i = 0; i < selfLastIndex; ++i) { QPointF current(self.at(i)); if (current.x() + current.y() <= selfPoint.x() + selfPoint.y()) { selfPoint = current; } } result.setPoints(selfPoint, otherPoint); break; case Uml::Region::SouthWest: // Find other's point with largest X and smallest Y value for (i = 0; i < otherLastIndex; ++i) { QPointF current(other.at(i)); if (current.x() >= otherPoint.x() && current.y() <= otherPoint.y()) { otherPoint = current; } } // Find own point with smallest X and largest Y value for (i = 0; i < selfLastIndex; ++i) { QPointF current(self.at(i)); if (current.x() <= selfPoint.x() && current.y() >= selfPoint.y()) { selfPoint = current; } } result.setPoints(selfPoint, otherPoint); break; case Uml::Region::NorthEast: // Find other's point with smallest X and largest Y value for (i = 0; i < otherLastIndex; ++i) { QPointF current(other.at(i)); if (current.x() <= otherPoint.x() && current.y() >= otherPoint.y()) { otherPoint = current; } } // Find own point with largest X and smallest Y value for (i = 0; i < selfLastIndex; ++i) { QPointF current(self.at(i)); if (current.x() >= selfPoint.x() && current.y() <= selfPoint.y()) { selfPoint = current; } } result.setPoints(selfPoint, otherPoint); break; case Uml::Region::SouthEast: // Find other's point with smallest X and smallest Y value for (i = 0; i < otherLastIndex; ++i) { QPointF current(other.at(i)); if (current.x() + current.y() <= otherPoint.x() + otherPoint.y()) { otherPoint = current; } } // Find own point with largest X and largest Y value for (i = 0; i < selfLastIndex; ++i) { QPointF current(self.at(i)); if (current.x() + current.y() >= selfPoint.x() + selfPoint.y()) { selfPoint = current; } } result.setPoints(selfPoint, otherPoint); break; default: // Error break; } return result; }
void Meshing::splitDiag() { for(int id=0;id<mesh_.size();id++){ QPolygonF poly = mesh_.at(id); if(poly.isEmpty()) continue; if(!poly.isClosed()) poly << poly.at(0); if(poly.size()<=4) continue; QStringList polyID; for(int k=0;k<poly.size();k++) polyID << findID(poly.at(k)); /*for(int i=0;i<poly.size()-2;i++){ QPointF p = (poly.at(i) + poly.at(i+2))/2.0; if(poly.containsPoint(p,Qt::WindingFill)){ QPolygonF p1,p2; for(int k=i;k<i+3;k++){ p1 << poly.at(k); } p1 << poly.at(i); for(int k=i+3;k<=poly.size()-1;k++){ p2 << poly.at(k); } for(int k=0;k<i;k++){ p2 << poly.at(k); } p2 << poly.at(i); mesh_.push_back(p1); mesh_.push_back(p2); mesh_.removeAt(id); splitDiag(); return; } }*/ //qDebug() << "Split poly" << polyID; for(int i=0;i<poly.size()-1;i++){ for(int j=i+2;j<poly.size()-(i==0?2:1);j++){ //qDebug() << "Try to split along" << findID(poly.at(i)) << findID(poly.at(j)); QLineF line(poly.at(i),poly.at(j)); QPointF middle = (poly.at(i)+poly.at(j))/2.0; if(!poly.containsPoint(middle,Qt::WindingFill)) continue; if(!intersects(poly,line)){ QPolygonF p1,p2; //QStringList poly1id,poly2id; for(int k=i;k<=j;k++){ p1 << poly.at(k); //poly1id << findID(poly.at(k)); } p1 << poly.at(i); //poly1id << findID(poly.at(i)); for(int k=j;k<poly.size()-1;k++){ p2 << poly.at(k); //poly2id << findID(poly.at(k)); } for(int k=0;k<=i;k++){ p2 << poly.at(k); //poly2id << findID(poly.at(k)); } p2 << poly.at(j); //poly2id << findID(poly.at(j)); //qDebug() << poly.size() << QPair<int,QString>(i,findID(poly.at(i))) << QPair<int,QString>(j,findID(poly.at(j))) << p1.size() << p2.size(); //qDebug() << "Poly1" << poly1id; //qDebug() << "Poly2" << poly2id; mesh_.push_back(p1); mesh_.push_back(p2); mesh_.removeAt(id); splitDiag(); return; } } } //qDebug() << "Can't split poly " << polyID; } }