A toolkit for working with phylogenetic data.
v0.18.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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-2017 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 <lucas.czech@h-its.org>
23  Exelixis Lab, Heidelberg Institute for Theoretical Studies
24  Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany
25 */
26 
34 #include <algorithm>
35 #include <ostream>
36 #include <sstream>
37 #include <string>
38 #include <vector>
39 
40 namespace genesis {
41 namespace utils {
42 
43 // =================================================================================================
44 // Svg Point
45 // =================================================================================================
46 
47 struct SvgPoint
48 {
49  explicit SvgPoint( double x = 0.0, double y = 0.0 )
50  : x(x)
51  , y(y)
52  {}
53 
54  double x;
55  double y;
56 };
57 
58 // =================================================================================================
59 // Svg Size
60 // =================================================================================================
61 
62 struct SvgSize
63 {
64  explicit SvgSize( double width = 0.0, double height = 0.0 )
65  : width(width)
66  , height(height)
67  {}
68 
69  double width;
70  double height;
71 };
72 
73 // =================================================================================================
74 // Svg Margin
75 // =================================================================================================
76 
77 struct SvgMargin
78 {
79  explicit SvgMargin()
80  : SvgMargin( 0.0, 0.0, 0.0, 0.0 )
81  {}
82 
83  explicit SvgMargin( double all )
84  : SvgMargin( all, all, all, all )
85  {}
86 
87  explicit SvgMargin( double top_bottom, double right_left )
88  : SvgMargin( top_bottom, right_left, top_bottom, right_left )
89  {}
90 
91  explicit SvgMargin( double top, double right_left, double bottom )
92  : SvgMargin( top, right_left, bottom, right_left )
93  {}
94 
95  explicit SvgMargin( double top, double right, double bottom, double left )
96  : top(top)
97  , right(right)
98  , bottom(bottom)
99  , left(left)
100  {}
101 
102  double top;
103  double right;
104  double bottom;
105  double left;
106 };
107 
108 // =================================================================================================
109 // Svg (Bounding) Box
110 // =================================================================================================
111 
112 struct SvgBox
113 {
114  SvgBox() = default;
115 
117  : top_left(top_left)
118  , bottom_right(bottom_right)
119  {
120  // Make it fool-proof.
121  if( bottom_right.x < top_left.x ) {
122  std::swap( bottom_right.x, top_left.x );
123  }
124  if( bottom_right.y < top_left.y ) {
125  std::swap( bottom_right.y, top_left.y );
126  }
127  }
128 
129  SvgBox( SvgPoint top_left_v, double width, double height )
130  : top_left(top_left_v)
131  , bottom_right( top_left.x + width, top_left.y + height )
132  {
133  // Allow negative size.
134  if( width < 0.0 ) {
136  }
137  if( height < 0.0 ) {
139  }
140  }
141 
142  double width() const
143  {
144  return bottom_right.x - top_left.x;
145  }
146 
147  double height() const
148  {
149  return bottom_right.y - top_left.y;
150  }
151 
152  SvgSize size() const
153  {
154  return SvgSize( width(), height() );
155  }
156 
157  bool empty() const
158  {
159  // If everything is zero, this either is an uninitialized default box, or we are at the
160  // big bang, where everything is condensed into one point. Either way, this means there
161  // is no bounding box, as the singularity does not have a dimension.
162  return top_left.x == 0.0 && top_left.y == 0.0 &&
163  bottom_right.x == 0.0 && bottom_right.y == 0.0;
164  }
165 
166  static SvgBox combine( SvgBox const& lhs, SvgBox const& rhs )
167  {
168  // If any of the two boxes is empty, return the other one.
169  // (If both are empty, this also returns an empty box.)
170  if( lhs.empty() ) {
171  return rhs;
172  }
173  if( rhs.empty() ) {
174  return lhs;
175  }
176 
177  return {
178  SvgPoint(
179  std::min( lhs.top_left.x, rhs.top_left.x ),
180  std::min( lhs.top_left.y, rhs.top_left.y )
181  ),
182  SvgPoint(
183  std::max( lhs.bottom_right.x, rhs.bottom_right.x ),
184  std::max( lhs.bottom_right.y, rhs.bottom_right.y )
185  )
186  };
187  }
188 
191 
192 };
193 
194 // =================================================================================================
195 // Svg Drawing Options
196 // =================================================================================================
197 
199 {
200  double offset_x = 0.0;
201  double offset_y = 0.0;
202 };
203 
204 // =================================================================================================
205 // Svg Helper Functions
206 // =================================================================================================
207 
208 inline std::string svg_comment( std::string const& content )
209 {
210  return "<!-- " + content + " -->";
211 }
212 
213 template< typename T >
214 std::string svg_attribute(
215  std::string const& name,
216  T const& value,
217  std::string const& unit = ""
218 ) {
219  std::stringstream ss;
220  ss << " " << name << "=\"" << value << unit << "\"";
221  return ss.str();
222 }
223 
224 // template< typename T >
225 // std::string svg_style(
226 // std::string const& name,
227 // T const& value,
228 // std::string const& unit = ""
229 // ) {
230 // std::stringstream ss;
231 // ss << name << ":\"" << value << unit << "\" ";
232 // return ss.str();
233 // }
234 
235 } // namespace utils
236 } // namespace genesis
237 
238 #endif // include guard
static SvgBox combine(SvgBox const &lhs, SvgBox const &rhs)
SvgPoint(double x=0.0, double y=0.0)
void swap(SequenceSet &lhs, SequenceSet &rhs)
std::string svg_attribute(std::string const &name, T const &value, std::string const &unit="")
SvgMargin(double top, double right_left, double bottom)
SvgSize(double width=0.0, double height=0.0)
std::string svg_comment(std::string const &content)
SvgBox(SvgPoint top_left_v, double width, double height)
SvgMargin(double top, double right, double bottom, double left)
SvgMargin(double top_bottom, double right_left)
SvgBox(SvgPoint top_left, SvgPoint bottom_right)