File indexing completed on 2024-06-23 04:27:03

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2007 Jan Hambrecht <jaham@gmx.net>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #include "EnhancedPathHandle.h"
0008 #include "EnhancedPathShape.h"
0009 #include "EnhancedPathParameter.h"
0010 #include <KoShapeSavingContext.h>
0011 #include <KoXmlWriter.h>
0012 #include <KoXmlNS.h>
0013 #include <KoShapeLoadingContext.h>
0014 
0015 #include <math.h>
0016 
0017 EnhancedPathHandle::EnhancedPathHandle(EnhancedPathShape *parent)
0018     : m_parent(parent)
0019     , m_positionX(0)
0020     , m_positionY(0)
0021     , m_minimumX(0)
0022     , m_minimumY(0)
0023     , m_maximumX(0)
0024     , m_maximumY(0)
0025     , m_polarX(0)
0026     , m_polarY(0)
0027     , m_minRadius(0)
0028     , m_maxRadius(0)
0029 {
0030     Q_ASSERT(m_parent);
0031 }
0032 
0033 EnhancedPathHandle::~EnhancedPathHandle()
0034 {
0035 }
0036 
0037 bool EnhancedPathHandle::hasPosition() const
0038 {
0039     return m_positionX && m_positionY;
0040 }
0041 
0042 void EnhancedPathHandle::setPosition(EnhancedPathParameter *positionX, EnhancedPathParameter *positionY)
0043 {
0044     m_positionX = positionX;
0045     m_positionY = positionY;
0046 }
0047 
0048 QPointF EnhancedPathHandle::position()
0049 {
0050     if (!hasPosition()) {
0051         return QPointF();
0052     }
0053 
0054     QPointF position(m_positionX->evaluate(), m_positionY->evaluate());
0055     if (isPolar()) {
0056         // convert polar coordinates into cartesian coordinates
0057         QPointF center(m_polarX->evaluate(), m_polarY->evaluate());
0058         qreal angleInRadian = position.x() * M_PI / 180.0;
0059         position = center + position.y() * QPointF(cos(angleInRadian), sin(angleInRadian));
0060     }
0061 
0062     return position;
0063 }
0064 
0065 void EnhancedPathHandle::changePosition(const QPointF &position)
0066 {
0067     if (!hasPosition()) {
0068         return;
0069     }
0070 
0071     QPointF constrainedPosition(position);
0072 
0073     if (isPolar()) {
0074         // convert cartesian coordinates into polar coordinates
0075         QPointF polarCenter(m_polarX->evaluate(), m_polarY->evaluate());
0076         QPointF diff = constrainedPosition - polarCenter;
0077         // compute the polar radius
0078         qreal radius = sqrt(diff.x() * diff.x() + diff.y() * diff.y());
0079         // compute the polar angle
0080         qreal angle = atan2(diff.y(), diff.x());
0081         if (angle < 0.0) {
0082             angle += 2 * M_PI;
0083         }
0084 
0085         // constrain the radius
0086         if (m_minRadius) {
0087             radius = qMax(m_minRadius->evaluate(), radius);
0088         }
0089         if (m_maxRadius) {
0090             radius = qMin(m_maxRadius->evaluate(), radius);
0091         }
0092 
0093         constrainedPosition.setX(angle * 180.0 / M_PI);
0094         constrainedPosition.setY(radius);
0095     } else {
0096         // constrain x coordinate
0097         if (m_minimumX) {
0098             constrainedPosition.setX(qMax(m_minimumX->evaluate(), constrainedPosition.x()));
0099         }
0100         if (m_maximumX) {
0101             constrainedPosition.setX(qMin(m_maximumX->evaluate(), constrainedPosition.x()));
0102         }
0103 
0104         // constrain y coordinate
0105         if (m_minimumY) {
0106             constrainedPosition.setY(qMax(m_minimumY->evaluate(), constrainedPosition.y()));
0107         }
0108         if (m_maximumY) {
0109             constrainedPosition.setY(qMin(m_maximumY->evaluate(), constrainedPosition.y()));
0110         }
0111     }
0112 
0113     m_positionX->modify(constrainedPosition.x());
0114     m_positionY->modify(constrainedPosition.y());
0115 }
0116 
0117 void EnhancedPathHandle::setRangeX(EnhancedPathParameter *minX, EnhancedPathParameter *maxX)
0118 {
0119     m_minimumX = minX;
0120     m_maximumX = maxX;
0121 }
0122 
0123 void EnhancedPathHandle::setRangeY(EnhancedPathParameter *minY, EnhancedPathParameter *maxY)
0124 {
0125     m_minimumY = minY;
0126     m_maximumY = maxY;
0127 }
0128 
0129 void EnhancedPathHandle::setPolarCenter(EnhancedPathParameter *polarX, EnhancedPathParameter *polarY)
0130 {
0131     m_polarX = polarX;
0132     m_polarY = polarY;
0133 }
0134 
0135 void EnhancedPathHandle::setRadiusRange(EnhancedPathParameter *minRadius, EnhancedPathParameter *maxRadius)
0136 {
0137     m_minRadius = minRadius;
0138     m_maxRadius = maxRadius;
0139 }
0140 
0141 bool EnhancedPathHandle::isPolar() const
0142 {
0143     return m_polarX && m_polarY;
0144 }