bpp-phyl3 3.0.0
PhylogramPlot.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: The Bio++ Development Group
2//
3// SPDX-License-Identifier: CECILL-2.1
4
5#include "../Tree/TreeTemplateTools.h"
6#include "PhylogramPlot.h"
7
8using namespace bpp;
9
10#include <string>
11
12using namespace std;
13
14PhylogramDrawBranchEvent::PhylogramDrawBranchEvent(const TreeDrawing* source, GraphicDevice* gd, const INode* node, const Cursor& cursor, short orientation) :
15 DrawIBranchEvent(source, gd, node, cursor), orientation_()
16{
18}
19
21{
22 double offset = 0;
23 if (getINode()->hasDistanceToFather())
24 {
25 double l = getINode()->getDistanceToFather();
26 offset = orientation_ * l * position * getTreeDrawing()->getXUnit();
27 }
28 return getCursor().getTranslation(offset, 0);
29}
30
32{
34 tree_->setVoidBranchLengths(0.);
35}
36
38{
39 if (hasTree())
40 {
41 DrawTreeEvent treeEvent(this, &gDevice);
42 fireBeforeTreeEvent_(treeEvent);
43 unsigned int tipCounter = 0;
44 double y;
45 recursivePlot_(gDevice, *const_cast<INode*>(tree_->getRootNode()),
47 y,
50 tipCounter);
51 fireAfterTreeEvent_(treeEvent);
52 }
53}
54
55void PhylogramPlot::recursivePlot_(GraphicDevice& gDevice, INode& node, double x, double& y, double hDirection, double vDirection, unsigned int& tipCounter) const
56{
57 double x2;
58 bool drawBranch = true;
59 if (node.hasDistanceToFather())
60 {
61 double length = node.hasDistanceToFather() ? node.getDistanceToFather() : 0.;
62 if (length < -10000000)
63 {
64 x2 = x;
65 drawBranch = false;
66 }
67 else
68 {
69 x2 = x + hDirection * length * getXUnit();
70 }
71 }
72 else
73 {
74 x2 = x;
75 drawBranch = false;
76 }
77
78 unique_ptr<Cursor> cursor;
79 unique_ptr<DrawINodeEvent> nodeEvent;
80 unique_ptr<DrawIBranchEvent> branchEvent;
82 if (node.isLeaf())
83 {
84 y = ((getVerticalOrientation() == ORIENTATION_TOP_TO_BOTTOM ? 0 : getHeight()) + static_cast<double>(tipCounter) * vDirection) * getYUnit();
85 tipCounter++;
86 cursor.reset(new Cursor(x2, y, 0, hpos));
87 nodeEvent.reset(new DrawINodeEvent(this, &gDevice, &node, *cursor));
88 fireBeforeNodeEvent_(*nodeEvent);
89 }
90 else if (node.getInfos().isCollapsed())
91 {
92 y = ((getVerticalOrientation() == ORIENTATION_TOP_TO_BOTTOM ? 0 : getHeight()) + static_cast<double>(tipCounter) * vDirection) * getYUnit();
93 tipCounter++;
94 cursor.reset(new Cursor(x2, y, 0, hpos));
95 nodeEvent.reset(new DrawINodeEvent(this, &gDevice, &node, *cursor));
96 fireBeforeNodeEvent_(*nodeEvent);
97 }
98 else
99 {
100 // Vertical line. Call the method on son nodes first:
101 double miny = 1000000; // (unsigned int)(-log(0));
102 double maxy = 0;
103 for (unsigned int i = 0; i < node.getNumberOfSons(); i++)
104 {
105 double yson;
106 recursivePlot_(gDevice, *node.getSon(i), x2, yson, hDirection, vDirection, tipCounter);
107 if (yson < miny)
108 miny = yson;
109 if (yson > maxy)
110 maxy = yson;
111 }
112 y = (maxy + miny) / 2.;
113 cursor.reset(new Cursor(x2, y, 0, hpos));
114 nodeEvent.reset(new DrawINodeEvent(this, &gDevice, &node, *cursor));
115 fireBeforeNodeEvent_(*nodeEvent);
116 gDevice.drawLine(x2, miny, x2, maxy);
117 }
118
119 // Actualize node infos:
120 node.getInfos().setX(x2);
121 node.getInfos().setY(y);
122 nodeEvent.reset(new DrawINodeEvent(this, &gDevice, &node, *cursor));
123 fireAfterNodeEvent_(*nodeEvent);
124
125 if (drawBranch)
126 {
127 // Horizontal line
128 branchEvent.reset(new PhylogramDrawBranchEvent(this, &gDevice, &node, *cursor, getHorizontalOrientation()));
129 fireBeforeBranchEvent_(*branchEvent);
130 gDevice.drawLine(x, y, x2, y);
131 fireAfterBranchEvent_(*branchEvent);
132 }
133}
void fireBeforeBranchEvent_(const DrawIBranchEvent &event) const
const Tree & tree() const override
double getXUnit() const override
double getYUnit() const override
void setTree(const Tree &tree) override
std::unique_ptr< TreeTemplate< INode > > tree_
void fireAfterTreeEvent_(const DrawTreeEvent &event) const
void fireBeforeNodeEvent_(const DrawINodeEvent &event) const
void fireAfterNodeEvent_(const DrawINodeEvent &event) const
bool hasTree() const override
void fireBeforeTreeEvent_(const DrawTreeEvent &event) const
void fireAfterBranchEvent_(const DrawIBranchEvent &event) const
Data structure describing a plotting direction.
Definition: TreeDrawing.h:54
Cursor getTranslation(double x, double y) const
Definition: TreeDrawing.h:75
virtual const Cursor & getCursor() const
Definition: TreeDrawing.h:159
virtual const TreeDrawing * getTreeDrawing() const
Definition: TreeDrawing.h:156
Event class that uses INode object (more efficient than relying on nodes id, but less generic).
const INode * getINode() const
Event class that uses INode object (more efficient than relying on nodes id, but less generic).
Event class used by TreeDrawing classes.
Definition: TreeDrawing.h:172
static short TEXT_HORIZONTAL_LEFT
static short TEXT_HORIZONTAL_RIGHT
virtual void drawLine(double x1, double y1, double x2, double y2)=0
The NodeTemplate class.
Definition: NodeTemplate.h:39
virtual const NodeInfos & getInfos() const
Definition: NodeTemplate.h:144
const NodeTemplate< NodeInfos > * getSon(size_t i) const
Definition: NodeTemplate.h:108
virtual bool hasDistanceToFather() const
Tell is this node has a distance to the father.
Definition: Node.h:288
virtual bool isLeaf() const
Definition: Node.h:679
virtual double getDistanceToFather() const
Get the distance to the father node is there is one, otherwise throw a NodeException.
Definition: Node.h:250
virtual size_t getNumberOfSons() const
Definition: Node.h:355
Cursor getBranchCursor(double position) const
void setTree(const Tree &tree) override
void recursivePlot_(GraphicDevice &gDevice, INode &node, double x, double &y, double hDirection, double vDirection, unsigned int &tipCounter) const
double getWidth() const override
Definition: PhylogramPlot.h:53
void drawDendrogram_(GraphicDevice &gDevice) const override
double getHeight() const override
Definition: PhylogramPlot.h:54
Basal interface for tree drawing classes.
Definition: TreeDrawing.h:223
virtual double getXUnit() const =0
Interface for phylogenetic tree objects.
Definition: Tree.h:115
Defines the basic types of data flow nodes.