A toolkit for working with phylogenetic data.
v0.20.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
shapes.cpp
Go to the documentation of this file.
1 /*
2  Genesis - A toolkit for working with phylogenetic data.
3  Copyright (C) 2014-2017 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 <lucas.czech@h-its.org>
20  Exelixis Lab, Heidelberg Institute for Theoretical Studies
21  Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany
22 */
23 
32 
35 
36 #include <algorithm>
37 #include <ostream>
38 #include <stdexcept>
39 
40 namespace genesis {
41 namespace utils {
42 
43 // =================================================================================================
44 // Svg Line
45 // =================================================================================================
46 
47 // -------------------------------------------------------------
48 // Constructors and Rule of Five
49 // -------------------------------------------------------------
50 
51 SvgLine::SvgLine( SvgPoint const& p1, SvgPoint const& p2, SvgStroke const& stroke )
52  : point_1( p1 )
53  , point_2( p2 )
54  , stroke( stroke )
55 {}
56 
57 SvgLine::SvgLine( double x1, double y1, double x2, double y2, SvgStroke const& stroke )
58  : SvgLine( SvgPoint( x1, y1 ), SvgPoint( x2, y2 ), stroke )
59 {}
60 
61 // -------------------------------------------------------------
62 // Members
63 // -------------------------------------------------------------
64 
66 {
67  return {
68  SvgPoint( std::min( point_1.x, point_2.x ), std::min( point_1.y, point_2.y )),
69  SvgPoint( std::max( point_1.x, point_2.x ), std::max( point_1.y, point_2.y ))
70  };
71 }
72 
73 void SvgLine::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
74 {
75  out << repeat( SvgDocument::indentation_string, indent );
76  out << "<line";
77 
78  if( ! id.empty() ) {
79  out << svg_attribute( "id", id );
80  }
81 
82  out << svg_attribute( "x1", point_1.x + options.offset_x );
83  out << svg_attribute( "y1", point_1.y + options.offset_y );
84  out << svg_attribute( "x2", point_2.x + options.offset_x );
85  out << svg_attribute( "y2", point_2.y + options.offset_y );
86 
87  stroke.write( out );
88  transform.write( out );
89  out << " />\n";
90 }
91 
92 // =================================================================================================
93 // Svg Rect
94 // =================================================================================================
95 
96 // -------------------------------------------------------------
97 // Constructors and Rule of Five
98 // -------------------------------------------------------------
99 
101  SvgPoint const& position,
102  SvgSize const& size,
103  SvgStroke const& stroke,
104  SvgFill const& fill
105 )
106  : position( position )
107  , size( size )
108  , stroke( stroke )
109  , fill( fill )
110  , rx( 0.0 )
111  , ry( 0.0 )
112 {}
113 
115  double x, double y,
116  double w, double h,
117  SvgStroke const& stroke ,
118  SvgFill const& fill
119 )
120  : SvgRect( SvgPoint( x, y ), SvgSize( w, h ), stroke, fill )
121 {}
122 
123 // -------------------------------------------------------------
124 // Members
125 // -------------------------------------------------------------
126 
128 {
129  return { position, size.width, size.height };
130 }
131 
132 void SvgRect::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
133 {
134  out << repeat( SvgDocument::indentation_string, indent );
135  out << "<rect";
136 
137  if( ! id.empty() ) {
138  out << svg_attribute( "id", id );
139  }
140 
141  out << svg_attribute( "x", position.x + options.offset_x );
142  out << svg_attribute( "y", position.y + options.offset_y );
143  out << svg_attribute( "width", size.width );
144  out << svg_attribute( "height", size.height );
145 
146  if( rx != 0.0 || ry != 0.0 ) {
147  out << svg_attribute( "rx", rx );
148  out << svg_attribute( "ry", ry );
149  }
150 
151  stroke.write( out );
152  fill.write( out );
153  transform.write( out );
154  out << " />\n";
155 }
156 
157 // =================================================================================================
158 // Svg Circle
159 // =================================================================================================
160 
161 // -------------------------------------------------------------
162 // Constructors and Rule of Five
163 // -------------------------------------------------------------
164 
166  SvgPoint const& center,
167  double radius,
168  SvgStroke const& stroke,
169  SvgFill const& fill
170 )
171  : center( center )
172  , radius( radius )
173  , stroke( stroke )
174  , fill( fill )
175 {}
176 
178  double cx, double cy,
179  double radius,
180  SvgStroke const& stroke,
181  SvgFill const& fill
182 )
183  : SvgCircle( SvgPoint( cx, cy ), radius, stroke, fill )
184 {}
185 
186 // -------------------------------------------------------------
187 // Members
188 // -------------------------------------------------------------
189 
191 {
192  return {
195  };
196 }
197 
198 void SvgCircle::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
199 {
200  out << repeat( SvgDocument::indentation_string, indent );
201  out << "<circle";
202 
203  if( ! id.empty() ) {
204  out << svg_attribute( "id", id );
205  }
206 
207  out << svg_attribute( "cx", center.x + options.offset_x );
208  out << svg_attribute( "cy", center.y + options.offset_y );
209  out << svg_attribute( "r", radius );
210 
211  stroke.write( out );
212  fill.write( out );
213  transform.write( out );
214  out << " />\n";
215 }
216 
217 // =================================================================================================
218 // Svg Ellipse
219 // =================================================================================================
220 
221 // -------------------------------------------------------------
222 // Constructors and Rule of Five
223 // -------------------------------------------------------------
224 
226  SvgPoint const& center,
227  double rx, double ry,
228  SvgStroke const& stroke,
229  SvgFill const& fill
230 )
231  : center( center )
232  , rx( rx )
233  , ry( ry )
234  , stroke( stroke )
235  , fill( fill )
236 {}
237 
239  double cx, double cy,
240  double rx, double ry,
241  SvgStroke const& stroke,
242  SvgFill const& fill
243 )
244  : SvgEllipse( SvgPoint( cx, cy ), rx, ry, stroke, fill )
245 {}
246 
247 // -------------------------------------------------------------
248 // Members
249 // -------------------------------------------------------------
250 
252 {
253  return {
254  SvgPoint( center.x - rx, center.y - ry ),
255  SvgPoint( center.x + rx, center.y + ry )
256  };
257 }
258 
259 void SvgEllipse::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
260 {
261  out << repeat( SvgDocument::indentation_string, indent );
262  out << "<ellipse";
263 
264  if( ! id.empty() ) {
265  out << svg_attribute( "id", id );
266  }
267 
268  out << svg_attribute( "cx", center.x + options.offset_x );
269  out << svg_attribute( "cy", center.y + options.offset_y );
270  out << svg_attribute( "rx", rx );
271  out << svg_attribute( "ry", ry );
272 
273  stroke.write( out );
274  fill.write( out );
275  transform.write( out );
276  out << " />\n";
277 }
278 
279 // =================================================================================================
280 // Svg Polyline
281 // =================================================================================================
282 
283 // -------------------------------------------------------------
284 // Constructors and Rule of Five
285 // -------------------------------------------------------------
286 
288  SvgStroke const& stroke,
289  SvgFill const& fill
290 )
291  : stroke( stroke )
292  , fill( fill )
293 {}
294 
296  std::vector< SvgPoint > points,
297  SvgStroke const& stroke,
298  SvgFill const& fill
299 )
300  : points( points )
301  , stroke( stroke )
302  , fill( fill )
303 {}
304 
305 // -------------------------------------------------------------
306 // Members
307 // -------------------------------------------------------------
308 
309 SvgPolyline& SvgPolyline::add( double x, double y )
310 {
311  return add( SvgPoint( x, y ));
312 }
313 
315 {
316  points.push_back( p );
317  return *this;
318 }
319 
321 {
322  return add( p );
323 }
324 
326 {
327  if( points.size() == 0 ) {
328  return {};
329  // throw std::runtime_error(
330  // "Cannot calculate bounding box of Polyline without any points."
331  // );
332  }
333 
334  auto minmax_x = std::minmax_element(
335  points.begin(), points.end(),
336  []( SvgPoint lhs, SvgPoint rhs ){ return lhs.x < rhs.x; }
337  );
338  auto minmax_y = std::minmax_element(
339  points.begin(), points.end(),
340  []( SvgPoint lhs, SvgPoint rhs ){ return lhs.y < rhs.y; }
341  );
342 
343  return {
344  SvgPoint( minmax_x.first->x, minmax_y.first->y ),
345  SvgPoint( minmax_x.second->x, minmax_y.second->y )
346  };
347 }
348 
349 void SvgPolyline::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
350 {
351  out << repeat( SvgDocument::indentation_string, indent );
352  out << "<polyline";
353 
354  if( ! id.empty() ) {
355  out << svg_attribute( "id", id );
356  }
357 
358  out << " points=\"";
359  for( size_t i = 0; i < points.size(); ++i ) {
360  if( i > 0 ) {
361  out << " ";
362  }
363  out << ( points[i].x + options.offset_x ) << ",";
364  out << ( points[i].y + options.offset_y );
365  }
366  out << "\"";
367 
368  stroke.write( out );
369  fill.write( out );
370  transform.write( out );
371  out << " />\n";
372 }
373 
374 // =================================================================================================
375 // Svg Polygon
376 // =================================================================================================
377 
378 // -------------------------------------------------------------
379 // Constructors and Rule of Five
380 // -------------------------------------------------------------
381 
383  SvgStroke const& stroke,
384  SvgFill const& fill
385 )
386  : stroke( stroke )
387  , fill( fill )
388 {}
389 
391  std::vector< SvgPoint > const& points,
392  SvgStroke const& stroke,
393  SvgFill const& fill
394 )
395  : points( points )
396  , stroke( stroke )
397  , fill( fill )
398 {}
399 
400 // -------------------------------------------------------------
401 // Members
402 // -------------------------------------------------------------
403 
404 SvgPolygon& SvgPolygon::add( double x, double y )
405 {
406  return add( SvgPoint( x, y ));
407 }
408 
410 {
411  points.push_back( p );
412  return *this;
413 }
414 
416 {
417  return add( p );
418 }
419 
421 {
422  if( points.size() == 0 ) {
423  return {};
424  // throw std::runtime_error(
425  // "Cannot calculate bounding box of Polygon without any points."
426  // );
427  }
428 
429  auto minmax_x = std::minmax_element(
430  points.begin(), points.end(),
431  []( SvgPoint lhs, SvgPoint rhs ){ return lhs.x < rhs.x; }
432  );
433  auto minmax_y = std::minmax_element(
434  points.begin(), points.end(),
435  []( SvgPoint lhs, SvgPoint rhs ){ return lhs.y < rhs.y; }
436  );
437 
438  return {
439  SvgPoint( minmax_x.first->x, minmax_y.first->y ),
440  SvgPoint( minmax_x.second->x, minmax_y.second->y )
441  };
442 }
443 
444 void SvgPolygon::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
445 {
446  out << repeat( SvgDocument::indentation_string, indent );
447  out << "<polygon";
448 
449  if( ! id.empty() ) {
450  out << svg_attribute( "id", id );
451  }
452 
453  out << " points=\"";
454  for( size_t i = 0; i < points.size(); ++i ) {
455  if( i > 0 ) {
456  out << " ";
457  }
458  out << ( points[i].x + options.offset_x ) << ",";
459  out << ( points[i].y + options.offset_y );
460  }
461  out << "\"";
462 
463  stroke.write( out );
464  fill.write( out );
465  transform.write( out );
466  out << " />\n";
467 }
468 
469 // =================================================================================================
470 // Svg Path
471 // =================================================================================================
472 
473 // -------------------------------------------------------------
474 // Constructors and Rule of Five
475 // -------------------------------------------------------------
476 
478  SvgStroke const& stroke,
479  SvgFill const& fill
480 )
481  : stroke( stroke )
482  , fill( fill )
483 {}
484 
486  std::vector< std::string > const& elements,
487  SvgStroke const& stroke,
488  SvgFill const& fill
489 )
490  : elements(elements)
491  , stroke( stroke )
492  , fill( fill )
493 {}
494 
495 // -------------------------------------------------------------
496 // Members
497 // -------------------------------------------------------------
498 
499 SvgPath& SvgPath::add( std::string elem )
500 {
501  elements.push_back( elem );
502  return *this;
503 }
504 
505 SvgPath& SvgPath::operator <<( std::string elem )
506 {
507  return add( elem );
508 }
509 
511 {
512  // TODO
513  return {};
514 }
515 
516 void SvgPath::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
517 {
518  (void) options;
519 
520  out << repeat( SvgDocument::indentation_string, indent );
521  out << "<path";
522 
523  if( ! id.empty() ) {
524  out << svg_attribute( "id", id );
525  }
526 
527  out << " d=\"";
528  for( size_t i = 0; i < elements.size(); ++i ) {
529  if( i > 0 ) {
530  out << " ";
531  }
532  out << elements[i];
533  }
534  out << "\"";
535 
536  stroke.write( out );
537  fill.write( out );
538  transform.write( out );
539  out << " />\n";
540 }
541 
542 // =================================================================================================
543 // Svg Use
544 // =================================================================================================
545 
547 {
548  // TODO
549  return {};
550 }
551 
552 void SvgUse::write( std::ostream& out, size_t indent, SvgDrawingOptions const& options ) const
553 {
554  out << repeat( SvgDocument::indentation_string, indent );
555  out << "<use";
556  out << svg_attribute( "xlink:href", "#" + referenced_id );
557  out << svg_attribute( "x", offset.x + options.offset_x );
558  out << svg_attribute( "y", offset.y + options.offset_y );
559  transform.write( out );
560  out << " />\n";
561 }
562 
563 } // namespace utils
564 } // namespace genesis
self_type & add(double x, double y)
Definition: shapes.cpp:404
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:349
SvgCircle(SvgPoint const &center, double radius, SvgStroke const &stroke=SvgStroke(), SvgFill const &fill=SvgFill())
Definition: shapes.cpp:165
SvgTransform transform
Definition: shapes.hpp:102
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:259
void write(std::ostream &out) const
Definition: attributes.cpp:163
SvgTransform transform
Definition: shapes.hpp:173
self_type & operator<<(SvgPoint p)
Definition: shapes.cpp:320
std::string svg_attribute(std::string const &name, T const &value, std::string const &unit="")
SvgBox bounding_box() const
Definition: shapes.cpp:65
SvgTransform transform
Definition: shapes.hpp:516
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:73
SvgTransform transform
Definition: shapes.hpp:448
SvgBox bounding_box() const
Definition: shapes.cpp:546
std::string repeat(std::string const &word, size_t times)
Take a string and repeat it a given number of times.
Definition: string.cpp:418
SvgEllipse(SvgPoint const &center, double rx, double ry, SvgStroke const &stroke=SvgStroke(), SvgFill const &fill=SvgFill())
Definition: shapes.cpp:225
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:132
SvgLine(SvgPoint const &point_1, SvgPoint const &point_2, SvgStroke const &stroke=SvgStroke())
Definition: shapes.cpp:51
SvgBox bounding_box() const
Definition: shapes.cpp:420
SvgTransform transform
Definition: shapes.hpp:581
self_type & operator<<(SvgPoint p)
Definition: shapes.cpp:415
SvgBox bounding_box() const
Definition: shapes.cpp:190
SvgPath(SvgStroke const &stroke=SvgStroke(), SvgFill const &fill=SvgFill())
Definition: shapes.cpp:477
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:272
SvgRect(SvgPoint const &position, SvgSize const &size, SvgStroke const &stroke=SvgStroke(), SvgFill const &fill=SvgFill())
Definition: shapes.cpp:100
SvgTransform transform
Definition: shapes.hpp:310
self_type & add(double x, double y)
Definition: shapes.cpp:309
SvgBox bounding_box() const
Definition: shapes.cpp:251
Provides some commonly used string utility functions.
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:198
void write(std::ostream &out) const
Definition: attributes.cpp:79
SvgPolygon(SvgStroke const &stroke=SvgStroke(), SvgFill const &fill=SvgFill())
Definition: shapes.cpp:382
self_type & operator<<(std::string elem)
Definition: shapes.cpp:505
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:552
void write(std::ostream &out) const
Definition: attributes.cpp:304
SvgPolyline(SvgStroke const &stroke=SvgStroke(), SvgFill const &fill=SvgFill())
Definition: shapes.cpp:287
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:516
std::string referenced_id
Definition: shapes.hpp:579
self_type & add(std::string elem)
Definition: shapes.cpp:499
SvgBox bounding_box() const
Definition: shapes.cpp:325
static std::string indentation_string
std::vector< SvgPoint > points
Definition: shapes.hpp:443
std::vector< std::string > elements
Definition: shapes.hpp:511
void write(std::ostream &out, size_t indent=0, SvgDrawingOptions const &options=SvgDrawingOptions()) const
Definition: shapes.cpp:444
std::vector< SvgPoint > points
Definition: shapes.hpp:374
SvgTransform transform
Definition: shapes.hpp:241
SvgBox bounding_box() const
Definition: shapes.cpp:127
SvgBox bounding_box() const
Definition: shapes.cpp:510