67 using namespace utils;
87 assert( !
tree().empty() );
108 for(
auto const& node :
tree().
nodes() ) {
110 auto const& node_data = node.data<LayoutNodeData>();
111 auto const& prnt_data =
tree().
node_at( node_data.parent_index ).
data<LayoutNodeData>();
113 auto const node_spreading = 2.0 *
utils::PI * node_data.spreading * max_spreading;
114 auto const prnt_spreading = 2.0 *
utils::PI * prnt_data.spreading * max_spreading;
116 auto const node_x = node_data.distance *
radius * cos( node_spreading );
117 auto const node_y = node_data.distance *
radius * sin( node_spreading );
120 auto edge_ptr =
edge_between( node,
tree().node_at( node_data.parent_index ) );
124 auto const& edge_data = edge_ptr->data<LayoutEdgeData>();
127 auto spreading_stroke = edge_data.spreading_stroke;
128 auto distance_stroke = edge_data.distance_stroke;
133 auto start_a = prnt_spreading;
134 auto end_a = node_spreading;
135 if( prnt_spreading > node_spreading ) {
140 auto const dist_start_x = prnt_data.distance *
radius * cos( node_spreading );
141 auto const dist_start_y = prnt_data.distance *
radius * sin( node_spreading );
144 tree_lines << SvgPath(
145 {
svg_arc( 0, 0, prnt_data.distance *
radius, start_a, end_a ) },
147 SvgFill( SvgFill::Type::kNone )
149 tree_lines << SvgLine(
150 dist_start_x, dist_start_y,
156 if( ! edge_data.shape.empty() ) {
157 auto const shape_x = ( dist_start_x + node_x ) / 2.0;
158 auto const shape_y = ( dist_start_y + node_y ) / 2.0;
160 auto es = edge_data.shape;
161 es.transform.append( SvgTransform::Translate( shape_x, shape_y ));
162 edge_shapes << std::move( es );
174 auto label_dist = node_data.distance *
radius;
184 taxa_lines << SvgLine(
186 label_dist * cos( node_spreading ),
187 label_dist * sin( node_spreading ),
188 node_data.spacer_stroke
193 if( node_data.name !=
"" ) {
198 label.text = node_data.name;
199 label.alignment_baseline = SvgText::AlignmentBaseline::kMiddle;
202 label.transform.append( SvgTransform::Translate(
203 ( label_dist + 10 ) * cos( node_spreading ),
204 ( label_dist + 10 ) * sin( node_spreading )
210 node_data.spreading * max_spreading > 0.25 &&
211 node_data.spreading * max_spreading <= 0.75
214 label.anchor = SvgText::Anchor::kEnd;
215 label.transform.append( SvgTransform::Rotate(
216 360 * node_data.spreading * max_spreading + 180
220 label.transform.append( SvgTransform::Rotate(
221 360 * node_data.spreading * max_spreading
225 taxa_names << std::move( label );
230 if( ! node_data.shape.empty() ) {
231 auto ns = node_data.shape;
232 ns.transform.append( SvgTransform::Translate( node_x, node_y ));
233 node_shapes << std::move( ns );
239 tree_lines.reverse();
246 doc << std::move( tree_lines );
247 if( ! taxa_lines.empty() ) {
248 doc << std::move( taxa_lines );
250 if( ! taxa_names.empty() ) {
251 doc << std::move( taxa_names );
253 if( ! edge_shapes.empty() ) {
254 doc << std::move( edge_shapes );
256 if( ! node_shapes.empty() ) {
257 doc << std::move( node_shapes );