예제 #1
0
 /**
  * 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);
 }
예제 #2
0
 /**
  * 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);
 }
예제 #3
0
 /**
  * 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);
 }
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
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;
}
예제 #7
0
    /**
     * 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;
    }
예제 #8
0
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;
    }
}