DGtal  1.2.0
Shapes.cpp
1 
8 /*
9  * \@copyright This File is part of the Board library which is
10  * licensed under the terms of the GNU Lesser General Public Licence.
11  * See the LICENCE file for further details.
12  */
13 #include "Board/Rect.h"
14 #include "Board/Shapes.h"
15 #include "Board/Tools.h"
16 #include "Board/PSFonts.h"
17 #include <cmath>
18 #include <cstring>
19 #include <vector>
20 #include <sstream>
21 
22 #include <assert.h>
23 
24 #ifndef M_PI
25 #define M_PI 3.14159265358979323846 /* pi */
26 #endif
27 
28 #ifdef _MSC_VER
29 //#define NOMINMAX
30 //#include <windows.h>
31 #endif
32 
33 namespace {
34 const char * xFigDashStylesPS[] = {
35  " [] 0 sd ", // SolidStyle
36  " [1 1] 0 sd ", // DashStyle
37  " [1.5 4.5] 45 sd ", // DotStyle
38  " [4.5 2.3 1.5 2.3] 0 sd ", // DashDotStyle
39  " [4.5 2.0 1.5 1.5 1.5 2.0] 0 sd ", // DashDotDotStyle
40  " [4.5 1.8 1.5 1.4 1.5 1.4 1.5 1.8 ] 0 sd " // DashDotDotDotStyle
41 };
42 
43 const char * xFigDashStylesSVG[] = {
44  "", // SolidStyle
45  "stroke-dasharray:1,1;stroke-dashoffset:0", // DashStyle
46  "stroke-dasharray:1.5,4.5;stroke-dashoffset:45", // DotStyle
47  "stroke-dasharray:4.5,2.3,1.5,2.3;stroke-dashoffset:0", // DashDotStyle
48  "stroke-dasharray:4.5,2.0,1.5,1.5,1.5,2.0;stroke-dashoffset;0", // DashDotDotStyle
49  "stroke-dasharray:4.5,1.8,1.5,1.4,1.5,1.4,1.5,1.8;stroke-dashoffset:0" // DashDotDotDotStyle
50 };
51 
52 const char * xFigDashStylesTikZ[] = {
53  "", // SolidStyle
54  "dash pattern=on 1pt off 1pt,", // DashStyle
55  "dotted,", // DotStyle
56  "dashdotted,", // DashDotStyle
57  "dashdotdotted,", // DashDotDotStyle
58  "dash pattern=on 2pt off 3pt on 4pt off 4pt," // DashDotDotDotStyle
59 };
60 
61 #ifdef WITH_CAIRO
62 // cairo
63 cairo_line_cap_t cairoLineCap[] = {
64  CAIRO_LINE_CAP_BUTT,
65  CAIRO_LINE_CAP_ROUND,
66  CAIRO_LINE_CAP_SQUARE
67 };
68 
69 cairo_line_join_t cairoLineJoin[] = {
70  CAIRO_LINE_JOIN_MITER,
71  CAIRO_LINE_JOIN_ROUND,
72  CAIRO_LINE_JOIN_BEVEL
73 };
74 
75 #define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0]))
76 
77 const double cairoSolidStyle[] = {1, 0}; const double cairoSolidStyle_offset = 0;
78 const double cairoDashStyle[] = {1, 1}; const double cairoDashStyle_offset = 0;
79 const double cairoDotStyle[] = {1.5, 4.5}; const double cairoDotStyle_offset = 45;
80 const double cairoDashDotStyle[] = {4.5, 2.3, 1.5, 2.3}; const double cairoDashDotStyle_offset = 0;
81 const double cairoDashDotDotStyle[] = {4.5, 2.0, 1.5, 1.5, 1.5, 2.0}; const double cairoDashDotDotStyle_offset = 0;
82 const double cairoDashDotDotDotStyle[] = {4.5, 1.8, 1.5, 1.4, 1.5, 1.4, 1.5, 1.8}; const double cairoDashDotDotDotStyle_offset = 0;
83 // cairo
84 #endif
85 }
86 
87 //todo cairo: gouraudtriangle, text (?)
88 //todo cairo: group (?)
89 
90 namespace LibBoard {
91 
92 extern const char * XFigPostscriptFontnames[];
93 
94 bool
95 shapeGreaterDepth( const Shape *s1, const Shape *s2 )
96 {
97  return s1->depth() > s2->depth();
98 }
99 
100 const std::string Shape::_name("AbstractShape");
101 
102 const std::string &
103 Shape::name() const
104 {
105  return _name;
106 }
107 
108 std::string
109 Shape::svgProperties( const TransformSVG & transform ) const
110 {
111  static const char * capStrings[3] = { "butt", "round", "square" };
112  static const char * joinStrings[3] = { "miter", "round", "bevel" };
113  std::stringstream str;
114  if ( _penColor != DGtal::Color::None ) {
115  str << " fill=\"" << _fillColor.svg() << '"'
116  << " stroke=\"" << _penColor.svg() << '"'
117  << " stroke-width=\"" << transform.mapWidth( _lineWidth ) << "mm\""
118  << " style=\"stroke-linecap:" << capStrings[ _lineCap ]
119  << ";stroke-linejoin:" << joinStrings[ _lineJoin ];
120  if ( _lineStyle != SolidStyle )
121  str << ";" << xFigDashStylesSVG[ _lineStyle ];
122  str << '"'
123  << _fillColor.svgAlpha( " fill" )
124  << _penColor.svgAlpha( " stroke" );
125  } else {
126  str << " fill=\"" << _fillColor.svg() << '"'
127 // << " stroke=\"" << _fillColor.svg() << '"'
128 // << " stroke-width=\"0.5px\""
129  << " stroke=\"none\""
130  << " stroke-width=\"0\""
131  << " style=\"stroke-linecap:round;stroke-linejoin:round;"
132  << '"'
133  << _fillColor.svgAlpha( " fill" )
134  << _fillColor.svgAlpha( " stroke" );
135  }
136  return str.str();
137 }
138 
139 std::string
141 {
142  std::stringstream str;
143  str << _lineWidth << " slw ";
144  str << _lineCap << " slc ";
145  str << _lineJoin << " slj";
146  str << xFigDashStylesPS[ _lineStyle ];
147 
148  return str.str();
149 }
150 
151 #ifdef WITH_CAIRO
152 void
153 Shape::setCairoDashStyle(cairo_t *cr, LineStyle type) const
154 {
155  switch (type)
156  {
157  case SolidStyle:
158  cairo_set_dash (cr, cairoSolidStyle, ARRAY_SIZE(cairoSolidStyle), cairoSolidStyle_offset); break;
159  case DashStyle:
160  cairo_set_dash (cr, cairoDashStyle, ARRAY_SIZE(cairoDashStyle), cairoDashStyle_offset); break;
161  case DotStyle:
162  cairo_set_dash (cr, cairoDotStyle, ARRAY_SIZE(cairoDotStyle), cairoDotStyle_offset); break;
163  case DashDotStyle:
164  cairo_set_dash (cr, cairoDashDotStyle, ARRAY_SIZE(cairoDashDotStyle), cairoDashDotStyle_offset); break;
165  case DashDotDotStyle:
166  cairo_set_dash (cr, cairoDashDotDotStyle, ARRAY_SIZE(cairoDashDotDotStyle), cairoDashDotDotStyle_offset); break;
167  case DashDotDotDotStyle:
168  cairo_set_dash (cr, cairoDashDotDotDotStyle, ARRAY_SIZE(cairoDashDotDotDotStyle), cairoDashDotDotDotStyle_offset); break;
169 
170  default: // SolidStyle
171  cairo_set_dash (cr, cairoSolidStyle, ARRAY_SIZE(cairoSolidStyle), cairoSolidStyle_offset);
172  }
173 }
174 #endif
175 
176 std::string
177 Shape::tikzProperties( const TransformTikZ & transform ) const
178 {
179  static const char * capStrings[3] = { "" /* initial value "butt" */, "line cap=round,", "line cap=rect," };
180  static const char * joinStrings[3] = { "" /* initial value "miter" */, "line join=round", "line join=bevel" };
181 
182  std::stringstream str;
183  str << "fill=" << _fillColor.tikz() << ',';
184  str << "draw=" << _penColor.tikz() << ',';
185  str << "line width=" << transform.mapWidth( _lineWidth ) << "mm,";
186  str << xFigDashStylesTikZ[ _lineStyle ];
187  str << capStrings[ _lineCap ];
188  str << joinStrings[ _lineJoin ];
189 
190  return str.str();
191 }
192 
193 void
194 Shape::depth( int d )
195 {
196  _depth = d;
197 }
198 
199 void
200 Shape::shiftDepth( int shift )
201 {
202  _depth += shift;
203 }
204 
205 /*
206  * Dot
207  */
208 
209 const std::string Dot::_name("Dot");
210 
211 const std::string &
212 Dot::name() const
213 {
214  return _name;
215 }
216 
217 Point
218 Dot::center() const {
219  return Point( _x, _y );
220 }
221 
222 Dot &
223 Dot::rotate( double angle, const Point & rotCenter )
224 {
225  Point( _x, _y ).rotate( angle, rotCenter ).get( _x, _y );
226  return *this;
227 }
228 
229 Dot
230 Dot::rotated( double angle, const Point & rotCenter ) const
231 {
232  return Dot(*this).rotate( angle, rotCenter );
233 }
234 
235 Dot &
236 Dot::rotate( double )
237 {
238  return *this;
239 }
240 
241 Dot
242 Dot::rotated( double ) const
243 {
244  return *this;
245 }
246 
247 Dot &
248 Dot::translate( double dx, double dy )
249 {
250  _x += dx;
251  _y += dy;
252  return *this;
253 }
254 
255 Dot
256 Dot::translated( double dx, double dy ) const
257 {
258  return Dot(*this).translate( dx, dy );
259 }
260 
261 Shape &
262 Dot::scale( double , double )
263 {
264  return *this;
265 }
266 
267 Shape &
268 Dot::scale( double )
269 {
270  return *this;
271 }
272 
273 Dot
274 Dot::scaled( double , double ) const
275 {
276  return *this;
277 }
278 
279 Dot
280 Dot::scaled( double ) const
281 {
282  return *this;
283 }
284 
285 void
286 Dot::scaleAll( double s )
287 {
288  _x *= s;
289  _y *= s;
290 }
291 
292 void
293 Dot::flushPostscript( std::ostream & stream,
294  const TransformEPS & transform ) const
295 {
296  stream << "\n% Dot\n";
297  stream << postscriptProperties() << " "
298  << "n "
299  << transform.mapX( _x ) << " "
300  << transform.mapY( _y ) << " "
301  << "m "
302  << transform.mapX( _x ) << " "
303  << transform.mapY( _y ) << " "
304  << "l " << _penColor.postscript() << " srgb stroke" << std::endl;
305 }
306 
307 void
308 Dot::flushFIG( std::ostream & stream,
309  const TransformFIG & transform,
310  std::map<DGtal::Color,int> & colormap ) const
311 {
312  stream << "2 1 0 ";
313  // Thickness
314  stream << ( _penColor.valid()?transform.mapWidth( _lineWidth ):0 ) << " ";
315  // Pen color
316  stream << colormap[ _penColor ] << " ";
317  // Fill color
318  stream << "0 ";
319  // Depth
320  stream << transform.mapDepth( _depth ) << " ";
321  // Pen style
322  stream << "-1 ";
323  // Area fill, style val, join style, cap style, radius, f_arrow, b_arrow
324  stream << "-1 0.000 " << _lineJoin << " " << _lineCap << " -1 0 0 ";
325  // Number of points
326  stream << "2\n";
327  stream << " ";
328  stream << static_cast<int>( transform.mapX( _x ) ) << " "
329  << static_cast<int>( transform.mapY( _y ) ) << " "
330  << static_cast<int>( transform.mapX( _x ) ) << " "
331  << static_cast<int>( transform.mapY( _y ) ) << std::endl;
332 }
333 
334 void
335 Dot::flushSVG( std::ostream & stream,
336  const TransformSVG & transform ) const
337 {
338  stream << "<line x1=\"" << transform.mapX( _x ) << "\""
339  << " y1=\"" << transform.mapY( _y ) << "\""
340  << " x2=\"" << transform.mapX( _x ) << "\""
341  << " y2=\"" << transform.mapY( _y ) << "\""
342  << svgProperties( transform )
343  << " />" << std::endl;
344 }
345 
346 #ifdef WITH_CAIRO
347 void
348 Dot::flushCairo( cairo_t *cr,
349  const TransformCairo & transform ) const
350 {
351  cairo_save (cr);
352 
353  cairo_set_source_rgba (cr, _penColor.red()/255.0, _penColor.green()/255.0, _penColor.blue()/255.0, 1.);
354 
355  cairo_move_to (cr, transform.mapX( _x ), transform.mapY( _y ));
356  cairo_line_to (cr, transform.mapX( _x ), transform.mapY( _y ));
357 
358  cairo_set_line_width (cr, _lineWidth);
359  cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
360  cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
362 
363  cairo_stroke (cr);
364 
365  cairo_restore (cr);
366 }
367 #endif
368 
369 void
370 Dot::flushTikZ( std::ostream & stream,
371  const TransformTikZ & /*transform*/ ) const
372 
373 {
374  // FIXME: unimplemented
375  stream << "% FIXME: Dot::flushTikZ unimplemented" << std::endl;
376 }
377 
378 Rect
380 {
381  return Rect( _x, _y, 0.0, 0.0 );
382 }
383 
384 Dot *
385 Dot::clone() const {
386  return new Dot(*this);
387 }
388 
389 /*
390  * Line
391  */
392 
393 const std::string Line::_name("Line");
394 
395 const std::string &
396 Line::name() const
397 {
398  return _name;
399 }
400 
401 Point
402 Line::center() const {
403  return 0.5 * Point( _x1 + _x2, _y1 + _y2 );
404 }
405 
406 Line &
407 Line::rotate( double angle, const Point & rotCenter )
408 {
409  Point( _x1, _y1 ).rotate( angle, rotCenter ).get( _x1, _y1 );
410  Point( _x2, _y2 ).rotate( angle, rotCenter ).get( _x2, _y2 );
411  return *this;
412 }
413 
414 Line &
415 Line::rotate( double angle )
416 {
417  return Line::rotate( angle, center() );
418 }
419 
420 Line
421 Line::rotated( double angle, const Point & rotCenter ) const
422 {
423  Line res(*this);
424  Point( _x1, _y1 ).rotate( angle, rotCenter ).get( res._x1, res._y1 );
425  Point( _x2, _y2 ).rotate( angle, rotCenter ).get( res._x2, res._y2 );
426  return res;
427 }
428 
429 Line
430 Line::rotated( double angle ) const
431 {
432  Line res(*this);
433  Point c = center();
434  Point( _x1, _y1 ).rotate( angle, c ).get( res._x1, res._y1 );
435  Point( _x2, _y2 ).rotate( angle, c ).get( res._x2, res._y2 );
436  return res;
437 }
438 
439 Line &
440 Line::translate( double dx, double dy )
441 {
442  _x1 += dx;
443  _x2 += dx;
444  _y1 += dy;
445  _y2 += dy;
446  return *this;
447 }
448 
449 Line
450 Line::translated( double dx, double dy ) const
451 {
452  Line res(*this);
453  res._x1 += dx;
454  res._x2 += dx;
455  res._y1 += dy;
456  res._y2 += dy;
457  return *this;
458 }
459 
460 Shape &
461 Line::scale( double sx, double sy )
462 {
463  Point c = center();
464  _x1 *= sx;
465  _x2 *= sx;
466  _y1 *= sy;
467  _y2 *= sy;
468  Point delta = c - center();
469  translate( delta.x, delta.y );
470  return *this;
471 }
472 
473 Shape &
474 Line::scale( double s )
475 {
476  scale( s, s );
477  return (*this);
478 }
479 
480 Line
481 Line::scaled( double sx, double sy ) const
482 {
483  Line res(*this);
484  Point c = center();
485  res._x1 *= sx;
486  res._x2 *= sx;
487  res._y1 *= sy;
488  res._y2 *= sy;
489  Point delta = c - res.center();
490  return res.translate( delta.x, delta.y );
491 }
492 
493 Line
494 Line::scaled( double s ) const
495 {
496  return Line::scaled( s , s );
497 }
498 
499 void
500 Line::scaleAll( double s )
501 {
502  _x1 *= s;
503  _y1 *= s;
504  _x2 *= s;
505  _y2 *= s;
506 }
507 
508 Line *
509 Line::clone() const {
510  return new Line(*this);
511 }
512 
513 void
514 Line::flushPostscript( std::ostream & stream,
515  const TransformEPS & transform ) const
516 {
517  stream << "\n% Line\n";
518  stream << postscriptProperties() << " "
519  << "n "
520  << transform.mapX( _x1 ) << " "
521  << transform.mapY( _y1 ) << " "
522  << "m "
523  << transform.mapX( _x2 ) << " "
524  << transform.mapY( _y2 ) << " "
525  << "l " << _penColor.postscript() << " srgb stroke" << std::endl;
526 }
527 
528 void
529 Line::flushFIG( std::ostream & stream,
530  const TransformFIG & transform,
531  std::map<DGtal::Color,int> & colormap ) const
532 {
533  stream << "2 1 ";
534  // Line style
535  stream << _lineStyle << " ";
536  // Thickness
537  stream << ( _penColor.valid()?transform.mapWidth( _lineWidth ):0 ) << " ";
538  // Pen color
539  stream << colormap[ _penColor ] << " ";
540  // Fill color
541  stream << "0 ";
542  // Depth
543  stream << transform.mapDepth( _depth ) << " ";
544  // Pen style
545  stream << "-1 ";
546  // Area fill, style val, join style, cap style, radius, f_arrow, b_arrow
547  stream << "-1 " << (_lineStyle?"4.000 ":"0.000 ") << _lineJoin << " " << _lineCap << " -1 0 0 ";
548  // Number of points
549  stream << "2\n";
550  stream << " ";
551  stream << static_cast<int>( transform.mapX( _x1 ) ) << " "
552  << static_cast<int>( transform.mapY( _y1 ) ) << " "
553  << static_cast<int>( transform.mapX( _x2 ) ) << " "
554  << static_cast<int>( transform.mapY( _y2 ) ) << std::endl;
555 }
556 
557 void
558 Line::flushSVG( std::ostream & stream,
559  const TransformSVG & transform ) const
560 {
561  stream << "<line x1=\"" << transform.mapX( _x1 ) << "\""
562  << " y1=\"" << transform.mapY( _y1 ) << "\""
563  << " x2=\"" << transform.mapX( _x2 ) << "\""
564  << " y2=\"" << transform.mapY( _y2 ) << "\""
565  << svgProperties( transform )
566  << " />" << std::endl;
567 }
568 
569 #ifdef WITH_CAIRO
570 void
571 Line::flushCairo( cairo_t *cr,
572  const TransformCairo & transform ) const
573 {
574  cairo_save (cr);
575 
576  cairo_set_source_rgba (cr, _penColor.red()/255.0, _penColor.green()/255.0, _penColor.blue()/255.0, 1.);
577 
578  cairo_move_to (cr, transform.mapX( _x1 ), transform.mapY( _y1 ));
579  cairo_line_to (cr, transform.mapX( _x2 ), transform.mapY( _y2 ));
580 
581  cairo_set_line_width (cr, _lineWidth);
582  cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
583  cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
585 
586  cairo_stroke (cr);
587 
588  cairo_restore (cr);
589 }
590 #endif
591 
592 void
593 Line::flushTikZ( std::ostream & stream,
594  const TransformTikZ & transform ) const
595 {
596  stream << "\\path[" << tikzProperties(transform) << "] ("
597  << transform.mapX( _x1 ) << ',' << transform.mapY( _y1 )
598  << ") -- ("
599  << transform.mapX( _x2 ) << ',' << transform.mapY( _y2 )
600  << ");" << std::endl;
601 }
602 
603 Rect
605 {
606  Rect rect;
607  if ( _x1 > _x2 ) {
608  rect.width = _x1 - _x2;
609  rect.left = _x2;
610  } else {
611  rect.width = _x2 - _x1;
612  rect.left = _x1;
613  }
614  if ( _y1 > _y2 ) {
615  rect.top = _y1;
616  rect.height = _y1 - _y2;
617  } else {
618  rect.top = _y2;
619  rect.height = _y2 - _y1;
620  }
621  return rect;
622 }
623 
624 
625 
626 /*
627  * Image
628  */
629 
630 const std::string Image::_name("Image");
631 
632 const std::string &
633 Image::name() const
634 {
635  return _name;
636 }
637 
638 Image *
639 Image::clone() const {
640  return new Image(*this);
641 }
642 
643 void
644 Image::flushFIG( std::ostream & stream,
645  const TransformFIG & transform,
646  std::map<DGtal::Color,int> & colormap ) const
647 
648 {
649  stream << "2 5 ";
650  // Line style
651  stream << _lineStyle << " ";
652  // Thickness
653  stream << ( _penColor.valid()?transform.mapWidth( _lineWidth ):0 ) << " ";
654  // Pen color
655  stream << colormap[ _penColor ] << " ";
656  // Fill color
657  stream << "0 ";
658  // Depth
659  stream << transform.mapDepth( _depth ) << " "
660  << "-1 -1 0.000 0 0 -1 0 0 5" << std::endl <<" 0 "
661  << _filename << std::endl;
662  _path.flushFIG( stream, transform );
663  stream << std::endl;
664 }
665 
666 
667 
668 void
669 Image::flushSVG( std::ostream & stream,
670  const TransformSVG & transform ) const
671 {
672 
673  stream << "<image x=\"" << transform.mapX( _path[0].x ) << '"'
674  << " y=\"" << transform.mapY( _path[0].y ) << '"'
675  << " width=\"" << transform.scale( (_path[1] - _path[0]).norm() ) << '"'
676  << " height=\"" << transform.scale( (_path[0] - _path[3]).norm() ) << '"'
677  << " xlink:href=\""<< _filename << "\" >" << std::endl
678  << " <title>My image</title>"<<std::endl
679  << " </image>" << std::endl;
680 
681 
682 }
683 
684 #ifdef WITH_CAIRO
685 void
686 Image::flushCairo( cairo_t *cr,
687  const TransformCairo & transform ) const
688 {
689  int w, h;
690  cairo_surface_t *image;
691  cairo_save (cr);
692  std::string extension = _filename.substr(_filename.find_last_of(".") + 1);
693  ASSERT(extension=="png");
694  image = cairo_image_surface_create_from_png (_filename.c_str());
695  assert(cairo_surface_status (image) == CAIRO_STATUS_SUCCESS);
696  w = cairo_image_surface_get_width (image);
697  h = cairo_image_surface_get_height (image);
698 
699  // tr
700  cairo_translate (cr, transform.mapX( _path[0].x ), transform.mapY( _path[0].y ));
701  //cairo_scale (cr, transform.scale( _path[1].x - _path[0].x )/w, transform.scale( _path[0].y - _path[3].y )/h);
702  cairo_scale (cr, transform.scale( (_path[1] - _path[0]).norm() )/w, transform.scale( (_path[0] - _path[3]).norm() )/h);
703  // tr
704 
705  cairo_set_source_surface (cr, image, 0, 0);
706  cairo_paint_with_alpha(cr, _alpha);
707  cairo_surface_destroy (image);
708 
709  cairo_restore (cr);
710 }
711 #endif
712 
713 void
714 Image::flushTikZ( std::ostream & stream,
715  const TransformTikZ & transform ) const
716 
717 {
718  stream << "\\node [below right=0pt] at ("
719  << transform.mapX( _path[0].x ) << "pt,"
720  << transform.mapY( _path[0].y ) << "pt) {\\pgfimage["
721  << "width=" << transform.scale( (_path[1] - _path[0]).norm() ) << "pt,"
722  << "height=" << transform.scale( (_path[0] - _path[3]).norm() ) << "pt,"
723  << "]{" << _filename << "}};" << std::endl;
724 }
725 
726 /*
727  * Arrow
728  */
729 
730 const std::string Arrow::_name("Arrow");
731 
732 const std::string &
733 Arrow::name() const
734 {
735  return _name;
736 }
737 
738 Arrow
739 Arrow::rotated( double angle, const Point & rotCenter ) const
740 {
741  Arrow res(*this);
742  Point( _x1, _y1 ).rotate( angle, rotCenter ).get( res._x1, res._y1 );
743  Point( _x2, _y2 ).rotate( angle, rotCenter ).get( res._x2, res._y2 );
744  return res;
745 }
746 
747 Arrow
748 Arrow::rotated( double angle ) const
749 {
750  Arrow res(*this);
751  Point c = center();
752  Point( _x1, _y1 ).rotate( angle, c ).get( res._x1, res._y1 );
753  Point( _x2, _y2 ).rotate( angle, c ).get( res._x2, res._y2 );
754  return res;
755 }
756 
757 Arrow
758 Arrow::translated( double dx, double dy ) const
759 {
760  Arrow res(*this);
761  res._x1 += dx;
762  res._x2 += dx;
763  res._y1 += dy;
764  res._y2 += dy;
765  return res;
766 }
767 
768 Arrow
769 Arrow::scaled( double sx, double sy ) const
770 {
771  Arrow res(*this);
772  Point c = center();
773  res._x1 *= sx;
774  res._x2 *= sx;
775  res._y1 *= sy;
776  res._y2 *= sy;
777  Point delta = c - res.center();
778  return static_cast<Arrow &>( res.translate( delta.x, delta.y ) );
779 }
780 
781 Arrow
782 Arrow::scaled( double s ) const
783 {
784  return Arrow::scaled( s, s );
785 }
786 
787 Arrow *
788 Arrow::clone() const {
789  return new Arrow(*this);
790 }
791 
792 void
793 Arrow::flushPostscript( std::ostream & stream,
794  const TransformEPS & transform ) const
795 {
796  double dx = _x1 - _x2;
797  double dy = _y1 - _y2;
798  double norm = sqrt( dx*dx + dy*dy );
799  dx /= norm;
800  dy /= norm;
801  dx *= 10*_lineWidth;
802  dy *= 10*_lineWidth;
803 
804  // double back_x = 0.8 * dx + _x2;
805  // double back_y = 0.8 * dy + _y2;
806 
807  double ndx1 = dx*cos(0.3)-dy*sin(0.3);
808  double ndy1 = dx*sin(0.3)+dy*cos(0.3);
809  double ndx2 = dx*cos(-0.3)-dy*sin(-0.3);
810  double ndy2 = dx*sin(-0.3)+dy*cos(-0.3);
811 
812  stream << "\n% Arrow\n";
813  stream << _penColor.postscript() << " srgb "
814  << postscriptProperties() << " "
815  << "n "
816  << transform.mapX( _x1 ) << " "
817  << transform.mapY( _y1 ) << " "
818  << "m "
819  << transform.mapX( _x2 + ( dx * cos(0.3) ) ) << " "
820  << transform.mapY( _y2 + ( dy * cos(0.3) ) ) << " "
821  << "l stroke" << std::endl;
822 
823  if ( filled() ) {
824  stream << "n "
825  << transform.mapX( _x2 ) + transform.scale( ndx1 ) << " "
826  << transform.mapY( _y2 ) + transform.scale( ndy1 ) << " "
827  << "m "
828  << transform.mapX( _x2 ) << " "
829  << transform.mapY( _y2 ) << " l "
830  << transform.mapX( _x2 ) + transform.scale( ndx2 ) << " "
831  << transform.mapY( _y2 ) + transform.scale( ndy2 ) << " ";
832  stream << "l cp " << _penColor.postscript() << " srgb fill" << std::endl;
833  }
834 
835  stream << "n "
836  << transform.mapX( _x2 ) + transform.scale( ndx1 ) << " "
837  << transform.mapY( _y2 ) + transform.scale( ndy1 ) << " "
838  << "m "
839  << transform.mapX( _x2 ) << " "
840  << transform.mapY( _y2 ) << " l "
841  << transform.mapX( _x2 ) + transform.scale( ndx2 ) << " "
842  << transform.mapY( _y2 ) + transform.scale( ndy2 ) << " l"
843  << " " << _penColor.postscript() << " srgb cp [] 0 sd stroke" << std::endl;
844 }
845 
846 void
847 Arrow::flushFIG( std::ostream & stream,
848  const TransformFIG & transform,
849  std::map<DGtal::Color,int> & colormap ) const
850 {
851  stream << "2 1 ";
852  // Line style
853  stream << _lineStyle << " ";
854  // Thickness
855  stream << ( _penColor.valid()?transform.mapWidth( _lineWidth ):0 ) << " ";
856  // Pen color
857  stream << colormap[ _penColor ] << " ";
858  // Fill color
859  stream << colormap[ _penColor ] << " ";
860  // Depth
861  stream << transform.mapDepth( _depth ) << " ";
862  // Pen style
863  stream << "-1 ";
864  // Area fill, style val, join style, cap style, radius, f_arrow, b_arrow
865  stream << "-1 " << (_lineStyle?"4.000 ":"0.000 ") << _lineJoin << " " << _lineCap << " -1 1 0 ";
866  // Number of points
867  stream << "2\n";
868  if ( filled() )
869  stream << " 1 1 1.00 60.00 120.00\n";
870  else
871  stream << " 1 0 1.00 60.00 120.00\n";
872  stream << " ";
873  stream << static_cast<int>( transform.mapX( _x1 ) ) << " "
874  << static_cast<int>( transform.mapY( _y1 ) ) << " "
875  << static_cast<int>( transform.mapX( _x2 ) ) << " "
876  << static_cast<int>( transform.mapY( _y2 ) ) << std::endl;
877 }
878 
879 void
880 Arrow::flushSVG( std::ostream & stream,
881  const TransformSVG & transform ) const
882 {
883  double dx = _x1 - _x2;
884  double dy = _y1 - _y2;
885  double norm = sqrt( dx*dx + dy*dy );
886  dx /= norm;
887  dy /= norm;
888  dx *= 10 * _lineWidth;
889  dy *= 10 * _lineWidth;
890 
891  // double back_x = 0.8 * dx + _x2;
892  // double back_y = 0.8 * dy + _y2;
893 
894  double ndx1 = dx*cos(0.3)-dy*sin(0.3);
895  double ndy1 = dx*sin(0.3)+dy*cos(0.3);
896  double ndx2 = dx*cos(-0.3)-dy*sin(-0.3);
897  double ndy2 = dx*sin(-0.3)+dy*cos(-0.3);
898 
899  stream << "<g>" << std::endl;
900  // The line
901  stream << " <path "
902  << "d=\"M " << transform.mapX( _x1 ) << " " << transform.mapY( _y1 )
903  << " L " << transform.mapX( _x2 + ( dx * cos(0.3) ) )
904  << " " << transform.mapY( _y2 + ( dy * cos(0.3) ) ) << " z\""
905  << " fill=\"none\" stroke=\"" << _penColor.svg() << "\""
906  << _penColor.svgAlpha( " stroke" );
907  if ( _lineStyle != SolidStyle )
908  stream << " style=\"" << xFigDashStylesSVG[ _lineStyle ] << '"';
909  stream << " stroke-width=\"" << transform.mapWidth( _lineWidth ) << "mm\" />";
910 
911  // The arrow
912  stream << " <polygon";
913  stream << " fill=\"" << _fillColor.svg() << "\"";
914  stream << " stroke=\"" << _penColor.svg() << "\""
915  << " stroke-width=\"" << transform.mapWidth( /* 0.33 * */ _lineWidth ) << "mm\""
916  << " style=\"stroke-linecap:butt;stroke-linejoin:miter\""
917  << _fillColor.svgAlpha( " fill" )
918  << _penColor.svgAlpha( " stroke" )
919  << " points=\""
920  << transform.mapX( _x2 ) + transform.scale( ndx1 ) << ","
921  << transform.mapY( _y2 ) - transform.scale( ndy1 ) << " "
922  << transform.mapX( _x2 ) << ","
923  << transform.mapY( _y2 ) << " "
924  << transform.mapX( _x2 ) + transform.scale( ndx2 ) << ","
925  << transform.mapY( _y2 ) - transform.scale( ndy2 ) << " "
926  << transform.mapX( _x2 ) + transform.scale( ndx1 ) << ","
927  << transform.mapY( _y2 ) - transform.scale( ndy1 ) << "\" />" << std::endl;
928  stream << "</g>" << std::endl;
929 }
930 
931 #ifdef WITH_CAIRO
932 void
933 Arrow::flushCairo( cairo_t *cr,
934  const TransformCairo & transform ) const
935 {
936  double dx = _x1 - _x2;
937  double dy = _y1 - _y2;
938  double norm = sqrt( dx*dx + dy*dy );
939  dx /= norm;
940  dy /= norm;
941  dx *= 10 * _lineWidth;
942  dy *= 10 * _lineWidth;
943 
944  // double back_x = 0.8 * dx + _x2;
945  // double back_y = 0.8 * dy + _y2;
946 
947  double ndx1 = dx*cos(0.3)-dy*sin(0.3);
948  double ndy1 = dx*sin(0.3)+dy*cos(0.3);
949  double ndx2 = dx*cos(-0.3)-dy*sin(-0.3);
950  double ndy2 = dx*sin(-0.3)+dy*cos(-0.3);
951 
952  cairo_save (cr);
953 
954  // The line
955  cairo_set_source_rgba (cr, _penColor.red()/255.0, _penColor.green()/255.0, _penColor.blue()/255.0, 1.);
956 
957  cairo_move_to (cr, transform.mapX( _x1 ), transform.mapY( _y1 ));
958  cairo_line_to (cr, transform.mapX( _x2 + ( dx * cos(0.3) ) ), transform.mapY( _y2 + ( dy * cos(0.3) ) ));
959 
960  cairo_set_line_width (cr, _lineWidth);
961  cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
962  cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
964 
965  cairo_stroke (cr);
966 
967  // The arrow
968  cairo_set_source_rgba (cr, _fillColor.red()/255.0, _fillColor.green()/255.0, _fillColor.blue()/255.0, 1.);
969 
970  cairo_move_to (cr, transform.mapX( _x2 ) + transform.scale( ndx1 ), transform.mapY( _y2 ) - transform.scale( ndy1 ));
971  cairo_line_to (cr, transform.mapX( _x2 ), transform.mapY( _y2 ));
972  cairo_line_to (cr, transform.mapX( _x2 ) + transform.scale( ndx2 ), transform.mapY( _y2 ) - transform.scale( ndy2 ));
973  cairo_close_path (cr);
974 
975  if ( filled() )
976  {
977  if ( _penColor != DGtal::Color::None )
978  cairo_fill_preserve (cr);
979  else
980  cairo_fill (cr);
981  }
982 
983  //
984 
985  if ( _penColor != DGtal::Color::None )
986  {
987  cairo_set_source_rgba (cr, _penColor.red()/255.0, _penColor.green()/255.0, _penColor.blue()/255.0, 1.);
988 
989  cairo_set_line_width (cr, _lineWidth);
990  cairo_set_line_cap (cr, cairoLineCap[ButtCap]);
991  cairo_set_line_join (cr, cairoLineJoin[MiterJoin]);
993 
994  cairo_stroke (cr);
995  }
996 
997  cairo_restore (cr);
998 }
999 #endif
1000 
1001 void
1002 Arrow::flushTikZ( std::ostream & stream,
1003  const TransformTikZ & transform ) const
1004 {
1005  //stream << "\\path[-triangle 45," << tikzProperties(transform) << "] (" // Requires \usetikzlibrary{arrows}
1006  stream << "\\path[-latex," << tikzProperties(transform) << "] ("
1007  << transform.mapX( _x1 ) << ',' << transform.mapY( _y1 )
1008  << ") -- ("
1009  << transform.mapX( _x2 ) << ',' << transform.mapY( _y2 )
1010  << ");" << std::endl;
1011 }
1012 
1013 /*
1014  * Ellipse
1015  */
1016 
1017 const std::string Ellipse::_name("Ellipse");
1018 
1019 const std::string &
1021 {
1022  return _name;
1023 }
1024 
1025 Point
1027  return _center;
1028 }
1029 
1030 Ellipse &
1031 Ellipse::rotate( double angle, const Point & rotCenter )
1032 {
1033  Point c( _center );
1034  Point e = (c + Point( _xRadius, 0 )).rotate( _angle, c );
1035  Point rc = c.rotated( angle, rotCenter );
1036  Point re = e.rotated( angle, rotCenter );
1037  Point axis = re - rc;
1038  _angle = atan( axis.y / axis.x );
1039  _center = rc;
1040  return *this;
1041 }
1042 
1043 Ellipse
1044 Ellipse::rotated( double angle, const Point & rotCenter ) const
1045 {
1046  return Ellipse(*this).rotate( angle, rotCenter );
1047 }
1048 
1049 Ellipse &
1050 Ellipse::rotate( double angle )
1051 {
1052  return Ellipse::rotate( angle, center() );
1053 }
1054 
1055 Ellipse
1056 Ellipse::rotated( double angle ) const
1057 {
1058  return Ellipse(*this).rotate( angle, center() );
1059 }
1060 
1061 Ellipse &
1062 Ellipse::translate( double dx, double dy )
1063 {
1064  _center += Point( dx, dy );
1065  return *this;
1066 }
1067 
1068 Ellipse
1069 Ellipse::translated( double dx, double dy ) const
1070 {
1071  return Ellipse(*this).translate( dx, dy );
1072 }
1073 
1074 Shape &
1075 Ellipse::scale( double sx, double sy )
1076 {
1077  // Thanks to Freddie Exall for pointing an error with the first version
1078  // of this function, and for pointing to a fix as well!
1079  if ( _angle != 0 ) {
1080  double co = cos( _angle );
1081  double si = sin( _angle );
1082 
1083  // current transformation matrix
1084  double m00 = ( 1 / _xRadius ) * co;
1085  double m01 = ( 1 / _xRadius ) * si;
1086  double m10 = - ( 1 / _yRadius ) * si;
1087  double m11 = ( 1 / _yRadius ) * co;
1088 
1089  // Implicit function of ellipse at current
1090  // ax^2 + bxy + cy^2 = 1
1091  double a = ( m00 * m00 ) + ( m10 * m10 );
1092  double b = 2 * ( ( m00 * m01 ) + ( m10 * m11 ) );
1093  double c = ( m01 * m01 ) + ( m11 * m11 );
1094 
1095  // Scale coefficients ( x_new = sx * x, y_new = sy * y )
1096  a = a / ( sx * sx );
1097  b = b / ( sx * sy );
1098  c = c / ( sy * sy );
1099 
1100  if ( b == 0 ) {
1101  _angle = 0;
1102  } else if ( a == c ) {
1103  _angle = M_PI / 4;
1104  a += ( b / 2 );
1105  c -= ( b / 2 );
1106  } else {
1107  _angle = 0.5 * atan( b / ( a - c ) );
1108  double k = 1 + ( ( b * b ) / ( ( a - c ) * ( a - c ) ) );
1109  k = sqrt( k );
1110  k *= ( a - c );
1111  c += a;
1112  a = 0.5 * ( c + k );
1113  c = 0.5 * ( c - k );
1114  }
1115  _xRadius = 1 / sqrt( a );
1116  _yRadius = 1 / sqrt( c );
1117  } else {
1118  _xRadius = _xRadius * sx;
1119  _yRadius = _yRadius * sy;
1120  }
1121  return *this;
1122 }
1123 
1124 Shape &
1125 Ellipse::scale( double s )
1126 {
1127  return Ellipse::scale( s, s );
1128 }
1129 
1130 Ellipse
1131 Ellipse::scaled( double sx, double sy ) const
1132 {
1133  return static_cast<Ellipse &>( Ellipse(*this).scale( sx, sy ) );
1134 }
1135 
1136 Ellipse
1137 Ellipse::scaled( double s ) const
1138 {
1139  return static_cast<Ellipse &>( Ellipse(*this).scale( s, s ) );
1140 }
1141 
1142 void
1144 {
1145  _xRadius *= s;
1146  _yRadius *= s;
1147  _center *= s;
1148 }
1149 
1150 Ellipse *
1152  return new Ellipse(*this);
1153 }
1154 
1155 void
1156 Ellipse::flushPostscript( std::ostream & stream,
1157  const TransformEPS & transform ) const
1158 {
1159  double yScale = _yRadius / _xRadius;
1160  stream << "\n% Ellipse\n";
1161  if ( filled() ) {
1162  stream << "gs "
1163  << transform.mapX( _center.x ) << " " << transform.mapY( _center.y ) << " tr";
1164  if ( _angle != 0.0 ) stream << " " << (_angle*180/M_PI) << " rot ";
1165  if ( ! _circle ) stream << " " << 1.0 << " " << yScale << " sc";
1166  stream << " n " << transform.scale( _xRadius ) << " 0 m "
1167  << " 0 0 " << transform.scale( _xRadius ) << " 0.0 360.0 arc ";
1168  stream << " " << _fillColor.postscript() << " srgb";
1169  stream << " fill gr" << std::endl;
1170  }
1171 
1172  if ( _penColor != DGtal::Color::None ) {
1173  stream << postscriptProperties() << "\n";
1174  stream << "gs " << transform.mapX( _center.x ) << " " << transform.mapY( _center.y ) << " tr";
1175  if ( _angle != 0.0 ) stream << " " << (_angle*180/M_PI) << " rot ";
1176  if ( ! _circle ) stream << " " << 1.0 << " " << yScale << " sc";
1177  stream << " n " << transform.scale( _xRadius ) << " 0 m "
1178  << " 0 0 " << transform.scale( _xRadius ) << " 0.0 360.0 arc ";
1179  stream << " " << _penColor.postscript() << " srgb";
1180  stream << " stroke gr" << std::endl;
1181  }
1182 }
1183 
1184 void
1185 Ellipse::flushFIG( std::ostream & stream,
1186  const TransformFIG & transform,
1187  std::map<DGtal::Color,int> & colormap ) const
1188 {
1189  // Ellipse, Sub type, Line style, Thickness
1190  if ( _circle )
1191  stream << "1 3 " << _lineStyle << " ";
1192  else
1193  stream << "1 1 " << _lineStyle << " ";
1194  stream << ( _penColor.valid()?transform.mapWidth( _lineWidth ):0 ) << " ";
1195  // Pen color, Fill color
1196  stream << colormap[ _penColor ] << " " << colormap[ _fillColor ] << " ";
1197  // Depth, Pen style, Area fill, Style val, Direction, angle
1198  if ( filled() )
1199  stream << transform.mapDepth( _depth ) << " -1 20 " << (_lineStyle?"4.000 ":"0.000 ") << " 1 " << _angle << " ";
1200  else
1201  stream << transform.mapDepth( _depth ) << " -1 -1 " << (_lineStyle?"4.000 ":"0.000 ") << " 1 " << _angle << " ";
1202  stream << static_cast<int>( transform.mapX( _center.x ) ) << " "
1203  << static_cast<int>( transform.mapY( _center.y ) ) << " "
1204  << static_cast<int>( transform.scale( _xRadius ) ) << " "
1205  << static_cast<int>( transform.scale( _yRadius ) ) << " "
1206  << static_cast<int>( transform.mapX( _center.x ) ) << " "
1207  << static_cast<int>( transform.mapY( _center.y ) ) << " "
1208  << static_cast<int>( transform.mapX( _center.x ) + transform.scale( _xRadius ) ) << " "
1209  << static_cast<int>( transform.mapY( _center.y ) ) << "\n";
1210 }
1211 
1212 void
1213 Ellipse::flushSVG( std::ostream & stream,
1214  const TransformSVG & transform ) const
1215 {
1216  stream << "<ellipse cx=\"" << transform.mapX( _center.x ) << '"'
1217  << " cy=\"" << transform.mapY( _center.y ) << '"'
1218  << " rx=\"" << transform.scale( _xRadius ) << '"'
1219  << " ry=\"" << transform.scale( _yRadius ) << '"'
1220  << svgProperties( transform ) ;
1221  if ( _angle != 0.0 ) {
1222  stream << " transform=\"rotate( "
1223  << -(_angle*180/M_PI) << ", "
1224  << transform.mapX( _center.x ) << ", "
1225  << transform.mapY( _center.y ) << " )\" ";
1226  }
1227  stream << " />" << std::endl;
1228 }
1229 
1230 #ifdef WITH_CAIRO
1231 void
1232 Ellipse::flushCairo( cairo_t *cr,
1233  const TransformCairo & transform ) const
1234 {
1235  cairo_save (cr);
1236 
1237  cairo_set_source_rgba (cr, _fillColor.red()/255.0, _fillColor.green()/255.0, _fillColor.blue()/255.0, 1.);
1238 
1239  // tr
1240  cairo_translate (cr, transform.mapX( _center.x ), transform.mapY( _center.y ));
1241  if ( _angle != 0.0 )
1242  cairo_rotate (cr, _angle);
1243  cairo_scale (cr, transform.scale( _xRadius ), transform.scale( _yRadius ));
1244  // tr
1245 
1246  cairo_arc (cr, 0, 0, 1, 0, 2*M_PI);
1247 
1248  if ( filled() )
1249  {
1250  if ( _penColor != DGtal::Color::None )
1251  cairo_fill_preserve (cr);
1252  else
1253  cairo_fill (cr);
1254  }
1255 
1256  //
1257 
1258  if ( _penColor != DGtal::Color::None )
1259  {
1260  cairo_set_source_rgba (cr, _penColor.red()/255.0, _penColor.green()/255.0, _penColor.blue()/255.0, 1.);
1261 
1262  cairo_set_line_width (cr, _lineWidth);
1263  cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
1264  cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
1266 
1267  cairo_stroke (cr);
1268  }
1269 
1270  cairo_restore (cr);
1271 }
1272 #endif
1273 
1274 void
1275 Ellipse::flushTikZ( std::ostream & stream,
1276  const TransformTikZ & transform ) const
1277 {
1278  // FIXME: unimplemented
1279  stream << "% FIXME: Ellipse::flushTikZ unimplemented" << std::endl;
1280  stream << "\\path[" << tikzProperties(transform) << "] ("
1281  << transform.mapX( _center.x ) << ','
1282  << transform.mapY( _center.y ) << ')'
1283  << " circle [x radius=" << transform.scale( _xRadius ) << ','
1284  << "y radius=" << transform.scale( _yRadius ) << ','
1285  << "rotate=" << -(_angle*180/M_PI)
1286  << "];"
1287  << std::endl;
1288 }
1289 
1290 Rect
1292 {
1293  if ( _angle == 0.0 )
1294  return Rect( _center.x - _xRadius, _center.y + _yRadius,
1295  2 * _xRadius, 2 * _yRadius );
1296 
1297  double angleXmax = -atan( (_yRadius/_xRadius)*(tan(_angle) ) );
1298  double angleXmin = -atan( (_yRadius/_xRadius)*(tan(_angle) ) ) + M_PI;
1299  double angleYmax = atan( (_yRadius/_xRadius)*(1/tan(_angle) ) );
1300  double angleYmin = M_PI + atan( (_yRadius/_xRadius)*(1/tan(_angle) ) );
1301 
1302  if ( _angle < 0.0 ) {
1303  angleYmax += M_PI;
1304  angleYmin -= M_PI;
1305  }
1306 
1307  return Rect( _center.x + _xRadius*cos(angleXmin)*cos(_angle) - _yRadius*sin(angleXmin)*sin(_angle),
1308  _center.y + _xRadius*cos(angleYmax)*sin(_angle) + _yRadius*sin(angleYmax)*cos(_angle),
1309  ( _xRadius*cos(angleXmax)*cos(_angle) - _yRadius*sin(angleXmax)*sin(_angle) ) -
1310  ( _xRadius*cos(angleXmin)*cos(_angle) - _yRadius*sin(angleXmin)*sin(_angle) ),
1311  ( _xRadius*cos(angleYmax)*sin(_angle) + _yRadius*sin(angleYmax)*cos(_angle) ) -
1312  ( _xRadius*cos(angleYmin)*sin(_angle) + _yRadius*sin(angleYmin)*cos(_angle) ) );
1313 }
1314 
1315 /*
1316  * Circle
1317  */
1318 
1319 const std::string Circle::_name("Circle");
1320 
1321 const std::string &
1323 {
1324  return _name;
1325 }
1326 
1327 Point
1329  return _center;
1330 }
1331 
1332 Circle &
1333 Circle::rotate( double angle, const Point & rotCenter )
1334 {
1335  if ( _circle ) {
1336  if ( rotCenter == _center ) return *this;
1337  _center.rotate( angle, rotCenter );
1338  return *this;
1339  }
1340  Ellipse::rotate( angle, rotCenter );
1341  return *this;
1342 }
1343 
1344 Circle
1345 Circle::rotated( double angle, const Point & rotCenter ) const
1346 {
1347  return Circle(*this).rotate( angle, rotCenter );
1348 }
1349 
1350 Circle &
1351 Circle::rotate( double angle )
1352 {
1353  if ( !_circle )
1354  Ellipse::rotate( angle );
1355  return *this;
1356 }
1357 
1358 Circle
1359 Circle::rotated( double angle ) const
1360 {
1361  return Circle(*this).rotate( angle );
1362 }
1363 
1364 Circle &
1365 Circle::translate( double dx, double dy )
1366 {
1367  _center += Point( dx, dy );
1368  return *this;
1369 }
1370 
1371 Circle
1372 Circle::translated( double dx, double dy ) const
1373 {
1374  return Circle(*this).translate( dx, dy );
1375 }
1376 
1377 Shape &
1378 Circle::scale( double sx, double sy )
1379 {
1380  return Ellipse::scale( sx, sy );
1381 }
1382 
1383 Shape &
1384 Circle::scale( double s )
1385 {
1386  return Ellipse::scale( s );
1387 }
1388 
1389 Circle
1390 Circle::scaled( double sx, double sy ) const
1391 {
1392  return static_cast<Circle &>( Circle(*this).scale( sx, sy ) );
1393 }
1394 
1395 Circle
1396 Circle::scaled( double s ) const
1397 {
1398  return static_cast<Circle &>( Circle(*this).scale( s, s ) );
1399 }
1400 
1401 void
1402 Circle::scaleAll( double s )
1403 {
1404  _center *= s;
1405  _xRadius *= s;
1406  _yRadius *= s;
1407 }
1408 
1409 Circle *
1410 Circle::clone() const {
1411  return new Circle(*this);
1412 }
1413 
1414 void
1415 Circle::flushSVG( std::ostream & stream,
1416  const TransformSVG & transform ) const
1417 {
1418  if ( ! _circle )
1419  Ellipse::flushSVG( stream, transform );
1420  else {
1421  stream << "<circle cx=\"" << transform.mapX( _center.x ) << '"'
1422  << " cy=\"" << transform.mapY( _center.y ) << '"'
1423  << " r=\"" << transform.scale( _xRadius ) << '"'
1424  << svgProperties( transform )
1425  << " />" << std::endl;
1426  }
1427 }
1428 
1429 #ifdef WITH_CAIRO
1430 void
1431 Circle::flushCairo( cairo_t *cr,
1432  const TransformCairo & transform ) const
1433 {
1434  if ( ! _circle )
1435  Ellipse::flushCairo( cr, transform );
1436  else
1437  {
1438  cairo_save (cr);
1439 
1440  cairo_set_source_rgba (cr, _fillColor.red()/255.0, _fillColor.green()/255.0, _fillColor.blue()/255.0, 1.);
1441 
1442  cairo_arc (cr, transform.mapX( _center.x ), transform.mapY( _center.y ), transform.scale( _xRadius ), 0, 2*M_PI);
1443 
1444  if ( filled() )
1445  {
1446  if ( _penColor != DGtal::Color::None )
1447  cairo_fill_preserve (cr);
1448  else
1449  cairo_fill (cr);
1450  }
1451 
1452  //
1453 
1454  if ( _penColor != DGtal::Color::None )
1455  {
1456  cairo_set_source_rgba (cr, _penColor.red()/255.0, _penColor.green()/255.0, _penColor.blue()/255.0, 1.);
1457 
1458  cairo_set_line_width (cr, _lineWidth);
1459  cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
1460  cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
1462 
1463  cairo_stroke (cr);
1464  }
1465 
1466  cairo_restore (cr);
1467  }
1468 }
1469 #endif
1470 
1471 void
1472 Circle::flushTikZ( std::ostream & stream,
1473  const TransformTikZ & transform ) const
1474 {
1475  if ( ! _circle )
1476  Ellipse::flushTikZ( stream, transform );
1477  else {
1478  stream << "\\path[" << tikzProperties(transform) << "] ("
1479  << transform.mapX( _center.x ) << ','
1480  << transform.mapY( _center.y ) << ')'
1481  << " circle (" << transform.scale( _xRadius ) << ");"
1482  << std::endl;
1483  }
1484 }
1485 
1486 /*
1487  * Arc
1488  */
1489 
1490 const std::string Arc::_name("Arc");
1491 
1492 const std::string &
1493 Arc::name() const
1494 {
1495  return _name;
1496 }
1497 
1498 #ifdef WITH_CAIRO
1499 void
1500 Arc::flushCairo( cairo_t *cr,
1501  const TransformCairo & transform ) const
1502 {
1503  cairo_save (cr);
1504 
1505  cairo_set_source_rgba (cr, _fillColor.red()/255.0, _fillColor.green()/255.0, _fillColor.blue()/255.0, 1.);
1506 
1507  if (_negative) // important: here for Cairo we must inverse 'cairo_arc' and 'cairo_arc_negative' and change alpha with 2.*M_PI-alpha
1508  cairo_arc (cr, transform.mapX( _center.x ), transform.mapY( _center.y ), transform.scale( _xRadius ), 2.*M_PI-_angle1, 2.*M_PI-_angle2);
1509  else
1510  cairo_arc_negative (cr, transform.mapX( _center.x ), transform.mapY( _center.y ), transform.scale( _xRadius ), 2.*M_PI-_angle1, 2.*M_PI-_angle2);
1511 
1512  if ( filled() )
1513  {
1514  if ( _penColor != DGtal::Color::None )
1515  cairo_fill_preserve (cr);
1516  else
1517  cairo_fill (cr);
1518  }
1519 
1520  //
1521 
1522  if ( _penColor != DGtal::Color::None )
1523  {
1524  cairo_set_source_rgba (cr, _penColor.red()/255.0, _penColor.green()/255.0, _penColor.blue()/255.0, 1.);
1525 
1526  cairo_set_line_width (cr, _lineWidth);
1527  cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
1528  cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
1530 
1531  cairo_stroke (cr);
1532  }
1533 
1534  cairo_restore (cr);
1535 }
1536 #endif
1537 
1538 void
1539 Arc::flushPostscript( std::ostream & stream,
1540  const TransformEPS & transform ) const
1541 {
1542 
1543 //The arc is generated by sweeping a line segment of length r, and tied at the point (x-coord y-coord), in a counter-clockwise direction from an angle _angle1 to an angle _angle2.
1544 //Thus, we have to swap _angle1 and _angle2 according to bool _negative
1545  double a1, a2;
1546  if (_negative == true)
1547  {
1548  a1 = _angle2;
1549  a2 = _angle1;
1550  }
1551  else
1552  {
1553  a1 = _angle1;
1554  a2 = _angle2;
1555  }
1556 
1557  stream << "\n% Arc\n";
1558  if ( filled() ) {
1559  stream << "gs "
1560  << transform.mapX( _center.x ) << " " << transform.mapY( _center.y ) << " "
1561  << transform.scale( _xRadius )<< " " << (a1*180/M_PI) << " "
1562  << (a2*180/M_PI) << " "<< "arc ";
1563  stream << " " << _fillColor.postscript() << " srgb";
1564  stream << " fill gr" << std::endl;
1565  }
1566 
1567  if ( _penColor != DGtal::Color::None ) {
1568 
1569  stream << "gs "
1570  << transform.mapX( _center.x ) << " " << transform.mapY( _center.y ) << " "
1571  << transform.scale( _xRadius )<< " " << (a1*180/M_PI) << " "
1572  << (a2*180/M_PI) << " "<< "arc ";
1573  _penColor.flushPostscript( stream );
1574  stream << " stroke gr" << std::endl;
1575  }
1576 }
1577 
1578 void
1579 Arc::flushSVG( std::ostream & stream,
1580  const TransformSVG & transform ) const
1581 {
1582 
1583 double fx = _center.x + _xRadius*std::cos(_angle1);
1584 double fy = _center.y + _xRadius*std::sin(_angle1);
1585 double lx = _center.x + _xRadius*std::cos(_angle2);
1586 double ly = _center.y + _xRadius*std::sin(_angle2);
1587 
1588 stream << "<path ";
1589 stream << svgProperties( transform ) << " ";
1590 //first point
1591 stream << "d='M " << transform.mapX( fx );
1592 stream << "," << transform.mapY( fy );
1593 //arc
1594 stream << " A " << transform.scale( _xRadius ) << " " << transform.scale( _xRadius );
1595 //something
1596 stream << " 0";
1597 //orientation and center position
1598 if (_negative)
1599 {
1600  if ( (std::cos(_angle1)*std::sin(_angle2) - std::sin(_angle1)*std::cos(_angle2))<0 )
1601  {
1602  stream << " 0 1";
1603  } else
1604  {
1605  stream << " 1 1";
1606  }
1607 } else
1608 {
1609  if ( (std::cos(_angle1)*std::sin(_angle2) - std::sin(_angle1)*std::cos(_angle2))<0 )
1610  {
1611  stream << " 1 0";
1612  } else
1613  {
1614  stream << " 0 0";
1615  }
1616 }
1617 //last point
1618 stream << " " << transform.mapX( lx );
1619 stream << "," << transform.mapY( ly );
1620 stream << "' />";
1621 
1622 }
1623 
1624 void
1625 Arc::flushTikZ( std::ostream & stream,
1626  const TransformTikZ & transform ) const
1627 {
1628  stream << "\\path[" << tikzProperties(transform) << "] ("
1629  << transform.mapX( _center.x ) << ',' << transform.mapY( _center.y ) << ')' // center
1630  << " +(" << -_angle1/M_PI*180. << ':' << transform.scale( _xRadius) << ')' // first point of arc
1631  << " arc (" << -_angle1/M_PI*180. << ':' << -_angle2/M_PI*180. + _negative * 360. << ':' << transform.scale( _xRadius ) << ");"
1632  << std::endl;
1633 }
1634 
1635 /*
1636  * Polyline
1637  */
1638 
1639 const std::string Polyline::_name("Polyline");
1640 
1641 const std::string &
1643 {
1644  return _name;
1645 }
1646 
1648 Polyline::operator<<( const Point & p )
1649 {
1650  _path << p;
1651  return *this;
1652 }
1653 
1654 Point
1656  return _path.center();
1657 }
1658 
1659 Polyline &
1660 Polyline::rotate( double angle, const Point & rotCenter )
1661 {
1662  _path.rotate( angle, rotCenter );
1663  return *this;
1664 }
1665 
1666 Polyline
1667 Polyline::rotated( double angle, const Point & rotCenter ) const
1668 {
1669  return Polyline(*this).rotate( angle, rotCenter );
1670 }
1671 
1672 Polyline &
1673 Polyline::rotate( double angle )
1674 {
1675  _path.rotate( angle, center() );
1676  return *this;
1677 }
1678 
1679 Polyline
1680 Polyline::rotated( double angle ) const
1681 {
1682  return Polyline(*this).rotate( angle, center() );
1683 }
1684 
1685 Polyline &
1686 Polyline::translate( double dx, double dy )
1687 {
1688  _path.translate( dx, dy );
1689  return *this;
1690 }
1691 
1692 Polyline
1693 Polyline::translated( double dx, double dy ) const
1694 {
1695  return Polyline(*this).translate( dx, dy );
1696 }
1697 
1698 Shape &
1699 Polyline::scale( double sx, double sy )
1700 {
1701  _path.scale( sx, sy );
1702  return *this;
1703 }
1704 
1705 Shape &
1706 Polyline::scale( double s )
1707 {
1708  Polyline::scale( s, s );
1709  return *this;
1710 }
1711 
1712 Polyline
1713 Polyline::scaled( double sx, double sy ) const
1714 {
1715  return static_cast<Polyline &>( Polyline(*this).scale( sx, sy ) );
1716 }
1717 
1718 Polyline
1719 Polyline::scaled( double s) const
1720 {
1721  return static_cast<Polyline &>( Polyline(*this).scale( s, s ) );
1722 }
1723 
1724 void
1726 {
1727  _path.scaleAll( s );
1728 }
1729 
1730 Polyline *
1732  return new Polyline(*this);
1733 }
1734 
1735 void
1736 Polyline::flushPostscript( std::ostream & stream,
1737  const TransformEPS & transform ) const
1738 {
1739  if ( _path.empty() ) return;
1740  stream << "\n% Polyline\n";
1741  if ( filled() ) {
1742  stream << "n ";
1743  _path.flushPostscript( stream, transform );
1744  stream << " ";
1745  _fillColor.flushPostscript( stream );
1746  stream << " " << postscriptProperties();
1747  stream << " fill" << std::endl;
1748  }
1749  if ( _penColor != DGtal::Color::None ) {
1750  stream << " " << postscriptProperties() << "\n";
1751  stream << "n ";
1752  _path.flushPostscript( stream, transform );
1753  stream << " ";
1754  _penColor.flushPostscript( stream );
1755  stream << " stroke" << std::endl;
1756  }
1757 }
1758 
1759 void
1760 Polyline::flushFIG( std::ostream & stream,
1761  const TransformFIG & transform,
1762  std::map<DGtal::Color,int> & colormap ) const
1763 {
1764  if ( _path.empty() )
1765  return;
1766  if ( _path.closed() )
1767  stream << "2 3 " << _lineStyle << " ";
1768  else
1769  stream << "2 1 " << _lineStyle << " ";
1770  // Thickness
1771  stream << ( _penColor.valid()?transform.mapWidth( _lineWidth ):0 ) << " ";
1772  // Pen color
1773  stream << colormap[ _penColor ] << " ";
1774  // Fill color
1775  stream << colormap[ _fillColor ] << " ";
1776  // Depth
1777  stream << transform.mapDepth( _depth ) << " ";
1778  // Pen style
1779  stream << "-1 ";
1780  // Area fill, style val, join style, cap style, radius, f_arrow, b_arrow
1781  if ( filled() )
1782  stream << "20 " << (_lineStyle?"4.000 ":"0.000 ") << _lineJoin << " " << _lineCap << " -1 0 0 ";
1783  else
1784  stream << "-1 " << (_lineStyle?"4.000 ":"0.000 ") << _lineJoin << " " << _lineCap << " -1 0 0 ";
1785  // Number of points
1786  stream << _path.size() + _path.closed() << std::endl;
1787  _path.flushFIG( stream << " ", transform );
1788  stream << std::endl;
1789 }
1790 
1791 void
1792 Polyline::flushSVG( std::ostream & stream,
1793  const TransformSVG & transform ) const
1794 {
1795  if ( _path.empty() )
1796  return;
1797  if ( _path.closed() )
1798  stream << "<polygon";
1799  else
1800  stream << "<polyline";
1801  stream << svgProperties( transform ) << std::endl;
1802  stream << " points=\"";
1803  _path.flushSVGPoints( stream, transform );
1804  stream << "\" />" << std::endl;
1805 }
1806 
1807 #ifdef WITH_CAIRO
1808 void
1810  const TransformCairo & transform ) const
1811 {
1812  if ( _path.empty() )
1813  return;
1814 
1815  cairo_save (cr);
1816 
1817  cairo_set_source_rgba (cr, _fillColor.red()/255.0, _fillColor.green()/255.0, _fillColor.blue()/255.0, 1.);
1818 
1819  _path.flushCairoPoints( cr, transform );
1820  if ( _path.closed() )
1821  cairo_close_path (cr);
1822 
1823  if ( filled() )
1824  {
1825  if ( _penColor != DGtal::Color::None )
1826  cairo_fill_preserve (cr);
1827  else
1828  cairo_fill (cr);
1829  }
1830 
1831  //
1832 
1833  if ( _penColor != DGtal::Color::None )
1834  {
1835  cairo_set_source_rgba (cr, _penColor.red()/255.0, _penColor.green()/255.0, _penColor.blue()/255.0, 1.);
1836 
1837  cairo_set_line_width (cr, _lineWidth);
1838  cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
1839  cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
1841 
1842  cairo_stroke (cr);
1843  }
1844 
1845  cairo_restore (cr);
1846 }
1847 #endif
1848 
1849 void
1850 Polyline::flushTikZ( std::ostream & stream,
1851  const TransformTikZ & transform ) const
1852 {
1853  if ( _path.empty() )
1854  return;
1855 
1856  stream << "\\path[" << tikzProperties(transform) << "] ";
1857  //stream << svgProperties( transform ) << std::endl;
1858 
1859  _path.flushTikZPoints( stream, transform );
1860 
1861  if ( _path.closed() )
1862  stream << " -- cycle";
1863  stream << ";" << std::endl;
1864 }
1865 
1866 Rect
1868 {
1869  return _path.boundingBox();
1870 }
1871 
1872 /*
1873  * Rectangle
1874  */
1875 
1876 const std::string Rectangle::_name("Rectangle");
1877 
1878 const std::string &
1880 {
1881  return _name;
1882 }
1883 
1884 Rectangle
1885 Rectangle::rotated( double angle, const Point & rotCenter ) const
1886 {
1887  return static_cast<Rectangle &>( Rectangle(*this).rotate( angle, rotCenter ) );
1888 }
1889 
1890 Rectangle
1891 Rectangle::rotated( double angle ) const
1892 {
1893  return static_cast<Rectangle &>( Rectangle(*this).rotate( angle, center() ) );
1894 }
1895 
1896 Rectangle
1897 Rectangle::translated( double dx, double dy ) const
1898 {
1899  return static_cast<Rectangle &>( Rectangle(*this).translate( dx, dy ) );
1900 }
1901 
1902 Rectangle
1903 Rectangle::scaled( double sx, double sy ) const
1904 {
1905  return static_cast<Rectangle &>( Rectangle(*this).scale( sx, sy ) );
1906 }
1907 
1908 Rectangle
1909 Rectangle::scaled( double s ) const
1910 {
1911  return static_cast<Rectangle &>( Rectangle(*this).scale( s, s ) );
1912 }
1913 
1914 void
1916 {
1917  _path.scaleAll( s );
1918 }
1919 
1920 Rectangle *
1922  return new Rectangle(*this);
1923 }
1924 
1925 void
1926 Rectangle::flushFIG( std::ostream & stream,
1927  const TransformFIG & transform,
1928  std::map<DGtal::Color,int> & colormap ) const
1929 {
1930  if ( _path[0].y != _path[1].y ) {
1931  Polyline::flushFIG( stream, transform, colormap );
1932  return;
1933  }
1934  if ( _path[0].x != _path[3].x ) {
1935  Polyline::flushFIG( stream, transform, colormap );
1936  return;
1937  }
1938  {
1939  double x1 = _path[1].x - _path[0].x;
1940  double y1 = _path[1].y - _path[0].y;
1941  double x2 = _path[3].x - _path[0].x;
1942  double y2 = _path[3].y - _path[0].y;
1943  if ( fabs(x1*x2 + y1*y2) > 0.01 ) {
1944  Polyline::flushFIG( stream, transform, colormap );
1945  return;
1946  }
1947  }
1948 
1949  stream << "2 2 " << _lineStyle << " ";
1950  // Thickness
1951  stream << ( _penColor.valid()?transform.mapWidth( _lineWidth ):0 ) << " ";
1952  // Pen color
1953  stream << colormap[ _penColor ] << " ";
1954  // Fill color
1955  stream << colormap[ _fillColor ] << " ";
1956  // Depth
1957  stream << transform.mapDepth( _depth ) << " ";
1958  // Pen style
1959  stream << "-1 ";
1960  // Area fill, style val, join style, cap style, radius, f_arrow, b_arrow, number of points
1961  if ( filled() )
1962  stream << "20 " << (_lineStyle?"4.000 ":"0.000 ") << _lineJoin << " " << _lineCap << " -1 0 0 5\n";
1963  else
1964  stream << "-1 " << (_lineStyle?"4.000 ":"0.000 ") << _lineJoin << " " << _lineCap << " -1 0 0 5\n";
1965  stream << " ";
1966  _path.flushFIG( stream, transform );
1967  stream << std::endl;
1968 }
1969 
1970 void
1971 Rectangle::flushSVG( std::ostream & stream,
1972  const TransformSVG & transform ) const
1973 {
1974  {
1975  double x1 = _path[1].x - _path[0].x;
1976  double y1 = _path[1].y - _path[0].y;
1977  double x2 = _path[3].x - _path[0].x;
1978  double y2 = _path[3].y - _path[0].y;
1979  if ( fabs(x1*x2 + y1*y2) > 0.01 ) {
1980  Polyline::flushSVG( stream, transform );
1981  return;
1982  }
1983  }
1984 
1985  if ( _path[0].y == _path[1].y ) {
1986  stream << "<rect x=\"" << transform.mapX( _path[0].x ) << '"'
1987  << " y=\"" << transform.mapY( _path[0].y ) << '"'
1988  << " width=\"" << transform.scale( _path[1].x - _path[0].x ) << '"'
1989  << " height=\"" << transform.scale( _path[0].y - _path[3].y ) << '"'
1990  << svgProperties( transform )
1991  << " />" << std::endl;
1992  } else {
1993  Point v = _path[1] - _path[0];
1994  v /= v.norm();
1995  double angle = ( _path[1].y > _path[0].y ) ? acos( v * Point(1,0) ) : -acos( v * Point( 1, 0 ) );
1996  angle = ( angle * 180 ) / M_PI;
1997  stream << "<rect x=\"" << transform.mapX( _path[0].x ) << '"'
1998  << " y=\"" << transform.mapY( _path[0].y ) << '"'
1999  << " width=\"" << transform.scale( (_path[1] - _path[0]).norm() ) << '"'
2000  << " height=\"" << transform.scale( (_path[0] - _path[3]).norm() ) << '"'
2001  << svgProperties( transform ) << ' '
2002  << " transform=\"rotate(" << -angle << ", "
2003  << transform.mapX( _path[0].x ) << ", " << transform.mapY( _path[0].y ) << ") \" "
2004  << " />" << std::endl;
2005  }
2006 }
2007 
2008 #ifdef WITH_CAIRO
2009 void
2011  const TransformCairo & transform ) const
2012 {
2013  {
2014  double x1 = _path[1].x - _path[0].x;
2015  double y1 = _path[1].y - _path[0].y;
2016  double x2 = _path[3].x - _path[0].x;
2017  double y2 = _path[3].y - _path[0].y;
2018  if ( fabs(x1*x2 + y1*y2) > 0.01 ) {
2019  Polyline::flushCairo( cr, transform );
2020  return;
2021  }
2022  }
2023 
2024  cairo_save (cr);
2025 
2026  cairo_set_source_rgba (cr, _fillColor.red()/255.0, _fillColor.green()/255.0, _fillColor.blue()/255.0, 1.);
2027 
2028  if ( _path[0].y == _path[1].y )
2029  cairo_rectangle (cr, transform.mapX( _path[0].x ), transform.mapY( _path[0].y ), transform.scale( _path[1].x - _path[0].x ), transform.scale( _path[0].y - _path[3].y ));
2030  else
2031  {
2032  Point v = _path[1] - _path[0];
2033  v /= v.norm();
2034  double angle = ( _path[1].y > _path[0].y ) ? acos( v * Point(1,0) ) : -acos( v * Point( 1, 0 ) );
2035 
2036  // tr
2037  cairo_translate (cr, transform.mapX( _path[0].x )+transform.scale( _path[1].x - _path[0].x )/2., transform.mapY( _path[0].y )+transform.scale( _path[0].y - _path[3].y )/2.);
2038  cairo_rotate (cr, angle);
2039  // tr
2040 
2041  cairo_rectangle (cr, -transform.scale( _path[1].x - _path[0].x )/2., -transform.scale( _path[0].y - _path[3].y )/2., transform.scale( (_path[1] - _path[0]).norm() ), transform.scale( (_path[0] - _path[3]).norm() ));
2042  }
2043 
2044  if ( filled() )
2045  {
2046  if ( _penColor != DGtal::Color::None )
2047  cairo_fill_preserve (cr);
2048  else
2049  cairo_fill (cr);
2050  }
2051 
2052  //
2053 
2054  if ( _penColor != DGtal::Color::None )
2055  {
2056  cairo_set_source_rgba (cr, _penColor.red()/255.0, _penColor.green()/255.0, _penColor.blue()/255.0, 1.);
2057 
2058  cairo_set_line_width (cr, _lineWidth);
2059  cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
2060  cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
2062 
2063  cairo_stroke (cr);
2064  }
2065 
2066  cairo_restore (cr);
2067 }
2068 #endif
2069 
2070 void
2071 Rectangle::flushTikZ( std::ostream & stream,
2072  const TransformTikZ & transform ) const
2073 {
2074  Polyline::flushTikZ( stream, transform );
2075  return;
2076 
2077  stream << "\\path[" << tikzProperties(transform) << "] ("
2078  << _path[0].x << ',' << _path[0].y << ')'
2079  << " rectangle (" << _path[1].x << ',' << _path[3].y << "); ";
2080 }
2081 
2082 /*
2083  * GouraudTriangle
2084  */
2085 
2086 const std::string GouraudTriangle::_name("GouraudTriangle");
2087 
2088 const std::string &
2090 {
2091  return _name;
2092 }
2093 
2095  const Point & p1, const DGtal::Color & color1,
2096  const Point & p2, const DGtal::Color & color2,
2097  int subdivisions,
2098  int depthValue )
2099  : Polyline( std::vector<Point>(), true, DGtal::Color::None, DGtal::Color::None,
2100  0.0f, SolidStyle, ButtCap, MiterJoin, depthValue ),
2101  _color0( color0 ), _color1( color1 ), _color2( color2 ), _subdivisions( subdivisions ) {
2102  _path << p0;
2103  _path << p1;
2104  _path << p2;
2105 
2106  Shape::_fillColor.red( ( color0.red() + color1.red() + color2.red() ) / 3 );
2107  Shape::_fillColor.green( ( color0.green() + color1.green() + color2.green() ) / 3 );
2108  Shape::_fillColor.blue( ( color0.blue() + color1.blue() + color2.blue() ) / 3 );
2109 }
2110 
2111 GouraudTriangle::GouraudTriangle( const Point & p0, float brightness0,
2112  const Point & p1, float brightness1,
2113  const Point & p2, float brightness2,
2114  const DGtal::Color & fill,
2115  int subdivisions,
2116  int depthValue )
2117  : Polyline( std::vector<Point>(), true, DGtal::Color::None, DGtal::Color::None,
2118  0.0f, SolidStyle, ButtCap, MiterJoin, depthValue ),
2119  _color0( fill ), _color1( fill ), _color2( fill ), _subdivisions( subdivisions )
2120 {
2121  _path << p0;
2122  _path << p1;
2123  _path << p2;
2124  _color0.red( static_cast<unsigned char>( std::min( 255.0f, _color0.red() * brightness0 ) ) );
2125  _color0.green( static_cast<unsigned char>( std::min( 255.0f, _color0.green() * brightness0 ) ) );
2126  _color0.blue( static_cast<unsigned char>( std::min( 255.0f, _color0.blue() * brightness0 ) ) );
2127  _color1.red( static_cast<unsigned char>( std::min( 255.0f, _color1.red() * brightness1 ) ) );
2128  _color1.green( static_cast<unsigned char>( std::min( 255.0f, _color1.green() * brightness1 ) ) );
2129  _color1.blue( static_cast<unsigned char>( std::min( 255.0f, _color1.blue() * brightness1 ) ) );
2130  _color2.red( static_cast<unsigned char>( std::min( 255.0f, _color2.red() * brightness2 ) ) );
2131  _color2.green( static_cast<unsigned char>( std::min( 255.0f, _color2.green() * brightness2 ) ) );
2132  _color2.blue( static_cast<unsigned char>( std::min( 255.0f, _color2.blue() * brightness2 ) ) );
2133 
2134  Shape::_fillColor.red( ( _color0.red() + _color1.red() + _color2.red() ) / 3 );
2136  Shape::_fillColor.blue( ( _color0.blue() + _color1.blue() + _color2.blue() ) / 3 );
2137 }
2138 
2139 Point
2141  return ( _path[0] + _path[1] + _path[2] ) / 3.0;
2142 }
2143 
2145 GouraudTriangle::rotate( double angle, const Point & rotCenter )
2146 {
2147  _path.rotate( angle, rotCenter );
2148  return *this;
2149 }
2150 
2152 GouraudTriangle::rotated( double angle, const Point & rotCenter ) const
2153 {
2154  return GouraudTriangle(*this).rotate( angle, rotCenter );
2155 }
2156 
2159 {
2160  return GouraudTriangle::rotate( angle, center() );
2161 }
2162 
2164 GouraudTriangle::rotated( double angle ) const
2165 {
2166  return GouraudTriangle(*this).rotate( angle, center() );
2167 }
2168 
2170 GouraudTriangle::translated( double dx, double dy ) const
2171 {
2172  return static_cast<GouraudTriangle &>( GouraudTriangle(*this).translate( dx, dy ) );
2173 }
2174 
2176 GouraudTriangle::scaled( double sx, double sy ) const
2177 {
2178  return static_cast<GouraudTriangle &>( GouraudTriangle(*this).scale( sx, sy ) );
2179 }
2180 
2182 GouraudTriangle::scaled( double s ) const
2183 {
2184  return static_cast<GouraudTriangle &>( GouraudTriangle(*this).scale( s, s ) );
2185 }
2186 
2187 void
2189 {
2190  _path.scaleAll( s );
2191 }
2192 
2195  return new GouraudTriangle(*this);
2196 }
2197 
2198 void
2199 GouraudTriangle::flushPostscript( std::ostream & stream,
2200  const TransformEPS & transform ) const
2201 {
2202  if ( ! _subdivisions ) {
2203  Polyline::flushPostscript( stream, transform );
2204  return;
2205  }
2206  const Point & p0 = _path[0];
2207  const Point & p1 = _path[1];
2208  const Point & p2 = _path[2];
2209  Point p01( 0.5*(p0.x+p1.x), 0.5*(p0.y+p1.y) );
2210  DGtal::Color c01( (_color0.red() + _color1.red())/2,
2211  (_color0.green() + _color1.green())/2,
2212  (_color0.blue() + _color1.blue())/2 );
2213  Point p12( 0.5*(p1.x+p2.x), 0.5*(p1.y+p2.y) );
2214  DGtal::Color c12( (_color1.red() + _color2.red())/2,
2215  (_color1.green() + _color2.green())/2,
2216  (_color1.blue() + _color2.blue())/2 );
2217  Point p20( 0.5*(p2.x+p0.x), 0.5*(p2.y+p0.y) );
2218  DGtal::Color c20( (_color2.red() + _color0.red())/2,
2219  (_color2.green() + _color0.green())/2,
2220  (_color2.blue() + _color0.blue())/2 );
2221  GouraudTriangle( p0, _color0, p20, c20, p01, c01, _subdivisions - 1, _depth ).flushPostscript( stream, transform );
2222  GouraudTriangle( p1, _color1, p01, c01, p12, c12, _subdivisions - 1, _depth ).flushPostscript( stream, transform );
2223  GouraudTriangle( p2, _color2, p20, c20, p12, c12, _subdivisions - 1, _depth ).flushPostscript( stream, transform );
2224  GouraudTriangle( p01, c01, p12, c12, p20, c20, _subdivisions - 1, _depth ).flushPostscript( stream, transform );
2225 }
2226 
2227 void
2228 GouraudTriangle::flushFIG( std::ostream & stream,
2229  const TransformFIG & transform,
2230  std::map<DGtal::Color,int> & colormap ) const
2231 {
2232 
2233  DGtal::Color c( static_cast<unsigned char>((_color0.red() + _color1.red() + _color2.red() )/3.0),
2234  static_cast<unsigned char>((_color0.green() + _color1.green() + _color2.green())/3.0),
2235  static_cast<unsigned char>((_color0.blue() + _color1.blue() + _color2.blue())/3.0 ));
2236  Polyline( _path, DGtal::Color::None, c, 0.0f ).flushFIG( stream, transform, colormap );
2237 
2238  // if ( ! _subdivisions ) {
2239  // Polyline::flushFIG( stream, transform, colormap );
2240  // return;
2241  // }
2242 // TODO : Handle extended colormap through clustering...
2243 // const Point & p0 = _points[0];
2244 // const Point & p1 = _points[1];
2245 // const Point & p2 = _points[2];
2246 // Point p01( 0.5*(p0.x+p1.x), 0.5*(p0.y+p1.y) );
2247 // DGtal::Color c01( (_color0.red() + _color1.red())/2,
2248 // (_color0.green() + _color1.green())/2,
2249 // (_color0.blue() + _color1.blue())/2 );
2250 // Point p12( 0.5*(p1.x+p2.x), 0.5*(p1.y+p2.y) );
2251 // DGtal::Color c12( (_color1.red() + _color2.red())/2,
2252 // (_color1.green() + _color2.green())/2,
2253 // (_color1.blue() + _color2.blue())/2 );
2254 // Point p20( 0.5*(p2.x+p0.x), 0.5*(p2.y+p0.y) );
2255 // DGtal::Color c20( (_color2.red() + _color0.red())/2,
2256 // (_color2.green() + _color0.green())/2,
2257 // (_color2.blue() + _color0.blue())/2 );
2258 // GouraudTriangle( p0, _color0, p20, c20, p01, c01, _subdivisions - 1, _depth ).flushFIG( stream, transform, colormap );
2259 // GouraudTriangle( p1, _color1, p01, c01, p12, c12, _subdivisions - 1, _depth ).flushFIG( stream, transform, colormap );
2260 // GouraudTriangle( p2, _color2, p20, c20, p12, c12, _subdivisions - 1, _depth ).flushFIG( stream, transform, colormap );
2261 // GouraudTriangle( p01, c01, p12, c12, p20, c20, _subdivisions - 1, _depth ).flushFIG( stream, transform, colormap );
2262 }
2263 
2264 void
2265 GouraudTriangle::flushSVG( std::ostream & stream,
2266  const TransformSVG & transform ) const
2267 {
2268  if ( ! _subdivisions ) {
2269  Polyline::flushSVG( stream, transform );
2270  return;
2271  }
2272  const Point & p0 = _path[0];
2273  const Point & p1 = _path[1];
2274  const Point & p2 = _path[2];
2275  Point p01( 0.5*(p0.x+p1.x), 0.5*(p0.y+p1.y) );
2276  DGtal::Color c01( (_color0.red() + _color1.red())/2,
2277  (_color0.green() + _color1.green())/2,
2278  (_color0.blue() + _color1.blue())/2 );
2279  Point p12( 0.5*(p1.x+p2.x), 0.5*(p1.y+p2.y) );
2280  DGtal::Color c12( (_color1.red() + _color2.red())/2,
2281  (_color1.green() + _color2.green())/2,
2282  (_color1.blue() + _color2.blue())/2 );
2283  Point p20( 0.5*(p2.x+p0.x), 0.5*(p2.y+p0.y) );
2284  DGtal::Color c20( (_color2.red() + _color0.red())/2,
2285  (_color2.green() + _color0.green())/2,
2286  (_color2.blue() + _color0.blue())/2 );
2287  GouraudTriangle( p0, _color0, p20, c20, p01, c01,
2288  _subdivisions - 1, _depth ).flushSVG( stream, transform );
2289  GouraudTriangle( p1, _color1, p01, c01, p12, c12,
2290  _subdivisions - 1, _depth ).flushSVG( stream, transform );
2291  GouraudTriangle( p2, _color2, p20, c20, p12, c12,
2292  _subdivisions - 1, _depth ).flushSVG( stream, transform );
2293  GouraudTriangle( p01, c01, p12, c12, p20, c20,
2294  _subdivisions - 1, _depth ).flushSVG( stream, transform );
2295 }
2296 
2297 #ifdef WITH_CAIRO
2298 void
2300  const TransformCairo & /*transform*/ ) const
2301 {
2302 }
2303 #endif
2304 
2305 void
2306 GouraudTriangle::flushTikZ( std::ostream & stream,
2307  const TransformTikZ & /*transform*/ ) const
2308 {
2309  // FIXME: unimplemented
2310  stream << "% FIXME: GouraudTriangle::flushTikZ unimplemented" << std::endl;
2311 }
2312 
2313 /*
2314  * Triangle
2315  */
2316 
2317 const std::string Triangle::_name("Triangle");
2318 
2319 const std::string &
2321 {
2322  return _name;
2323 }
2324 
2325 Triangle
2326 Triangle::rotated( double angle ) const
2327 {
2328  return static_cast<Triangle &>( Triangle( *this ).rotate( angle ) );
2329 }
2330 
2331 Triangle
2332 Triangle::translated( double dx, double dy ) const
2333 {
2334  return static_cast<Triangle &>( Triangle( *this ).translate( dx, dy ) );
2335 }
2336 
2337 Triangle
2338 Triangle::scaled( double sx, double sy ) const
2339 {
2340  return static_cast<Triangle &>( Triangle( *this ).scale( sx, sy ) );
2341 }
2342 
2343 Triangle
2344 Triangle::scaled( double s ) const
2345 {
2346  return static_cast<Triangle &>( Triangle( *this ).scale( s ) );
2347 }
2348 
2349 Triangle *
2351  return new Triangle(*this);
2352 }
2353 
2354 /*
2355  * QuadraticBezierCurve
2356  */
2357 const std::string QuadraticBezierCurve::_name("QuadraticBezierCurve");
2358 
2359 const std::string &
2361 {
2362  return _name;
2363 }
2364 
2365 void
2367  const TransformEPS & transform ) const
2368 {
2369  double x1, y1, x2, y2, x3, y3, x4, y4; //coordinates of the control points
2370  _path[ 0 ].get(x1, y1);
2371  _path[ 1 ].get(x3, y3);
2372  _path[ 2 ].get(x4, y4);
2373  //we compute the two middle control points of a cubic Bezier curve
2374  //from the three control points of the quadratic Bezier curve
2375  x2 = x1 + 2/3.0*(x3-x1);
2376  y2 = y1 + 2/3.0*(y3-y1);
2377  x3 = x2 + 1/3.0*(x4-x1);
2378  y3 = y2 + 1/3.0*(y4-y1);
2379 
2380  stream << std::endl << "% Bezier curve" << std::endl;
2381  if ( _fillColor != DGtal::Color::None ) {
2382  stream << "n "
2383  << transform.mapX( x1 ) << " "
2384  << transform.mapY( y1 ) << " "
2385  << "m "
2386  << transform.mapX( x2 ) << " "
2387  << transform.mapY( y2 ) << " "
2388  << transform.mapX( x3 ) << " "
2389  << transform.mapY( y3 ) << " "
2390  << transform.mapX( x4 ) << " "
2391  << transform.mapY( y4 ) << " "
2392  << "curveto ";
2393  _fillColor.flushPostscript( stream );
2394  stream << " " << postscriptProperties();
2395  stream << " fill" << std::endl;
2396  }
2397  if ( _penColor != DGtal::Color::None ) {
2398  stream << " " << postscriptProperties() << " ";
2399  stream << "n "
2400  << transform.mapX( x1 ) << " "
2401  << transform.mapY( y1 ) << " "
2402  << "m "
2403  << transform.mapX( x2 ) << " "
2404  << transform.mapY( y2 ) << " "
2405  << transform.mapX( x3 ) << " "
2406  << transform.mapY( y3 ) << " "
2407  << transform.mapX( x4 ) << " "
2408  << transform.mapY( y4 ) << " "
2409  << "curveto ";
2410  _penColor.flushPostscript( stream );
2411  stream << " stroke" << std::endl;
2412  }
2413 }
2414 
2415 void
2416 QuadraticBezierCurve::flushFIG( std::ostream & stream,
2417  const TransformFIG & transform,
2418  std::map<DGtal::Color,int> & colormap ) const
2419 {
2420  stream << "#FIXME: quadratic Bezier curve unimplemented" << std::endl;
2421  Triangle::flushFIG(stream, transform, colormap);
2422 }
2423 
2424 void
2425 QuadraticBezierCurve::flushSVG( std::ostream & stream,
2426  const TransformSVG & transform ) const
2427 {
2428  double x1, y1, x2, y2, x3, y3; //coordinates of the control points
2429  _path[ 0 ].get(x1, y1);
2430  _path[ 1 ].get(x2, y2);
2431  _path[ 2 ].get(x3, y3);
2432 
2433  stream << "<path ";
2434  stream << svgProperties( transform ) << " ";
2435  //first point
2436  stream << "d='M " << transform.mapX( x1 );
2437  stream << "," << transform.mapY( y1 );
2438  //arc
2439  stream << " Q " << transform.mapX( x2 ) << "," << transform.mapY( y2 );
2440  //last point
2441  stream << " " << transform.mapX( x3 );
2442  stream << "," << transform.mapY( y3 );
2443  stream << "' />";
2444 }
2445 
2446 #ifdef WITH_CAIRO
2447 void
2449  const TransformCairo & transform ) const
2450 {
2451  double x1, y1, x2, y2, x3, y3, x4, y4; //coordinates of the control points
2452  _path[ 0 ].get(x1, y1);
2453  _path[ 1 ].get(x3, y3);
2454  _path[ 2 ].get(x4, y4);
2455  //we compute the two middle control points of a cubic Bezier curve
2456  //from the three control points of the quadratic Bezier curve
2457  x2 = x1 + 2/3.0*(x3-x1);
2458  y2 = y1 + 2/3.0*(y3-y1);
2459  x3 = x2 + 1/3.0*(x4-x1);
2460  y3 = y2 + 1/3.0*(y4-y1);
2461 
2462  cairo_save (cr);
2463 
2464  cairo_set_source_rgba (cr, _fillColor.red()/255.0, _fillColor.green()/255.0, _fillColor.blue()/255.0, 1.);
2465 
2466  cairo_move_to( cr, transform.mapX( x1 ), transform.mapY( y1 ) );
2467  cairo_curve_to( cr, transform.mapX( x2 ), transform.mapY( y2 ),
2468  transform.mapX( x3 ), transform.mapY( y3 ),
2469  transform.mapX( x4 ), transform.mapY( y4 ) );
2470 
2471  if ( filled() )
2472  {
2473  if ( _penColor != DGtal::Color::None )
2474  cairo_fill_preserve (cr);
2475  else
2476  cairo_fill (cr);
2477  }
2478 
2479  if ( _penColor != DGtal::Color::None )
2480  {
2481  cairo_set_source_rgba (cr, _penColor.red()/255.0, _penColor.green()/255.0, _penColor.blue()/255.0, 1.);
2482 
2483  cairo_set_line_width (cr, _lineWidth);
2484  cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
2485  cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
2487 
2488  cairo_stroke (cr);
2489  }
2490 
2491  cairo_restore (cr);
2492 }
2493 #endif
2494 
2495 void
2496 QuadraticBezierCurve::flushTikZ( std::ostream & stream,
2497  const TransformTikZ & transform ) const
2498 {
2499  double x1, y1, x2, y2, x3, y3, x4, y4; //coordinates of the control points
2500  _path[ 0 ].get(x1, y1);
2501  _path[ 1 ].get(x3, y3);
2502  _path[ 2 ].get(x4, y4);
2503  //we compute the two middle control points of a cubic Bezier curve
2504  //from the three control points of the quadratic Bezier curve
2505  x2 = x1 + 2/3.0*(x3-x1);
2506  y2 = y1 + 2/3.0*(y3-y1);
2507  x3 = x2 + 1/3.0*(x4-x1);
2508  y3 = y2 + 1/3.0*(y4-y1);
2509 
2510  stream << "\\draw[" << tikzProperties(transform) << "] ("
2511  << transform.mapX( x1 ) << ',' << transform.mapY( y1 )
2512  << ") .. controls ("
2513  << transform.mapX( x2 ) << ',' << transform.mapY( y2 )
2514  << ") and ("
2515  << transform.mapX( x3 ) << ',' << transform.mapY( y3 )
2516  << ") .. ("
2517  << transform.mapX( x4 ) << ',' << transform.mapY( y4 )
2518  << ");" << std::endl;
2519 }
2520 
2521 
2522 /*
2523  * Text
2524  */
2525 
2526 const std::string Text::_name("Text");
2527 
2528 const std::string &
2529 Text::name() const
2530 {
2531  return _name;
2532 }
2533 
2534 Point
2535 Text::center() const {
2536  return _position;
2537 }
2538 
2539 Text &
2540 Text::rotate( double angle, const Point & rotCenter )
2541 {
2542  Point endPos = _position + Point( 10000 * cos( _angle ), 10000 * sin( _angle ) );
2543  _position.rotate( angle, rotCenter );
2544  endPos.rotate( angle, rotCenter );
2545  Point v = endPos - _position;
2546  v /= v.norm();
2547  if ( v.x >= 0 ) _angle = asin( v.y );
2548  else if ( v.y > 0 ) _angle = (M_PI/2.0) + acos( v.y );
2549  else _angle = (-M_PI/2.0) - acos( -v.y );
2550  return *this;
2551 }
2552 
2553 Text
2554 Text::rotated( double angle, const Point & rotCenter ) const
2555 {
2556  return Text(*this).rotate( angle, rotCenter );
2557 }
2558 
2559 Text &
2560 Text::rotate( double angle )
2561 {
2562  _angle += angle;
2563  if ( _angle < 0 )
2564  while ( _angle < M_PI ) _angle += 2 * M_PI;
2565  if ( _angle > 0 )
2566  while ( _angle > M_PI ) _angle -= 2 * M_PI;
2567  return *this;
2568 }
2569 
2570 Text
2571 Text::rotated( double angle ) const
2572 {
2573  return Text(*this).rotate( angle );
2574 }
2575 
2576 Text &
2577 Text::translate( double dx, double dy )
2578 {
2579  _position += Point( dx, dy );
2580  return *this;
2581 }
2582 
2583 Text
2584 Text::translated( double dx, double dy ) const
2585 {
2586  return static_cast<Text&>( Text(*this).translate( dx, dy ) );
2587 }
2588 
2589 Shape &
2590 Text::scale( double sx, double sy )
2591 {
2592  _xScale = sx;
2593  _yScale = sy;
2594  return *this;
2595 }
2596 
2597 Shape &
2598 Text::scale( double s )
2599 {
2600  _xScale = _yScale = s;
2601  return *this;
2602 }
2603 
2604 Text
2605 Text::scaled( double sx, double sy ) const
2606 {
2607  return static_cast<Text &>( Text(*this).scale( sx, sy ) );
2608 }
2609 
2610 Text
2611 Text::scaled( double s ) const
2612 {
2613  return static_cast<Text &>( Text(*this).scale( s, s ) );
2614 }
2615 
2616 void
2617 Text::scaleAll( double s )
2618 {
2619  _position *= s;
2620 }
2621 
2622 Text *
2623 Text::clone() const {
2624  return new Text(*this);
2625 }
2626 
2627 void
2628 Text::flushPostscript( std::ostream & stream,
2629  const TransformEPS & transform ) const
2630 {
2631  stream << "\n% Text\n";
2632  stream << "gs /" << PSFontNames[ _font ] << " ff " << _size << " scf sf";
2633  stream << " " << transform.mapX( _position.x ) << " " << transform.mapY( _position.y ) << " m";
2634  if ( _angle != 0.0 ) stream << " " << (_angle/M_PI)*180.0 << " rot ";
2635  stream << " (" << _text << ")"
2636  << " " << _penColor.postscript() << " srgb"
2637  << " sh gr" << std::endl;
2638 }
2639 
2640 void
2641 Text::flushFIG( std::ostream & stream,
2642  const TransformFIG & transform,
2643  std::map<DGtal::Color,int> & colormap ) const
2644 {
2645  stream << "4 0 " ;
2646  // Color, depth, unused, Font
2647  stream << colormap[ _penColor ] << " " << transform.mapDepth( _depth ) << " -1 " << _font << " ";
2648  // Font size, Angle, Font flags
2649  stream << _size << " " << _angle << " 4 ";
2650  // Height
2651  stream << static_cast<int>( _size * 135 / 12.0 ) << " ";
2652  // Width
2653  stream << static_cast<int>( _text.size() * _size * 135 / 12.0 ) << " ";
2654  // x y
2655  stream << static_cast<int>( transform.mapX( _position.x ) ) << " "
2656  << static_cast<int>( transform.mapY( _position.y ) ) << " ";
2657  stream << _text << "\\001\n";
2658 }
2659 
2660 void
2661 Text::flushSVG( std::ostream & stream,
2662  const TransformSVG & transform ) const
2663 {
2664  if ( _angle != 0.0f ) {
2665  stream << "<g transform=\"translate("
2666  << transform.mapX( _position.x ) << ","
2667  << transform.mapY( _position.y ) << ")\" >"
2668  << "<g transform=\"rotate(" << (-_angle*180.0/M_PI) << ")\" >"
2669  << "<text x=\"0\" y=\"0\""
2670  << " font-family=\"" << ( _svgFont.length() ? _svgFont : PSFontNames[ _font ] ) << "\""
2671  << " font-size=\"" << _size << "\""
2672  << " fill=\"" << _penColor.svg() << "\""
2673  << _fillColor.svgAlpha( " fill" )
2674  << _penColor.svgAlpha( " stroke" )
2675  << ">"
2676  << _text
2677  << "</text></g></g>" << std::endl;
2678  } else {
2679  stream << "<text x=\"" << transform.mapX( _position.x )
2680  << "\" y=\"" << transform.mapY( _position.y ) << "\" "
2681  << " font-family=\"" << ( _svgFont.length() ? _svgFont : PSFontNames[ _font ] ) << "\""
2682  << " font-size=\"" << _size << "\""
2683  << " fill=\"" << _penColor.svg() << "\""
2684  << _fillColor.svgAlpha( " fill" )
2685  << _penColor.svgAlpha( " stroke" )
2686  << ">"
2687  << _text
2688  << "</text>" << std::endl;
2689  }
2690 }
2691 
2692 #ifdef WITH_CAIRO
2693 void
2694 Text::flushCairo( cairo_t * /*cr*/,
2695  const TransformCairo & /*transform*/ ) const
2696 {
2697 }
2698 #endif
2699 
2700 void
2701 Text::flushTikZ( std::ostream & stream,
2702  const TransformTikZ & transform ) const
2703 {
2704  // FIXME: honor font-size
2705 #define BOLD_FONT 0x01
2706 #define ITALIC_FONT 0x02
2707 #define MONOSPACE_FONT 0x04
2708 #define SANSSERIF_FONT 0x08
2709  char fontTraits[] = {
2710  0, // TimesRoman,
2711  ITALIC_FONT, // TimesItalic,
2712  BOLD_FONT, // TimesBold,
2713  BOLD_FONT | ITALIC_FONT, // TimesBoldItalic,
2714  SANSSERIF_FONT, // AvantGardeBook,
2715  SANSSERIF_FONT | ITALIC_FONT, // AvantGardeBookOblique,
2716  SANSSERIF_FONT, // AvantGardeDemi,
2717  SANSSERIF_FONT | ITALIC_FONT, // AvantGardeDemiOblique,
2718  0, // BookmanLight,
2719  ITALIC_FONT, // BookmanLightItalic,
2720  0, // BookmanDemi,
2721  ITALIC_FONT, // BookmanDemiItalic,
2722  MONOSPACE_FONT, // Courier,
2723  MONOSPACE_FONT | ITALIC_FONT, // CourierOblique,
2724  MONOSPACE_FONT | BOLD_FONT, // CourierBold,
2725  MONOSPACE_FONT | BOLD_FONT | ITALIC_FONT, // CourierBoldOblique,
2726  SANSSERIF_FONT, // Helvetica,
2727  SANSSERIF_FONT | ITALIC_FONT, // HelveticaOblique,
2728  SANSSERIF_FONT | BOLD_FONT, // HelveticaBold,
2729  SANSSERIF_FONT | BOLD_FONT | ITALIC_FONT, // HelveticaBoldOblique,
2730  SANSSERIF_FONT, // HelveticaNarrow,
2731  SANSSERIF_FONT | ITALIC_FONT, // HelveticaNarrowOblique,
2732  SANSSERIF_FONT | BOLD_FONT, // HelveticaNarrowBold,
2733  SANSSERIF_FONT | BOLD_FONT | ITALIC_FONT, // HelveticaNarrowBoldOblique,
2734  0, // NewCenturySchoolbookRoman,
2735  ITALIC_FONT, // NewCenturySchoolbookItalic,
2736  BOLD_FONT, // NewCenturySchoolbookBold,
2737  BOLD_FONT | ITALIC_FONT, // NewCenturySchoolbookBoldItalic,
2738  0, // PalatinoRoman,
2739  ITALIC_FONT, // PalatinoItalic,
2740  BOLD_FONT, // PalatinoBold,
2741  BOLD_FONT | ITALIC_FONT, // PalatinoBoldItalic,
2742  0, // Symbol,
2743  ITALIC_FONT, // ZapfChanceryMediumItalic,
2744  0 // ZapfDingbats
2745  };
2746 
2747  stream << "\\path[" << tikzProperties(transform) << "] ("
2748  << transform.mapX( _position.x ) << ',' << transform.mapY( _position.y )
2749  << ") node {"
2750  << (fontTraits[ _font ] & ITALIC_FONT ? "\\itshape " : "")
2751  << (fontTraits[ _font ] & BOLD_FONT ? "\\bfseries " : "")
2752  << (fontTraits[ _font ] & MONOSPACE_FONT ? "\\ttfamily " : "")
2753  << (fontTraits[ _font ] & SANSSERIF_FONT ? "\\sffamily " : "")
2754  << _text
2755  << "};" << std::endl;
2756 }
2757 
2758 Rect
2760 {
2761  return Rect( _position.x, _position.y, 0, 0 );
2762 }
2763 
2764 } // namespace LibBoard
Structure representing an RGB triple with alpha component.
Definition: Color.h:67
std::string postscript() const
Definition: Color.cpp:150
void flushPostscript(std::ostream &) const
Definition: Color.cpp:142
bool valid() const
static const Color None
Definition: Color.h:388
void green(const unsigned char aGreenValue)
std::string svg() const
Definition: Color.cpp:158
std::string tikz() const
Definition: Color.cpp:176
void red(const unsigned char aRedValue)
std::string svgAlpha(const char *aPrefix) const
Definition: Color.cpp:167
void blue(const unsigned char aBlueValue)
DGtal is the top-level namespace which contains all DGtal functions and types.
bool shapeGreaterDepth(const Shape *s1, const Shape *s2)
Definition: Shapes.cpp:95
const char * XFigPostscriptFontnames[]
const char * PSFontNames[]
Definition: PSFonts.cpp:16
static const std::string _name
void flushPostscript(std::ostream &stream, const TransformEPS &transform) const
Definition: Shapes.cpp:1539
const std::string & name() const
Definition: Shapes.cpp:1493
void flushCairo(cairo_t *cr, const TransformCairo &transform) const
Definition: Shapes.cpp:1500
void flushSVG(std::ostream &stream, const TransformSVG &transform) const
Definition: Shapes.cpp:1579
void flushTikZ(std::ostream &stream, const TransformTikZ &transform) const
Definition: Shapes.cpp:1625
A line between two points with an arrow at one extremity.
Definition: Board/Shapes.h:665
Arrow(double x1, double y1, double x2, double y2, DGtal::Color penColor, DGtal::Color fillColor, double lineWidth, const LineStyle style=SolidStyle, const LineCap cap=ButtCap, const LineJoin join=MiterJoin, int depth=-1)
Arrow * clone() const
Definition: Shapes.cpp:788
Arrow translated(double dx, double dy) const
Definition: Shapes.cpp:758
void flushSVG(std::ostream &stream, const TransformSVG &transform) const
Definition: Shapes.cpp:880
void flushFIG(std::ostream &stream, const TransformFIG &transform, std::map< DGtal::Color, int > &colormap) const
Definition: Shapes.cpp:847
static const std::string _name
Definition: Board/Shapes.h:758
void flushCairo(cairo_t *cr, const TransformCairo &transform) const
Definition: Shapes.cpp:933
void flushTikZ(std::ostream &stream, const TransformTikZ &transform) const
Definition: Shapes.cpp:1002
Arrow rotated(double angle, const Point &center) const
Definition: Shapes.cpp:739
void flushPostscript(std::ostream &stream, const TransformEPS &transform) const
Definition: Shapes.cpp:793
Arrow scaled(double sx, double sy) const
Definition: Shapes.cpp:769
const std::string & name() const
Definition: Shapes.cpp:733
void scaleAll(double s)
Definition: Shapes.cpp:1402
const std::string & name() const
Definition: Shapes.cpp:1322
Point center() const
Definition: Shapes.cpp:1328
Circle & translate(double dx, double dy)
Definition: Shapes.cpp:1365
Circle rotated(double angle, const Point &center) const
Definition: Shapes.cpp:1345
static const std::string _name
Circle & rotate(double angle, const Point &center)
Definition: Shapes.cpp:1333
Circle * clone() const
Definition: Shapes.cpp:1410
Circle translated(double dx, double dy) const
Definition: Shapes.cpp:1372
Shape & scale(double sx, double sy)
Definition: Shapes.cpp:1378
void flushCairo(cairo_t *cr, const TransformCairo &transform) const
Definition: Shapes.cpp:1431
void flushSVG(std::ostream &stream, const TransformSVG &transform) const
Definition: Shapes.cpp:1415
Circle(double x, double y, double radius, DGtal::Color pen, DGtal::Color fill, double lineWidth, const LineStyle style=SolidStyle, int depthValue=-1)
Circle scaled(double sx, double sy) const
Definition: Shapes.cpp:1390
void flushTikZ(std::ostream &stream, const TransformTikZ &transform) const
Definition: Shapes.cpp:1472
A line between two points.
Definition: Board/Shapes.h:398
void flushFIG(std::ostream &stream, const TransformFIG &transform, std::map< DGtal::Color, int > &colormap) const
Definition: Shapes.cpp:308
Dot(double x, double y, DGtal::Color color, double lineWidth, int depth=-1)
Dot scaled(double sx, double sy) const
Definition: Shapes.cpp:274
Dot & rotate(double angle, const Point &center)
Definition: Shapes.cpp:223
Dot * clone() const
Definition: Shapes.cpp:385
void flushPostscript(std::ostream &stream, const TransformEPS &transform) const
Definition: Shapes.cpp:293
void flushCairo(cairo_t *cr, const TransformCairo &transform) const
Definition: Shapes.cpp:348
Point center() const
Definition: Shapes.cpp:218
Dot translated(double dx, double dy) const
Definition: Shapes.cpp:256
Rect boundingBox() const
Definition: Shapes.cpp:379
static const std::string _name
Definition: Board/Shapes.h:521
void flushTikZ(std::ostream &stream, const TransformTikZ &transform) const
Definition: Shapes.cpp:370
Dot & translate(double dx, double dy)
Definition: Shapes.cpp:248
Shape & scale(double sx, double sy)
Definition: Shapes.cpp:262
void flushSVG(std::ostream &stream, const TransformSVG &transform) const
Definition: Shapes.cpp:335
const std::string & name() const
Definition: Shapes.cpp:212
Dot rotated(double angle, const Point &center) const
Definition: Shapes.cpp:230
void scaleAll(double s)
Definition: Shapes.cpp:286
static const std::string _name
void flushTikZ(std::ostream &stream, const TransformTikZ &transform) const
Definition: Shapes.cpp:1275
void scaleAll(double s)
Definition: Shapes.cpp:1143
Shape & scale(double sx, double sy)
Definition: Shapes.cpp:1075
void flushFIG(std::ostream &stream, const TransformFIG &transform, std::map< DGtal::Color, int > &colormap) const
Definition: Shapes.cpp:1185
Point center() const
Definition: Shapes.cpp:1026
void flushSVG(std::ostream &stream, const TransformSVG &transform) const
Definition: Shapes.cpp:1213
const std::string & name() const
Definition: Shapes.cpp:1020
void flushCairo(cairo_t *cr, const TransformCairo &transform) const
Definition: Shapes.cpp:1232
void flushPostscript(std::ostream &stream, const TransformEPS &transform) const
Definition: Shapes.cpp:1156
Ellipse & rotate(double angle, const Point &center)
Definition: Shapes.cpp:1031
Ellipse(double x, double y, double xRadius, double yRadius, DGtal::Color pen, DGtal::Color fill, double lineWidth, const LineStyle lineStyle=SolidStyle, int depthValue=-1)
Ellipse scaled(double sx, double sy) const
Definition: Shapes.cpp:1131
Rect boundingBox() const
Definition: Shapes.cpp:1291
Ellipse * clone() const
Definition: Shapes.cpp:1151
Ellipse rotated(double angle, const Point &center) const
Definition: Shapes.cpp:1044
Ellipse & translate(double dx, double dy)
Definition: Shapes.cpp:1062
Ellipse translated(double dx, double dy) const
Definition: Shapes.cpp:1069
A triangle with shaded filling according to colors given for each vertex.
GouraudTriangle * clone() const
Definition: Shapes.cpp:2194
GouraudTriangle rotated(double angle, const Point &center) const
Definition: Shapes.cpp:2152
void scaleAll(double s)
Definition: Shapes.cpp:2188
Point center() const
Definition: Shapes.cpp:2140
GouraudTriangle scaled(double sx, double sy) const
Definition: Shapes.cpp:2176
GouraudTriangle & rotate(double angle, const Point &center)
Definition: Shapes.cpp:2145
void flushSVG(std::ostream &stream, const TransformSVG &transform) const
Definition: Shapes.cpp:2265
void flushFIG(std::ostream &stream, const TransformFIG &transform, std::map< DGtal::Color, int > &colormap) const
Definition: Shapes.cpp:2228
void flushTikZ(std::ostream &stream, const TransformTikZ &transform) const
Definition: Shapes.cpp:2306
GouraudTriangle translated(double dx, double dy) const
Definition: Shapes.cpp:2170
GouraudTriangle(const Point &p0, const DGtal::Color &color0, const Point &p1, const DGtal::Color &color1, const Point &p2, const DGtal::Color &color2, int subdivisions, int depth=-1)
Definition: Shapes.cpp:2094
void flushPostscript(std::ostream &stream, const TransformEPS &transform) const
Definition: Shapes.cpp:2199
void flushCairo(cairo_t *cr, const TransformCairo &transform) const
Definition: Shapes.cpp:2299
const std::string & name() const
Definition: Shapes.cpp:2089
static const std::string _name
Used to draw image in figure.
void flushFIG(std::ostream &stream, const TransformFIG &transform, std::map< DGtal::Color, int > &colormap) const
Definition: Shapes.cpp:644
const std::string & name() const
Definition: Shapes.cpp:633
std::string _filename
void flushSVG(std::ostream &stream, const TransformSVG &transform) const
Definition: Shapes.cpp:669
Image * clone() const
Definition: Shapes.cpp:639
void flushTikZ(std::ostream &stream, const TransformTikZ &transform) const
Definition: Shapes.cpp:714
void flushCairo(cairo_t *cr, const TransformCairo &transform) const
Definition: Shapes.cpp:686
static const std::string _name
Image(double x0, double y0, double width, double height, std::string fileName, int depthValue, double alpha=1.0)
A line between two points.
Definition: Board/Shapes.h:534
Line & rotate(double angle, const Point &center)
Definition: Shapes.cpp:407
Line(double x1, double y1, double x2, double y2, DGtal::Color color, double lineWidth, const LineStyle style=SolidStyle, const LineCap cap=ButtCap, const LineJoin join=MiterJoin, int depth=-1)
void scaleAll(double s)
Definition: Shapes.cpp:500
Line rotated(double angle, const Point &center) const
Definition: Shapes.cpp:421
void flushPostscript(std::ostream &stream, const TransformEPS &transform) const
Definition: Shapes.cpp:514
void flushTikZ(std::ostream &stream, const TransformTikZ &transform) const
Definition: Shapes.cpp:593
Line * clone() const
Definition: Shapes.cpp:509
void flushSVG(std::ostream &stream, const TransformSVG &transform) const
Definition: Shapes.cpp:558
Point center() const
Definition: Shapes.cpp:402
Line translated(double dx, double dy) const
Definition: Shapes.cpp:450
Line & translate(double dx, double dy)
Definition: Shapes.cpp:440
void flushFIG(std::ostream &stream, const TransformFIG &transform, std::map< DGtal::Color, int > &colormap) const
Definition: Shapes.cpp:529
Shape & scale(double sx, double sy)
Definition: Shapes.cpp:461
static const std::string _name
Definition: Board/Shapes.h:649
void flushCairo(cairo_t *cr, const TransformCairo &transform) const
Definition: Shapes.cpp:571
const std::string & name() const
Definition: Shapes.cpp:396
Line scaled(double sx, double sy) const
Definition: Shapes.cpp:481
Rect boundingBox() const
Definition: Shapes.cpp:604
unsigned int size() const
Definition: Path.h:249
void flushCairoPoints(cairo_t *cr, const TransformCairo &transform) const
Definition: Path.cpp:235
Path & scale(double sx, double sy)
Definition: Path.cpp:108
void flushFIG(std::ostream &stream, const TransformFIG &transform) const
Definition: Path.cpp:173
Point center() const
Definition: Path.cpp:36
bool closed() const
Definition: Path.h:237
void flushSVGPoints(std::ostream &stream, const TransformSVG &transform) const
Definition: Path.cpp:215
bool empty() const
Definition: Path.h:243
void scaleAll(double s)
Definition: Path.cpp:143
Rect boundingBox() const
Definition: Path.cpp:272
Path & translate(double dx, double dy)
Definition: Path.cpp:81
void flushPostscript(std::ostream &stream, const TransformEPS &transform) const
Definition: Path.cpp:154
void flushTikZPoints(std::ostream &stream, const TransformTikZ &transform) const
Definition: Path.cpp:255
Path & rotate(double angle, const Point &center)
Definition: Path.cpp:43
Struct representing a 2D point.
Definition: Point.h:27
double y
Definition: Point.h:30
Point rotated(double angle) const
Definition: Point.h:200
double x
Definition: Point.h:29
Point & rotate(double angle)
Definition: Point.h:190
double norm() const
Definition: Point.h:221
A polygonal line described by a series of 2D points.
Definition: Board/Shapes.h:765
void flushSVG(std::ostream &stream, const TransformSVG &transform) const
Definition: Shapes.cpp:1792
Polyline rotated(double angle, const Point &center) const
Definition: Shapes.cpp:1667
const std::string & name() const
Definition: Shapes.cpp:1642
void flushCairo(cairo_t *cr, const TransformCairo &transform) const
Definition: Shapes.cpp:1809
Rect boundingBox() const
Definition: Shapes.cpp:1867
Point center() const
Definition: Shapes.cpp:1655
Shape & scale(double sx, double sy)
Definition: Shapes.cpp:1699
Polyline & operator<<(const Point &p)
Definition: Shapes.cpp:1648
Polyline translated(double dx, double dy) const
Definition: Shapes.cpp:1693
Polyline & rotate(double angle, const Point &center)
Definition: Shapes.cpp:1660
Polyline(const std::vector< Point > &points, bool closed, DGtal::Color penColor, DGtal::Color fillColor, double lineWidth, const LineStyle lineStyle=SolidStyle, const LineCap cap=ButtCap, const LineJoin join=MiterJoin, int depth=-1)
void scaleAll(double s)
Definition: Shapes.cpp:1725
void flushFIG(std::ostream &stream, const TransformFIG &transform, std::map< DGtal::Color, int > &colormap) const
Definition: Shapes.cpp:1760
void flushTikZ(std::ostream &stream, const TransformTikZ &transform) const
Definition: Shapes.cpp:1850
Polyline & translate(double dx, double dy)
Definition: Shapes.cpp:1686
Polyline * clone() const
Definition: Shapes.cpp:1731
Polyline scaled(double sx, double sy) const
Definition: Shapes.cpp:1713
void flushPostscript(std::ostream &stream, const TransformEPS &transform) const
Definition: Shapes.cpp:1736
static const std::string _name
Definition: Board/Shapes.h:902
void flushSVG(std::ostream &stream, const TransformSVG &transform) const
Definition: Shapes.cpp:2425
const std::string & name() const
Definition: Shapes.cpp:2360
void flushCairo(cairo_t *cr, const TransformCairo &transform) const
Definition: Shapes.cpp:2448
static const std::string _name
void flushPostscript(std::ostream &stream, const TransformEPS &transform) const
Definition: Shapes.cpp:2366
void flushTikZ(std::ostream &stream, const TransformTikZ &transform) const
Definition: Shapes.cpp:2496
void flushFIG(std::ostream &stream, const TransformFIG &transform, std::map< DGtal::Color, int > &colormap) const
Definition: Shapes.cpp:2416
Struct representing a rectangle on the plane.
Definition: Rect.h:26
double height
Definition: Rect.h:31
double width
Definition: Rect.h:30
double left
Definition: Rect.h:28
double top
Definition: Rect.h:29
Rectangle rotated(double angle, const Point &center) const
Definition: Shapes.cpp:1885
Rectangle scaled(double sx, double sy) const
Definition: Shapes.cpp:1903
Rectangle(double x, double y, double width, double height, DGtal::Color penColor, DGtal::Color fillColor, double lineWidth, const LineStyle style=SolidStyle, const LineCap cap=ButtCap, const LineJoin join=MiterJoin, int depth=-1)
Rectangle translated(double dx, double dy) const
Definition: Shapes.cpp:1897
Rectangle * clone() const
Definition: Shapes.cpp:1921
void flushCairo(cairo_t *cr, const TransformCairo &transform) const
Definition: Shapes.cpp:2010
void flushTikZ(std::ostream &stream, const TransformTikZ &transform) const
Definition: Shapes.cpp:2071
const std::string & name() const
Definition: Shapes.cpp:1879
void scaleAll(double s)
Definition: Shapes.cpp:1915
void flushFIG(std::ostream &stream, const TransformFIG &transform, std::map< DGtal::Color, int > &colormap) const
Definition: Shapes.cpp:1926
static const std::string _name
void flushSVG(std::ostream &stream, const TransformSVG &transform) const
Definition: Shapes.cpp:1971
Abstract structure for a 2D shape.
Definition: Board/Shapes.h:58
std::string svgProperties(const TransformSVG &transform) const
Definition: Shapes.cpp:109
int depth() const
Definition: Board/Shapes.h:361
DGtal::Color _fillColor
Definition: Board/Shapes.h:297
virtual void shiftDepth(int shift)
Definition: Shapes.cpp:200
std::string postscriptProperties() const
Definition: Shapes.cpp:140
virtual const std::string & name() const
Definition: Shapes.cpp:103
DGtal::Color _penColor
Definition: Board/Shapes.h:296
LineJoin _lineJoin
Definition: Board/Shapes.h:301
std::string tikzProperties(const TransformTikZ &transform) const
Definition: Shapes.cpp:177
static const std::string _name
Definition: Board/Shapes.h:291
void setCairoDashStyle(cairo_t *cr, LineStyle type) const
Definition: Shapes.cpp:153
LineStyle _lineStyle
Definition: Board/Shapes.h:299
bool filled() const
Definition: Board/Shapes.h:111
A piece of text.
Point center() const
Definition: Shapes.cpp:2535
void flushSVG(std::ostream &stream, const TransformSVG &transform) const
Definition: Shapes.cpp:2661
Text & translate(double dx, double dy)
Definition: Shapes.cpp:2577
Text(double x, double y, const std::string &text, const Fonts::Font font, double size, DGtal::Color color=DGtal::Color::Black, int depthValue=-1)
Rect boundingBox() const
Definition: Shapes.cpp:2759
Text scaled(double sx, double sy) const
Definition: Shapes.cpp:2605
const std::string & name() const
Definition: Shapes.cpp:2529
static const std::string _name
Text * clone() const
Definition: Shapes.cpp:2623
Text translated(double dx, double dy) const
Definition: Shapes.cpp:2584
void flushFIG(std::ostream &stream, const TransformFIG &transform, std::map< DGtal::Color, int > &colormap) const
Definition: Shapes.cpp:2641
std::string _text
std::string _svgFont
Text rotated(double angle, const Point &center) const
Definition: Shapes.cpp:2554
void flushTikZ(std::ostream &stream, const TransformTikZ &transform) const
Definition: Shapes.cpp:2701
void flushPostscript(std::ostream &stream, const TransformEPS &transform) const
Definition: Shapes.cpp:2628
Fonts::Font _font
Text & rotate(double angle, const Point &center)
Definition: Shapes.cpp:2540
void scaleAll(double s)
Definition: Shapes.cpp:2617
Shape & scale(double sx, double sy)
Definition: Shapes.cpp:2590
void flushCairo(cairo_t *cr, const TransformCairo &transform) const
Definition: Shapes.cpp:2694
Structure representing a scaling and translation suitable for an Cairo output.
Definition: Transforms.h:112
Structure representing a scaling and translation suitable for an EPS output.
Definition: Transforms.h:59
Structure representing a scaling and translation suitable for an XFig output.
Definition: Transforms.h:73
Structure representing a scaling and translation suitable for an SVG output.
Definition: Transforms.h:95
Structure representing a scaling and translation suitable for an TikZ output.
Definition: Transforms.h:129
A triangle. Basically a Polyline with a convenient constructor.
static const std::string _name
Triangle translated(double dx, double dy) const
Definition: Shapes.cpp:2332
Triangle(const Point &p1, const Point &p2, const Point &p3, DGtal::Color pen, DGtal::Color fill, double lineWidth, const LineStyle style=SolidStyle, const LineCap cap=ButtCap, const LineJoin join=MiterJoin, int depthValue=-1)
Triangle rotated(double angle) const
Definition: Shapes.cpp:2326
Triangle * clone() const
Definition: Shapes.cpp:2350
const std::string & name() const
Definition: Shapes.cpp:2320
Triangle scaled(double sx, double sy) const
Definition: Shapes.cpp:2338
MyPointD Point
Definition: testClone2.cpp:383
double angle(const DGtal::Z2i::RealPoint &point)
std::default_random_engine re
Image image(domain)