67 using namespace utils;
87 assert( !
tree().empty() );
105 double const max_spreading = node_count / ( node_count + 1 );
107 size_t max_text_len = 0;
109 for(
auto const& node :
tree().
nodes() ) {
114 auto const node_spreading = 2.0 *
utils::PI * node_data.spreading * max_spreading;
117 auto const node_x = node_data.distance *
radius * cos( node_spreading );
118 auto const node_y = node_data.distance *
radius * sin( node_spreading );
121 auto edge_ptr =
edge_between( node,
tree().node_at( node_data.parent_index ) );
129 auto distance_stroke = edge_data.distance_stroke;
134 auto start_a = prnt_spreading;
135 auto end_a = node_spreading;
136 if( prnt_spreading > node_spreading ) {
141 auto const dist_start_x = prnt_data.
distance *
radius * cos( node_spreading );
142 auto const dist_start_y = prnt_data.
distance *
radius * sin( node_spreading );
145 tree_lines << SvgPath(
148 SvgFill( SvgFill::Type::kNone )
150 tree_lines << SvgLine(
151 dist_start_x, dist_start_y,
157 if( ! edge_data.shape.empty() ) {
158 auto const shape_x = ( dist_start_x + node_x ) / 2.0;
159 auto const shape_y = ( dist_start_y + node_y ) / 2.0;
161 auto es = edge_data.shape;
162 es.transform.append( SvgTransform::Translate( shape_x, shape_y ));
163 edge_shapes << std::move( es );
175 auto label_dist = node_data.distance *
radius;
185 taxa_lines << SvgLine(
187 label_dist * cos( node_spreading ),
188 label_dist * sin( node_spreading ),
189 node_data.spacer_stroke
194 if( node_data.name !=
"" ) {
199 label.text = node_data.name;
200 label.alignment_baseline = SvgText::AlignmentBaseline::kMiddle;
203 label.transform.append( SvgTransform::Translate(
204 ( label_dist + 10 ) * cos( node_spreading ),
205 ( label_dist + 10 ) * sin( node_spreading )
211 node_data.spreading * max_spreading > 0.25 &&
212 node_data.spreading * max_spreading <= 0.75
215 label.anchor = SvgText::Anchor::kEnd;
216 label.transform.append( SvgTransform::Rotate(
217 360 * node_data.spreading * max_spreading + 180
221 label.transform.append( SvgTransform::Rotate(
222 360 * node_data.spreading * max_spreading
226 taxa_names << std::move( label );
227 max_text_len = std::max( max_text_len, node_data.name.size() );
231 if( ! node_data.shape.empty() ) {
232 auto ns = node_data.shape;
233 ns.transform.append( SvgTransform::Translate( node_x, node_y ));
234 node_shapes << std::move( ns );
240 tree_lines.reverse();
243 auto const marg = std::max( 30.0, max_text_len *
text_template().font.size );
244 doc.margin = SvgMargin( marg );
247 doc << std::move( tree_lines );
248 if( ! taxa_lines.empty() ) {
249 doc << std::move( taxa_lines );
251 if( ! taxa_names.empty() ) {
252 doc << std::move( taxa_names );
254 if( ! edge_shapes.empty() ) {
255 doc << std::move( edge_shapes );
257 if( ! node_shapes.empty() ) {
258 doc << std::move( node_shapes );
bool align_labels() const
double distance
Distance of the node to the root.
bool is_root(TreeLink const &link)
Return whether the link belongs to the root node of its Tree.
void swap(SequenceSet &lhs, SequenceSet &rhs)
double extra_spacer() const
size_t node_count(Tree const &tree)
Return the number of Nodes of a Tree. Same as Tree::node_count().
Container namespace for all symbols of genesis in order to keep them separate when used as a library...
LayoutSpreading inner_node_spreading() const
TreeEdge * edge_between(TreeNode &lhs, TreeNode &rhs)
Return the TreeEdge between two TreeNode&s, if they are neighbours, or nullptr otherwise.
Data class for LayoutTreeEdges.
constexpr double PI
Make the world go round.
size_t leaf_node_count(Tree const &tree)
Count the number of leaf Nodes of a Tree.
utils::Range< IteratorNodes > nodes()
TreeNode & node_at(size_t index)
Return the TreeNode at a certain index.
utils::SvgStroke spreading_stroke
Tree const & tree() const
std::string svg_arc(double center_x, double center_y, double radius, double start_angle, double end_angle)
Create an arc to use in an SvgPath.
size_t node_count() const
Return the number of TreeNodes of the Tree.
double spreading
Position of the node along the second axis.
Data class for LayoutTreeNodes.
utils::SvgText & text_template()