DGtal 1.3.0
Loading...
Searching...
No Matches
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
33namespace {
34const 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
43const 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
52const 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
63cairo_line_cap_t cairoLineCap[] = {
64 CAIRO_LINE_CAP_BUTT,
65 CAIRO_LINE_CAP_ROUND,
66 CAIRO_LINE_CAP_SQUARE
67};
68
69cairo_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
77const double cairoSolidStyle[] = {1, 0}; const double cairoSolidStyle_offset = 0;
78const double cairoDashStyle[] = {1, 1}; const double cairoDashStyle_offset = 0;
79const double cairoDotStyle[] = {1.5, 4.5}; const double cairoDotStyle_offset = 45;
80const double cairoDashDotStyle[] = {4.5, 2.3, 1.5, 2.3}; const double cairoDashDotStyle_offset = 0;
81const double cairoDashDotDotStyle[] = {4.5, 2.0, 1.5, 1.5, 1.5, 2.0}; const double cairoDashDotDotStyle_offset = 0;
82const 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
90namespace LibBoard {
91
92extern const char * XFigPostscriptFontnames[];
93
94bool
95shapeGreaterDepth( const Shape *s1, const Shape *s2 )
96{
97 return s1->depth() > s2->depth();
98}
99
100const std::string Shape::_name("AbstractShape");
101
102const std::string &
103Shape::name() const
104{
105 return _name;
106}
107
108std::string
109Shape::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
139std::string
140Shape::postscriptProperties() const
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
152void
153Shape::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;
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
176std::string
177Shape::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
193void
194Shape::depth( int d )
195{
196 _depth = d;
197}
198
199void
200Shape::shiftDepth( int shift )
201{
202 _depth += shift;
203}
204
205/*
206 * Dot
207 */
208
209const std::string Dot::_name("Dot");
210
211const std::string &
213{
214 return _name;
215}
216
217Point
218Dot::center() const {
219 return Point( _x, _y );
220}
221
222Dot &
223Dot::rotate( double angle, const Point & rotCenter )
224{
225 Point( _x, _y ).rotate( angle, rotCenter ).get( _x, _y );
226 return *this;
227}
228
229Dot
230Dot::rotated( double angle, const Point & rotCenter ) const
231{
232 return Dot(*this).rotate( angle, rotCenter );
233}
234
235Dot &
236Dot::rotate( double )
237{
238 return *this;
239}
240
241Dot
242Dot::rotated( double ) const
243{
244 return *this;
245}
246
247Dot &
248Dot::translate( double dx, double dy )
249{
250 _x += dx;
251 _y += dy;
252 return *this;
253}
254
255Dot
256Dot::translated( double dx, double dy ) const
257{
258 return Dot(*this).translate( dx, dy );
259}
260
261Shape &
262Dot::scale( double , double )
263{
264 return *this;
265}
266
267Shape &
268Dot::scale( double )
269{
270 return *this;
271}
272
273Dot
274Dot::scaled( double , double ) const
275{
276 return *this;
277}
278
279Dot
280Dot::scaled( double ) const
281{
282 return *this;
283}
284
285void
286Dot::scaleAll( double s )
287{
288 _x *= s;
289 _y *= s;
290}
291
292void
293Dot::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
307void
308Dot::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
334void
335Dot::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
347void
348Dot::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
369void
370Dot::flushTikZ( std::ostream & stream,
371 const TransformTikZ & /*transform*/ ) const
372
373{
374 // FIXME: unimplemented
375 stream << "% FIXME: Dot::flushTikZ unimplemented" << std::endl;
376}
377
378Rect
380{
381 return Rect( _x, _y, 0.0, 0.0 );
382}
383
384Dot *
385Dot::clone() const {
386 return new Dot(*this);
387}
388
389/*
390 * Line
391 */
392
393const std::string Line::_name("Line");
394
395const std::string &
397{
398 return _name;
399}
400
401Point
403 return 0.5 * Point( _x1 + _x2, _y1 + _y2 );
404}
405
406Line &
407Line::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
414Line &
415Line::rotate( double angle )
416{
417 return Line::rotate( angle, center() );
418}
419
420Line
421Line::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
429Line
430Line::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
439Line &
440Line::translate( double dx, double dy )
441{
442 _x1 += dx;
443 _x2 += dx;
444 _y1 += dy;
445 _y2 += dy;
446 return *this;
447}
448
449Line
450Line::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
460Shape &
461Line::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
473Shape &
474Line::scale( double s )
475{
476 scale( s, s );
477 return (*this);
478}
479
480Line
481Line::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
493Line
494Line::scaled( double s ) const
495{
496 return Line::scaled( s , s );
497}
498
499void
500Line::scaleAll( double s )
501{
502 _x1 *= s;
503 _y1 *= s;
504 _x2 *= s;
505 _y2 *= s;
506}
507
508Line *
509Line::clone() const {
510 return new Line(*this);
511}
512
513void
514Line::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
528void
529Line::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
557void
558Line::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
570void
571Line::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
592void
593Line::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
603Rect
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
630const std::string Image::_name("Image");
631
632const std::string &
633Image::name() const
634{
635 return _name;
636}
637
638Image *
639Image::clone() const {
640 return new Image(*this);
641}
642
643void
644Image::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
668void
669Image::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
685void
686Image::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
713void
714Image::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
730const std::string Arrow::_name("Arrow");
731
732const std::string &
734{
735 return _name;
736}
737
738Arrow
739Arrow::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
747Arrow
748Arrow::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
757Arrow
758Arrow::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
768Arrow
769Arrow::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
781Arrow
782Arrow::scaled( double s ) const
783{
784 return Arrow::scaled( s, s );
785}
786
787Arrow *
789 return new Arrow(*this);
790}
791
792void
793Arrow::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
846void
847Arrow::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
879void
880Arrow::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
932void
933Arrow::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 {
978 cairo_fill_preserve (cr);
979 else
980 cairo_fill (cr);
981 }
982
983 //
984
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
1001void
1002Arrow::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
1017const std::string Ellipse::_name("Ellipse");
1018
1019const std::string &
1020Ellipse::name() const
1021{
1022 return _name;
1023}
1024
1025Point
1026Ellipse::center() const {
1027 return _center;
1028}
1029
1030Ellipse &
1031Ellipse::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
1043Ellipse
1044Ellipse::rotated( double angle, const Point & rotCenter ) const
1045{
1046 return Ellipse(*this).rotate( angle, rotCenter );
1047}
1048
1049Ellipse &
1050Ellipse::rotate( double angle )
1051{
1052 return Ellipse::rotate( angle, center() );
1053}
1054
1055Ellipse
1056Ellipse::rotated( double angle ) const
1057{
1058 return Ellipse(*this).rotate( angle, center() );
1059}
1060
1061Ellipse &
1062Ellipse::translate( double dx, double dy )
1063{
1064 _center += Point( dx, dy );
1065 return *this;
1066}
1067
1068Ellipse
1069Ellipse::translated( double dx, double dy ) const
1070{
1071 return Ellipse(*this).translate( dx, dy );
1072}
1073
1074Shape &
1075Ellipse::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
1124Shape &
1125Ellipse::scale( double s )
1126{
1127 return Ellipse::scale( s, s );
1128}
1129
1130Ellipse
1131Ellipse::scaled( double sx, double sy ) const
1132{
1133 return static_cast<Ellipse &>( Ellipse(*this).scale( sx, sy ) );
1134}
1135
1136Ellipse
1137Ellipse::scaled( double s ) const
1138{
1139 return static_cast<Ellipse &>( Ellipse(*this).scale( s, s ) );
1140}
1141
1142void
1143Ellipse::scaleAll( double s )
1144{
1145 _xRadius *= s;
1146 _yRadius *= s;
1147 _center *= s;
1148}
1149
1150Ellipse *
1151Ellipse::clone() const {
1152 return new Ellipse(*this);
1153}
1154
1155void
1156Ellipse::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
1184void
1185Ellipse::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
1212void
1213Ellipse::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
1231void
1232Ellipse::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 {
1251 cairo_fill_preserve (cr);
1252 else
1253 cairo_fill (cr);
1254 }
1255
1256 //
1257
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
1274void
1275Ellipse::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
1290Rect
1291Ellipse::boundingBox() const
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
1319const std::string Circle::_name("Circle");
1320
1321const std::string &
1323{
1324 return _name;
1325}
1326
1327Point
1329 return _center;
1330}
1331
1332Circle &
1333Circle::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
1344Circle
1345Circle::rotated( double angle, const Point & rotCenter ) const
1346{
1347 return Circle(*this).rotate( angle, rotCenter );
1348}
1349
1350Circle &
1351Circle::rotate( double angle )
1352{
1353 if ( !_circle )
1354 Ellipse::rotate( angle );
1355 return *this;
1356}
1357
1358Circle
1359Circle::rotated( double angle ) const
1360{
1361 return Circle(*this).rotate( angle );
1362}
1363
1364Circle &
1365Circle::translate( double dx, double dy )
1366{
1367 _center += Point( dx, dy );
1368 return *this;
1369}
1370
1371Circle
1372Circle::translated( double dx, double dy ) const
1373{
1374 return Circle(*this).translate( dx, dy );
1375}
1376
1377Shape &
1378Circle::scale( double sx, double sy )
1379{
1380 return Ellipse::scale( sx, sy );
1381}
1382
1383Shape &
1384Circle::scale( double s )
1385{
1386 return Ellipse::scale( s );
1387}
1388
1389Circle
1390Circle::scaled( double sx, double sy ) const
1391{
1392 return static_cast<Circle &>( Circle(*this).scale( sx, sy ) );
1393}
1394
1395Circle
1396Circle::scaled( double s ) const
1397{
1398 return static_cast<Circle &>( Circle(*this).scale( s, s ) );
1399}
1400
1401void
1403{
1404 _center *= s;
1405 _xRadius *= s;
1406 _yRadius *= s;
1407}
1408
1409Circle *
1411 return new Circle(*this);
1412}
1413
1414void
1415Circle::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
1430void
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 {
1447 cairo_fill_preserve (cr);
1448 else
1449 cairo_fill (cr);
1450 }
1451
1452 //
1453
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
1471void
1472Circle::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
1490const std::string Arc::_name("Arc");
1491
1492const std::string &
1494{
1495 return _name;
1496}
1497
1498#ifdef WITH_CAIRO
1499void
1500Arc::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 {
1515 cairo_fill_preserve (cr);
1516 else
1517 cairo_fill (cr);
1518 }
1519
1520 //
1521
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
1538void
1539Arc::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
1578void
1579Arc::flushSVG( std::ostream & stream,
1580 const TransformSVG & transform ) const
1581{
1582
1583double fx = _center.x + _xRadius*std::cos(_angle1);
1584double fy = _center.y + _xRadius*std::sin(_angle1);
1585double lx = _center.x + _xRadius*std::cos(_angle2);
1586double ly = _center.y + _xRadius*std::sin(_angle2);
1587
1588stream << "<path ";
1589stream << svgProperties( transform ) << " ";
1590//first point
1591stream << "d='M " << transform.mapX( fx );
1592stream << "," << transform.mapY( fy );
1593//arc
1594stream << " A " << transform.scale( _xRadius ) << " " << transform.scale( _xRadius );
1595//something
1596stream << " 0";
1597//orientation and center position
1598if (_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
1618stream << " " << transform.mapX( lx );
1619stream << "," << transform.mapY( ly );
1620stream << "' />";
1621
1622}
1623
1624void
1625Arc::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
1639const std::string Polyline::_name("Polyline");
1640
1641const std::string &
1643{
1644 return _name;
1645}
1646
1648Polyline::operator<<( const Point & p )
1649{
1650 _path << p;
1651 return *this;
1652}
1653
1654Point
1656 return _path.center();
1657}
1658
1659Polyline &
1660Polyline::rotate( double angle, const Point & rotCenter )
1661{
1662 _path.rotate( angle, rotCenter );
1663 return *this;
1664}
1665
1667Polyline::rotated( double angle, const Point & rotCenter ) const
1668{
1669 return Polyline(*this).rotate( angle, rotCenter );
1670}
1671
1672Polyline &
1673Polyline::rotate( double angle )
1674{
1675 _path.rotate( angle, center() );
1676 return *this;
1677}
1678
1680Polyline::rotated( double angle ) const
1681{
1682 return Polyline(*this).rotate( angle, center() );
1683}
1684
1685Polyline &
1686Polyline::translate( double dx, double dy )
1687{
1688 _path.translate( dx, dy );
1689 return *this;
1690}
1691
1693Polyline::translated( double dx, double dy ) const
1694{
1695 return Polyline(*this).translate( dx, dy );
1696}
1697
1698Shape &
1699Polyline::scale( double sx, double sy )
1700{
1701 _path.scale( sx, sy );
1702 return *this;
1703}
1704
1705Shape &
1707{
1708 Polyline::scale( s, s );
1709 return *this;
1710}
1711
1713Polyline::scaled( double sx, double sy ) const
1714{
1715 return static_cast<Polyline &>( Polyline(*this).scale( sx, sy ) );
1716}
1717
1719Polyline::scaled( double s) const
1720{
1721 return static_cast<Polyline &>( Polyline(*this).scale( s, s ) );
1722}
1723
1724void
1726{
1727 _path.scaleAll( s );
1728}
1729
1730Polyline *
1732 return new Polyline(*this);
1733}
1734
1735void
1736Polyline::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
1759void
1760Polyline::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
1791void
1792Polyline::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
1808void
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 {
1826 cairo_fill_preserve (cr);
1827 else
1828 cairo_fill (cr);
1829 }
1830
1831 //
1832
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
1849void
1850Polyline::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
1866Rect
1868{
1869 return _path.boundingBox();
1870}
1871
1872/*
1873 * Rectangle
1874 */
1875
1876const std::string Rectangle::_name("Rectangle");
1877
1878const std::string &
1880{
1881 return _name;
1882}
1883
1885Rectangle::rotated( double angle, const Point & rotCenter ) const
1886{
1887 return static_cast<Rectangle &>( Rectangle(*this).rotate( angle, rotCenter ) );
1888}
1889
1891Rectangle::rotated( double angle ) const
1892{
1893 return static_cast<Rectangle &>( Rectangle(*this).rotate( angle, center() ) );
1894}
1895
1897Rectangle::translated( double dx, double dy ) const
1898{
1899 return static_cast<Rectangle &>( Rectangle(*this).translate( dx, dy ) );
1900}
1901
1903Rectangle::scaled( double sx, double sy ) const
1904{
1905 return static_cast<Rectangle &>( Rectangle(*this).scale( sx, sy ) );
1906}
1907
1909Rectangle::scaled( double s ) const
1910{
1911 return static_cast<Rectangle &>( Rectangle(*this).scale( s, s ) );
1912}
1913
1914void
1916{
1917 _path.scaleAll( s );
1918}
1919
1920Rectangle *
1922 return new Rectangle(*this);
1923}
1924
1925void
1926Rectangle::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
1970void
1971Rectangle::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
2009void
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 {
2047 cairo_fill_preserve (cr);
2048 else
2049 cairo_fill (cr);
2050 }
2051
2052 //
2053
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
2070void
2071Rectangle::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
2086const std::string GouraudTriangle::_name("GouraudTriangle");
2087
2088const 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
2111GouraudTriangle::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 );
2135 Shape::_fillColor.green( ( _color0.green() + _color1.green() + _color2.green() ) / 3 );
2136 Shape::_fillColor.blue( ( _color0.blue() + _color1.blue() + _color2.blue() ) / 3 );
2137}
2138
2139Point
2141 return ( _path[0] + _path[1] + _path[2] ) / 3.0;
2142}
2143
2145GouraudTriangle::rotate( double angle, const Point & rotCenter )
2146{
2147 _path.rotate( angle, rotCenter );
2148 return *this;
2149}
2150
2152GouraudTriangle::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
2164GouraudTriangle::rotated( double angle ) const
2165{
2166 return GouraudTriangle(*this).rotate( angle, center() );
2167}
2168
2170GouraudTriangle::translated( double dx, double dy ) const
2171{
2172 return static_cast<GouraudTriangle &>( GouraudTriangle(*this).translate( dx, dy ) );
2173}
2174
2176GouraudTriangle::scaled( double sx, double sy ) const
2177{
2178 return static_cast<GouraudTriangle &>( GouraudTriangle(*this).scale( sx, sy ) );
2179}
2180
2183{
2184 return static_cast<GouraudTriangle &>( GouraudTriangle(*this).scale( s, s ) );
2185}
2186
2187void
2189{
2190 _path.scaleAll( s );
2191}
2192
2195 return new GouraudTriangle(*this);
2196}
2197
2198void
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
2227void
2228GouraudTriangle::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
2264void
2265GouraudTriangle::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
2298void
2300 const TransformCairo & /*transform*/ ) const
2301{
2302}
2303#endif
2304
2305void
2306GouraudTriangle::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
2317const std::string Triangle::_name("Triangle");
2318
2319const std::string &
2320Triangle::name() const
2321{
2322 return _name;
2323}
2324
2326Triangle::rotated( double angle ) const
2327{
2328 return static_cast<Triangle &>( Triangle( *this ).rotate( angle ) );
2329}
2330
2332Triangle::translated( double dx, double dy ) const
2333{
2334 return static_cast<Triangle &>( Triangle( *this ).translate( dx, dy ) );
2335}
2336
2338Triangle::scaled( double sx, double sy ) const
2339{
2340 return static_cast<Triangle &>( Triangle( *this ).scale( sx, sy ) );
2341}
2342
2344Triangle::scaled( double s ) const
2345{
2346 return static_cast<Triangle &>( Triangle( *this ).scale( s ) );
2347}
2348
2349Triangle *
2350Triangle::clone() const {
2351 return new Triangle(*this);
2352}
2353
2354/*
2355 * QuadraticBezierCurve
2356 */
2357const std::string QuadraticBezierCurve::_name("QuadraticBezierCurve");
2358
2359const std::string &
2361{
2362 return _name;
2363}
2364
2365void
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
2415void
2416QuadraticBezierCurve::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
2424void
2425QuadraticBezierCurve::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
2447void
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 {
2474 cairo_fill_preserve (cr);
2475 else
2476 cairo_fill (cr);
2477 }
2478
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
2495void
2496QuadraticBezierCurve::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
2526const std::string Text::_name("Text");
2527
2528const std::string &
2530{
2531 return _name;
2532}
2533
2534Point
2536 return _position;
2537}
2538
2539Text &
2540Text::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
2553Text
2554Text::rotated( double angle, const Point & rotCenter ) const
2555{
2556 return Text(*this).rotate( angle, rotCenter );
2557}
2558
2559Text &
2560Text::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
2570Text
2571Text::rotated( double angle ) const
2572{
2573 return Text(*this).rotate( angle );
2574}
2575
2576Text &
2577Text::translate( double dx, double dy )
2578{
2579 _position += Point( dx, dy );
2580 return *this;
2581}
2582
2583Text
2584Text::translated( double dx, double dy ) const
2585{
2586 return static_cast<Text&>( Text(*this).translate( dx, dy ) );
2587}
2588
2589Shape &
2590Text::scale( double sx, double sy )
2591{
2592 _xScale = sx;
2593 _yScale = sy;
2594 return *this;
2595}
2596
2597Shape &
2598Text::scale( double s )
2599{
2600 _xScale = _yScale = s;
2601 return *this;
2602}
2603
2604Text
2605Text::scaled( double sx, double sy ) const
2606{
2607 return static_cast<Text &>( Text(*this).scale( sx, sy ) );
2608}
2609
2610Text
2611Text::scaled( double s ) const
2612{
2613 return static_cast<Text &>( Text(*this).scale( s, s ) );
2614}
2615
2616void
2618{
2619 _position *= s;
2620}
2621
2622Text *
2624 return new Text(*this);
2625}
2626
2627void
2628Text::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
2640void
2641Text::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
2660void
2661Text::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
2693void
2694Text::flushCairo( cairo_t * /*cr*/,
2695 const TransformCairo & /*transform*/ ) const
2696{
2697}
2698#endif
2699
2700void
2701Text::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
2758Rect
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:68
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:412
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
STL namespace.
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 * 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 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 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
Shape & scale(double sx, double sy)
Definition: Shapes.cpp:1075
Point center() const
Definition: Shapes.cpp:1026
Ellipse & rotate(double angle, const Point &center)
Definition: Shapes.cpp:1031
Ellipse & translate(double dx, double dy)
Definition: Shapes.cpp:1062
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.
std::string _filename
static const std::string _name
A line between two points.
Definition: Board/Shapes.h:534
Line & rotate(double angle, const Point &center)
Definition: Shapes.cpp:407
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
void get(double &xout, double &yout) const
Definition: Point.h:103
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
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 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
std::string postscriptProperties() const
Definition: Shapes.cpp:140
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
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
std::default_random_engine re