drawlipse的PyQt实现到Matlab的转换

2024-09-28 20:46:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个python程序,可以在窗口中绘制一些椭圆。下面的python代码用于w

from PyQt4.QtGui import *

def draw_ellipse(self, center, rad_x, rad_y, angle, color):
qp = QtGui.QPainter()
qp.begin(self)
qp.translate(center)
qp.rotate(math.degrees(angle))
qp.setPen(QtGui.QColor(color))
qp.drawEllipse(QPoint(0, 0), rad_x, rad_y)
qp.end()

如您所见,我的输入参数是centerrad_xrad_y和{}。这些参数是从文本文件中读入的。在

我想在Matlab程序中使用相同的参数文件。为此,我需要知道drawEllipse的实现,这样我就可以在Matlab中实现同样的功能。在

不幸的是,我似乎找不到drawEllipse的源代码。我发现this link包含以下代码:

^{pr2}$

这就引出了this代码(QPainterPath.addEllipse):

01052 void QPainterPath::addEllipse(const QRectF &boundingRect)
01053 {
01054 #ifndef QT_NO_DEBUG
01055     if (qIsNan(boundingRect.x()) || qIsNan(boundingRect.y())
01056         || qIsNan(boundingRect.width()) || qIsNan(boundingRect.height()))
01057         qWarning("QPainterPath::addEllipse: Adding ellipse where a parameter is NaN, results are undefined");
01058 #endif
01059     if (boundingRect.isNull())
01060         return;
01061 
01062     ensureData();
01063     detach();
01064 
01065     Q_D(QPainterPath);
01066     d->elements.reserve(d->elements.size() + 13);
01067 
01068     QPointF pts[12];
01069     int point_count;
01070     QPointF start = qt_curves_for_arc(boundingRect, 0, 360, pts, &point_count);
01071 
01072     moveTo(start);
01073     cubicTo(pts[0], pts[1], pts[2]);           // 0 -> 270
01074     cubicTo(pts[3], pts[4], pts[5]);           // 270 -> 180
01075     cubicTo(pts[6], pts[7], pts[8]);           // 180 -> 90
01076     cubicTo(pts[9], pts[10], pts[11]);         // 90 - >0
01077     d_func()->require_moveTo = true;
01078 }

让我们进入qstroker_8cpp,看看qt_curves_for_arc

00722 QPointF qt_curves_for_arc(const QRectF &rect, qreal startAngle, qreal sweepLength,
00723                        QPointF *curves, int *point_count)
00724 {
00725     Q_ASSERT(point_count);
00726     Q_ASSERT(curves);
00727 
00728 #ifndef QT_NO_DEBUG
00729     if (qIsNan(rect.x()) || qIsNan(rect.y()) || qIsNan(rect.width()) || qIsNan(rect.height())
00730         || qIsNan(startAngle) || qIsNan(sweepLength))
00731         qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN, results are undefined");
00732 #endif
00733     *point_count = 0;
00734 
00735     if (rect.isNull()) {
00736         return QPointF();
00737     }
00738 
00739     if (sweepLength > 360) sweepLength = 360;
00740     else if (sweepLength < -360) sweepLength = -360;
00741 
00742     // Special case fast path
00743     if (startAngle == 0.0 && sweepLength == 360.0) {
00744         qreal x = rect.x();
00745         qreal y = rect.y();
00746 
00747         qreal w = rect.width();
00748         qreal w2 = rect.width() / 2;
00749         qreal w2k = w2 * QT_PATH_KAPPA;
00750 
00751         qreal h = rect.height();
00752         qreal h2 = rect.height() / 2;
00753         qreal h2k = h2 * QT_PATH_KAPPA;
00754 
00755         // 0 -> 270 degrees
00756         curves[(*point_count)++] = QPointF(x + w, y + h2 + h2k);
00757         curves[(*point_count)++] = QPointF(x + w2 + w2k, y + h);
00758         curves[(*point_count)++] = QPointF(x + w2, y + h);
00759 
00760         // 270 -> 180 degrees
00761         curves[(*point_count)++] = QPointF(x + w2 - w2k, y + h);
00762         curves[(*point_count)++] = QPointF(x, y + h2 + h2k);
00763         curves[(*point_count)++] = QPointF(x, y + h2);
00764 
00765         // 180 -> 90 degrees
00766         curves[(*point_count)++] = QPointF(x, y + h2 - h2k);
00767         curves[(*point_count)++] = QPointF(x + w2 - w2k, y);
00768         curves[(*point_count)++] = QPointF(x + w2, y);
00769 
00770         // 90 -> 0 degrees
00771         curves[(*point_count)++] = QPointF(x + w2 + w2k, y);
00772         curves[(*point_count)++] = QPointF(x + w, y + h2 - h2k);
00773         curves[(*point_count)++] = QPointF(x + w, y + h2);
00774 
00775         return QPointF(x + w, y + h2);
00776     }
00777 
00778 #define ANGLE(t) ((t) * 2 * Q_PI / 360.0)
00779 #define SIGN(t) (t > 0 ? 1 : -1)
00780     qreal a = rect.width() / 2.0;
00781     qreal b = rect.height() / 2.0;
00782 
00783     qreal absSweepLength = (sweepLength < 0 ? -sweepLength : sweepLength);
00784     int iterations = (int)ceil((absSweepLength) / 90.0);
00785 
00786     QPointF first_point;
00787 
00788     if (iterations == 0) {
00789         first_point = rect.center() + QPointF(a * qCos(ANGLE(startAngle)),
00790                                               -b * qSin(ANGLE(startAngle)));
00791     } else {
00792         qreal clength = sweepLength / iterations;
00793         qreal cosangle1, sinangle1, cosangle2, sinangle2;
00794 
00795         for (int i=0; i<iterations; ++i) {
00796             qreal cangle = startAngle + i * clength;
00797 
00798             cosangle1 = qCos(ANGLE(cangle));
00799             sinangle1 = qSin(ANGLE(cangle));
00800             cosangle2 = qCos(ANGLE(cangle + clength));
00801             sinangle2 = qSin(ANGLE(cangle + clength));
00802 
00803             // Find the start and end point of the curve.
00804             QPointF startPoint = rect.center() + QPointF(a * cosangle1, -b * sinangle1);
00805             QPointF endPoint = rect.center() + QPointF(a * cosangle2, -b * sinangle2);
00806 
00807             // The derived at the start and end point.
00808             qreal sdx = -a * sinangle1;
00809             qreal sdy = -b * cosangle1;
00810             qreal edx = -a * sinangle2;
00811             qreal edy = -b * cosangle2;
00812 
00813             // Creating the tangent lines. We need to reverse their direction if the
00814             // sweep is negative (clockwise)
00815             QLineF controlLine1(startPoint, startPoint + SIGN(sweepLength) * QPointF(sdx, sdy));
00816             QLineF controlLine2(endPoint, endPoint - SIGN(sweepLength) * QPointF(edx, edy));
00817 
00818             // We need to scale down the control lines to match that of the current sweeplength.
00819             // qAbs because we only want to scale, not change direction.
00820             qreal kappa = QT_PATH_KAPPA * qAbs(clength) / 90.0;
00821             // Adjust their length to fit the magic KAPPA length.
00822             controlLine1.setLength(controlLine1.length() * kappa);
00823             controlLine2.setLength(controlLine2.length() * kappa);
00824 
00825             curves[(*point_count)++] = controlLine1.p2();
00826             curves[(*point_count)++] = controlLine2.p2();
00827             curves[(*point_count)++] = endPoint;
00828 
00829             if (i == 0)
00830                 first_point = startPoint;
00831         }
00832     }
00833 
00834     return first_point;
00835 }

这是相当多的代码绘制一个简单的椭圆!如果一个简单的椭圆可以这样绘制,那么在Matlab中重写所有这些都是不正确的:

a = rad_x; % horizontal radius
b = rad_y; % vertical radius
x0 = center_x; % x0, y0 ellipse centre coordinates
y0 = center_y;
steps = 50;
t = linspace(0, 2*pi, steps);
theta0 = angle;
x = x0 + (a * sin(t - theta0));
y = y0 + (b * cos(t));

plot(x, y, '.-'),

问题:
给定上面列出的四个参数(centerrad_xrad_yangle),我在matlab中正确绘制椭圆最简单的方法是什么?用我上面的matlab代码,绘图目前只适用于小角度和特殊的rad_x&;rad_y组合。在


Tags: therectifcounth2ptspointcenter
1条回答
网友
1楼 · 发布于 2024-09-28 20:46:30

这样的怎么样?在

a = rad_x;
b = rad_y;
r0 = center_x + i*center_y;  % <  origin of ellipse

theta0=angle;   % <  angle of rotation of ellipse

steps = 200;

t = linspace(0, 2*pi, steps);

r = a*sin(t) + i*b*cos(t);


R = exp(i*theta0);
r = R*r;
r = r0 + r;

figure(1), hold on 
plot(real(r), imag(r), '-r')

使用矩阵而不是复数:

^{pr2}$

相关问题 更多 >