VPTissue Reference Manual
Wall.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2016 Universiteit Antwerpen
3  *
4  * Licensed under the EUPL, Version 1.1 or as soon they will be approved by
5  * the European Commission - subsequent versions of the EUPL (the "Licence");
6  * You may not use this work except in compliance with the Licence.
7  * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl5
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the Licence is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the Licence for the specific language governing
13  * permissions and limitations under the Licence.
14  */
20 #include "Wall.h"
21 
22 #include "Cell.h"
23 #include "Edge.h"
24 #include "Node.h"
25 #include "NodeAttributes.h"
26 #include "WallAttributes.h"
27 #include "math/array3.h"
28 #include "math/constants.h"
31 
32 #include <functional>
33 #include <ostream>
34 
35 using namespace std;
36 using namespace boost::property_tree;
37 using namespace SimPT_Sim;
38 using namespace SimPT_Sim::Container;
39 using namespace SimPT_Sim::Util;
40 
41 namespace SimPT_Sim {
42 
43 Wall::Wall(unsigned int index, Node* n1, Node* n2, Cell* c1, Cell* c2, unsigned int num_chem)
44  : WallAttributes(num_chem),
45  m_c1(c1), m_c2(c2), m_n1(n1), m_n2(n2), m_wall_index(index), m_length(0.0), m_length_dirty(true)
46 {
47  assert( (n1 != nullptr) && "Wall::Wall> Attempting to build a node with nullptr cell!" );
48  assert( (n2 != nullptr) && "Wall::Wall> Attempting to build a node with nullptr cell!" );
49  assert( (c1 != nullptr) && "Wall::Wall> Attempting to build a wall with nullptr cell!" );
50  assert( (c2 != nullptr) && "Wall::Wall> Attempting to build a wall with nullptr cell!" );
51  assert( (c1 != c2) && "Wall::Wall> Attempting to build a wall between identical cells!" );
52 
53  std::array<double, 3> ref{{1., 0., 0.}};
54  std::array<double, 3> tot1 = *n1;
55  std::array<double, 3> tot2 = *n2;
56  std::array<double, 3> tot3 = tot1 - tot2;
57  double t2 = SignedAngle(tot3, ref);
58  if ( ( t2 > (-pi() * 3 / 4) && t2 <= (-pi() / 4) ) || ( t2 > (pi() / 4) && t2 <= (pi() * 3 / 4) ) )
59  {
60  SetStrength(1.);
61  } else {
62  SetStrength(5.);//DDV: should be 1 for Blad, 5 for Wortel.
63  }
64 }
65 
66 void Wall::CalculateLength() const
67 {
68  const auto& nodes = m_c1->GetNodes();
69  const auto n_begin = nodes.begin();
70  const auto n_end = nodes.end();
71  auto from = make_const_circular(nodes, std::find(n_begin, n_end, m_n1));
72  auto to = make_const_circular(nodes, std::find(n_begin, n_end, m_n2));
73 
74  assert(from != m_c1->GetNodes().end() && "N1 wall endpoint not in cell C1!");
75  assert(to != m_c1->GetNodes().end() && "N2 wall endpoint not in cell C1!");
76 
77  m_length = 0.0;
78  do {
79  m_length += Norm(**from - **std::next(from));
80  } while (++from != to); // Loop until the next node is end point of wall
81 }
82 
83 vector<Edge> Wall::GetEdges() const
84 {
85  vector<Edge> v;
86  const auto& nodes = GetC1()->GetNodes();
87  const auto cit_start = find(nodes.begin(), nodes.end(), GetN1());
88  const auto cit_stop = find(nodes.begin(), nodes.end(), GetN2());
89 
90  auto cit = make_const_circular(nodes, cit_start);
91  do {
92  v.push_back(Edge(*cit, *next(cit)));
93  } while(++cit != cit_stop);
94  return v;
95 }
96 
97 double Wall::GetLength() const
98 {
99  if (m_length_dirty) {
100  CalculateLength();
101  m_length_dirty = false;
102  }
103  return m_length;
104 }
105 
106 array<double, 3> Wall::GetInfluxVector(Cell* c) const
107 {
108  assert( (m_c1 == c || m_c2 == c) && "Wall::GetWallVector called with wrong cell!" );
109  const double sign = ( c == m_c1 ? 1.0 : -1.0 );
110  return sign * Orthogonalize(Normalize(*m_n2 - *m_n1));
111 }
112 
113 array<double, 3> Wall::GetWallVector(Cell* c) const
114 {
115  assert( (m_c1 == c || m_c2 ==c) && "Wall::GetWallVector called with wrong cell!" );
116  const double sign = ( c == m_c1 ? 1.0 : -1.0 );
117  return sign * (*m_n2 - *m_n1);
118 }
119 
120 bool Wall::IsAtBoundary() const
121 {
122  return (m_c1->GetIndex() == -1 || m_c2->GetIndex() == -1);
123 }
124 
125 bool Wall::IsSam() const
126 {
127  return GetN1()->IsSam() || GetN2()->IsSam();
128 }
129 
130 bool Wall::IncludesEdge(const Edge& edge) const
131 {
132  bool status = false;
133 
134  const auto& nodes = GetC1()->GetNodes();
135  const auto cit_start = find(nodes.begin(), nodes.end(), GetN1());
136  const auto cit_stop = find(nodes.begin(), nodes.end(), GetN2());
137 
138  auto cit = make_const_circular(nodes, cit_start);
139  do {
140  status = (Edge(*cit, *next(cit)) == edge);
141  } while(!status && ++cit != cit_stop);
142 
143  return status;
144 }
145 
146 bool Wall::IncludesNode(const Node* node) const
147 {
148  bool status = false;
149 
150  const auto& nodes = GetC1()->GetNodes();
151  const auto cit_start = find(nodes.begin(), nodes.end(), GetN1());
152  const auto cit_stop = find(nodes.begin(), nodes.end(), GetN2());
153 
154  auto cit = make_const_circular(nodes, cit_start);
155  do {
156  status = (*cit == node);
157  } while(!status && cit++ != cit_stop);
158 
159  return status;
160 }
161 
162 bool Wall::IsIntersectingWithDivisionPlane(const array<double, 3>& p1, const array<double, 3>& p2) const
163 {
164  const double x1 = (*m_n1)[0];
165  const double y1 = (*m_n1)[1];
166  const double x2 = (*m_n2)[0];
167  const double y2 = (*m_n2)[1];
168  const double x3 = p1[0];
169  const double y3 = p1[1];
170  const double x4 = p2[0];
171  const double y4 = p2[1];
172  const double ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3))
173  / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));
174 
175  // If ua is between 0 and 1, line p1 to p2 intersects the wall segment.
176  return (ua >= 0. && ua <= 1.) ? true : false;
177 
178 }
179 
180 ostream& Wall::Print(ostream& os) const
181 {
182  os << "Wall: " << GetIndex() << " "<< "{ " << m_n1->GetIndex() << "->" << m_n2->GetIndex()
183  << ", " << m_c1->GetIndex() << " | " << m_c2->GetIndex() << "} ";
184  return os;
185 }
186 
187 void Wall::ReadPtree(boost::property_tree::ptree const& wall_pt)
188 {
189  WallAttributes::ReadPtree(wall_pt.get_child("attributes"));
190 }
191 
192 ptree Wall::ToPtree() const
193 {
194  ptree ret;
195  ret.put("id", GetIndex());
196  ret.put("c1", m_c1->GetIndex());
197  ret.put("c2", m_c2->GetIndex());
198  ret.put("n1", m_n1->GetIndex());
199  ret.put("n2", m_n2->GetIndex());
200  ret.put("length", GetLength());
201  ret.add_child("attributes", WallAttributes::ToPtree());
202 
203  return ret;
204 }
205 
206 ostream& operator<<(ostream& os, const Wall& w)
207 {
208  w.Print(os);
209  return os;
210 }
211 
212 }
Math constants.
bool IsAtBoundary() const
Checks whether a wall is at the boundary of the mesh.
Definition: Wall.cpp:120
STL namespace.
A cell contains walls and nodes.
Definition: Cell.h:48
bool IncludesNode(const Node *node) const
Checks whether edge is part of this wall.
Definition: Wall.cpp:146
Node in cell wall.
Definition: Node.h:39
Namespace for miscellaneous utilities.
Definition: PTreeFile.cpp:44
bool IncludesEdge(const Edge &edge) const
Checks whether edge is part of this wall.
Definition: Wall.cpp:130
Interface for NodeAttributes.
Namespace for the core simulator.
An Edge connects two nodes and is ambidextrous.
Definition: Edge.h:31
Interface for Cell.
Namespace for container related classes.
Interface for WallAttributes.
const std::vector< Node * > & GetNodes() const
Access the nodes of cell's polygon.
Definition: Cell.h:79
Attributes associated with a wall.
Interface for Node.
ConstCircularIterator class and helper functions.
int GetIndex() const
Return the index.
Definition: Cell.h:76
virtual boost::property_tree::ptree ToPtree() const
Convert the wall to a ptree.
Definition: Wall.cpp:192
double GetLength() const
Returns (and calculates, if length marked as dirty) the length along all nodes.
Definition: Wall.cpp:97
Interface for Edge.
Extending std with arithmetic for std::array.
CircularIterator< T > next(CircularIterator< T > i)
Helper yields the position the iterator would have if moved forward (in circular fashion) by 1 positi...
ConstCircularIterator< typename T::const_iterator > make_const_circular(const T &c)
Helper produces const circular iterator whose range corresponds to the begin and end iterators of a c...
CircularIterator class and helper functions.
constexpr double pi()
Math constant pi.
Definition: constants.h:29
A cell wall, runs between cell corner points and consists of wall elements.
Definition: Wall.h:48
virtual boost::property_tree::ptree ToPtree() const
Convert the wall attributes to a ptree.
Interface for Wall.
bool IsSam() const
True if the Wall adheres to the SAM (shoot apical meristem)
Definition: Wall.cpp:125