Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
NekPoint.hpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: NekPoint.hpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Generic N-Dimensional Point.
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 #ifndef NEKTAR_LIB_UTILITIES_NEK_POINT_HPP
37 #define NEKTAR_LIB_UTILITIES_NEK_POINT_HPP
38 
39 #include <ExpressionTemplates/ExpressionTemplates.hpp>
44 
45 #include <boost/concept_check.hpp>
46 #include <boost/lexical_cast.hpp>
47 #include <boost/tokenizer.hpp>
48 #include <boost/call_traits.hpp>
49 #include <boost/type_traits.hpp>
50 #include <boost/mpl/or.hpp>
51 #include <boost/mpl/logical.hpp>
52 #include <boost/mpl/assert.hpp>
53 
54 #include <math.h>
55 #include <functional>
56 #include <algorithm>
57 
58 namespace Nektar
59 {
60  template<typename data_type>
61  class NekPoint
62  {
63  public:
64  typedef data_type DataType;
65  typedef ThreeD dim;
66 
67  public:
69  {
70  // This may be suboptimal if DataType isn't numeric.
71  // If we use them then maybe we could look at an enable_if
72  // template to choose a better constructor.
73  for(unsigned int i = 0; i < dim::Value; ++i)
74  {
75  // If you get a compile error pointing you here then
76  // the DataType being stored in the point doesn't have an
77  // accessible operator= or default copy constructor.
78  m_data[i] = DataType();
79  }
80  }
81 
82  NekPoint(const std::string& pointValues)
83  {
84  bool result = fromString(pointValues, *this);
85  ASSERTL0(result, "Unable to create a point from a string.");
86  }
87 
88  NekPoint(typename boost::call_traits<DataType>::param_type x,
89  typename boost::call_traits<DataType>::param_type y,
90  typename boost::call_traits<DataType>::param_type z)
91  {
92  m_data[0] = x;
93  m_data[1] = y;
94  m_data[2] = z;
95  }
96 
97  explicit NekPoint(typename boost::call_traits<DataType>::const_reference a)
98  {
99  boost::function_requires< Nektar::AssignableConcept<DataType> >();
100 
101  for(unsigned int i = 0; i < dim::Value; ++i)
102  {
103  m_data[i] = a;
104  }
105  }
106 
107 
109  {
110  for(unsigned int i = 0; i < dim::Value; ++i)
111  {
112  m_data[i] = rhs.m_data[i];
113  }
114  }
115 
117  {
118  }
119 
120 
122  {
123  for(unsigned int i = 0; i < dim::Value; ++i)
124  {
125  m_data[i] = rhs.m_data[i];
126  }
127  return *this;
128  }
129 
130  /// \brief Returns the number of dimensions for the point.
131  static unsigned int dimension() { return dim::Value; }
132 
133  /// \brief Returns i^{th} element.
134  /// \param i The element to return.
135  /// \pre i < dim
136  /// \return A reference to the i^{th} element.
137  ///
138  /// Retrieves the i^{th} element. Since it returns a reference you may
139  /// assign a new value (i.e., p(2) = 3.2;)
140  ///
141  /// This operator performs range checking.
142  typename boost::call_traits<DataType>::reference operator()(unsigned int i)
143  {
144  ASSERTL0( (i>=0) && (i<dim::Value), "Invalid access to NekPoint data via parenthesis operator: index out of range");
145  return m_data[i];
146  }
147 
148  typename boost::call_traits<DataType>::const_reference operator()(unsigned int i) const
149  {
150  ASSERTL0( (i>=0) && (i<dim::Value), "Invalid access to NekPoint data via parenthesis operator: index out of range");
151  return m_data[i];
152  }
153 
154  typename boost::call_traits<DataType>::reference operator[](unsigned int i)
155  {
156  return m_data[i];
157  }
158 
159  typename boost::call_traits<DataType>::const_reference operator[](unsigned int i) const
160  {
161  return m_data[i];
162  }
163 
164  typename boost::call_traits<DataType>::const_reference x() const
165  {
166  BOOST_STATIC_ASSERT(dim::Value >= 1);
167  return m_data[0];
168  }
169 
170  typename boost::call_traits<DataType>::const_reference y() const
171  {
172  BOOST_STATIC_ASSERT(dim::Value >= 2);
173  return (*this)[1];
174  }
175 
176  typename boost::call_traits<DataType>::const_reference z() const
177  {
178  BOOST_STATIC_ASSERT(dim::Value >= 3);
179  return (*this)[2];
180  }
181 
182  typename boost::call_traits<DataType>::const_reference a() const
183  {
184  BOOST_STATIC_ASSERT(dim::Value >= 1);
185  return m_data[0];
186  }
187 
188  typename boost::call_traits<DataType>::const_reference b() const
189  {
190  BOOST_STATIC_ASSERT(dim::Value >= 2);
191  return (*this)[1];
192  }
193 
194  typename boost::call_traits<DataType>::const_reference c() const
195  {
196  BOOST_STATIC_ASSERT(dim::Value >= 3);
197  return (*this)[2];
198  }
199 
200  typename boost::call_traits<DataType>::const_reference r() const
201  {
202  BOOST_STATIC_ASSERT(dim::Value >= 1);
203  return m_data[0];
204  }
205 
206  typename boost::call_traits<DataType>::const_reference s() const
207  {
208  BOOST_STATIC_ASSERT(dim::Value >= 2);
209  return (*this)[1];
210  }
211 
212  typename boost::call_traits<DataType>::const_reference t() const
213  {
214  BOOST_STATIC_ASSERT(dim::Value >= 3);
215  return (*this)[2];
216  }
217 
218  void SetX(typename boost::call_traits<DataType>::const_reference val)
219  {
220  BOOST_STATIC_ASSERT(dim::Value >= 1);
221  m_data[0] = val;
222  }
223 
224  void SetY(typename boost::call_traits<DataType>::const_reference val)
225  {
226  BOOST_STATIC_ASSERT(dim::Value >= 2);
227  m_data[1] = val;
228  }
229 
230  void SetZ(typename boost::call_traits<DataType>::const_reference val)
231  {
232  BOOST_STATIC_ASSERT(dim::Value >= 2);
233  m_data[2] = val;
234  }
235 
236  typename boost::call_traits<DataType>::reference x()
237  {
238  BOOST_STATIC_ASSERT(dim::Value >= 1);
239  return (*this)(0);
240  }
241 
242  typename boost::call_traits<DataType>::reference y()
243  {
244  BOOST_STATIC_ASSERT(dim::Value >= 2);
245  return (*this)(1);
246  }
247 
248  typename boost::call_traits<DataType>::reference z()
249  {
250  BOOST_STATIC_ASSERT(dim::Value >= 3);
251  return (*this)(2);
252  }
253 
254  const DataType* GetPtr() const
255  {
256  return &m_data[0];
257  }
258 
259  bool operator==(const NekPoint<DataType>& rhs) const
260  {
261  for(unsigned int i = 0; i < dim::Value; ++i)
262  {
263  // If you get a compile error here then you have to
264  // add a != operator to the DataType class.
265  if( m_data[i] != rhs.m_data[i] )
266  {
267  return false;
268  }
269  }
270  return true;
271  }
272 
273  bool operator!=(const NekPoint<DataType>& rhs) const
274  {
275  return !(*this == rhs);
276  }
277 
278  /// Arithmetic Routines
279 
280  // Unitary operators
281  void negate()
282  {
283  for(int i=0; i < dim::Value; ++i)
284  {
285  (*this)[i] = -(*this)[i];
286  }
287  }
288 
290  {
291  NekPoint<DataType> result(*this);
292  result.negate();
293  return result;
294  }
295 
296 
298  {
299  for(unsigned int i=0; i < dim::Value; ++i)
300  {
301  m_data[i] += rhs.m_data[i];
302  }
303  return *this;
304  }
305 
306  NekPoint<DataType>& operator+=(typename boost::call_traits<DataType>::param_type rhs)
307  {
308  for(unsigned int i = 0; i < dim::Value; ++i)
309  {
310  m_data[i] += rhs;
311  }
312  return *this;
313  }
314 
316  {
317  for(unsigned int i=0; i < dim::Value; ++i)
318  {
319  m_data[i] -= rhs.m_data[i];
320  }
321  return *this;
322  }
323 
324 
325  NekPoint<DataType>& operator-=(typename boost::call_traits<DataType>::param_type rhs)
326  {
327  for(unsigned int i = 0; i < dim::Value; ++i)
328  {
329  m_data[i] -= rhs;
330  }
331  return *this;
332  }
333 
334  NekPoint<DataType>& operator*=(typename boost::call_traits<DataType>::param_type rhs)
335  {
336  for(unsigned int i = 0; i < dim::Value; ++i)
337  {
338  m_data[i] *= rhs;
339  }
340  return *this;
341  }
342 
343  NekPoint<DataType>& operator/=(typename boost::call_traits<DataType>::param_type rhs)
344  {
345  for(unsigned int i = 0; i < dim::Value; ++i)
346  {
347  m_data[i] /= rhs;
348  }
349  return *this;
350  }
351 
352  std::string AsString() const
353  {
354  std::string result = "(";
355  for(unsigned int i = 0; i < dim::Value; ++i)
356  {
357  result += boost::lexical_cast<std::string>(m_data[i]);
358  if( i < dim::Value-1 )
359  {
360  result += ", ";
361  }
362  }
363  result += ")";
364  return result;
365  }
366 
367  private:
369  };
370 
371  // Operators for expression templates
372  template<typename DataType>
374  {
375  rhs.negate();
376  }
377 
378  template<typename DataType>
379  NekPoint<DataType>
381  {
382  NekPoint<DataType> result(lhs);
383  result += rhs;
384  return result;
385  }
386 
387  template<typename DataType>
388  NekPoint<DataType>
389  operator+(typename boost::call_traits<DataType>::const_reference lhs, const NekPoint<DataType>& rhs)
390  {
391  NekPoint<DataType> result(rhs);
392  result += lhs;
393  return result;
394  }
395 
396  template<typename DataType>
397  NekPoint<DataType>
398  operator+(const NekPoint<DataType>& lhs, typename boost::call_traits<DataType>::const_reference rhs)
399  {
400  NekPoint<DataType> result(lhs);
401  result += rhs;
402  return result;
403  }
404 
405  template<typename DataType>
406  NekPoint<DataType>
408  {
409  NekPoint<DataType> result(lhs);
410  result -= rhs;
411  return result;
412  }
413 
414  template<typename DataType>
415  NekPoint<DataType>
416  operator-(typename boost::call_traits<DataType>::const_reference lhs, const NekPoint<DataType>& rhs)
417  {
418  NekPoint<DataType> result(-rhs);
419  result += lhs;
420  return result;
421  }
422 
423  template<typename DataType>
424  NekPoint<DataType>
425  operator-(const NekPoint<DataType>& lhs, typename boost::call_traits<DataType>::const_reference rhs)
426  {
427  NekPoint<DataType> result(lhs);
428  result -= rhs;
429  return result;
430  }
431 
432  template<typename DataType, typename dim, typename space, typename ScalarType>
433  NekPoint<DataType>
434  operator*(const ScalarType& lhs, const NekPoint<DataType>& rhs)
435  {
436  NekPoint<DataType> result(rhs);
437  result *= lhs;
438  return result;
439  }
440 
441  template<typename DataType, typename dim, typename space, typename ScalarType>
442  NekPoint<DataType>
443  operator*(const NekPoint<DataType>& lhs, const ScalarType& rhs)
444  {
445  NekPoint<DataType> result(lhs);
446  result *= rhs;
447  return result;
448  }
449 
450  template<typename DataType>
451  NekPoint<DataType>
452  operator/(const NekPoint<DataType>& lhs, typename boost::call_traits<DataType>::param_type rhs)
453  {
454  NekPoint<DataType> result(lhs);
455  result /= rhs;
456  return result;
457  }
458 
459  template<typename DataType>
460  typename boost::call_traits<DataType>::value_type distanceBetween(const NekPoint<DataType>& lhs,
461  const NekPoint<DataType>& rhs)
462  {
463  DataType result = 0.0;
464  for(unsigned int i = 0; i < 3; ++i)
465  {
466  DataType temp = lhs[i] - rhs[i];
467  result += temp*temp;
468  }
469  return sqrt(result);
470  }
471 
472  template<typename DataType>
473  bool fromString(const std::string& str, NekPoint<DataType>& result)
474  {
475  try
476  {
477  typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
478  boost::char_separator<char> sep("(<,>) ");
479  tokenizer tokens(str, sep);
480  unsigned int i = 0;
481  for(tokenizer::iterator iter = tokens.begin(); iter != tokens.end(); ++iter)
482  {
483  result[i] = boost::lexical_cast<DataType>(*iter);
484  ++i;
485  }
486 
487  return i == 3;
488  }
489  catch(boost::bad_lexical_cast&)
490  {
491  return false;
492  }
493  }
494 
495  template<typename DataType>
496  std::ostream& operator<<(std::ostream& os, const NekPoint<DataType>& p)
497  {
498  os << p.AsString();
499  return os;
500  }
501 
502  //template<typename DataType>
503  //NekPoint<DataType> operator+(const NekPoint<DataType>& lhs, const NekPoint<DataType>& rhs)
504  //{
505  // NekPoint<DataType> result(lhs);
506  // result += rhs;
507  // return result;
508  //}
509 
510  //template<typename DataType>
511  //NekPoint<DataType,dim,space> operator+(const NekPoint<DataType,dim,space>& P, const NekVector<DataType>& V){
512  //ASSERTL0(P.dimension() == V.size(),"NekPoint::operator", "Point and Vector dimensions do not match");
513 
514  //NekPoint<DataType,dim> temp(P);
515  //for(int i=0;i<P.dimension();++i)
516  //temp(i) = temp(i) + V(i);
517  //return temp;
518  //}
519 //
520 // template<typename DataType, int dim>
521 // NekPoint<DataType,dim> operator+(const NekVector<DataType>& V, const NekPoint<DataType,dim>& P){
522 // ASSERTL0(dim == V.size(),"NekPoint::operator", "Point and Vector dimensions do not match");
523 //
524 // NekPoint<DataType,dim> temp(P);
525 // for(int i=0;i<dim;++i)
526  //temp(i) += V(i);
527 // return temp;
528 // }
529 //
530 // template<typename DataType, int dim>
531 
532 // NekPoint<DataType,dim> operator-(const NekPoint<DataType,dim>& P, const NekVector<DataType>& V){
533 // ASSERTL0(dim == V.size(),"NekPoint::operator", "Point and Vector dimensions do not match");
534 //
535 // NekPoint<DataType,dim> temp(P);
536 // for(int i=0;i<dim;++i)
537  //temp(i) -= V(i);
538 // return temp;
539 // }
540 }
541 
542 #endif // NEKTAR_LIB_UTILITIES_NEK_POINT_HPP
543 
544 /**
545  $Log: NekPoint.hpp,v $
546  Revision 1.18 2008/03/23 16:33:01 bnelson
547  *** empty log message ***
548 
549  Revision 1.17 2008/03/03 02:28:39 bnelson
550  Changed OneD, TwoD, and ThreeD to classes instead of enums to support type parameters in NekVector instead of unsigned int for the dimensions.
551 
552  Added a new NekVector<DataType> to allow wrapping of ConstArrays.
553 
554  Revision 1.16 2008/01/03 04:16:09 bnelson
555  Changed method name in the expression library from Apply to Evaluate.
556 
557  Revision 1.15 2007/08/16 02:09:56 bnelson
558  Moved expression templates to the Nektar namespace.
559 
560  Revision 1.14 2007/01/23 03:12:50 jfrazier
561  Added more conditional compilation directives for expression templates.
562 
563  Revision 1.13 2006/09/30 15:18:37 bnelson
564  no message
565 
566  Revision 1.12 2006/09/16 23:53:36 bnelson
567  Modified the negation operation to reflect changes in the unary expression templates.
568 
569  Revision 1.11 2006/09/15 02:18:39 bnelson
570  Fixed a problem with operator*
571 
572  Revision 1.10 2006/09/14 02:06:16 bnelson
573  Fixed gcc compiler errors.
574 
575  Revision 1.9 2006/09/11 03:26:26 bnelson
576  Updated to use new policy based expression templates.
577 
578  Revision 1.8 2006/09/10 20:40:24 bnelson
579  Changed DataType to data_type
580 
581  Revision 1.7 2006/09/08 03:37:18 bnelson
582  Fixed an ambiguous case with the templated copy constructor.
583 
584  Revision 1.6 2006/08/28 02:40:21 bnelson
585  *** empty log message ***
586 
587  Revision 1.5 2006/08/25 01:27:04 bnelson
588  Added construction and assignment from expressions.
589 
590  Added the unary negation expression template.
591 
592  Revision 1.4 2006/08/14 02:40:24 bnelson
593  no message
594 
595  Revision 1.3 2006/08/14 02:29:49 bnelson
596  Updated points, vectors, and matrix classes to work with ElVis. Added a variety of methods to all of these classes.
597 
598  Revision 1.2 2006/06/01 13:44:28 kirby
599  *** empty log message ***
600 
601  Revision 1.1 2006/06/01 09:12:42 kirby
602  *** empty log message ***
603 
604  Revision 1.1 2006/05/04 18:57:44 kirby
605  *** empty log message ***
606 
607  Revision 1.5 2006/04/11 02:01:32 bnelson
608  Fleshed out the interface.
609 
610  Revision 1.4 2006/04/06 03:45:22 bnelson
611  Added a third template parameter space.
612 
613  Revision 1.3 2006/03/25 00:52:43 jfrazier
614  Minor formatting stuff to correct indenting.
615 
616  Revision 1.2 2006/01/31 13:51:13 bnelson
617  Updated for new configure.
618 
619  Revision 1.1 2006/01/10 14:50:31 bnelson
620  Initial Revision.
621 
622 **/
623