bpp-phyl3  3.0.0
CladogramPlot.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 "CladogramPlot.h"
7 
8 // From the STL:
9 #include <memory>
10 
11 using namespace bpp;
12 using namespace std;
13 
14 CladogramDrawBranchEvent::CladogramDrawBranchEvent(const TreeDrawing* source, GraphicDevice* gd, const INode* node, double length, const Cursor& cursor, short orientation) :
15  DrawIBranchEvent(source, gd, node, cursor), orientation_(), length_(length)
16 {
18 }
19 
21 {
22  double offset = 0;
23  if (getINode()->hasDistanceToFather())
24  {
25  offset = orientation_ * length_ * position;
26  }
27  return getCursor().getTranslation(offset, 0);
28 }
29 
30 void CladogramPlot::setTree(const Tree* tree)
31 {
33  if (hasTree())
34  totalDepth_ = static_cast<double>(TreeTemplateTools::getDepth(*getTree_()->getRootNode()));
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*>(getTree_()->getRootNode()),
47  y,
50  tipCounter);
51  fireAfterTreeEvent_(treeEvent);
52  }
53 }
54 
55 void CladogramPlot::recursivePlot_(GraphicDevice& gDevice, INode& node, double x, double& y, double hDirection, double vDirection, unsigned int& tipCounter) const
56 {
57  double depth = static_cast<double>(TreeTemplateTools::getDepth(node));
58  double x2 = ((getHorizontalOrientation() == ORIENTATION_LEFT_TO_RIGHT ? totalDepth_ : 0) - depth) * getXUnit() * hDirection;
59  unique_ptr<Cursor> cursor;
60  unique_ptr<DrawINodeEvent> nodeEvent;
61  unique_ptr<DrawIBranchEvent> branchEvent;
63  if (node.isLeaf())
64  {
65  y = ((getVerticalOrientation() == ORIENTATION_TOP_TO_BOTTOM ? 0 : getHeight()) + static_cast<double>(tipCounter) * vDirection) * getYUnit();
66  tipCounter++;
67  cursor.reset(new Cursor(x2, y, 0, hpos));
68  nodeEvent.reset(new DrawINodeEvent(this, &gDevice, &node, *cursor));
69  fireBeforeNodeEvent_(*nodeEvent);
70  }
71  else if (node.getInfos().isCollapsed())
72  {
73  y = ((getVerticalOrientation() == ORIENTATION_TOP_TO_BOTTOM ? 0 : getHeight()) + static_cast<double>(tipCounter) * vDirection) * getYUnit();
74  tipCounter++;
75  cursor.reset(new Cursor(x2, y, 0, hpos));
76  nodeEvent.reset(new DrawINodeEvent(this, &gDevice, &node, *cursor));
77  fireBeforeNodeEvent_(*nodeEvent);
78  }
79  else
80  {
81  // Vertical line. Call the method on son nodes first:
82  double miny = 1000000; // (unsigned int)(-log(0));
83  double maxy = 0;
84  for (unsigned int i = 0; i < node.getNumberOfSons(); i++)
85  {
86  double yson;
87  recursivePlot_(gDevice, *node.getSon(i), x2, yson, hDirection, vDirection, tipCounter);
88  if (yson < miny)
89  miny = yson;
90  if (yson > maxy)
91  maxy = yson;
92  }
93  y = (maxy + miny) / 2.;
94  cursor.reset(new Cursor(x2, y, 0, hpos));
95  nodeEvent.reset(new DrawINodeEvent(this, &gDevice, &node, *cursor));
96  fireBeforeNodeEvent_(*nodeEvent);
97  gDevice.drawLine(x2, miny, x2, maxy);
98  }
99  // Actualize node infos:
100  node.getInfos().setX(x2);
101  node.getInfos().setY(y);
102  nodeEvent.reset(new DrawINodeEvent(this, &gDevice, &node, *cursor));
103  fireAfterNodeEvent_(*nodeEvent);
104 
105  // Horizontal line
106  branchEvent.reset(new CladogramDrawBranchEvent(this, &gDevice, &node, x2 - x, *cursor, getHorizontalOrientation()));
107  fireBeforeBranchEvent_(*branchEvent);
108  gDevice.drawLine(x, y, x2, y);
109  fireAfterBranchEvent_(*branchEvent);
110 }
void fireBeforeBranchEvent_(const DrawIBranchEvent &event) const
TreeTemplate< INode > * getTree_()
void fireAfterTreeEvent_(const DrawTreeEvent &event) const
void fireBeforeNodeEvent_(const DrawINodeEvent &event) const
void setTree(const Tree *tree)
void fireAfterNodeEvent_(const DrawINodeEvent &event) const
void fireBeforeTreeEvent_(const DrawTreeEvent &event) const
void fireAfterBranchEvent_(const DrawIBranchEvent &event) const
CladogramDrawBranchEvent(const TreeDrawing *source, GraphicDevice *gd, const INode *node, double length_, const Cursor &cursor, short orientation)
Cursor getBranchCursor(double position) const
void recursivePlot_(GraphicDevice &gDevice, INode &node, double x, double &y, double hDirection, double vDirection, unsigned int &tipCounter) const
double getHeight() const
Definition: CladogramPlot.h:56
void drawDendrogram_(GraphicDevice &gDevice) const
void setTree(const Tree *tree=0)
double getWidth() const
Definition: CladogramPlot.h:55
Data structure describing a plotting direction.
Definition: TreeDrawing.h:53
Cursor getTranslation(double x, double y) const
Definition: TreeDrawing.h:74
virtual const Cursor & getCursor() const
Definition: TreeDrawing.h:158
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:171
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
const NodeTemplate< NodeInfos > * getSon(size_t i) const
Definition: NodeTemplate.h:108
virtual const NodeInfos & getInfos() const
Definition: NodeTemplate.h:144
virtual bool isLeaf() const
Definition: Node.h:667
virtual size_t getNumberOfSons() const
Definition: Node.h:355
Basal interface for tree drawing classes.
Definition: TreeDrawing.h:223
static unsigned int getDepth(const Node &node)
Get the depth of the subtree defined by node 'node', i.e. the maximum number of sons 'generations'.
Interface for phylogenetic tree objects.
Definition: Tree.h:115
Defines the basic types of data flow nodes.