14 #include "Board/Rect.h"
15 #include "Board/Shapes.h"
16 #include "Board/Tools.h"
17 #include "Board/PSFonts.h"
26 #define M_PI 3.14159265358979323846
35 const char * xFigDashStylesPS[] = {
39 " [4.5 2.3 1.5 2.3] 0 sd ",
40 " [4.5 2.0 1.5 1.5 1.5 2.0] 0 sd ",
41 " [4.5 1.8 1.5 1.4 1.5 1.4 1.5 1.8 ] 0 sd "
44 const char * xFigDashStylesSVG[] = {
46 "stroke-dasharray:1,1;stroke-dashoffset:0",
47 "stroke-dasharray:1.5,4.5;stroke-dashoffset:45",
48 "stroke-dasharray:4.5,2.3,1.5,2.3;stroke-dashoffset:0",
49 "stroke-dasharray:4.5,2.0,1.5,1.5,1.5,2.0;stroke-dashoffset;0",
50 "stroke-dasharray:4.5,1.8,1.5,1.4,1.5,1.4,1.5,1.8;stroke-dashoffset:0"
53 const char * xFigDashStylesTikZ[] = {
55 "dash pattern=on 1pt off 1pt,",
59 "dash pattern=on 2pt off 3pt on 4pt off 4pt,"
64 cairo_line_cap_t cairoLineCap[] = {
70 cairo_line_join_t cairoLineJoin[] = {
71 CAIRO_LINE_JOIN_MITER,
72 CAIRO_LINE_JOIN_ROUND,
76 #define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0]))
78 const double cairoSolidStyle[] = {1, 0};
const double cairoSolidStyle_offset = 0;
79 const double cairoDashStyle[] = {1, 1};
const double cairoDashStyle_offset = 0;
80 const double cairoDotStyle[] = {1.5, 4.5};
const double cairoDotStyle_offset = 45;
81 const double cairoDashDotStyle[] = {4.5, 2.3, 1.5, 2.3};
const double cairoDashDotStyle_offset = 0;
82 const double cairoDashDotDotStyle[] = {4.5, 2.0, 1.5, 1.5, 1.5, 2.0};
const double cairoDashDotDotStyle_offset = 0;
83 const double cairoDashDotDotDotStyle[] = {4.5, 1.8, 1.5, 1.4, 1.5, 1.4, 1.5, 1.8};
const double cairoDashDotDotDotStyle_offset = 0;
98 return s1->depth() > s2->depth();
112 static const char * capStrings[3] = {
"butt",
"round",
"square" };
113 static const char * joinStrings[3] = {
"miter",
"round",
"bevel" };
114 std::stringstream str;
118 <<
" stroke-width=\"" << transform.mapWidth(
_lineWidth ) <<
"mm\""
119 <<
" style=\"stroke-linecap:" << capStrings[
_lineCap ]
120 <<
";stroke-linejoin:" << joinStrings[
_lineJoin ];
122 str <<
";" << xFigDashStylesSVG[
_lineStyle ];
130 <<
" stroke=\"none\""
131 <<
" stroke-width=\"0\""
132 <<
" style=\"stroke-linecap:round;stroke-linejoin:round;"
143 std::stringstream str;
154 Shape::setCairoDashStyle(cairo_t *cr, LineStyle type)
const
159 cairo_set_dash (cr, cairoSolidStyle, ARRAY_SIZE(cairoSolidStyle), cairoSolidStyle_offset);
break;
161 cairo_set_dash (cr, cairoDashStyle, ARRAY_SIZE(cairoDashStyle), cairoDashStyle_offset);
break;
163 cairo_set_dash (cr, cairoDotStyle, ARRAY_SIZE(cairoDotStyle), cairoDotStyle_offset);
break;
165 cairo_set_dash (cr, cairoDashDotStyle, ARRAY_SIZE(cairoDashDotStyle), cairoDashDotStyle_offset);
break;
167 cairo_set_dash (cr, cairoDashDotDotStyle, ARRAY_SIZE(cairoDashDotDotStyle), cairoDashDotDotStyle_offset);
break;
169 cairo_set_dash (cr, cairoDashDotDotDotStyle, ARRAY_SIZE(cairoDashDotDotDotStyle), cairoDashDotDotDotStyle_offset);
break;
172 cairo_set_dash (cr, cairoSolidStyle, ARRAY_SIZE(cairoSolidStyle), cairoSolidStyle_offset);
180 static const char * capStrings[3] = {
"" ,
"line cap=round,",
"line cap=rect," };
181 static const char * joinStrings[3] = {
"" ,
"line join=round",
"line join=bevel" };
183 std::stringstream str;
186 str <<
"line width=" << transform.mapWidth( _lineWidth ) <<
"mm,";
233 return Dot(*this).rotate( angle, rotCenter );
259 return Dot(*this).translate( dx, dy );
295 const TransformEPS & transform )
const
297 stream <<
"\n% Dot\n";
300 << transform.mapX(
_x ) <<
" "
301 << transform.mapY(
_y ) <<
" "
303 << transform.mapX(
_x ) <<
" "
304 << transform.mapY(
_y ) <<
" "
310 const TransformFIG & transform,
311 std::map<Color,int> & colormap )
const
315 stream << (
_penColor.
valid()?transform.mapWidth( _lineWidth ):0 ) <<
" ";
321 stream << transform.mapDepth(
_depth ) <<
" ";
325 stream <<
"-1 0.000 " << _lineJoin <<
" " << _lineCap <<
" -1 0 0 ";
329 stream << static_cast<int>( transform.mapX(
_x ) ) <<
" "
330 << static_cast<int>( transform.mapY(
_y ) ) <<
" "
331 << static_cast<int>( transform.mapX(
_x ) ) <<
" "
332 << static_cast<int>( transform.mapY(
_y ) ) << std::endl;
337 const TransformSVG & transform )
const
339 stream <<
"<line x1=\"" << transform.mapX(
_x ) <<
"\""
340 <<
" y1=\"" << transform.mapY(
_y ) <<
"\""
341 <<
" x2=\"" << transform.mapX(
_x ) <<
"\""
342 <<
" y2=\"" << transform.mapY(
_y ) <<
"\""
344 <<
" />" << std::endl;
349 Dot::flushCairo( cairo_t *cr,
350 const TransformCairo & transform )
const
356 cairo_move_to (cr, transform.mapX(
_x ), transform.mapY(
_y ));
357 cairo_line_to (cr, transform.mapX(
_x ), transform.mapY(
_y ));
359 cairo_set_line_width (cr, _lineWidth);
360 cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
361 cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
372 const TransformTikZ & )
const
376 stream <<
"% FIXME: Dot::flushTikZ unimplemented" << endl;
382 return Rect(
_x,
_y, 0.0, 0.0 );
387 return new Dot(*
this);
425 Point(
_x1,
_y1 ).rotate( angle, rotCenter ).get( res._x1, res._y1 );
426 Point(
_x2,
_y2 ).rotate( angle, rotCenter ).get( res._x2, res._y2 );
435 Point(
_x1,
_y1 ).rotate( angle, c ).get( res._x1, res._y1 );
436 Point(
_x2,
_y2 ).rotate( angle, c ).get( res._x2, res._y2 );
490 Point delta = c - res.center();
491 return res.translate( delta.
x, delta.
y );
511 return new Line(*
this);
516 const TransformEPS & transform )
const
518 stream <<
"\n% Line\n";
521 << transform.mapX(
_x1 ) <<
" "
522 << transform.mapY(
_y1 ) <<
" "
524 << transform.mapX(
_x2 ) <<
" "
525 << transform.mapY(
_y2 ) <<
" "
531 const TransformFIG & transform,
532 std::map<DGtal::Color,int> & colormap )
const
538 stream << (
_penColor.
valid()?transform.mapWidth( _lineWidth ):0 ) <<
" ";
544 stream << transform.mapDepth(
_depth ) <<
" ";
548 stream <<
"-1 " << (_lineStyle?
"4.000 ":
"0.000 ") << _lineJoin <<
" " << _lineCap <<
" -1 0 0 ";
552 stream << static_cast<int>( transform.mapX(
_x1 ) ) <<
" "
553 << static_cast<int>( transform.mapY(
_y1 ) ) <<
" "
554 << static_cast<int>( transform.mapX(
_x2 ) ) <<
" "
555 << static_cast<int>( transform.mapY(
_y2 ) ) << std::endl;
560 const TransformSVG & transform )
const
562 stream <<
"<line x1=\"" << transform.mapX(
_x1 ) <<
"\""
563 <<
" y1=\"" << transform.mapY(
_y1 ) <<
"\""
564 <<
" x2=\"" << transform.mapX(
_x2 ) <<
"\""
565 <<
" y2=\"" << transform.mapY(
_y2 ) <<
"\""
567 <<
" />" << std::endl;
572 Line::flushCairo( cairo_t *cr,
573 const TransformCairo & transform )
const
579 cairo_move_to (cr, transform.mapX(
_x1 ), transform.mapY(
_y1 ));
580 cairo_line_to (cr, transform.mapX(
_x2 ), transform.mapY(
_y2 ));
582 cairo_set_line_width (cr, _lineWidth);
583 cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
584 cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
585 setCairoDashStyle (cr, _lineStyle);
595 const TransformTikZ & transform )
const
598 << transform.mapX(
_x1 ) <<
',' << transform.mapY(
_y1 )
600 << transform.mapX(
_x2 ) <<
',' << transform.mapY(
_y2 )
601 <<
");" << std::endl;
641 return new Image(*
this);
646 const TransformFIG & transform,
647 std::map<DGtal::Color,int> & colormap )
const
652 stream << _lineStyle <<
" ";
654 stream << (
_penColor.
valid()?transform.mapWidth( _lineWidth ):0 ) <<
" ";
660 stream << transform.mapDepth(
_depth ) <<
" "
661 <<
"-1 -1 0.000 0 0 -1 0 0 5" << std::endl <<
" 0 "
671 const TransformSVG & transform )
const
674 stream <<
"<image x=\"" << transform.mapX(
_path[0].x ) <<
'"'
675 <<
" y=\"" << transform.mapY(
_path[0].y ) <<
'"'
676 <<
" width=\"" << transform.scale( (
_path[1] -
_path[0]).norm() ) <<
'"'
677 <<
" height=\"" << transform.scale( (
_path[0] -
_path[3]).norm() ) <<
'"'
678 <<
" xlink:href=\""<<
_filename <<
"\" >" << std::endl
679 <<
" <title>My image</title>"<<std::endl
680 <<
" </image>" << std::endl;
687 Image::flushCairo( cairo_t *cr,
688 const TransformCairo & transform )
const
691 cairo_surface_t *image;
695 image = cairo_image_surface_create_from_png (
_filename.c_str());
696 assert(cairo_surface_status (image) == CAIRO_STATUS_SUCCESS);
697 w = cairo_image_surface_get_width (image);
698 h = cairo_image_surface_get_height (image);
701 cairo_translate (cr, transform.mapX(
_path[0].x ), transform.mapY(
_path[0].y ));
703 cairo_scale (cr, transform.scale( (
_path[1] -
_path[0]).norm() )/w, transform.scale( (
_path[0] -
_path[3]).norm() )/h);
706 cairo_set_source_surface (cr, image, 0, 0);
707 cairo_paint_with_alpha(cr,
_alpha);
708 cairo_surface_destroy (image);
716 const TransformTikZ & transform )
const
719 stream <<
"\\node [below right=0pt] at ("
720 << transform.mapX(
_path[0].x ) <<
"pt,"
721 << transform.mapY(
_path[0].y ) <<
"pt) {\\pgfimage["
722 <<
"width=" << transform.scale( (
_path[1] -
_path[0]).norm() ) <<
"pt,"
723 <<
"height=" << transform.scale( (
_path[0] -
_path[3]).norm() ) <<
"pt,"
743 Point(
_x1,
_y1 ).rotate( angle, rotCenter ).get( res._x1, res._y1 );
744 Point(
_x2,
_y2 ).rotate( angle, rotCenter ).get( res._x2, res._y2 );
753 Point(
_x1,
_y1 ).rotate( angle, c ).get( res._x1, res._y1 );
754 Point(
_x2,
_y2 ).rotate( angle, c ).get( res._x2, res._y2 );
778 Point delta = c - res.center();
779 return static_cast<Arrow &
>( res.translate( delta.
x, delta.
y ) );
790 return new Arrow(*
this);
795 const TransformEPS & transform )
const
799 double norm = sqrt( dx*dx + dy*dy );
808 double ndx1 = dx*cos(0.3)-dy*sin(0.3);
809 double ndy1 = dx*sin(0.3)+dy*cos(0.3);
810 double ndx2 = dx*cos(-0.3)-dy*sin(-0.3);
811 double ndy2 = dx*sin(-0.3)+dy*cos(-0.3);
813 stream <<
"\n% Arrow\n";
817 << transform.mapX(
_x1 ) <<
" "
818 << transform.mapY(
_y1 ) <<
" "
820 << transform.mapX( _x2 + ( dx * cos(0.3) ) ) <<
" "
821 << transform.mapY( _y2 + ( dy * cos(0.3) ) ) <<
" "
822 <<
"l stroke" << std::endl;
826 << transform.mapX( _x2 ) + transform.scale( ndx1 ) <<
" "
827 << transform.mapY( _y2 ) + transform.scale( ndy1 ) <<
" "
829 << transform.mapX( _x2 ) <<
" "
830 << transform.mapY( _y2 ) <<
" l "
831 << transform.mapX( _x2 ) + transform.scale( ndx2 ) <<
" "
832 << transform.mapY( _y2 ) + transform.scale( ndy2 ) <<
" ";
837 << transform.mapX( _x2 ) + transform.scale( ndx1 ) <<
" "
838 << transform.mapY( _y2 ) + transform.scale( ndy1 ) <<
" "
840 << transform.mapX( _x2 ) <<
" "
841 << transform.mapY( _y2 ) <<
" l "
842 << transform.mapX( _x2 ) + transform.scale( ndx2 ) <<
" "
843 << transform.mapY( _y2 ) + transform.scale( ndy2 ) <<
" l"
849 const TransformFIG & transform,
850 std::map<DGtal::Color,int> & colormap )
const
854 stream << _lineStyle <<
" ";
856 stream << (
_penColor.
valid()?transform.mapWidth( _lineWidth ):0 ) <<
" ";
862 stream << transform.mapDepth(
_depth ) <<
" ";
866 stream <<
"-1 " << (_lineStyle?
"4.000 ":
"0.000 ") << _lineJoin <<
" " << _lineCap <<
" -1 1 0 ";
870 stream <<
" 1 1 1.00 60.00 120.00\n";
872 stream <<
" 1 0 1.00 60.00 120.00\n";
874 stream << static_cast<int>( transform.mapX(
_x1 ) ) <<
" "
875 << static_cast<int>( transform.mapY(
_y1 ) ) <<
" "
876 << static_cast<int>( transform.mapX( _x2 ) ) <<
" "
877 << static_cast<int>( transform.mapY( _y2 ) ) << std::endl;
882 const TransformSVG & transform )
const
886 double norm = sqrt( dx*dx + dy*dy );
895 double ndx1 = dx*cos(0.3)-dy*sin(0.3);
896 double ndy1 = dx*sin(0.3)+dy*cos(0.3);
897 double ndx2 = dx*cos(-0.3)-dy*sin(-0.3);
898 double ndy2 = dx*sin(-0.3)+dy*cos(-0.3);
900 stream <<
"<g>" << std::endl;
903 <<
"d=\"M " << transform.mapX(
_x1 ) <<
" " << transform.mapY(
_y1 )
904 <<
" L " << transform.mapX( _x2 + ( dx * cos(0.3) ) )
905 <<
" " << transform.mapY( _y2 + ( dy * cos(0.3) ) ) <<
" z\""
906 <<
" fill=\"none\" stroke=\"" <<
_penColor.
svg() <<
"\""
909 stream <<
" style=\"" << xFigDashStylesSVG[
_lineStyle ] <<
'"';
910 stream <<
" stroke-width=\"" << transform.mapWidth( _lineWidth ) <<
"mm\" />";
913 stream <<
" <polygon";
916 <<
" stroke-width=\"" << transform.mapWidth( _lineWidth ) <<
"mm\""
917 <<
" style=\"stroke-linecap:butt;stroke-linejoin:miter\""
921 << transform.mapX( _x2 ) + transform.scale( ndx1 ) <<
","
922 << transform.mapY( _y2 ) - transform.scale( ndy1 ) <<
" "
923 << transform.mapX( _x2 ) <<
","
924 << transform.mapY( _y2 ) <<
" "
925 << transform.mapX( _x2 ) + transform.scale( ndx2 ) <<
","
926 << transform.mapY( _y2 ) - transform.scale( ndy2 ) <<
" "
927 << transform.mapX( _x2 ) + transform.scale( ndx1 ) <<
","
928 << transform.mapY( _y2 ) - transform.scale( ndy1 ) <<
"\" />" << std::endl;
929 stream <<
"</g>" << std::endl;
934 Arrow::flushCairo( cairo_t *cr,
935 const TransformCairo & transform )
const
939 double norm = sqrt( dx*dx + dy*dy );
948 double ndx1 = dx*cos(0.3)-dy*sin(0.3);
949 double ndy1 = dx*sin(0.3)+dy*cos(0.3);
950 double ndx2 = dx*cos(-0.3)-dy*sin(-0.3);
951 double ndy2 = dx*sin(-0.3)+dy*cos(-0.3);
958 cairo_move_to (cr, transform.mapX(
_x1 ), transform.mapY(
_y1 ));
959 cairo_line_to (cr, transform.mapX( _x2 + ( dx * cos(0.3) ) ), transform.mapY( _y2 + ( dy * cos(0.3) ) ));
961 cairo_set_line_width (cr, _lineWidth);
962 cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
963 cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
964 setCairoDashStyle (cr, _lineStyle);
971 cairo_move_to (cr, transform.mapX( _x2 ) + transform.scale( ndx1 ), transform.mapY( _y2 ) - transform.scale( ndy1 ));
972 cairo_line_to (cr, transform.mapX( _x2 ), transform.mapY( _y2 ));
973 cairo_line_to (cr, transform.mapX( _x2 ) + transform.scale( ndx2 ), transform.mapY( _y2 ) - transform.scale( ndy2 ));
974 cairo_close_path (cr);
979 cairo_fill_preserve (cr);
990 cairo_set_line_width (cr, _lineWidth);
991 cairo_set_line_cap (cr, cairoLineCap[
ButtCap]);
992 cairo_set_line_join (cr, cairoLineJoin[
MiterJoin]);
1004 const TransformTikZ & transform )
const
1008 << transform.mapX(
_x1 ) <<
',' << transform.mapY(
_y1 )
1010 << transform.mapX( _x2 ) <<
',' << transform.mapY( _y2 )
1011 <<
");" << std::endl;
1036 Point rc = c.rotated( angle, rotCenter );
1037 Point re = e.rotated( angle, rotCenter );
1038 Point axis = re - rc;
1047 return Ellipse(*this).rotate( angle, rotCenter );
1072 return Ellipse(*this).translate( dx, dy );
1081 double co = cos(
_angle );
1082 double si = sin(
_angle );
1085 double m00 = ( 1 /
_xRadius ) * co;
1086 double m01 = ( 1 /
_xRadius ) * si;
1087 double m10 = - ( 1 /
_yRadius ) * si;
1088 double m11 = ( 1 /
_yRadius ) * co;
1092 double a = ( m00 * m00 ) + ( m10 * m10 );
1093 double b = 2 * ( ( m00 * m01 ) + ( m10 * m11 ) );
1094 double c = ( m01 * m01 ) + ( m11 * m11 );
1097 a = a / ( sx * sx );
1098 b = b / ( sx * sy );
1099 c = c / ( sy * sy );
1103 }
else if ( a == c ) {
1108 _angle = 0.5 * atan( b / ( a - c ) );
1109 double k = 1 + ( ( b * b ) / ( ( a - c ) * ( a - c ) ) );
1113 a = 0.5 * ( c + k );
1114 c = 0.5 * ( c - k );
1158 const TransformEPS & transform )
const
1161 stream <<
"\n% Ellipse\n";
1164 << transform.mapX(
_center.
x ) <<
" " << transform.mapY(
_center.
y ) <<
" tr";
1166 if ( !
_circle ) stream <<
" " << 1.0 <<
" " << yScale <<
" sc";
1167 stream <<
" n " << transform.scale(
_xRadius ) <<
" 0 m "
1168 <<
" 0 0 " << transform.scale(
_xRadius ) <<
" 0.0 360.0 arc ";
1170 stream <<
" fill gr" << std::endl;
1175 stream <<
"gs " << transform.mapX(
_center.
x ) <<
" " << transform.mapY(
_center.
y ) <<
" tr";
1177 if ( !
_circle ) stream <<
" " << 1.0 <<
" " << yScale <<
" sc";
1178 stream <<
" n " << transform.scale(
_xRadius ) <<
" 0 m "
1179 <<
" 0 0 " << transform.scale(
_xRadius ) <<
" 0.0 360.0 arc ";
1181 stream <<
" stroke gr" << std::endl;
1187 const TransformFIG & transform,
1188 std::map<DGtal::Color,int> & colormap )
const
1192 stream <<
"1 3 " << _lineStyle <<
" ";
1194 stream <<
"1 1 " << _lineStyle <<
" ";
1195 stream << (
_penColor.
valid()?transform.mapWidth( _lineWidth ):0 ) <<
" ";
1200 stream << transform.mapDepth(
_depth ) <<
" -1 20 " << (_lineStyle?
"4.000 ":
"0.000 ") <<
" 1 " <<
_angle <<
" ";
1202 stream << transform.mapDepth(
_depth ) <<
" -1 -1 " << (_lineStyle?
"4.000 ":
"0.000 ") <<
" 1 " <<
_angle <<
" ";
1203 stream << static_cast<int>( transform.mapX(
_center.
x ) ) <<
" "
1204 << static_cast<int>( transform.mapY(
_center.
y ) ) <<
" "
1205 << static_cast<int>( transform.scale(
_xRadius ) ) <<
" "
1206 << static_cast<int>( transform.scale(
_yRadius ) ) <<
" "
1207 << static_cast<int>( transform.mapX(
_center.
x ) ) <<
" "
1208 << static_cast<int>( transform.mapY(
_center.
y ) ) <<
" "
1209 << static_cast<int>( transform.mapX(
_center.
x ) + transform.scale(
_xRadius ) ) <<
" "
1210 << static_cast<int>( transform.mapY(
_center.
y ) ) <<
"\n";
1215 const TransformSVG & transform )
const
1217 stream <<
"<ellipse cx=\"" << transform.mapX(
_center.
x ) <<
'"'
1218 <<
" cy=\"" << transform.mapY(
_center.
y ) <<
'"'
1219 <<
" rx=\"" << transform.scale(
_xRadius ) <<
'"'
1220 <<
" ry=\"" << transform.scale(
_yRadius ) <<
'"'
1223 stream <<
" transform=\"rotate( "
1225 << transform.mapX(
_center.
x ) <<
", "
1226 << transform.mapY(
_center.
y ) <<
" )\" ";
1228 stream <<
" />" << std::endl;
1233 Ellipse::flushCairo( cairo_t *cr,
1234 const TransformCairo & transform )
const
1241 cairo_translate (cr, transform.mapX(
_center.
x ), transform.mapY(
_center.
y ));
1243 cairo_rotate (cr,
_angle);
1244 cairo_scale (cr, transform.scale(
_xRadius ), transform.scale(
_yRadius ));
1247 cairo_arc (cr, 0, 0, 1, 0, 2*M_PI);
1252 cairo_fill_preserve (cr);
1263 cairo_set_line_width (cr, _lineWidth);
1264 cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
1265 cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
1266 setCairoDashStyle (cr, _lineStyle);
1277 const TransformTikZ & transform )
const
1280 stream <<
"% FIXME: Ellipse::flushTikZ unimplemented" << endl;
1282 << transform.mapX(
_center.
x ) <<
','
1283 << transform.mapY(
_center.
y ) <<
')'
1284 <<
" circle [x radius=" << transform.scale(
_xRadius ) <<
','
1285 <<
"y radius=" << transform.scale(
_yRadius ) <<
','
1337 if ( rotCenter ==
_center )
return *
this;
1348 return Circle(*this).rotate( angle, rotCenter );
1362 return Circle(*this).rotate( angle );
1375 return Circle(*this).translate( dx, dy );
1393 return static_cast<Circle &
>(
Circle(*this).scale( sx, sy ) );
1399 return static_cast<Circle &
>(
Circle(*this).scale( s, s ) );
1412 return new Circle(*
this);
1417 const TransformSVG & transform )
const
1422 stream <<
"<circle cx=\"" << transform.mapX(
_center.
x ) <<
'"'
1423 <<
" cy=\"" << transform.mapY(
_center.
y ) <<
'"'
1424 <<
" r=\"" << transform.scale(
_xRadius ) <<
'"'
1426 <<
" />" << std::endl;
1432 Circle::flushCairo( cairo_t *cr,
1433 const TransformCairo & transform )
const
1436 Ellipse::flushCairo( cr, transform );
1448 cairo_fill_preserve (cr);
1459 cairo_set_line_width (cr, _lineWidth);
1460 cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
1461 cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
1462 setCairoDashStyle (cr, _lineStyle);
1474 const TransformTikZ & transform )
const
1480 << transform.mapX(
_center.
x ) <<
','
1481 << transform.mapY(
_center.
y ) <<
')'
1482 <<
" circle (" << transform.scale(
_xRadius ) <<
");"
1501 Arc::flushCairo( cairo_t *cr,
1502 const TransformCairo & transform )
const
1516 cairo_fill_preserve (cr);
1527 cairo_set_line_width (cr, _lineWidth);
1528 cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
1529 cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
1530 setCairoDashStyle (cr, _lineStyle);
1541 const TransformEPS & transform )
const
1558 stream <<
"\n% Arc\n";
1561 << transform.mapX(
_center.
x ) <<
" " << transform.mapY(
_center.
y ) <<
" "
1562 << transform.scale(
_xRadius )<<
" " << (a1*180/
M_PI) <<
" "
1563 << (a2*180/M_PI) <<
" "<<
"arc ";
1565 stream <<
" fill gr" << std::endl;
1571 << transform.mapX(
_center.
x ) <<
" " << transform.mapY(
_center.
y ) <<
" "
1572 << transform.scale(
_xRadius )<<
" " << (a1*180/
M_PI) <<
" "
1573 << (a2*180/M_PI) <<
" "<<
"arc ";
1575 stream <<
" stroke gr" << std::endl;
1581 const TransformSVG & transform )
const
1592 stream <<
"d='M " << transform.mapX( fx );
1593 stream <<
"," << transform.mapY( fy );
1595 stream <<
" A " << transform.scale(
_xRadius ) <<
" " << transform.scale(
_xRadius );
1601 if ( (std::cos(_angle1)*std::sin(
_angle2) - std::sin(_angle1)*std::cos(
_angle2))<0 )
1610 if ( (std::cos(_angle1)*std::sin(
_angle2) - std::sin(_angle1)*std::cos(
_angle2))<0 )
1619 stream <<
" " << transform.mapX( lx );
1620 stream <<
"," << transform.mapY( ly );
1627 const TransformTikZ & transform )
const
1630 << transform.mapX(
_center.
x ) <<
',' << transform.mapY(
_center.
y ) <<
')'
1631 <<
" +(" << -_angle1/
M_PI*180. <<
':' << transform.scale(
_xRadius) <<
')'
1670 return Polyline(*this).rotate( angle, rotCenter );
1696 return Polyline(*this).translate( dx, dy );
1738 const TransformEPS & transform )
const
1741 stream <<
"\n% Polyline\n";
1748 stream <<
" fill" << std::endl;
1756 stream <<
" stroke" << std::endl;
1762 const TransformFIG & transform,
1763 std::map<DGtal::Color,int> & colormap )
const
1768 stream <<
"2 3 " << _lineStyle <<
" ";
1770 stream <<
"2 1 " << _lineStyle <<
" ";
1772 stream << (
_penColor.
valid()?transform.mapWidth( _lineWidth ):0 ) <<
" ";
1778 stream << transform.mapDepth(
_depth ) <<
" ";
1783 stream <<
"20 " << (_lineStyle?
"4.000 ":
"0.000 ") << _lineJoin <<
" " << _lineCap <<
" -1 0 0 ";
1785 stream <<
"-1 " << (_lineStyle?
"4.000 ":
"0.000 ") << _lineJoin <<
" " << _lineCap <<
" -1 0 0 ";
1789 stream << std::endl;
1794 const TransformSVG & transform )
const
1799 stream <<
"<polygon";
1801 stream <<
"<polyline";
1803 stream <<
" points=\"";
1805 stream <<
"\" />" << std::endl;
1810 Polyline::flushCairo( cairo_t *cr,
1811 const TransformCairo & transform )
const
1820 _path.flushCairoPoints( cr, transform );
1822 cairo_close_path (cr);
1827 cairo_fill_preserve (cr);
1838 cairo_set_line_width (cr, _lineWidth);
1839 cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
1840 cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
1841 setCairoDashStyle (cr, _lineStyle);
1852 const TransformTikZ & transform )
const
1863 stream <<
" -- cycle";
1864 stream <<
";" << std::endl;
1928 const TransformFIG & transform,
1929 std::map<DGtal::Color,int> & colormap )
const
1944 if ( fabs(x1*x2 + y1*y2) > 0.01 ) {
1950 stream <<
"2 2 " << _lineStyle <<
" ";
1952 stream << (
_penColor.
valid()?transform.mapWidth( _lineWidth ):0 ) <<
" ";
1958 stream << transform.mapDepth(
_depth ) <<
" ";
1963 stream <<
"20 " << (_lineStyle?
"4.000 ":
"0.000 ") << _lineJoin <<
" " << _lineCap <<
" -1 0 0 5\n";
1965 stream <<
"-1 " << (_lineStyle?
"4.000 ":
"0.000 ") << _lineJoin <<
" " << _lineCap <<
" -1 0 0 5\n";
1968 stream << std::endl;
1973 const TransformSVG & transform )
const
1980 if ( fabs(x1*x2 + y1*y2) > 0.01 ) {
1987 stream <<
"<rect x=\"" << transform.mapX(
_path[0].x ) <<
'"'
1988 <<
" y=\"" << transform.mapY(
_path[0].y ) <<
'"'
1989 <<
" width=\"" << transform.scale(
_path[1].x -
_path[0].x ) <<
'"'
1990 <<
" height=\"" << transform.scale(
_path[0].y -
_path[3].y ) <<
'"'
1992 <<
" />" << std::endl;
1996 double angle = ( _path[1].y > _path[0].y ) ? acos( v *
Point(1,0) ) : -acos( v *
Point( 1, 0 ) );
1997 angle = ( angle * 180 ) / M_PI;
1998 stream <<
"<rect x=\"" << transform.mapX( _path[0].x ) <<
'"'
1999 <<
" y=\"" << transform.mapY( _path[0].y ) <<
'"'
2000 <<
" width=\"" << transform.scale( (_path[1] - _path[0]).norm() ) <<
'"'
2001 <<
" height=\"" << transform.scale( (_path[0] - _path[3]).norm() ) <<
'"'
2003 <<
" transform=\"rotate(" << -angle <<
", "
2004 << transform.mapX( _path[0].x ) <<
", " << transform.mapY( _path[0].y ) <<
") \" "
2005 <<
" />" << std::endl;
2011 Rectangle::flushCairo( cairo_t *cr,
2012 const TransformCairo & transform )
const
2015 double x1 = _path[1].x - _path[0].x;
2016 double y1 = _path[1].y - _path[0].y;
2017 double x2 = _path[3].x - _path[0].x;
2018 double y2 = _path[3].y - _path[0].y;
2019 if ( fabs(x1*x2 + y1*y2) > 0.01 ) {
2020 Polyline::flushCairo( cr, transform );
2029 if ( _path[0].y == _path[1].y )
2030 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 ));
2033 Point v = _path[1] - _path[0];
2035 double angle = ( _path[1].y > _path[0].y ) ? acos( v *
Point(1,0) ) : -acos( v *
Point( 1, 0 ) );
2038 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.);
2039 cairo_rotate (cr, angle);
2042 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() ));
2048 cairo_fill_preserve (cr);
2059 cairo_set_line_width (cr, _lineWidth);
2060 cairo_set_line_cap (cr, cairoLineCap[_lineCap]);
2061 cairo_set_line_join (cr, cairoLineJoin[_lineJoin]);
2062 setCairoDashStyle (cr, _lineStyle);
2073 const TransformTikZ & transform )
const
2079 << _path[0].x <<
',' << _path[0].y <<
')'
2081 << _path[1].x <<
',' << _path[3].y <<
");" << std::endl;
2124 : Polyline( std::vector<
Point>(), true, DGtal::Color::None, DGtal::Color::None,
2125 0.0f, SolidStyle, ButtCap, MiterJoin, depthValue ),
2126 _color0( color0 ), _color1( color1 ), _color2( color2 ), _subdivisions( subdivisions ) {
2131 Shape::_fillColor.red( ( color0.
red() + color1.
red() + color2.
red() ) / 3 );
2132 Shape::_fillColor.green( ( color0.
green() + color1.
green() + color2.
green() ) / 3 );
2133 Shape::_fillColor.blue( ( color0.
blue() + color1.
blue() + color2.
blue() ) / 3 );
2136 GouraudTriangle::GouraudTriangle(
const Point & p0,
float brightness0,
2137 const Point & p1,
float brightness1,
2138 const Point & p2,
float brightness2,
2142 : Polyline( std::vector<
Point>(), true, DGtal::Color::None, DGtal::Color::None,
2143 0.0f, SolidStyle, ButtCap, MiterJoin, depthValue ),
2144 _color0( fill ), _color1( fill ), _color2( fill ), _subdivisions( subdivisions )
2149 _color0.red( static_cast<unsigned char>( min( 255.0f, _color0.red() * brightness0 ) ) );
2150 _color0.green( static_cast<unsigned char>( min( 255.0f, _color0.green() * brightness0 ) ) );
2151 _color0.blue( static_cast<unsigned char>( min( 255.0f, _color0.blue() * brightness0 ) ) );
2152 _color1.red( static_cast<unsigned char>( min( 255.0f, _color1.red() * brightness1 ) ) );
2153 _color1.green( static_cast<unsigned char>( min( 255.0f, _color1.green() * brightness1 ) ) );
2154 _color1.blue( static_cast<unsigned char>( min( 255.0f, _color1.blue() * brightness1 ) ) );
2155 _color2.red( static_cast<unsigned char>( min( 255.0f, _color2.red() * brightness2 ) ) );
2156 _color2.green( static_cast<unsigned char>( min( 255.0f, _color2.green() * brightness2 ) ) );
2157 _color2.blue( static_cast<unsigned char>( min( 255.0f, _color2.blue() * brightness2 ) ) );
2159 Shape::_fillColor.red( ( _color0.red() + _color1.red() + _color2.red() ) / 3 );
2160 Shape::_fillColor.green( ( _color0.green() + _color1.green() + _color2.green() ) / 3 );
2161 Shape::_fillColor.blue( ( _color0.blue() + _color1.blue() + _color2.blue() ) / 3 );
2165 GouraudTriangle::center()
const {
2166 return ( _path[0] + _path[1] + _path[2] ) / 3.0;
2170 GouraudTriangle::rotate(
double angle,
const Point & rotCenter )
2172 _path.rotate( angle, rotCenter );
2177 GouraudTriangle::rotated(
double angle,
const Point & rotCenter )
const
2179 return GouraudTriangle(*this).rotate( angle, rotCenter );
2183 GouraudTriangle::rotate(
double angle )
2185 return GouraudTriangle::rotate( angle, center() );
2189 GouraudTriangle::rotated(
double angle )
const
2191 return GouraudTriangle(*this).rotate( angle, center() );
2195 GouraudTriangle::translated(
double dx,
double dy )
const
2197 return static_cast<GouraudTriangle &
>( GouraudTriangle(*this).translate( dx, dy ) );
2201 GouraudTriangle::scaled(
double sx,
double sy )
const
2203 return static_cast<GouraudTriangle &
>( GouraudTriangle(*this).scale( sx, sy ) );
2207 GouraudTriangle::scaled(
double s )
const
2209 return static_cast<GouraudTriangle &
>( GouraudTriangle(*this).scale( s, s ) );
2213 GouraudTriangle::scaleAll(
double s )
2215 _path.scaleAll( s );
2219 GouraudTriangle::clone()
const {
2220 return new GouraudTriangle(*
this);
2224 GouraudTriangle::flushPostscript( std::ostream & stream,
2225 const TransformEPS & transform )
const
2227 if ( ! _subdivisions ) {
2228 Polyline::flushPostscript( stream, transform );
2231 const Point & p0 = _path[0];
2232 const Point & p1 = _path[1];
2233 const Point & p2 = _path[2];
2234 Point p01( 0.5*(p0.
x+p1.
x), 0.5*(p0.
y+p1.
y) );
2236 (_color0.green() + _color1.green())/2,
2237 (_color0.blue() + _color1.blue())/2 );
2238 Point p12( 0.5*(p1.
x+p2.
x), 0.5*(p1.
y+p2.
y) );
2240 (_color1.green() + _color2.green())/2,
2241 (_color1.blue() + _color2.blue())/2 );
2242 Point p20( 0.5*(p2.
x+p0.
x), 0.5*(p2.
y+p0.
y) );
2244 (_color2.green() + _color0.green())/2,
2245 (_color2.blue() + _color0.blue())/2 );
2246 GouraudTriangle( p0, _color0, p20, c20, p01, c01, _subdivisions - 1, _depth ).flushPostscript( stream, transform );
2247 GouraudTriangle( p1, _color1, p01, c01, p12, c12, _subdivisions - 1, _depth ).flushPostscript( stream, transform );
2248 GouraudTriangle( p2, _color2, p20, c20, p12, c12, _subdivisions - 1, _depth ).flushPostscript( stream, transform );
2249 GouraudTriangle( p01, c01, p12, c12, p20, c20, _subdivisions - 1, _depth ).flushPostscript( stream, transform );
2253 GouraudTriangle::flushFIG( std::ostream & stream,
2254 const TransformFIG & transform,
2255 std::map<DGtal::Color,int> & colormap )
const
2258 DGtal::Color c( static_cast<unsigned char>((_color0.red() + _color1.red() + _color2.red() )/3.0),
2259 static_cast<unsigned char>((_color0.green() + _color1.green() + _color2.green())/3.0),
2260 static_cast<unsigned char>((_color0.blue() + _color1.blue() + _color2.blue())/3.0 ));
2261 Polyline( _path,
DGtal::Color::None, c, 0.0f ).flushFIG( stream, transform, colormap );
2290 GouraudTriangle::flushSVG( std::ostream & stream,
2291 const TransformSVG & transform )
const
2293 if ( ! _subdivisions ) {
2294 Polyline::flushSVG( stream, transform );
2297 const Point & p0 = _path[0];
2298 const Point & p1 = _path[1];
2299 const Point & p2 = _path[2];
2300 Point p01( 0.5*(p0.
x+p1.
x), 0.5*(p0.
y+p1.
y) );
2302 (_color0.green() + _color1.green())/2,
2303 (_color0.blue() + _color1.blue())/2 );
2304 Point p12( 0.5*(p1.
x+p2.
x), 0.5*(p1.
y+p2.
y) );
2306 (_color1.green() + _color2.green())/2,
2307 (_color1.blue() + _color2.blue())/2 );
2308 Point p20( 0.5*(p2.
x+p0.
x), 0.5*(p2.
y+p0.
y) );
2310 (_color2.green() + _color0.green())/2,
2311 (_color2.blue() + _color0.blue())/2 );
2312 GouraudTriangle( p0, _color0, p20, c20, p01, c01,
2313 _subdivisions - 1, _depth ).flushSVG( stream, transform );
2314 GouraudTriangle( p1, _color1, p01, c01, p12, c12,
2315 _subdivisions - 1, _depth ).flushSVG( stream, transform );
2316 GouraudTriangle( p2, _color2, p20, c20, p12, c12,
2317 _subdivisions - 1, _depth ).flushSVG( stream, transform );
2318 GouraudTriangle( p01, c01, p12, c12, p20, c20,
2319 _subdivisions - 1, _depth ).flushSVG( stream, transform );
2324 GouraudTriangle::flushCairo( cairo_t * ,
2325 const TransformCairo & )
const
2331 GouraudTriangle::flushTikZ( std::ostream & stream,
2332 const TransformTikZ & )
const
2335 stream <<
"% FIXME: GouraudTriangle::flushTikZ unimplemented" << endl;
2342 const std::string Triangle::_name(
"Triangle");
2345 Triangle::name()
const
2351 Triangle::rotated(
double angle )
const
2353 return static_cast<Triangle &
>( Triangle( *this ).rotate( angle ) );
2357 Triangle::translated(
double dx,
double dy )
const
2359 return static_cast<Triangle &
>( Triangle( *this ).translate( dx, dy ) );
2363 Triangle::scaled(
double sx,
double sy )
const
2365 return static_cast<Triangle &
>( Triangle( *this ).scale( sx, sy ) );
2369 Triangle::scaled(
double s )
const
2371 return static_cast<Triangle &
>( Triangle( *this ).scale( s ) );
2375 Triangle::clone()
const {
2376 return new Triangle(*
this);
2383 const std::string Text::_name(
"Text");
2392 Text::center()
const {
2397 Text::rotate(
double angle,
const Point & rotCenter )
2399 Point endPos = _position +
Point( 10000 * cos( _angle ), 10000 * sin( _angle ) );
2400 _position.rotate( angle, rotCenter );
2401 endPos.rotate( angle, rotCenter );
2402 Point v = endPos - _position;
2404 if ( v.
x >= 0 ) _angle = asin( v.
y );
2405 else if ( v.
y > 0 ) _angle = (
M_PI/2.0) + acos( v.
y );
2406 else _angle = (-
M_PI/2.0) - acos( -v.
y );
2411 Text::rotated(
double angle,
const Point & rotCenter )
const
2413 return Text(*this).rotate( angle, rotCenter );
2417 Text::rotate(
double angle )
2421 while ( _angle < M_PI ) _angle += 2 *
M_PI;
2423 while ( _angle > M_PI ) _angle -= 2 *
M_PI;
2428 Text::rotated(
double angle )
const
2430 return Text(*this).rotate( angle );
2434 Text::translate(
double dx,
double dy )
2436 _position +=
Point( dx, dy );
2441 Text::translated(
double dx,
double dy )
const
2443 return static_cast<Text&
>( Text(*this).translate( dx, dy ) );
2447 Text::scale(
double sx,
double sy )
2455 Text::scale(
double s )
2457 _xScale = _yScale = s;
2462 Text::scaled(
double sx,
double sy )
const
2464 return static_cast<Text &
>( Text(*this).scale( sx, sy ) );
2468 Text::scaled(
double s )
const
2470 return static_cast<Text &
>( Text(*this).scale( s, s ) );
2474 Text::scaleAll(
double s )
2480 Text::clone()
const {
2481 return new Text(*
this);
2485 Text::flushPostscript( std::ostream & stream,
2486 const TransformEPS & transform )
const
2488 stream <<
"\n% Text\n";
2489 stream <<
"gs /" <<
PSFontNames[ _font ] <<
" ff " << _size <<
" scf sf";
2490 stream <<
" " << transform.mapX( _position.x ) <<
" " << transform.mapY( _position.y ) <<
" m";
2491 if ( _angle != 0.0 ) stream <<
" " << (_angle/
M_PI)*180.0 <<
" rot ";
2492 stream <<
" (" << _text <<
")"
2493 <<
" " << _penColor.postscript() <<
" srgb"
2494 <<
" sh gr" << std::endl;
2498 Text::flushFIG( std::ostream & stream,
2499 const TransformFIG & transform,
2500 std::map<Color,int> & colormap )
const
2504 stream << colormap[ _penColor ] <<
" " << transform.mapDepth( _depth ) <<
" -1 " << _font <<
" ";
2506 stream << _size <<
" " << _angle <<
" 4 ";
2508 stream << static_cast<int>( _size * 135 / 12.0 ) <<
" ";
2510 stream << static_cast<int>( _text.size() * _size * 135 / 12.0 ) <<
" ";
2512 stream << static_cast<int>( transform.mapX( _position.x ) ) <<
" "
2513 << static_cast<int>( transform.mapY( _position.y ) ) <<
" ";
2514 stream << _text <<
"\\001\n";
2518 Text::flushSVG( std::ostream & stream,
2519 const TransformSVG & transform )
const
2521 if ( _angle != 0.0f ) {
2522 stream <<
"<g transform=\"translate("
2523 << transform.mapX( _position.x ) <<
","
2524 << transform.mapY( _position.y ) <<
")\" >"
2525 <<
"<g transform=\"rotate(" << (-_angle*180.0/
M_PI) <<
")\" >"
2526 <<
"<text x=\"0\" y=\"0\""
2527 <<
" font-family=\"" << ( _svgFont.length() ? _svgFont :
PSFontNames[ _font ] ) <<
"\""
2528 <<
" font-size=\"" << _size <<
"\""
2529 <<
" fill=\"" << _penColor.svg() <<
"\""
2530 << _fillColor.svgAlpha(
" fill" )
2531 << _penColor.svgAlpha(
" stroke" )
2534 <<
"</text></g></g>" << std::endl;
2536 stream <<
"<text x=\"" << transform.mapX( _position.x )
2537 <<
"\" y=\"" << transform.mapY( _position.y ) <<
"\" "
2538 <<
" font-family=\"" << ( _svgFont.length() ? _svgFont :
PSFontNames[ _font ] ) <<
"\""
2539 <<
" font-size=\"" << _size <<
"\""
2540 <<
" fill=\"" << _penColor.svg() <<
"\""
2541 << _fillColor.svgAlpha(
" fill" )
2542 << _penColor.svgAlpha(
" stroke" )
2545 <<
"</text>" << std::endl;
2551 Text::flushCairo( cairo_t * ,
2552 const TransformCairo & )
const
2558 Text::flushTikZ( std::ostream & stream,
2559 const TransformTikZ & transform )
const
2562 #define BOLD_FONT 0x01
2563 #define ITALIC_FONT 0x02
2564 #define MONOSPACE_FONT 0x04
2565 #define SANSSERIF_FONT 0x08
2566 char fontTraits[] = {
2580 MONOSPACE_FONT | ITALIC_FONT,
2581 MONOSPACE_FONT | BOLD_FONT,
2582 MONOSPACE_FONT | BOLD_FONT | ITALIC_FONT,
2584 SANSSERIF_FONT | ITALIC_FONT,
2585 SANSSERIF_FONT | BOLD_FONT,
2586 SANSSERIF_FONT | BOLD_FONT | ITALIC_FONT,
2588 SANSSERIF_FONT | ITALIC_FONT,
2589 SANSSERIF_FONT | BOLD_FONT,
2590 SANSSERIF_FONT | BOLD_FONT | ITALIC_FONT,
2594 BOLD_FONT | ITALIC_FONT,
2598 BOLD_FONT | ITALIC_FONT,
2604 stream <<
"\\path[" << tikzProperties(transform) <<
"] ("
2605 << transform.mapX( _position.x ) <<
',' << transform.mapY( _position.y )
2607 << (fontTraits[ _font ] &
ITALIC_FONT ?
"\\itshape " :
"")
2608 << (fontTraits[ _font ] & BOLD_FONT ?
"\\bfseries " :
"")
2610 << (fontTraits[ _font ] & SANSSERIF_FONT ?
"\\sffamily " :
"")
2612 <<
"};" << std::endl;
2616 Text::boundingBox()
const
2618 return Rect( _position.x, _position.y, 0, 0 );