Chaste  Build::
VesselSegment.cpp
1 /*
2 
3 Copyright (c) 2005-2016, University of Oxford.
4  All rights reserved.
5 
6  University of Oxford means the Chancellor, Masters and Scholars of the
7  University of Oxford, having an administrative office at Wellington
8  Square, Oxford OX1 2JD, UK.
9 
10  This file is part of Chaste.
11 
12  Redistribution and use in source and binary forms, with or without
13  modification, are permitted provided that the following conditions are met:
14  * Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16  * Redistributions in binary form must reproduce the above copyright notice,
17  this list of conditions and the following disclaimer in the documentation
18  and/or other materials provided with the distribution.
19  * Neither the name of the University of Oxford nor the names of its
20  contributors may be used to endorse or promote products derived from this
21  software without specific prior written permission.
22 
23  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 
34  */
35 
36 #include "SmartPointers.hpp"
37 #include "UblasIncludes.hpp"
38 #include "VesselNode.hpp"
39 #include "Vessel.hpp"
40 #include "VesselSegment.hpp"
41 #include "GeometryTools.hpp"
42 
43 template<unsigned DIM>
44 VesselSegment<DIM>::VesselSegment(boost::shared_ptr<VesselNode<DIM> > pNode1, boost::shared_ptr<VesselNode<DIM> > pNode2) :
46  mNodes(std::pair<boost::shared_ptr<VesselNode<DIM> >, boost::shared_ptr<VesselNode<DIM> > >(pNode1, pNode2)),
47  mVessel(boost::weak_ptr<Vessel<DIM> >()),
49 {
50 }
51 
52 template<unsigned DIM>
54  boost::enable_shared_from_this<VesselSegment<DIM> >(), AbstractVesselNetworkComponent<DIM>(),
55  mNodes(rSegment.GetNodes()),
56  mVessel(boost::weak_ptr<Vessel<DIM> >()),
58 {
59  this->SetFlowProperties(*(rSegment.GetFlowProperties()));
60 }
61 
62 template<unsigned DIM>
63 boost::shared_ptr<VesselSegment<DIM> > VesselSegment<DIM>::Create(boost::shared_ptr<VesselNode<DIM> > pNode1, boost::shared_ptr<VesselNode<DIM> > pNode2)
64 {
65  boost::shared_ptr<VesselSegment<DIM> > pSelf(new VesselSegment<DIM>(pNode1, pNode2));
66 
67  // Make sure the specified nodes are not the same
68  if (pNode1 == pNode2)
69  {
70  EXCEPTION("Attempted to assign the same node to both ends of a vessel segment.");
71  }
72 
73  // Add the segment to the nodes
74  pNode1->AddSegment(pSelf->shared_from_this());
75  pNode2->AddSegment(pSelf->shared_from_this());
76  return pSelf;
77 }
78 
79 template<unsigned DIM>
80 boost::shared_ptr<VesselSegment<DIM> > VesselSegment<DIM>::Create(boost::shared_ptr<VesselSegment<DIM> > pSegment)
81 {
82  if(!pSegment)
83  {
84  EXCEPTION("A Null pointer cannot be used when copying segments.");
85  }
86  MAKE_PTR_ARGS(VesselSegment<DIM>, pSelf, (*pSegment));
87 
88  // Add the segment to the nodes
89  pSelf->GetNode(0)->AddSegment(pSelf->shared_from_this());
90  pSelf->GetNode(1)->AddSegment(pSelf->shared_from_this());
91  return pSelf;
92 }
93 
94 template<unsigned DIM>
96 {
97 }
98 
99 template<unsigned DIM>
100 void VesselSegment<DIM>::AddVessel(boost::shared_ptr<Vessel<DIM> > pVessel)
101 {
102  mVessel = pVessel;
103 }
104 
105 template<unsigned DIM>
106 void VesselSegment<DIM>::CopyDataFromExistingSegment(const boost::shared_ptr<VesselSegment<DIM> > pTargetSegment)
107 {
108  this->mOutputData = pTargetSegment->GetOutputData();
109  this->SetRadius(pTargetSegment->GetRadius());
110  this->SetFlowProperties(*(pTargetSegment->GetFlowProperties()));
111 }
112 
113 template<unsigned DIM>
114 units::quantity<unit::length> VesselSegment<DIM>::GetDistance(const DimensionalChastePoint<DIM>& location) const
115 {
116  return GetDistanceToLineSegment(mNodes.first->rGetLocation(), mNodes.second->rGetLocation(), location);
117 }
118 
119 template<unsigned DIM>
120 boost::shared_ptr<SegmentFlowProperties<DIM> > VesselSegment<DIM>::GetFlowProperties() const
121 {
122  return this->mpFlowProperties;
123 }
124 
125 template<unsigned DIM>
126 units::quantity<unit::length> VesselSegment<DIM>::GetLength() const
127 {
128  return mNodes.second->GetDistance(mNodes.first->rGetLocation());
129 }
130 
131 template<unsigned DIM>
132 std::map<std::string, double> VesselSegment<DIM>::GetOutputData()
133 {
134  this->mOutputData.clear();
135  std::map<std::string, double> flow_data = this->mpFlowProperties->GetOutputData();
136  this->mOutputData.insert(flow_data.begin(), flow_data.end());
137  this->mOutputData["Segment Id"] = double(this->GetId());
138  this->mOutputData["Segment Radius m: "] = this->GetRadius() / unit::metres;
139  return this->mOutputData;
140 }
141 
142 template<unsigned DIM>
144 {
145  return mNodes.first->rGetLocation().GetMidPoint(mNodes.second->rGetLocation());
146 }
147 
148 template<unsigned DIM>
149 boost::shared_ptr<VesselNode<DIM> > VesselSegment<DIM>::GetNode(unsigned index) const
150 {
151  if (index == 0u)
152  {
153  return mNodes.first;
154  }
155  else if (index == 1u)
156  {
157  return mNodes.second;
158  }
159  else
160  {
161  EXCEPTION("A node index other than 0 or 1 has been requested for a Vessel Segment.");
162  }
163 }
164 
165 template<unsigned DIM>
166 boost::shared_ptr<VesselNode<DIM> > VesselSegment<DIM>::GetOppositeNode(boost::shared_ptr<VesselNode<DIM> > pInputNode) const
167 {
168  if(pInputNode == mNodes.first)
169  {
170  return mNodes.second;
171  }
172  else if(pInputNode == mNodes.second)
173  {
174  return mNodes.first;
175  }
176  else
177  {
178  EXCEPTION("Input node is not on the segment");
179  }
180 }
181 
182 template<unsigned DIM>
183 std::pair<boost::shared_ptr<VesselNode<DIM> >, boost::shared_ptr<VesselNode<DIM> > > VesselSegment<DIM>::GetNodes() const
184 {
185  return mNodes;
186 }
187 
188 template<unsigned DIM>
190 {
191  return GetPointProjectionOnLineSegment(mNodes.first->rGetLocation(), mNodes.second->rGetLocation(), location, projectToEnds);
192 }
193 
194 template<unsigned DIM>
195 c_vector<double, DIM> VesselSegment<DIM>::GetUnitTangent() const
196 {
197  return mNodes.first->rGetLocation().GetUnitTangent(mNodes.second->rGetLocation());
198 }
199 
200 template<unsigned DIM>
201 boost::shared_ptr<Vessel<DIM> > VesselSegment<DIM>::GetVessel() const
202 {
203  if (mVessel.lock())
204  {
205  return mVessel.lock();
206  }
207  else
208  {
209  EXCEPTION("A vessel has been requested but this segment doesn't have one.");
210  }
211 }
212 
213 template<unsigned DIM>
214 bool VesselSegment<DIM>::HasNode(boost::shared_ptr<VesselNode<DIM> > pNode) const
215 {
216  return (pNode == GetNode(0) || pNode == GetNode(1));
217 }
218 
219 template<unsigned DIM>
220 bool VesselSegment<DIM>::IsConnectedTo(boost::shared_ptr<VesselSegment<DIM> > otherSegment) const
221 {
222  bool isConnectedToSegment = false;
223  if (this->GetNode(0) == otherSegment->GetNode(0) || this->GetNode(0) == otherSegment->GetNode(1)
224  || this->GetNode(1) == otherSegment->GetNode(0) || this->GetNode(1) == otherSegment->GetNode(1))
225  {
226  isConnectedToSegment = true;
227  }
228 
229  return isConnectedToSegment;
230 }
231 
232 template<unsigned DIM>
234 {
235  mVessel = boost::weak_ptr<Vessel<DIM> >();
236 }
237 
238 template<unsigned DIM>
240 {
241  mNodes.first->RemoveSegment(Shared());
242  mNodes.second->RemoveSegment(Shared());
243  RemoveVessel();
244 }
245 
246 template<unsigned DIM>
247 void VesselSegment<DIM>::ReplaceNode(unsigned oldNodeIndex, boost::shared_ptr<VesselNode<DIM> > pNewNode)
248 {
249  if (oldNodeIndex == 0u)
250  {
251  mNodes.first->RemoveSegment(Shared());
252  mNodes.first = pNewNode;
253  mNodes.first->AddSegment(Shared());
254  }
255  else if (oldNodeIndex == 1u)
256  {
257  mNodes.second->RemoveSegment(Shared());
258  mNodes.second = pNewNode;
259  mNodes.second->AddSegment(Shared());
260  }
261  else
262  {
263  EXCEPTION("A node index other than 0 or 1 has been requested for a Vessel Segment.");
264  }
265 
266  if (mVessel.lock() != NULL)
267  {
268  mVessel.lock()->UpdateNodes();
269  }
270 }
271 
272 template<unsigned DIM>
274 {
275  this->mpFlowProperties = boost::shared_ptr<SegmentFlowProperties<DIM> >(new SegmentFlowProperties<DIM> (rFlowProperties));
276 }
277 
278 template<unsigned DIM>
279 boost::shared_ptr<VesselSegment<DIM> > VesselSegment<DIM>::Shared()
280 {
281  boost::shared_ptr<VesselSegment<DIM> > pSegment = this->shared_from_this();
282  return pSegment;
283 }
284 
285 // Explicit instantiation
286 template class VesselSegment<2>;
287 template class VesselSegment<3>;
VesselSegment(boost::shared_ptr< VesselNode< DIM > > pNode1, boost::shared_ptr< VesselNode< DIM > > pNode2)
void SetFlowProperties(const SegmentFlowProperties< DIM > &rFlowProperties)
std::pair< boost::shared_ptr< VesselNode< DIM > >, boost::shared_ptr< VesselNode< DIM > > > mNodes
boost::shared_ptr< VesselNode< DIM > > GetOppositeNode(boost::shared_ptr< VesselNode< DIM > > pInputNode) const
void ReplaceNode(unsigned oldNodeIndex, boost::shared_ptr< VesselNode< DIM > > pNewNode)
std::pair< boost::shared_ptr< VesselNode< DIM > >, boost::shared_ptr< VesselNode< DIM > > > GetNodes() const
boost::shared_ptr< SegmentFlowProperties< DIM > > mpFlowProperties
boost::shared_ptr< SegmentFlowProperties< DIM > > GetFlowProperties() const
c_vector< double, DIM > GetUnitTangent() const
boost::shared_ptr< VesselSegment< DIM > > Shared()
bool IsConnectedTo(boost::shared_ptr< VesselSegment< DIM > > pOtherSegment) const
DimensionalChastePoint< DIM > GetMidPoint() const
std::map< std::string, double > mOutputData
boost::weak_ptr< Vessel< DIM > > mVessel
boost::shared_ptr< Vessel< DIM > > GetVessel() const
static boost::shared_ptr< VesselSegment< DIM > > Create(boost::shared_ptr< VesselNode< DIM > > pNode1, boost::shared_ptr< VesselNode< DIM > > pNode2)
units::quantity< unit::length > GetDistance(const DimensionalChastePoint< DIM > &location) const
void AddVessel(boost::shared_ptr< Vessel< DIM > > pVessel)
boost::shared_ptr< VesselNode< DIM > > GetNode(unsigned index) const
virtual units::quantity< unit::length > GetRadius() const
virtual void SetRadius(units::quantity< unit::length > radius)
units::quantity< unit::length > GetLength() const
DimensionalChastePoint< DIM > GetPointProjection(const DimensionalChastePoint< DIM > &location, bool projectToEnds=false) const
void CopyDataFromExistingSegment(const boost::shared_ptr< VesselSegment< DIM > > pTargetSegment)
bool HasNode(boost::shared_ptr< VesselNode< DIM > > pNode) const
std::map< std::string, double > GetOutputData()