SplinePath.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package
19 * @author
20 * @date
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24#include "SplinePath.h"
25
26#include <cassert>
27#include <cmath>
28
30
34
35QPainterPath
37{
38 //assert((simpleControlPoints.size() == 2) || (simpleControlPoints.size() % 3 == 1));
39
40 QPainterPath path;
41
42 if (simpleControlPoints.size() == 2)
43 {
44 // ARMARX_DEBUG_S << "Direct Line";
45 path.moveTo(simpleControlPoints.first());
46 path.lineTo(simpleControlPoints.last());
47 }
48 else if (simpleControlPoints.size() == 3)
49 {
50 // ARMARX_DEBUG_S << "Quad. path";
51 path.moveTo(simpleControlPoints.first());
52 path.quadTo(simpleControlPoints.at(1), simpleControlPoints.last());
53 }
54 else
55 {
56 // ARMARX_DEBUG_S << "complex path";
57 path = complexPath(simpleControlPoints);
58 }
59
60 return path;
61
62 /*
63 * this doesn't work
64 *
65 QPointVector fullControlPoints;
66
67 if(simpleControlPoints.size() > 1)
68 {
69 //add first given simpleControlPoint also as first complexControlPoint
70 auto iter = simpleControlPoints.begin();
71 fullControlPoints.push_back(*iter);
72
73 //create point between the first two simpleControlPoints
74 QPoint2Array linePoints = line(*iter, *(iter + 1));
75 iter++;
76 //add the new point and the second simpleControlPoint to the fullControlPoints
77 fullControlPoints.insert(fullControlPoints.end(), linePoints.begin(), linePoints.end());
78
79 while(iter < simpleControlPoints.end() - 1)
80 {
81 QPoint2Array linePoints = line(*iter, *(iter + 1));
82 iter++;
83 fullControlPoints.insert(fullControlPoints.end(), linePoints.begin(), linePoints.end());
84
85 if(iter < simpleControlPoints.end() - 2)
86 {
87 QPoint4Array transitionPoints = smoothTransition(*iter, *(iter + 1), *(iter + 2));
88 iter = iter + 2;
89 fullControlPoints.insert(fullControlPoints.end(), transitionPoints.begin(), transitionPoints.end());
90 }
91 }
92 }
93
94 //ensure that there are enough control points to create a cubic Bezierspline
95 while((fullControlPoints.size() % 3 != 1) || (fullControlPoints.size() < 4))
96 {
97 fullControlPoints.insert(fullControlPoints.begin(), simpleControlPoints.front());
98 }
99
100 return complexPath(fullControlPoints);
101 */
102}
103
104QPainterPath
106{
107 assert((fullControlPoints.size() % 3 == 1) && (fullControlPoints.size() > 3));
108
109 QPainterPath path{fullControlPoints.at(0)};
110
111 for (int i = 1; i < fullControlPoints.size(); i += 3)
112 {
113 assert(i + 2 < fullControlPoints.size()); //size of controlPoints == 1 mod 3
114
115 path.cubicTo(
116 fullControlPoints.at(i), fullControlPoints.at(i + 1), fullControlPoints.at(i + 2));
117 }
118
119 /*
120 //print circles on control points
121 for(QPointF controlPoint : fullControlPoints)
122 {
123 path.addEllipse(controlPoint, 5, 5);
124 }
125 */
126
127 //only for debugging
128 //pathToString(path);
129 return path;
130}
131
133armarx::SplinePath::line(QPointF start, QPointF end)
134{
135 QPointF direction = end - start; //vector from start to end
136 QPointF middle = start + 0.5 * direction;
137
138 QPoint2Array array{{middle, end}};
139 return array;
140}
141
143armarx::SplinePath::smoothTransition(QPointF start, QPointF middle, QPointF end)
144{
145 QPointF parallelLine = end - start; //vector from start to end
146
147 //put the two new points on the line parallel to parallelLine that goes through middle.
148 QPointF new1 = middle - relativeDistance * parallelLine;
149 QPointF new2 = middle + relativeDistance * parallelLine;
150
151 QPoint4Array array{{new1, middle, new2, end}};
152 return array;
153}
154
155void
156armarx::SplinePath::pathToString(QPainterPath path)
157{
158 // ARMARX_LOG_S << "New path begins:";
159 for (size_t i = 0; i < static_cast<size_t>(path.elementCount()); i++)
160 {
161 QPainterPath::Element elem = path.elementAt(i);
162
163 std::string type;
164
165 switch (elem.type)
166 {
167 case QPainterPath::MoveToElement:
168 {
169 type = "Move";
170 break;
171 }
172
173 case QPainterPath::LineToElement:
174 {
175 type = "Line";
176 break;
177 }
178
179 case QPainterPath::CurveToElement:
180 {
181 type = "Curve";
182 break;
183 }
184
185 default:
186 break;
187 }
188
189 if (elem.type != QPainterPath::CurveToDataElement)
190 {
191 // ARMARX_LOG_S << type << " at (" << elem.x << ", " << elem.y << ")";
192 }
193 }
194}
static QPainterPath complexPath(QPointList fullControlPoints)
complexPath Constructs a cubic Beziercurve with a correctly specified vector of control points.
static QPainterPath simplePath(QPointList simpleControlPoints)
simplePath Constructs a cubic Beziercurve with an arbitrary number of control points.
std::array< QPointF, 2 > QPoint2Array
Definition SplinePath.h:36
std::array< QPointF, 4 > QPoint4Array
Definition SplinePath.h:37
QList< QPointF > QPointList
Definition Transition.h:38