A library for working with phylogenetic and population genetic data.
v0.32.0
shapes.cpp
Go to the documentation of this file.
1 /*
2  Genesis - A toolkit for working with phylogenetic data.
3  Copyright (C) 2014-2022 Lucas Czech
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  Contact:
19  Lucas Czech <lczech@carnegiescience.edu>
20  Department of Plant Biology, Carnegie Institution For Science
21  260 Panama Street, Stanford, CA 94305, USA
22 */
23 
32 
38 
39 #include <algorithm>
40 #include <cassert>
41 #include <limits>
42 #include <ostream>
43 #include <sstream>
44 #include <stdexcept>
45 
46 namespace genesis {
47 namespace utils {
48 
49 // =================================================================================================
50 // Svg Line
51 // =================================================================================================
52 
53 // -------------------------------------------------------------
54 // Constructors and Rule of Five
55 // -------------------------------------------------------------
56 
57 SvgLine::SvgLine( SvgPoint const& p1, SvgPoint const& p2, SvgStroke const& stroke )
58  : point_1( p1 )
59  , point_2( p2 )
60  , stroke( stroke )
61 {}
62 
63 SvgLine::SvgLine( double x1, double y1, double x2, double y2, SvgStroke const& stroke )
64  : SvgLine( SvgPoint( x1, y1 ), SvgPoint( x2, y2 ), stroke )
65 {}
66 
67 // -------------------------------------------------------------
68 // Members
69 // -------------------------------------------------------------
70 
72 {
73  // For a line, we do not want to just apply the transformations on the whole box,
74  // as this might give a way too large box under rotation. Instead, we rotate both
75  // points individually, and then compute the box from that.
76  auto const t1 = transform.apply( point_1 );
77  auto const t2 = transform.apply( point_2 );
78  return {
79  SvgPoint( std::min( t1.x, point_2.x ), std::min( t1.y, point_2.y )),
80  SvgPoint( std::max( t2.x, point_2.x ), std::max( t2.y, point_2.y ))
81  };
82 
83  // Without applying transformations:
84  // return {
85  // SvgPoint( std::min( point_1.x, point_2.x ), std::min( point_1.y, point_2.y )),
86  // SvgPoint( std::max( point_1.x, point_2.x ), std::max( point_1.y, point_2.y ))
87  // };
88 }
89 
90 void SvgLine::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
91 {
93  out << "<line";
94 
95  if( ! id.empty() ) {
96  out << svg_attribute( "id", id );
97  }
98 
99  out << svg_attribute( "x1", point_1.x + options.offset_x );
100  out << svg_attribute( "y1", point_1.y + options.offset_y );
101  out << svg_attribute( "x2", point_2.x + options.offset_x );
102  out << svg_attribute( "y2", point_2.y + options.offset_y );
103 
104  stroke.write( out );
105  transform.write( out );
106  out << " />\n";
107 }
108 
109 // =================================================================================================
110 // Svg Rect
111 // =================================================================================================
112 
113 // -------------------------------------------------------------
114 // Constructors and Rule of Five
115 // -------------------------------------------------------------
116 
118  SvgPoint const& position,
119  SvgSize const& size,
120  SvgStroke const& stroke,
121  SvgFill const& fill
122 )
123  : position( position )
124  , size( size )
125  , stroke( stroke )
126  , fill( fill )
127  , rx( 0.0 )
128  , ry( 0.0 )
129 {}
130 
132  double x, double y,
133  double w, double h,
134  SvgStroke const& stroke ,
135  SvgFill const& fill
136 )
137  : SvgRect( SvgPoint( x, y ), SvgSize( w, h ), stroke, fill )
138 {}
139 
140 // -------------------------------------------------------------
141 // Members
142 // -------------------------------------------------------------
143 
145 {
147 }
148 
149 void SvgRect::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
150 {
152  out << "<rect";
153 
154  if( ! id.empty() ) {
155  out << svg_attribute( "id", id );
156  }
157 
158  out << svg_attribute( "x", position.x + options.offset_x );
159  out << svg_attribute( "y", position.y + options.offset_y );
160  out << svg_attribute( "width", size.width );
161  out << svg_attribute( "height", size.height );
162 
163  if( rx != 0.0 || ry != 0.0 ) {
164  out << svg_attribute( "rx", rx );
165  out << svg_attribute( "ry", ry );
166  }
167 
168  stroke.write( out );
169  fill.write( out );
170  transform.write( out );
171  out << " />\n";
172 }
173 
174 // =================================================================================================
175 // Svg Circle
176 // =================================================================================================
177 
178 // -------------------------------------------------------------
179 // Constructors and Rule of Five
180 // -------------------------------------------------------------
181 
183  SvgPoint const& center,
184  double radius,
185  SvgStroke const& stroke,
186  SvgFill const& fill
187 )
188  : center( center )
189  , radius( radius )
190  , stroke( stroke )
191  , fill( fill )
192 {}
193 
195  double cx, double cy,
196  double radius,
197  SvgStroke const& stroke,
198  SvgFill const& fill
199 )
200  : SvgCircle( SvgPoint( cx, cy ), radius, stroke, fill )
201 {}
202 
203 // -------------------------------------------------------------
204 // Members
205 // -------------------------------------------------------------
206 
208 {
209  // Computing the transformations of a circle is tricky... Not bothering with that for now,
210  // and instead just compute the transformed large box that definitly fits it.
211  return transform.apply( SvgBox{
214  });
215 }
216 
217 void SvgCircle::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
218 {
220  out << "<circle";
221 
222  if( ! id.empty() ) {
223  out << svg_attribute( "id", id );
224  }
225 
226  out << svg_attribute( "cx", center.x + options.offset_x );
227  out << svg_attribute( "cy", center.y + options.offset_y );
228  out << svg_attribute( "r", radius );
229 
230  stroke.write( out );
231  fill.write( out );
232  transform.write( out );
233  out << " />\n";
234 }
235 
236 // =================================================================================================
237 // Svg Ellipse
238 // =================================================================================================
239 
240 // -------------------------------------------------------------
241 // Constructors and Rule of Five
242 // -------------------------------------------------------------
243 
245  SvgPoint const& center,
246  double rx, double ry,
247  SvgStroke const& stroke,
248  SvgFill const& fill
249 )
250  : center( center )
251  , rx( rx )
252  , ry( ry )
253  , stroke( stroke )
254  , fill( fill )
255 {}
256 
258  double cx, double cy,
259  double rx, double ry,
260  SvgStroke const& stroke,
261  SvgFill const& fill
262 )
263  : SvgEllipse( SvgPoint( cx, cy ), rx, ry, stroke, fill )
264 {}
265 
266 // -------------------------------------------------------------
267 // Members
268 // -------------------------------------------------------------
269 
271 {
272  // Same as for the circle, not bothering with the complex transformations as of now...
273  return transform.apply( SvgBox{
274  SvgPoint( center.x - rx, center.y - ry ),
275  SvgPoint( center.x + rx, center.y + ry )
276  });
277 }
278 
279 void SvgEllipse::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
280 {
282  out << "<ellipse";
283 
284  if( ! id.empty() ) {
285  out << svg_attribute( "id", id );
286  }
287 
288  out << svg_attribute( "cx", center.x + options.offset_x );
289  out << svg_attribute( "cy", center.y + options.offset_y );
290  out << svg_attribute( "rx", rx );
291  out << svg_attribute( "ry", ry );
292 
293  stroke.write( out );
294  fill.write( out );
295  transform.write( out );
296  out << " />\n";
297 }
298 
299 // =================================================================================================
300 // Svg Polyline
301 // =================================================================================================
302 
303 // -------------------------------------------------------------
304 // Constructors and Rule of Five
305 // -------------------------------------------------------------
306 
308  SvgStroke const& stroke,
309  SvgFill const& fill
310 )
311  : stroke( stroke )
312  , fill( fill )
313 {}
314 
316  std::vector< SvgPoint > points,
317  SvgStroke const& stroke,
318  SvgFill const& fill
319 )
320  : points( points )
321  , stroke( stroke )
322  , fill( fill )
323 {}
324 
325 // -------------------------------------------------------------
326 // Members
327 // -------------------------------------------------------------
328 
329 SvgPolyline& SvgPolyline::add( double x, double y )
330 {
331  return add( SvgPoint( x, y ));
332 }
333 
335 {
336  points.push_back( p );
337  return *this;
338 }
339 
341 {
342  return add( p );
343 }
344 
346 {
347  return svg_bounding_box( points, transform );
348 }
349 
350 void SvgPolyline::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
351 {
353  out << "<polyline";
354 
355  if( ! id.empty() ) {
356  out << svg_attribute( "id", id );
357  }
358 
359  out << " points=\"";
360  for( size_t i = 0; i < points.size(); ++i ) {
361  if( i > 0 ) {
362  out << " ";
363  }
364  out << ( points[i].x + options.offset_x ) << ",";
365  out << ( points[i].y + options.offset_y );
366  }
367  out << "\"";
368 
369  stroke.write( out );
370  fill.write( out );
371  transform.write( out );
372  out << " />\n";
373 }
374 
375 // =================================================================================================
376 // Svg Polygon
377 // =================================================================================================
378 
379 // -------------------------------------------------------------
380 // Constructors and Rule of Five
381 // -------------------------------------------------------------
382 
384  SvgStroke const& stroke,
385  SvgFill const& fill
386 )
387  : stroke( stroke )
388  , fill( fill )
389 {}
390 
392  std::vector< SvgPoint > const& points,
393  SvgStroke const& stroke,
394  SvgFill const& fill
395 )
396  : points( points )
397  , stroke( stroke )
398  , fill( fill )
399 {}
400 
401 // -------------------------------------------------------------
402 // Members
403 // -------------------------------------------------------------
404 
405 SvgPolygon& SvgPolygon::add( double x, double y )
406 {
407  return add( SvgPoint( x, y ));
408 }
409 
411 {
412  points.push_back( p );
413  return *this;
414 }
415 
417 {
418  return add( p );
419 }
420 
422 {
423  return svg_bounding_box( points, transform );
424 }
425 
426 void SvgPolygon::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
427 {
429  out << "<polygon";
430 
431  if( ! id.empty() ) {
432  out << svg_attribute( "id", id );
433  }
434 
435  out << " points=\"";
436  for( size_t i = 0; i < points.size(); ++i ) {
437  if( i > 0 ) {
438  out << " ";
439  }
440  out << ( points[i].x + options.offset_x ) << ",";
441  out << ( points[i].y + options.offset_y );
442  }
443  out << "\"";
444 
445  stroke.write( out );
446  fill.write( out );
447  transform.write( out );
448  out << " />\n";
449 }
450 
451 // =================================================================================================
452 // Svg Path
453 // =================================================================================================
454 
455 // -------------------------------------------------------------
456 // Constructors and Rule of Five
457 // -------------------------------------------------------------
458 
460  SvgStroke const& stroke,
461  SvgFill const& fill
462 )
463  : stroke( stroke )
464  , fill( fill )
465 {}
466 
468  std::vector< std::string > const& elements,
469  SvgStroke const& stroke,
470  SvgFill const& fill
471 )
472  : elements(elements)
473  , stroke( stroke )
474  , fill( fill )
475 {}
476 
477 // -------------------------------------------------------------
478 // Members
479 // -------------------------------------------------------------
480 
481 SvgPath& SvgPath::add( std::string elem )
482 {
483  elements.push_back( elem );
484  return *this;
485 }
486 
487 SvgPath& SvgPath::operator <<( std::string elem )
488 {
489  return add( elem );
490 }
491 
493 {
494  // We collect all points that are part of the path, and transform later.
495  // Could be done more mem efficient by doing the transforms immediately,
496  // but well... easier that way for now.
497  std::vector<SvgPoint> points;
498 
499  // Helper functions to read a single value and a pair of values, e.g., a coordinate.
500  // We check that these are values, and not new commands. In the check, we access the first
501  // character of the current list element, which is valid, as our split function
502  // does not output empty elements.
503  auto read_value_ = []( std::vector<std::string> const& list, size_t& i, double& value )
504  {
505  if( i >= list.size() ) {
506  return false;
507  }
508  assert( ! list[i].empty() );
509  if( is_alpha( list[i][0] ) ) {
510  return false;
511  }
512  value = convert_to_double( list[i + 0] );
513  ++i;
514  return true;
515  };
516  auto read_coord_ = []( std::vector<std::string> const& list, size_t& i, SvgPoint& coord )
517  {
518  if( i + 1 >= list.size() ) {
519  return false;
520  }
521  assert( ! list[ i + 0 ].empty() );
522  assert( ! list[ i + 1 ].empty() );
523  if( is_alpha( list[ i + 0 ][0] ) || is_alpha( list[ i + 1 ][0] )) {
524  return false;
525  }
526  coord.x = convert_to_double( list[ i + 0 ] );
527  coord.y = convert_to_double( list[ i + 1 ] );
528  i += 2;
529  return true;
530  };
531 
532  bool start = true;
533  SvgPoint cur;
534  for( auto const& elem : elements ) {
535  auto const list = split( elem, " \t," );
536 
537  // We expect the commands to be separated from their values... That is not according
538  // to the svg standard, where there does not need to be a delimiter, but it works for now,
539  // where we have control over the path commands that we use.
540  // If we ever need to change that, we might be able to just replace the above split call
541  // by something that also splits at alpha char boundaries. Might be a bit tricky in case
542  // that doubles are printed with e or E for exponents... But something along those lines.
543  for( size_t i = 0; i < list.size(); ) {
544  auto const& tok = list[i];
545  if( start && tok != "M" && tok != "m" ) {
546  throw std::invalid_argument( "SvgPath has to start with an M or m command." );
547  }
548  start = false;
549 
550  // Start the token processing at the first value. Easier for all below code.
551  // We also define a value and a coord var, to fill with data by the helper functions.
552  ++i;
553  double value;
554  SvgPoint coord;
555 
556  // moveto and lineto
557  // https://svgwg.org/svg2-draft/paths.html#PathDataMovetoCommands
558  // https://svgwg.org/svg2-draft/paths.html#PathDataLinetoCommands
559  if( tok == "M" || tok == "m" || tok == "L" || tok == "l" ) {
560  bool once = false;
561  while( read_coord_( list, i, coord )) {
562  if( tok == "M" || tok == "L" ) {
563  cur = coord;
564  }
565  if( tok == "m" || tok == "l" ) {
566  cur = cur + coord;
567  }
568  points.push_back( cur );
569  once = true;
570  }
571  if( ! once ) {
572  throw std::runtime_error( "Invalid SvgPath moveto or lineto command." );
573  }
574  continue;
575  }
576 
577  // closepath
578  // https://svgwg.org/svg2-draft/paths.html#PathDataClosePathCommand
579  if( tok == "Z" || tok == "z" ) {
580  continue;
581  }
582 
583  // lineto h and v
584  // https://svgwg.org/svg2-draft/paths.html#PathDataLinetoCommands
585  if( tok == "H" || tok == "h" || tok == "V" || tok == "v" ) {
586  bool once = false;
587  while( read_value_( list, i, value )) {
588  if( tok == "H" ) {
589  cur.x = value;
590  }
591  if( tok == "h" ) {
592  cur.x += value;
593  }
594  if( tok == "V" ) {
595  cur.y = value;
596  }
597  if( tok == "v" ) {
598  cur.y += value;
599  }
600  points.push_back( cur );
601  once = true;
602  }
603  if( ! once ) {
604  throw std::runtime_error( "Invalid SvgPath hor or ver line command." );
605  }
606  continue;
607  }
608 
609  // cubic and quadratic bezier
610  // https://svgwg.org/svg2-draft/paths.html#PathDataCubicBezierCommands
611  // https://svgwg.org/svg2-draft/paths.html#PathDataQuadraticBezierCommands
612  if(
613  tok == "C" || tok == "c" || tok == "S" || tok == "s" ||
614  tok == "Q" || tok == "q" || tok == "T" || tok == "t"
615  ) {
616  bool once = false;
617  while( read_coord_( list, i, coord )) {
618  // We read extra coordinates as needed. Only the last pair is what we want.
619  bool good = true;
620  if(
621  tok == "C" || tok == "c" ||
622  tok == "S" || tok == "s" ||
623  tok == "Q" || tok == "q"
624  ) {
625  good &= read_coord_( list, i, coord );
626  }
627  if( tok == "C" || tok == "c" ) {
628  good &= read_coord_( list, i, coord );
629  }
630  if( ! good ) {
631  throw std::runtime_error( "Invalid SvgPath Bezier command." );
632  }
633 
634  // Turn them into our current coordinate as needed, and store it.
635  if( tok == "C" || tok == "S" || tok == "Q" || tok == "T" ) {
636  cur = coord;
637  }
638  if( tok == "c" || tok == "s" || tok == "q" || tok == "t" ) {
639  cur = cur + coord;
640  }
641  points.push_back( cur );
642  once = true;
643  }
644  if( ! once ) {
645  throw std::runtime_error( "Invalid SvgPath Beziercommand." );
646  }
647  continue;
648  }
649 
650  // elliptical arc curve
651  // https://svgwg.org/svg2-draft/paths.html#PathDataEllipticalArcCommands
652  if( tok == "A" || tok == "a" ) {
653  bool once = false;
654  while( read_coord_( list, i, coord )) {
655  // We simplify our code here a bit, and read the flags as doubles...
656  // we ignore them anyway, so that should work.
657  bool good = true;
658  good &= read_value_( list, i, value );
659  good &= read_coord_( list, i, coord );
660  good &= read_coord_( list, i, coord );
661  if( ! good ) {
662  throw std::runtime_error( "Invalid SvgPath elliptical arc curve command." );
663  }
664 
665  // Turn them into our current coordinate as needed, and store it.
666  if( tok == "A" ) {
667  cur = coord;
668  }
669  if( tok == "a" ) {
670  cur = cur + coord;
671  }
672  points.push_back( cur );
673  once = true;
674  }
675  if( ! once ) {
676  throw std::runtime_error( "Invalid SvgPath elliptical arc curve command." );
677  }
678  continue;
679  }
680 
681  // Reaching here means we were not able to process the token.
682  throw std::runtime_error( "Invalid SvgPath command '" + tok + "'." );
683  }
684  }
685 
686  // Now we have all the raw points involved in the path. Send all of them through the
687  // list of transformations to get where they actually end up in the rendering.
688  return svg_bounding_box( points, transform );
689 }
690 
691 void SvgPath::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
692 {
693  (void) options;
694 
696  out << "<path";
697 
698  if( ! id.empty() ) {
699  out << svg_attribute( "id", id );
700  }
701 
702  out << " d=\"";
703  for( size_t i = 0; i < elements.size(); ++i ) {
704  if( i > 0 ) {
705  out << " ";
706  }
707  out << elements[i];
708  }
709  out << "\"";
710 
711  stroke.write( out );
712  fill.write( out );
713  transform.write( out );
714  out << " />\n";
715 }
716 
717 // =================================================================================================
718 // Svg Use
719 // =================================================================================================
720 
722 {
723  // Computing the bounding box here is super involved, as the object could have its own
724  // transformations first. Then, its bounding box might already be oversized due to how we
725  // apply transformations on bounding boxes, and then we add the offset and apply the
726  // transformations of this SvgUse object here afterwards, potentally overscaling again...
727  // But that's the best that we can do for now. Good enough.
728  auto ob = object->bounding_box();
729  ob.top_left.x += offset.x;
730  ob.top_left.y += offset.y;
731  ob.bottom_right.x += offset.x;
732  ob.bottom_right.y += offset.y;
733  return transform.apply( ob );
734 }
735 
736 void SvgUse::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
737 {
739  out << "<use";
740  if( ! id.empty() ) {
741  out << svg_attribute( "id", id );
742  }
743  out << svg_attribute( "xlink:href", "#" + object->id() );
744  out << svg_attribute( "x", offset.x + options.offset_x );
745  out << svg_attribute( "y", offset.y + options.offset_y );
746  transform.write( out );
747  out << " />\n";
748 }
749 
750 } // namespace utils
751 } // namespace genesis
genesis::utils::SvgPolygon::bounding_box
SvgBox bounding_box() const
Definition: shapes.cpp:421
genesis::utils::SvgRect::stroke
SvgStroke stroke
Definition: shapes.hpp:169
genesis::utils::SvgEllipse::center
SvgPoint center
Definition: shapes.hpp:305
genesis::utils::SvgPoint::x
double x
Definition: utils/formats/svg/helper.hpp:69
genesis::utils::SvgPolygon::points
std::vector< SvgPoint > points
Definition: shapes.hpp:445
genesis::utils::SvgCircle::radius
double radius
Definition: shapes.hpp:238
genesis::utils::SvgEllipse
Definition: shapes.hpp:251
helper.hpp
genesis::utils::SvgRect::size
SvgSize size
Definition: shapes.hpp:167
genesis::utils::SvgPath::elements
std::vector< std::string > elements
Definition: shapes.hpp:521
genesis::utils::SvgRect::rx
double rx
Definition: shapes.hpp:172
genesis::utils::indent
std::string indent(std::string const &text, std::string const &indentation)
Indent each line of text with indentation and return the result.
Definition: string.cpp:719
genesis::utils::SvgCircle::stroke
SvgStroke stroke
Definition: shapes.hpp:240
genesis::utils::SvgPath::stroke
SvgStroke stroke
Definition: shapes.hpp:523
genesis::utils::SvgCircle::transform
SvgTransform transform
Definition: shapes.hpp:243
genesis::utils::SvgEllipse::SvgEllipse
SvgEllipse(SvgPoint const &center, double rx, double ry, SvgStroke const &stroke=SvgStroke(), SvgFill const &fill=SvgFill())
Definition: shapes.cpp:244
genesis::utils::SvgPoint::y
double y
Definition: utils/formats/svg/helper.hpp:70
genesis::utils::SvgPath::operator<<
self_type & operator<<(std::string elem)
Definition: shapes.cpp:487
genesis::utils::SvgEllipse::transform
SvgTransform transform
Definition: shapes.hpp:312
genesis::utils::SvgPath::write
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:691
genesis::utils::SvgTransform::apply
SvgPoint apply(SvgPoint const &p) const
Apply all transformations to a point, and return the new transformed coordinate.
Definition: attributes.cpp:363
genesis::utils::SvgPolyline::fill
SvgFill fill
Definition: shapes.hpp:379
genesis::utils::SvgPolyline
Definition: shapes.hpp:320
genesis::utils::SvgPolyline::operator<<
self_type & operator<<(SvgPoint p)
Definition: shapes.cpp:340
genesis::utils::SvgPath
Definition: shapes.hpp:458
shapes.hpp
genesis::utils::SvgPolyline::transform
SvgTransform transform
Definition: shapes.hpp:381
genesis::utils::SvgCircle::write
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:217
genesis::utils::SvgPolygon::stroke
SvgStroke stroke
Definition: shapes.hpp:447
genesis::utils::SvgObject::id
std::string const & id() const
Definition: object.hpp:88
genesis::utils::SvgLine
Definition: shapes.hpp:50
genesis::utils::SvgBox::top_left
SvgPoint top_left
Definition: utils/formats/svg/helper.hpp:204
genesis::utils::SvgUse::transform
SvgTransform transform
Definition: shapes.hpp:606
genesis::utils::SvgDrawingOptions::offset_y
double offset_y
Definition: utils/formats/svg/helper.hpp:216
genesis::utils::SvgRect::bounding_box
SvgBox bounding_box() const
Definition: shapes.cpp:144
genesis::utils::SvgBox
Definition: utils/formats/svg/helper.hpp:127
genesis::utils::SvgDrawingOptions::offset_x
double offset_x
Definition: utils/formats/svg/helper.hpp:215
genesis::utils::SvgCircle
Definition: shapes.hpp:183
genesis::utils::SvgLine::write
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:90
genesis::utils::SvgPolyline::add
self_type & add(double x, double y)
Definition: shapes.cpp:329
genesis::utils::SvgLine::bounding_box
SvgBox bounding_box() const
Definition: shapes.cpp:71
genesis::utils::SvgTransform::write
void write(std::ostream &out) const
Definition: attributes.cpp:394
genesis::utils::SvgPolyline::bounding_box
SvgBox bounding_box() const
Definition: shapes.cpp:345
genesis::utils::SvgPath::bounding_box
SvgBox bounding_box() const
Compute the bounding box of the path.
Definition: shapes.cpp:492
genesis::utils::split
std::vector< std::string > split(std::string const &str, char delimiter, const bool trim_empty)
Spilt a string into parts, given a delimiter char.
Definition: string.cpp:575
genesis::utils::SvgPolygon::add
self_type & add(double x, double y)
Definition: shapes.cpp:405
genesis::utils::SvgEllipse::ry
double ry
Definition: shapes.hpp:307
genesis::utils::SvgDocument::indentation_string
static std::string indentation_string
Definition: svg/document.hpp:60
genesis::utils::SvgCircle::center
SvgPoint center
Definition: shapes.hpp:237
genesis::utils::SvgPoint
Definition: utils/formats/svg/helper.hpp:57
genesis::utils::convert_to_double
void convert_to_double(Dataframe &df, size_t col_index)
Definition: utils/containers/dataframe/operators.cpp:192
genesis::utils::SvgStroke
Definition: attributes.hpp:49
string.hpp
Provides some commonly used string utility functions.
genesis::utils::SvgRect
Definition: shapes.hpp:112
genesis::utils::SvgLine::transform
SvgTransform transform
Definition: shapes.hpp:104
document.hpp
genesis::utils::SvgLine::SvgLine
SvgLine(SvgPoint const &point_1, SvgPoint const &point_2, SvgStroke const &stroke=SvgStroke())
Definition: shapes.cpp:57
genesis::utils::SvgUse::object
SvgObject const * object
Definition: shapes.hpp:602
genesis::utils::SvgPolyline::points
std::vector< SvgPoint > points
Definition: shapes.hpp:376
genesis::utils::SvgPolygon
Definition: shapes.hpp:389
genesis::utils::SvgLine::stroke
SvgStroke stroke
Definition: shapes.hpp:103
genesis::utils::SvgUse::bounding_box
SvgBox bounding_box() const
Definition: shapes.cpp:721
genesis::utils::SvgEllipse::fill
SvgFill fill
Definition: shapes.hpp:310
genesis::utils::SvgPolyline::SvgPolyline
SvgPolyline(SvgStroke const &stroke=SvgStroke(), SvgFill const &fill=SvgFill())
Definition: shapes.cpp:307
genesis::utils::SvgRect::ry
double ry
Definition: shapes.hpp:173
genesis::utils::SvgRect::fill
SvgFill fill
Definition: shapes.hpp:170
genesis::utils::SvgUse::write
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:736
genesis::utils::SvgRect::write
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:149
genesis::utils::SvgPolygon::fill
SvgFill fill
Definition: shapes.hpp:448
genesis::utils::SvgCircle::fill
SvgFill fill
Definition: shapes.hpp:241
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
genesis::utils::SvgPolygon::SvgPolygon
SvgPolygon(SvgStroke const &stroke=SvgStroke(), SvgFill const &fill=SvgFill())
Definition: shapes.cpp:383
genesis::utils::SvgFill
Definition: attributes.hpp:131
genesis::utils::svg_attribute
std::string svg_attribute(std::string const &name, T const &value, std::string const &unit="")
Definition: utils/formats/svg/helper.hpp:229
genesis::utils::SvgPath::SvgPath
SvgPath(SvgStroke const &stroke=SvgStroke(), SvgFill const &fill=SvgFill())
Definition: shapes.cpp:459
genesis::utils::SvgFill::write
void write(std::ostream &out) const
Definition: attributes.cpp:166
convert.hpp
genesis::utils::SvgEllipse::bounding_box
SvgBox bounding_box() const
Definition: shapes.cpp:270
genesis::utils::SvgCircle::bounding_box
SvgBox bounding_box() const
Definition: shapes.cpp:207
genesis::utils::SvgRect::SvgRect
SvgRect(SvgPoint const &position, SvgSize const &size, SvgStroke const &stroke=SvgStroke(), SvgFill const &fill=SvgFill())
Definition: shapes.cpp:117
char.hpp
genesis::utils::SvgSize
Definition: utils/formats/svg/helper.hpp:77
genesis::utils::SvgCircle::SvgCircle
SvgCircle(SvgPoint const &center, double radius, SvgStroke const &stroke=SvgStroke(), SvgFill const &fill=SvgFill())
Definition: shapes.cpp:182
genesis::utils::SvgPath::add
self_type & add(std::string elem)
Definition: shapes.cpp:481
genesis::utils::SvgPath::fill
SvgFill fill
Definition: shapes.hpp:524
genesis::utils::SvgPolygon::write
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:426
genesis::utils::SvgPolygon::operator<<
self_type & operator<<(SvgPoint p)
Definition: shapes.cpp:416
genesis::utils::SvgLine::point_2
SvgPoint point_2
Definition: shapes.hpp:102
genesis::utils::repeat
std::string repeat(std::string const &word, size_t times)
Take a string and repeat it a given number of times.
Definition: string.cpp:1001
genesis::utils::SvgPath::transform
SvgTransform transform
Definition: shapes.hpp:526
genesis::utils::SvgEllipse::stroke
SvgStroke stroke
Definition: shapes.hpp:309
genesis::utils::svg_bounding_box
SvgBox svg_bounding_box(std::vector< SvgPoint > const &points)
Compute the bounding box of a set of points.
Definition: utils/formats/svg/helper.cpp:87
genesis::utils::SvgLine::point_1
SvgPoint point_1
Definition: shapes.hpp:101
genesis::utils::SvgSize::width
double width
Definition: utils/formats/svg/helper.hpp:84
genesis::utils::SvgEllipse::write
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:279
genesis::utils::SvgStroke::write
void write(std::ostream &out) const
Definition: attributes.cpp:82
genesis::utils::SvgPolygon::transform
SvgTransform transform
Definition: shapes.hpp:450
genesis::utils::SvgSize::height
double height
Definition: utils/formats/svg/helper.hpp:85
genesis::utils::SvgRect::transform
SvgTransform transform
Definition: shapes.hpp:175
genesis::utils::SvgDrawingOptions
Definition: utils/formats/svg/helper.hpp:213
genesis::utils::SvgRect::position
SvgPoint position
Definition: shapes.hpp:166
genesis::utils::SvgEllipse::rx
double rx
Definition: shapes.hpp:306
genesis::utils::SvgPolyline::write
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:350
genesis::utils::is_alpha
constexpr bool is_alpha(char c) noexcept
Return whether a char is a letter (a-z or A-Z), ASCII-only.
Definition: char.hpp:135
genesis::utils::SvgUse::offset
SvgPoint offset
Definition: shapes.hpp:605
genesis::utils::SvgPolyline::stroke
SvgStroke stroke
Definition: shapes.hpp:378