Линия интерполяция в Qt?

Я пытаюсь уменьшить расстояние между мазками (на QPixmap) путем деления длины линии. Если я умножу линию, то интервал увеличивается, но интервал никогда не уменьшается. Также кажется, что минимальная длина строки может быть одна. Очевидно, что его разделение уменьшит это - возможно, ниже допустимой суммы? Не уверен, что это негативно скажется на рисовании растрового изображения.

Вот оскорбительный код:

QLineF line = QLineF(lastPoint, endPoint);
float lineLength = line.length();
qDebug() << line.length();
line.setLength(lineLength / 50.0f);
qDebug() << line.length();

painter.drawPixmap(line.p1().x() - 16, line.p2().y() - 16, 32, 32, testPixmap);

И вот весь код в этом конкретном файле:

#include "inkspot.h"
#include "inkpuppet.h"
#include "ui_inkpuppet.h"

#include "newdialog.h"
#include "ui_newdialog.h"

#include <QtCore>
#include <QtGui>
#include <QWidget>
#include <QPainter>
#include <QPaintEvent>

InkSpot::InkSpot(QWidget *parent) :
    QWidget(parent)
{
    widget = this;
    drawing = false;
}

void InkSpot::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        lastPoint = event->pos();
        drawing = true;
    }
}

void InkSpot::mouseMoveEvent(QMouseEvent *event)
{
    if((event->buttons() & Qt::LeftButton) && drawing)
    {
        drawLineTo(event->pos());
    }
}

void InkSpot::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton && drawing)
    {
        drawLineTo(event->pos());
        drawing = false;
    }
}

void InkSpot::drawLineTo(const QPoint &endPoint)
{
    QPainter painter(&pixmap);
    painter.setPen(Qt::NoPen);
    painter.setBrush(Qt::NoBrush);

    QFile *stencilInput; // file for input, assumes a SQUARE RAW 8 bit grayscale image, no JPG no GIF, no size/format header, just 8 bit values in the file
    char *brushPrototype; // raw brush prototype
    uchar *brushData; // raw brush data

    stencilInput = new QFile("C:/brush3.raw");  // open raw file
    stencilInput->open(QIODevice::ReadOnly);
    QDataStream in;
    in.setDevice(stencilInput);
    int size = stencilInput->size();  // set size to the length of the raw file

    brushPrototype = new char[size];  // create the brush prototype array
    in.readRawData(brushPrototype, size);  // read the file into the prototype
    brushData = new uchar[size];  // create the uchar array you need to construct QImage

    for (int i = 0; i < size; ++i)
        brushData[i] = (uchar)brushPrototype[i];  // copy the char to the uchar array

    QImage test(brushData, 128, 128, QImage::Format_Indexed8); // create QImage from the brush data array
     // 128x128 was my raw file, for any file size just use the square root of the size variable provided it is SQUARE
    QImage test2(128, 128, QImage::Format_ARGB32);


   QVector<QRgb> vectorColors(256);  // create a color table for the image
    for (int c = 0; c < 256; c++)
        vectorColors[c] = qRgb(c, c, c);

    test.setColorTable(vectorColors);  // set the color table to the image

    for (int iX = 0; iX < 128; ++iX)  // fill all pixels with 255 0 0 (red) with random variations for OIL PAINT effect
    // use your color of choice and remove random stuff for solid color
    // the fourth parameter of setPixel is the ALPHA, use that to make your brush transparent by multiplying by opacity 0 to 1
    {
        for (int iY = 0; iY < 128; ++iY)
        {
            test2.setPixel(iX, iY, qRgba(255, 100, 100, (255-qGray(test.pixel(iX, iY)))*0.5));
        }
    }
    // final convertions of the stencil and color brush
    QPixmap testPixmap = QPixmap::fromImage(test2);
    QPixmap testPixmap2 = QPixmap::fromImage(test);

    painter.setBrush(Qt::NoBrush);
    painter.setPen(Qt::NoPen);
    // in a paint event you can test out both pixmaps
    QLineF line = QLineF(lastPoint, endPoint);
    float lineLength = line.length();
    qDebug() << line.length();
    line.setLength(lineLength / 50.0f);
    qDebug() << line.length();

    painter.drawPixmap(line.p1().x() - 16, line.p2().y() - 16, 32, 32, testPixmap);

    //delete all dynamically allocated objects with no parents
    delete [] brushPrototype;
    delete [] brushData;
    delete stencilInput;


    lastPoint = endPoint;

}


void InkSpot::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setPen(Qt::NoPen);
    painter.setBrush(Qt::NoBrush);
    QRect rect = event->rect();
    painter.drawPixmap(rect, pixmap, rect);
    update();

}

1 ответ

Решение

Не использовать QLineFиспользовать QPainterPath - у него есть несколько очень удобных методов:

qreal QPainterPath::percentAtLength ( qreal len ) const
QPointF QPainterPath::pointAtPercent ( qreal t ) const
qreal length () const

Таким образом, вместо использования QLineF Вы создаете путь рисования, который состоит только из одной строки от старой до новой позиции курсора рисования, получаете длину этой линии и перебираете длину, увеличивая интервал, чтобы получить процентное значение, из которого вы можете получить QPointF для каждого местоположения необходимо нарисовать растровое изображение кисти. Это так просто.

РЕДАКТИРОВАТЬ: ОК, вот оно, не проверял, мозг до терминала, но что-то вроде этого:

QPointF lastPosition, currentPosition;
qreal spacing;

void draw() {
    QPainterPath path;
    path.moveTo(lastPosition);
    path.lineTo(currentPosition);
    qreal length = path.length();
    qreal pos = 0;

    while (pos < length) {
        qreal percent = path.percentAtLength(pos);
        drawYourPixmapAt(path.pointAtPercent(percent)); // pseudo method, use QPainter and your brush pixmap instead
        pos += spacing;
    }
}
Другие вопросы по тегам