File indexing completed on 2024-05-12 15:26:43
0001 /*************************************************************************** 0002 File : Transform.cpp 0003 Project : LabPlot 0004 Description : transformation for mapping between scene and 0005 logical coordinates of Datapicker-image 0006 -------------------------------------------------------------------- 0007 Copyright : (C) 2015 by Ankit Wagadre (wagadre.ankit@gmail.com) 0008 ***************************************************************************/ 0009 /*************************************************************************** 0010 * * 0011 * This program is free software; you can redistribute it and/or modify * 0012 * it under the terms of the GNU General Public License as published by * 0013 * the Free Software Foundation; either version 2 of the License, or * 0014 * (at your option) any later version. * 0015 * * 0016 * This program is distributed in the hope that it will be useful, * 0017 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0019 * GNU General Public License for more details. * 0020 * * 0021 * You should have received a copy of the GNU General Public License * 0022 * along with this program; if not, write to the Free Software * 0023 * Foundation, Inc., 51 Franklin Street, Fifth Floor, * 0024 * Boston, MA 02110-1301 USA * 0025 * * 0026 ***************************************************************************/ 0027 0028 #include "Transform.h" 0029 //TODO: replace with GSL or better methods 0030 #include <cmath> 0031 0032 extern "C" { 0033 #include <gsl/gsl_math.h> 0034 #include "backend/nsl/nsl_math.h" 0035 } 0036 0037 //Transform::Transform() = default; 0038 0039 bool Transform::mapTypeToCartesian(const DatapickerImage::ReferencePoints& axisPoints) { 0040 if (axisPoints.type == DatapickerImage::GraphType::LogarithmicX) { 0041 for (int i = 0; i < 3; ++i) { 0042 if (axisPoints.logicalPos[i].x() <= 0) 0043 return false; 0044 x[i] = log(axisPoints.logicalPos[i].x()); 0045 y[i] = axisPoints.logicalPos[i].y(); 0046 X[i] = axisPoints.scenePos[i].x(); 0047 Y[i] = axisPoints.scenePos[i].y(); 0048 } 0049 } else if (axisPoints.type == DatapickerImage::GraphType::LogarithmicY) { 0050 for (int i = 0; i < 3; ++i) { 0051 if (axisPoints.logicalPos[i].y() <= 0) 0052 return false; 0053 x[i] = axisPoints.logicalPos[i].x(); 0054 y[i] = log(axisPoints.logicalPos[i].y()); 0055 X[i] = axisPoints.scenePos[i].x(); 0056 Y[i] = axisPoints.scenePos[i].y(); 0057 } 0058 } else if (axisPoints.type == DatapickerImage::GraphType::PolarInDegree) { 0059 for (int i = 0; i < 3; ++i) { 0060 if (axisPoints.logicalPos[i].x() < 0) 0061 return false; 0062 x[i] = axisPoints.logicalPos[i].x()*cos(axisPoints.logicalPos[i].y() * M_PI_180); 0063 y[i] = axisPoints.logicalPos[i].x()*sin(axisPoints.logicalPos[i].y() * M_PI_180); 0064 X[i] = axisPoints.scenePos[i].x(); 0065 Y[i] = axisPoints.scenePos[i].y(); 0066 } 0067 } else if (axisPoints.type == DatapickerImage::GraphType::PolarInRadians) { 0068 for (int i = 0; i < 3; ++i) { 0069 if (axisPoints.logicalPos[i].x() < 0) 0070 return false; 0071 x[i] = axisPoints.logicalPos[i].x()*cos(axisPoints.logicalPos[i].y()); 0072 y[i] = axisPoints.logicalPos[i].x()*sin(axisPoints.logicalPos[i].y()); 0073 X[i] = axisPoints.scenePos[i].x(); 0074 Y[i] = axisPoints.scenePos[i].y(); 0075 } 0076 } else if (axisPoints.type == DatapickerImage::GraphType::Ternary) { 0077 for (int i = 0; i < 3; ++i) { 0078 x[i] = (2*axisPoints.logicalPos[i].y() + axisPoints.logicalPos[i].z())/(2*axisPoints.ternaryScale); 0079 y[i] = (M_SQRT3 * axisPoints.logicalPos[i].z())/(2*axisPoints.ternaryScale); 0080 X[i] = axisPoints.scenePos[i].x(); 0081 Y[i] = axisPoints.scenePos[i].y(); 0082 } 0083 } else { 0084 for (int i = 0; i < 3; ++i) { 0085 x[i] = axisPoints.logicalPos[i].x(); 0086 y[i] = axisPoints.logicalPos[i].y(); 0087 X[i] = axisPoints.scenePos[i].x(); 0088 Y[i] = axisPoints.scenePos[i].y(); 0089 } 0090 } 0091 0092 return true; 0093 } 0094 0095 QVector3D Transform::mapSceneToLogical(QPointF scenePoint, const DatapickerImage::ReferencePoints& axisPoints) { 0096 X[3] = scenePoint.x(); 0097 Y[3] = scenePoint.y(); 0098 0099 if (mapTypeToCartesian(axisPoints)) { 0100 double sin; 0101 double cos; 0102 double scaleOfX; 0103 double scaleOfY; 0104 if (((Y[1] - Y[0])*(x[2] - x[0]) - (Y[2] - Y[0])*(x[1] - x[0])) != 0) { 0105 double tan = ((X[1] - X[0])*(x[2] - x[0]) - (X[2] - X[0])*(x[1] - x[0]))/((Y[1] - Y[0])*(x[2] - x[0]) - (Y[2] - Y[0])*(x[1] - x[0])); 0106 sin = tan/sqrt(1 + tan*tan); 0107 cos = sqrt(1 - sin*sin); 0108 } else { 0109 sin = 1; 0110 cos = 0; 0111 } 0112 0113 if ((x[1] - x[0]) != 0) { 0114 scaleOfX = (x[1] - x[0])/((X[1] - X[0])*cos - (Y[1] - Y[0])*sin); 0115 } else { 0116 scaleOfX = (x[2] - x[0])/((X[2] - X[0])*cos - (Y[2] - Y[0])*sin); 0117 } 0118 0119 if ((y[1]-y[0]) != 0) { 0120 scaleOfY = (y[1] - y[0])/((X[1] - X[0])*sin + (Y[1] - Y[0])*cos); 0121 } else { 0122 scaleOfY = (y[2] - y[0])/((X[2] - X[0])*sin + (Y[2] - Y[0])*cos); 0123 } 0124 0125 x[3] = x[0] + (((X[3] - X[0])*cos - (Y[3] - Y[0])*sin)*scaleOfX); 0126 y[3] = y[0] + (((X[3] - X[0])*sin + (Y[3] - Y[0])*cos)*scaleOfY); 0127 return mapCartesianToType(QPointF(x[3], y[3]), axisPoints); 0128 } 0129 return QVector3D{}; 0130 } 0131 0132 QVector3D Transform::mapSceneLengthToLogical(QPointF errorSpan, const DatapickerImage::ReferencePoints& axisPoints) { 0133 return mapSceneToLogical(errorSpan, axisPoints) - mapSceneToLogical(QPointF(0,0), axisPoints); 0134 } 0135 0136 QVector3D Transform::mapCartesianToType(QPointF point, const DatapickerImage::ReferencePoints &axisPoints) const { 0137 if (axisPoints.type == DatapickerImage::GraphType::LogarithmicX) { 0138 return QVector3D(exp(point.x()), point.y(), 0); 0139 } else if (axisPoints.type == DatapickerImage::GraphType::LogarithmicY) { 0140 return QVector3D(point.x(), exp(point.y()), 0); 0141 } else if (axisPoints.type == DatapickerImage::GraphType::PolarInDegree) { 0142 double r = sqrt(point.x()*point.x() + point.y()*point.y()); 0143 double angle = atan(point.y() / point.x() * M_180_PI); 0144 return QVector3D(r, angle, 0); 0145 } else if (axisPoints.type == DatapickerImage::GraphType::PolarInRadians) { 0146 double r = sqrt(point.x()*point.x() + point.y()*point.y()); 0147 double angle = atan(point.y()/point.x()); 0148 return QVector3D(r, angle, 0); 0149 } else if (axisPoints.type == DatapickerImage::GraphType::Ternary) { 0150 double c = (point.y()*2*axisPoints.ternaryScale)/M_SQRT3; 0151 double b = (point.x()*2*axisPoints.ternaryScale - c)/2; 0152 double a = axisPoints.ternaryScale - b - c; 0153 return QVector3D(a, b, c); 0154 } else { 0155 return QVector3D(point.x(), point.y(), 0); 0156 } 0157 } 0158