GraphvizConverter.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 "GraphvizConverter.h"
25
26#include <cassert>
27
28#include <boost/lexical_cast.hpp>
29
30#include <QPainterPath>
31#include <QPointF>
32
33#include <SimoxUtility/algorithm/string/string_tools.h>
34
38//#include <iomanip> //setprecision
39#include <stdexcept>
40//#include <sstream>
41#include <string>
42#include <vector>
43
47
48//TODO: ggf. diese beiden Funktionen und deren includes löschen
49float
50armarx::GraphvizConverter::convertToFloat(const std::string& graphvizNumber)
51{
52 /*
53 //replace ',' by '.'
54 size_t pointPos = graphvizNumber.find_first_of(",");
55 graphvizNumber.replace(pointPos, 1, ".");
56 */
57 try
58 {
59 return boost::lexical_cast<float>(graphvizNumber);
60 }
61 catch (boost::bad_lexical_cast&)
62 {
63 ARMARX_WARNING_S << " bad lexical cast to float - value:" << graphvizNumber;
64 throw;
65 }
66}
67
68std::string
70{
71 std::string graphvizNumber = to_string(number);
72
73 /*
74 //replace '.' by ','
75 size_t pointPos = graphvizNumber.find_first_of(".");
76 graphvizNumber.replace(pointPos, 1, ",");
77 */
78
79 return graphvizNumber;
80}
81
82QPointF
84{
85 auto pos = graphvizPoint.find('!');
86 if (pos != std::string::npos)
87 {
88 graphvizPoint.erase(pos, 1);
89 }
90 tokenVector tokens = splitBy(graphvizPoint, ",");
91 ARMARX_CHECK_EXPRESSION(tokens.size() == 2) << graphvizPoint;
92
93 try
94 {
95 float y = boost::lexical_cast<float>(tokens.at(1));
96 return QPointF{boost::lexical_cast<float>(tokens.at(0)), y};
97 }
98 catch (boost::bad_lexical_cast&)
99 {
100 ARMARX_WARNING_S << " bad lexical cast to point - value:" << graphvizPoint;
101 throw;
102 }
103 catch (const std::invalid_argument& ia)
104 {
105 ARMARX_ERROR_S << "Invalid argument for float conversion: " << ia.what() << " "
106 << tokens.at(0) << ", " << tokens.at(1);
107 }
108 catch (const std::out_of_range& e)
109 {
110 ARMARX_ERROR_S << "Out of range: " << e.what();
111 }
112
113 return QPointF(0, 0);
114}
115
116std::string
118{
119 std::string graphvizPoint = to_string(point.x());
120 graphvizPoint += ",";
121 graphvizPoint += to_string(point.y());
122
123 /*
124 * might be neccessary to use this version because graphviz wants a comma instead of a
125 * decimal point
126 *
127 std::stringstream ss;
128 // setprecision + fixed that 4 post decimal positions are shown
129 ss << std::setprecision(4) << std::fixed;
130 ss << point.x() << "," << point.y();
131 std::string graphvizPoint = ss.str();
132
133 //replace '.' by ','
134 size_t pointPos = graphvizPoint.find_first_of(".");
135 while(pointPos != std::string::npos)
136 {
137 graphvizPoint.replace(pointPos, 1, ",");
138 pointPos = graphvizPoint.find_first_of(".", pointPos + 1);
139 }
140 */
141
142 return graphvizPoint;
143}
144
145QRectF
146armarx::GraphvizConverter::convertToRectangle(const std::string& graphvizPoint)
147{
148 tokenVector tokens = splitBy(graphvizPoint, ",");
149 ARMARX_CHECK_EXPRESSION(tokens.size() == 4);
150
151 try
152 {
153 float y = boost::lexical_cast<float>(tokens.at(1));
154 float y2 = boost::lexical_cast<float>(tokens.at(3));
155 return QRectF{boost::lexical_cast<float>(tokens.at(0)),
156 y,
157 boost::lexical_cast<float>(tokens.at(2)),
158 y2};
159 }
160 catch (boost::bad_lexical_cast&)
161 {
162 ARMARX_WARNING_S << " bad lexical cast to float - point:" << graphvizPoint;
163 throw;
164 }
165 catch (const std::invalid_argument& ia)
166 {
167 ARMARX_ERROR_S << "Invalid argument for float conversion: " << ia.what() << " "
168 << tokens.at(0) << ", " << tokens.at(1);
169 }
170 catch (const std::out_of_range& e)
171 {
172 ARMARX_ERROR_S << "Out of range: " << e.what();
173 }
174
175 return QRectF(0, 0, 0, 0);
176}
177
179armarx::GraphvizConverter::convertToSpline(const std::string& graphVizSplineType)
180{
181 splineVector splines;
182
183 tokenVector splineStrings = splitBy(graphVizSplineType, ";");
184 ARMARX_CHECK_EXPRESSION(splineStrings.size() > 0);
185
186 for (auto spline : splineStrings)
187 {
188 splines.push_back(tokenize(spline));
189 }
190
191 return mergeSplines(splines);
192}
193
194std::string
196{
197 //assert(spline.controlPoints.size() % 3 == 1);
198
199 std::string graphvizSpline;
200
201 if (spline.endPoint)
202 {
203 graphvizSpline += "e,";
204 graphvizSpline += convertFromPoint(*(spline.endPoint));
205 graphvizSpline += " ";
206 }
207
208 if (spline.startPoint)
209 {
210 graphvizSpline += "s,";
211 graphvizSpline += convertFromPoint(*(spline.startPoint));
212 graphvizSpline += " ";
213 }
214
215 for (auto point : spline.controlPoints)
216 {
217 graphvizSpline += convertFromPoint(point);
218 graphvizSpline += " ";
219 }
220
221 ARMARX_CHECK_EXPRESSION(graphvizSpline.size() > 0);
222 simox::alg::trim(graphvizSpline); //remove trailing whitespace
223
224 return graphvizSpline;
225}
226
228armarx::GraphvizConverter::tokenize(std::string graphVizSpline)
229{
230 tokenVector points = splitBy(graphVizSpline, " ");
231 /* TODO: de-comment
232 assert(points.size() >= 4); //there has to be a starting control point and a triple of control points
233 */
234 SupportPoints spline;
235
236 for (auto point : points)
237 {
238 tokenVector tokens = splitBy(point, ",");
239
240 if (tokens.size() == 3)
241 {
242 ARMARX_CHECK_EXPRESSION((tokens.at(0) == "s") || (tokens.at(0) == "e"));
243
244 try
245 {
246 QPointF floatPoint{boost::lexical_cast<float>(tokens.at(1)),
247 boost::lexical_cast<float>(tokens.at(2))};
248
249 if (tokens.at(0) == "s")
250 {
251 spline.startPoint = std::make_shared<QPointF>(floatPoint);
252 }
253 else
254 {
255 spline.endPoint = std::make_shared<QPointF>(floatPoint);
256 }
257 }
258 catch (boost::bad_lexical_cast&)
259 {
260 ARMARX_WARNING_S << " bad lexical cast to pointlist - value:" << graphVizSpline;
261 throw;
262 }
263 catch (const std::invalid_argument& ia)
264 {
265 ARMARX_ERROR_S << "Invalid argument for float conversion: " << ia.what();
266 }
267 catch (const std::out_of_range& e)
268 {
269 ARMARX_ERROR_S << "Out of range: " << e.what();
270 }
271 }
272 else if (tokens.size() == 2)
273 {
274 try
275 {
276 QPointF p{boost::lexical_cast<float>(tokens.at(0)),
277 boost::lexical_cast<float>(tokens.at(1))};
278 spline.controlPoints.push_back(p);
279 }
280 catch (const std::invalid_argument& ia)
281 {
282 ARMARX_ERROR_S << "Invalid argument for float conversion: " << ia.what() << " "
283 << tokens.at(0) << ", " << tokens.at(1);
284 }
285 catch (const std::out_of_range& e)
286 {
287 ARMARX_ERROR_S << "Out of range: " << e.what();
288 }
289 }
290 else
291 {
292 ARMARX_ERROR_S << "Not a valid string to represent a spline control point: " << point;
293 }
294 }
295
296 //assert(spline.controlPoints.size() % 3 == 1);
297
298 return spline;
299}
300
302armarx::GraphvizConverter::splitBy(std::string toSplit, std::string divider)
303{
304 tokenVector tokenVec;
305 size_t dividerPos = 0;
306
307 while (dividerPos != std::string::npos)
308 {
309 dividerPos = toSplit.find_first_of(divider);
310 std::string token = toSplit.substr(0, dividerPos);
311 toSplit = toSplit.substr(dividerPos + 1);
312
313 tokenVec.push_back(token);
314 }
315
316 return tokenVec;
317}
318
319armarx::SupportPoints
320armarx::GraphvizConverter::mergeSplines(armarx::splineVector toMerge)
321{
322 if (toMerge.size() >= 1)
323 {
324 return toMerge.front();
325 }
326 SupportPoints merged;
327 merged.startPoint = toMerge.front().startPoint;
328 merged.endPoint = toMerge.back().endPoint;
329
330 for (SupportPoints otherSpline : toMerge)
331 {
332 merged.controlPoints.append(otherSpline.controlPoints);
333 }
334
335 return merged;
336}
337
338/*
339QPainterPath armarx::SplineConverter::calcArrowhead(QPointF start, QPointF destination)
340{
341 QPointF directionVector = destination - start;
342 QPointF baseVector {- directionVector.y(), directionVector.x()}; //vector orthogonal to directionVector
343
344 QPointF leftWingEnd = start + 0.5 * baseVector;
345 QPointF rightWingEnd = start - 0.5 * baseVector;
346
347 QPolygonF triangle;
348 triangle << leftWingEnd << rightWingEnd << destination;
349
350 QPainterPath arrowhead;
351 arrowhead.addPolygon(triangle);
352 arrowhead.closeSubpath();
353
354 return arrowhead;
355}
356*/
357
358
359QList<QPointF>
361{
362 QList<QPointF> list;
363
364 if (startPoint)
365 {
366 list.append(*startPoint.get());
367 }
368
369 list.append(controlPointList());
370
371 if (endPoint)
372 {
373 list.append(*endPoint.get());
374 }
375
376 return list;
377}
378
379QList<QPointF>
381{
382 QList<QPointF> list;
383
384 for (QPointF point : controlPoints)
385 {
386 list.append(point);
387 }
388
389 return list;
390}
391
392void
394{
395 controlPoints.clear();
396
397 for (auto point : list)
398 {
399 controlPoints.push_back(point);
400 }
401}
402
403void
404armarx::SupportPoints::append(const QPointF& point)
405{
406 controlPoints.append(point);
407}
static QRectF convertToRectangle(const std::string &graphvizPoint)
static std::string convertFromPoint(QPointF point)
static float convertToFloat(const std::string &graphvizNumber)
static SupportPoints convertToSpline(const std::string &graphVizSplineType)
static std::string convertFromSpline(SupportPoints spline)
static std::string convertFromFloat(float number)
static QPointF convertToPoint(std::string graphvizPoint)
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_ERROR_S
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:216
#define ARMARX_WARNING_S
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:213
std::vector< std::string > tokenVector
const std::string & to_string(const std::string &s)
std::vector< SupportPoints > splineVector
QPointList controlPoints
Definition Transition.h:54
void setControlPoints(QList< QPointF > list)
QList< QPointF > toPointList() const
void append(const QPointF &point)
QList< QPointF > controlPointList() const