A library for working with phylogenetic and population genetic data.
v0.32.0
utils/formats/svg/helper.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_FORMATS_SVG_HELPER_H_
2 #define GENESIS_UTILS_FORMATS_SVG_HELPER_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2022 Lucas Czech
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lczech@carnegiescience.edu>
23  Department of Plant Biology, Carnegie Institution For Science
24  260 Panama Street, Stanford, CA 94305, USA
25 */
26 
36 
37 #include <algorithm>
38 #include <cmath>
39 #include <ostream>
40 #include <sstream>
41 #include <string>
42 #include <vector>
43 
44 namespace genesis {
45 namespace utils {
46 
47 // =================================================================================================
48 // Forward Declarations
49 // =================================================================================================
50 
51 struct SvgTransform;
52 
53 // =================================================================================================
54 // Svg Point
55 // =================================================================================================
56 
57 struct SvgPoint
58 {
59  explicit SvgPoint( double x = 0.0, double y = 0.0 )
60  : x(x)
61  , y(y)
62  {}
63 
64  SvgPoint operator+ ( SvgPoint const& other ) const
65  {
66  return SvgPoint( x + other.x, y + other.y );
67  }
68 
69  double x;
70  double y;
71 };
72 
73 // =================================================================================================
74 // Svg Size
75 // =================================================================================================
76 
77 struct SvgSize
78 {
79  explicit SvgSize( double width = 0.0, double height = 0.0 )
80  : width(width)
81  , height(height)
82  {}
83 
84  double width;
85  double height;
86 };
87 
88 // =================================================================================================
89 // Svg Margin
90 // =================================================================================================
91 
92 struct SvgMargin
93 {
94  explicit SvgMargin()
95  : SvgMargin( 0.0, 0.0, 0.0, 0.0 )
96  {}
97 
98  explicit SvgMargin( double all )
99  : SvgMargin( all, all, all, all )
100  {}
101 
102  explicit SvgMargin( double top_bottom, double right_left )
103  : SvgMargin( top_bottom, right_left, top_bottom, right_left )
104  {}
105 
106  explicit SvgMargin( double top, double right_left, double bottom )
107  : SvgMargin( top, right_left, bottom, right_left )
108  {}
109 
110  explicit SvgMargin( double top, double right, double bottom, double left )
111  : top(top)
112  , right(right)
113  , bottom(bottom)
114  , left(left)
115  {}
116 
117  double top;
118  double right;
119  double bottom;
120  double left;
121 };
122 
123 // =================================================================================================
124 // Svg (Bounding) Box
125 // =================================================================================================
126 
127 struct SvgBox
128 {
129  SvgBox() = default;
130 
132  : top_left(top_left)
134  {
135  // Make it fool-proof.
136  if( bottom_right.x < top_left.x ) {
138  }
139  if( bottom_right.y < top_left.y ) {
141  }
142  }
143 
144  SvgBox( SvgPoint top_left_v, double width, double height )
145  : top_left(top_left_v)
147  {
148  // Allow negative size.
149  if( width < 0.0 ) {
151  }
152  if( height < 0.0 ) {
154  }
155  }
156 
157  double width() const
158  {
159  return bottom_right.x - top_left.x;
160  }
161 
162  double height() const
163  {
164  return bottom_right.y - top_left.y;
165  }
166 
167  SvgSize size() const
168  {
169  return SvgSize( width(), height() );
170  }
171 
172  bool empty() const
173  {
174  // If everything is zero, this either is an uninitialized default box, or we are at the
175  // big bang, where everything is condensed into one point. Either way, this means there
176  // is no bounding box, as the singularity does not have a dimension.
177  return top_left.x == 0.0 && top_left.y == 0.0 &&
178  bottom_right.x == 0.0 && bottom_right.y == 0.0;
179  }
180 
181  static SvgBox combine( SvgBox const& lhs, SvgBox const& rhs )
182  {
183  // If any of the two boxes is empty, return the other one.
184  // (If both are empty, this also returns an empty box.)
185  if( lhs.empty() ) {
186  return rhs;
187  }
188  if( rhs.empty() ) {
189  return lhs;
190  }
191 
192  return {
193  SvgPoint(
194  std::min( lhs.top_left.x, rhs.top_left.x ),
195  std::min( lhs.top_left.y, rhs.top_left.y )
196  ),
197  SvgPoint(
198  std::max( lhs.bottom_right.x, rhs.bottom_right.x ),
199  std::max( lhs.bottom_right.y, rhs.bottom_right.y )
200  )
201  };
202  }
203 
206 
207 };
208 
209 // =================================================================================================
210 // Svg Drawing Options
211 // =================================================================================================
212 
214 {
215  double offset_x = 0.0;
216  double offset_y = 0.0;
217 };
218 
219 // =================================================================================================
220 // Svg Helper Functions
221 // =================================================================================================
222 
223 inline std::string svg_comment( std::string const& content )
224 {
225  return "<!-- " + content + " -->";
226 }
227 
228 template< typename T >
229 std::string svg_attribute(
230  std::string const& name,
231  T const& value,
232  std::string const& unit = ""
233 ) {
234  std::stringstream ss;
235  ss << " " << name << "=\"" << value << unit << "\"";
236  return ss.str();
237 }
238 
239 inline std::string svg_data_uri(
240  std::string const& media_type,
241  std::string const& content,
242  bool encode_base64 = false
243 ) {
244  return "data:" + media_type + (
245  encode_base64
246  ? ( ";base64," + base64_encode( content ))
247  : ( "," + content )
248  );
249 }
250 
265 std::string svg_arc(
266  double center_x, double center_y, double radius,
267  double start_angle, double end_angle,
268  bool wedge = false
269 );
270 
274 SvgBox svg_bounding_box(
275  std::vector<SvgPoint> const& points
276 );
277 
281 SvgBox svg_bounding_box(
282  std::vector<SvgPoint> const& points,
283  SvgTransform const& transform
284 );
285 
286 // template< typename T >
287 // std::string svg_style(
288 // std::string const& name,
289 // T const& value,
290 // std::string const& unit = ""
291 // ) {
292 // std::stringstream ss;
293 // ss << name << ":\"" << value << unit << "\" ";
294 // return ss.str();
295 // }
296 
297 } // namespace utils
298 } // namespace genesis
299 
300 #endif // include guard
genesis::utils::SvgMargin::bottom
double bottom
Definition: utils/formats/svg/helper.hpp:119
genesis::placement::swap
void swap(Sample &lhs, Sample &rhs)
Definition: sample.cpp:104
genesis::utils::svg_data_uri
std::string svg_data_uri(std::string const &media_type, std::string const &content, bool encode_base64=false)
Definition: utils/formats/svg/helper.hpp:239
genesis::utils::SvgPoint::x
double x
Definition: utils/formats/svg/helper.hpp:69
genesis::utils::SvgBox::combine
static SvgBox combine(SvgBox const &lhs, SvgBox const &rhs)
Definition: utils/formats/svg/helper.hpp:181
genesis::utils::SvgPoint::y
double y
Definition: utils/formats/svg/helper.hpp:70
genesis::utils::SvgMargin::SvgMargin
SvgMargin(double top, double right_left, double bottom)
Definition: utils/formats/svg/helper.hpp:106
genesis::utils::svg_comment
std::string svg_comment(std::string const &content)
Definition: utils/formats/svg/helper.hpp:223
common.hpp
genesis::utils::base64_encode
std::string base64_encode(std::vector< std::uint8_t > const &input, size_t line_length)
Definition: base64.cpp:267
genesis::utils::SvgBox::SvgBox
SvgBox()=default
genesis::utils::SvgMargin::SvgMargin
SvgMargin(double all)
Definition: utils/formats/svg/helper.hpp:98
genesis::utils::SvgMargin::top
double top
Definition: utils/formats/svg/helper.hpp:117
genesis::utils::SvgBox::top_left
SvgPoint top_left
Definition: utils/formats/svg/helper.hpp:204
genesis::utils::SvgDrawingOptions::offset_y
double offset_y
Definition: utils/formats/svg/helper.hpp:216
genesis::utils::svg_arc
std::string svg_arc(double center_x, double center_y, double radius, double start_angle, double end_angle, bool wedge)
Create an arc to use in an SvgPath.
Definition: utils/formats/svg/helper.cpp:50
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::SvgBox::bottom_right
SvgPoint bottom_right
Definition: utils/formats/svg/helper.hpp:205
genesis::utils::SvgMargin
Definition: utils/formats/svg/helper.hpp:92
genesis::utils::SvgBox::width
double width() const
Definition: utils/formats/svg/helper.hpp:157
genesis::utils::SvgPoint
Definition: utils/formats/svg/helper.hpp:57
genesis::utils::SvgBox::size
SvgSize size() const
Definition: utils/formats/svg/helper.hpp:167
genesis::utils::SvgBox::SvgBox
SvgBox(SvgPoint top_left_v, double width, double height)
Definition: utils/formats/svg/helper.hpp:144
genesis::utils::SvgMargin::SvgMargin
SvgMargin()
Definition: utils/formats/svg/helper.hpp:94
genesis::utils::SvgBox::empty
bool empty() const
Definition: utils/formats/svg/helper.hpp:172
genesis::utils::SvgMargin::SvgMargin
SvgMargin(double top, double right, double bottom, double left)
Definition: utils/formats/svg/helper.hpp:110
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::SvgBox::height
double height() const
Definition: utils/formats/svg/helper.hpp:162
genesis::utils::SvgMargin::right
double right
Definition: utils/formats/svg/helper.hpp:118
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::SvgPoint::operator+
SvgPoint operator+(SvgPoint const &other) const
Definition: utils/formats/svg/helper.hpp:64
genesis::utils::SvgSize
Definition: utils/formats/svg/helper.hpp:77
base64.hpp
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::SvgSize::width
double width
Definition: utils/formats/svg/helper.hpp:84
genesis::utils::SvgSize::SvgSize
SvgSize(double width=0.0, double height=0.0)
Definition: utils/formats/svg/helper.hpp:79
genesis::utils::SvgMargin::SvgMargin
SvgMargin(double top_bottom, double right_left)
Definition: utils/formats/svg/helper.hpp:102
genesis::utils::SvgSize::height
double height
Definition: utils/formats/svg/helper.hpp:85
genesis::utils::SvgDrawingOptions
Definition: utils/formats/svg/helper.hpp:213
genesis::utils::SvgBox::SvgBox
SvgBox(SvgPoint top_left, SvgPoint bottom_right)
Definition: utils/formats/svg/helper.hpp:131
genesis::utils::SvgMargin::left
double left
Definition: utils/formats/svg/helper.hpp:120
genesis::utils::SvgPoint::SvgPoint
SvgPoint(double x=0.0, double y=0.0)
Definition: utils/formats/svg/helper.hpp:59