ug4
geometry_util.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3  * Author: Andreas Vogel
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 #ifndef __H__UG__LIB_DISC__COMMON__GEOMETRY_UTIL__
34 #define __H__UG__LIB_DISC__COMMON__GEOMETRY_UTIL__
35 
36 #include <vector>
37 #include <cmath>
38 
39 #include "common/common.h"
42 #include "lib_disc/domain_traits.h"
43 #include "common/util/provider.h"
44 
45 namespace ug{
46 
49 template <typename TRefElem, int TWorldDim>
50 inline number ElementSize(const MathVector<TWorldDim>* vCornerCoords);
51 
54 // 1D Reference Elements
57 
60 
66 template <>
68 {
69  return VecDistance(vCornerCoords[0], vCornerCoords[1]);
70 }
71 
74 
80 template <>
82 {
83  return VecDistance(vCornerCoords[0], vCornerCoords[1]);
84 }
85 
88 
94 template <>
96 {
97  return VecDistance(vCornerCoords[0], vCornerCoords[1]);
98 }
99 
102 // 2D Reference Elements
105 
108 
117 template <>
119 {
120  return(0.5*fabs((vCornerCoords[1][1]-vCornerCoords[0][1])*(vCornerCoords[2][0]-vCornerCoords[0][0])
121  -(vCornerCoords[1][0]-vCornerCoords[0][0])*(vCornerCoords[2][1]-vCornerCoords[0][1])));
122 }
123 
126 
134 template <>
136 {
137  MathVector<3> x10, x20, n;
138 
139  VecSubtract(x10, vCornerCoords[1], vCornerCoords[0]);
140  VecSubtract(x20, vCornerCoords[2], vCornerCoords[0]);
141  VecCross(n, x10, x20);
142 
143  return(0.5 * VecTwoNorm(n) );
144 }
145 
148 
156 template <>
158 {
159  return( 0.5*fabs( (vCornerCoords[3][1]-vCornerCoords[1][1])*(vCornerCoords[2][0]-vCornerCoords[0][0])
160  -(vCornerCoords[3][0]-vCornerCoords[1][0])*(vCornerCoords[2][1]-vCornerCoords[0][1]) ) );
161 }
162 
165 
175 template <>
177 {
178  MathVector<3> x20, x31, n;
179 
180  VecSubtract(x20, vCornerCoords[2], vCornerCoords[0]);
181  VecSubtract(x31, vCornerCoords[3], vCornerCoords[1]);
182  VecCross(n, x20, x31);
183 
184  return(0.5 * VecTwoNorm(n) );
185 }
186 
187 
190 // 3D Reference Elements
193 
196 
208 template <>
210 {
211  MathVector<3> x10, x20, x30, n;
212 
213  VecSubtract(x10, vCornerCoords[1], vCornerCoords[0]);
214  VecSubtract(x20, vCornerCoords[2], vCornerCoords[0]);
215  VecSubtract(x30, vCornerCoords[3], vCornerCoords[0]);
216  VecCross(n, x10, x20);
217 
218  return (1./6.) * fabs ( VecDot(n, x30) );
219 }
220 
223 
234 template <>
236 {
237  MathVector<3> x20, x31, x40, n;
238 
239  VecSubtract(x20, vCornerCoords[2], vCornerCoords[0]);
240  VecSubtract(x31, vCornerCoords[3], vCornerCoords[1]);
241  VecSubtract(x40, vCornerCoords[4], vCornerCoords[0]);
242  VecCross(n, x20, x31);
243 
244  return (1./6.) * VecDot(n, x40);
245 }
246 
249 
259 template <>
261 {
262  MathVector<3> x40, x13, x10, x20, x50, m, n;
263 
264  VecSubtract(x40, vCornerCoords[4], vCornerCoords[0]);
265  VecSubtract(x13, vCornerCoords[1], vCornerCoords[3]);
266  VecSubtract(x10, vCornerCoords[1], vCornerCoords[0]);
267  VecSubtract(x20, vCornerCoords[2], vCornerCoords[0]);
268 
269  // height for both subelements
270  VecSubtract(x50, vCornerCoords[5], vCornerCoords[0]);
271 
272  VecCross(m, x40, x13); // base of pyramid
273  VecCross(n, x10, x20); // base of tetrahedron
274 
275  // n = n + m
276  VecAppend(n, m);
277 
278  return (1./6.) * VecDot(n, x50);
279 }
280 
283 
294 template <>
296 {
297  MathVector<3> x50, x14, x10, x20, x60, m1, n1;
298  MathVector<3> x24, x30, x70, m2, n2;
299 
300  // 1. prism
301  VecSubtract(x50, vCornerCoords[5], vCornerCoords[0]);
302  VecSubtract(x14, vCornerCoords[1], vCornerCoords[4]);
303  VecSubtract(x10, vCornerCoords[1], vCornerCoords[0]);
304  VecSubtract(x20, vCornerCoords[2], vCornerCoords[0]);
305  VecSubtract(x60, vCornerCoords[6], vCornerCoords[0]);
306 
307  VecCross(m1, x50, x14); // base of pyramid
308  VecCross(n1, x10, x20); // base of tetrahedron
309 
310  // n1 = n1 + m1
311  VecAppend(n1, m1);
312 
313  // 2. prism
314  //VecSubtract(x60, vCornerCoords[6], vCornerCoords[0]);
315  VecSubtract(x24, vCornerCoords[2], vCornerCoords[4]);
316  //VecSubtract(x20, vCornerCoords[2], vCornerCoords[0]);
317  VecSubtract(x30, vCornerCoords[3], vCornerCoords[0]);
318  VecSubtract(x70, vCornerCoords[7], vCornerCoords[0]);
319 
320  VecCross(m2, x60, x24); // base of pyramid
321  VecCross(n2, x20, x30); // base of tetrahedron
322 
323  // n2 = n2 + m2
324  VecAppend(n2, m2);
325 
326  return (1./6.) * (VecDot(n1, x60) + VecDot(n2, x70));
327 }
328 
331 
344 template <>
346 {
347  MathVector<3> x31, x42, x51, n;
348  MathVector<3> x01;
349 
350  VecSubtract(x31, vCornerCoords[3], vCornerCoords[1]);
351  VecSubtract(x42, vCornerCoords[4], vCornerCoords[2]);
352  VecSubtract(x51, vCornerCoords[5], vCornerCoords[1]);
353  VecCross(n, x31, x42);
354 
355  //VecSubtract(x31, vCornerCoords[3], vCornerCoords[1]);
356  //VecSubtract(x42, vCornerCoords[4], vCornerCoords[2]);
357  VecSubtract(x01, vCornerCoords[0], vCornerCoords[1]);
358  //VecCross(n, x31, x42);
359 
360  number volTopPyr = (1./6.) * fabs(VecDot(n, x51));
361  number volBottomPyr = (1./6.) * fabs(VecDot(n, x01));
362 
363  return volTopPyr + volBottomPyr;
364 }
365 
367 // run-time size of element
369 
370 template <int dim>
371 inline number ElementSize(ReferenceObjectID roid, const MathVector<dim>* vCornerCoords);
372 
373 template <>
374 inline number ElementSize<1>(ReferenceObjectID roid, const MathVector<1>* vCornerCoords)
375 {
376  switch(roid)
377  {
378  case ROID_VERTEX: return 1.0;
379  case ROID_EDGE: return ElementSize<ReferenceEdge, 1>(vCornerCoords);
380  default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 1.");
381  }
382 }
383 
384 template <>
385 inline number ElementSize<2>(ReferenceObjectID roid, const MathVector<2>* vCornerCoords)
386 {
387  switch(roid)
388  {
389  case ROID_VERTEX: return 1.0;
390  case ROID_EDGE: return ElementSize<ReferenceEdge, 2>(vCornerCoords);
391  case ROID_TRIANGLE: return ElementSize<ReferenceTriangle, 2>(vCornerCoords);
393  default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 2.");
394  }
395 }
396 
397 template <>
398 inline number ElementSize<3>(ReferenceObjectID roid, const MathVector<3>* vCornerCoords)
399 {
400  switch(roid)
401  {
402  case ROID_VERTEX: return 1.0;
403  case ROID_EDGE: return ElementSize<ReferenceEdge, 3>(vCornerCoords);
404  case ROID_TRIANGLE: return ElementSize<ReferenceTriangle, 3>(vCornerCoords);
406  case ROID_TETRAHEDRON: return ElementSize<ReferenceTetrahedron, 3>(vCornerCoords);
407  case ROID_PYRAMID: return ElementSize<ReferencePyramid, 3>(vCornerCoords);
408  case ROID_PRISM: return ElementSize<ReferencePrism, 3>(vCornerCoords);
409  case ROID_HEXAHEDRON: return ElementSize<ReferenceHexahedron, 3>(vCornerCoords);
410  case ROID_OCTAHEDRON: return ElementSize<ReferenceOctahedron, 3>(vCornerCoords);
411  default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 3.");
412  }
413 }
414 
417 // Normals on Elements
420 
423 template <typename TRefElem, int TWorldDim>
424 inline void ElementNormal(MathVector<TWorldDim>& normalOut, const MathVector<TWorldDim>* vCornerCoords);
425 
428 
435 template <>
436 inline void ElementNormal<ReferenceVertex, 1>(MathVector<1>& normalOut, const MathVector<1>* vCornerCoords)
437 {
438  normalOut[0] = 1.0;
439 }
440 
443 
453 template <>
454 inline void ElementNormal<ReferenceVertex, 2>(MathVector<2>& normalOut, const MathVector<2>* vCornerCoords)
455 {
456  try
457  {
458  normalOut = vCornerCoords[0];
459  normalOut -= vCornerCoords[1];
460  VecNormalize(normalOut, normalOut);
461  }
462  UG_CATCH_THROW("Element normal can not be computed. Maybe there are not enough vertices to work on.")
463 }
464 
467 
477 template <>
478 inline void ElementNormal<ReferenceVertex, 3>(MathVector<3>& normalOut, const MathVector<3>* vCornerCoords)
479 {
480  try
481  {
482  normalOut = vCornerCoords[0];
483  normalOut -= vCornerCoords[1];
484  VecNormalize(normalOut, normalOut);
485  }
486  UG_CATCH_THROW("Element normal can not be computed. Maybe there are not enough vertices to work on.")
487 }
488 
491 
499 template <>
500 inline void ElementNormal<ReferenceEdge, 2>(MathVector<2>& normalOut, const MathVector<2>* vCornerCoords)
501 {
502  MathVector<2> diff(vCornerCoords[1]);
503  diff -= vCornerCoords[0];
504 
505  normalOut[0] = diff[1];
506  normalOut[1] = -diff[0];
507 }
508 
511 
523 template <>
524 inline void ElementNormal<ReferenceEdge, 3>(MathVector<3>& normalOut, const MathVector<3>* vCornerCoords)
525 {
526  try
527  {
528  // normal on triangle
529  MathVector<3> edge0, edge1;
530  VecSubtract(edge0, vCornerCoords[1], vCornerCoords[0]);
531  VecSubtract(edge1, vCornerCoords[2], vCornerCoords[1]);
532  VecCross(normalOut, edge0, edge1);
533  // normal an edge is edge x normal on triangle
534  VecCross(normalOut, edge0, normalOut);
535  // scale
536  VecNormalize(normalOut, normalOut);
537  VecScale(normalOut, normalOut, VecTwoNorm(edge0));
538  }
539  UG_CATCH_THROW("Element normal can not be computed. Maybe there are not enough vertices to work on.")
540 }
541 
544 
555 template <>
556 inline void ElementNormal<ReferenceTriangle, 3>(MathVector<3>& normalOut, const MathVector<3>* vCornerCoords)
557 {
558  MathVector<3> a, b;
559  VecSubtract(a, vCornerCoords[1], vCornerCoords[0]);
560  VecSubtract(b, vCornerCoords[2], vCornerCoords[0]);
561  VecCross(normalOut, a,b);
562  VecScale(normalOut, normalOut, 0.5);
563 }
564 
567 
578 template <>
579 inline void ElementNormal<ReferenceQuadrilateral, 3>(MathVector<3>& normalOut, const MathVector<3>* vCornerCoords)
580 {
581  MathVector<3> a, b;
582  VecSubtract(a, vCornerCoords[2], vCornerCoords[0]);
583  VecSubtract(b, vCornerCoords[3], vCornerCoords[1]);
584  VecCross(normalOut, a,b);
585  VecScale(normalOut, normalOut, 0.5);
586 }
587 
589 // run-time normal of element
591 
592 template <int dim>
593 inline void ElementNormal(ReferenceObjectID roid, MathVector<dim>& normalOut, const MathVector<dim>* vCornerCoords);
594 
595 template <>
596 inline void ElementNormal<1>(ReferenceObjectID roid, MathVector<1>& normalOut, const MathVector<1>* vCornerCoords)
597 {
598  switch(roid)
599  {
600  case ROID_VERTEX: ElementNormal<ReferenceVertex, 1>(normalOut, vCornerCoords); return;
601  default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 1.");
602  }
603 }
604 
605 template <>
606 inline void ElementNormal<2>(ReferenceObjectID roid, MathVector<2>& normalOut, const MathVector<2>* vCornerCoords)
607 {
608  switch(roid)
609  {
610  case ROID_VERTEX: ElementNormal<ReferenceVertex, 2>(normalOut, vCornerCoords); return;
611  case ROID_EDGE: ElementNormal<ReferenceEdge, 2>(normalOut, vCornerCoords); return;
612  default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 2.");
613  }
614 }
615 
616 template <>
617 inline void ElementNormal<3>(ReferenceObjectID roid, MathVector<3>& normalOut, const MathVector<3>* vCornerCoords)
618 {
619  switch(roid)
620  {
621  case ROID_VERTEX: ElementNormal<ReferenceVertex, 3>(normalOut, vCornerCoords); return;
622  case ROID_EDGE: ElementNormal<ReferenceEdge, 3>(normalOut, vCornerCoords); return;
623  case ROID_TRIANGLE: ElementNormal<ReferenceTriangle, 3>(normalOut, vCornerCoords); return;
624  case ROID_QUADRILATERAL: ElementNormal<ReferenceQuadrilateral, 3>(normalOut, vCornerCoords); return;
625  default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 3.");
626  }
627 }
628 
631 
641 template <typename TRefElem, int TWorldDim>
642 inline void SideNormal(MathVector<TWorldDim>& normalOut, int side, const MathVector<TWorldDim>* vCornerCoords)
643 {
644  static const int dim = (int) TRefElem::dim;
645  static const int maxSideCorners = element_list_traits<typename domain_traits<dim-1>::DimElemList>::maxCorners;
646 
647 // Get own reference element and the side roid:
648  TRefElem & rRefElem = (TRefElem&) ReferenceElementProvider::get(TRefElem::REFERENCE_OBJECT_ID);
649  ReferenceObjectID sideRoid = rRefElem.roid(dim-1,side);
650 
651 // Get the coordinates of the vertices:
652  MathVector<TWorldDim> vSideCorner [(dim == TWorldDim)? maxSideCorners : maxSideCorners + 1];
653  size_t numSideCorners = rRefElem.num(dim-1, side, 0);
654  for (size_t co = 0; co < numSideCorners; ++co)
655  vSideCorner[co] = vCornerCoords[rRefElem.id(dim-1, side, 0, co)];
656  // we need another point if dim != TWorldDim:
657  // take the highest-numbered corner of the next side, since
658  // it is always different from the other points (is it not?)
659  if (dim != TWorldDim)
660  {
661  vSideCorner[numSideCorners] =
662  vCornerCoords[rRefElem.id(dim-1, (side+1)%rRefElem.num(dim-1), 0,
663  rRefElem.num(dim-1, (side+1)%rRefElem.num(dim-1), 0)-1)];
664  }
665 
666 // Get the normal:
667  ElementNormal<TWorldDim>(sideRoid, normalOut, vSideCorner);
668 // Note: We assume that the for the standard ordering, the last line computes
669 // the outer normal.
670 }
671 
673 template <int dim>
674 inline void SideNormal(ReferenceObjectID roid, MathVector<dim>& normalOut, int side, const MathVector<dim>* vCornerCoords);
675 
676 template <>
677 inline void SideNormal<1>(ReferenceObjectID roid, MathVector<1>& normalOut, int side, const MathVector<1>* vCornerCoords)
678 {
679  switch(roid)
680  {
681  case ROID_EDGE: SideNormal<ReferenceEdge,1>(normalOut, side, vCornerCoords); return;
682  default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 1.");
683  }
684 }
685 
686 template <>
687 inline void SideNormal<2>(ReferenceObjectID roid, MathVector<2>& normalOut, int side, const MathVector<2>* vCornerCoords)
688 {
689  switch(roid)
690  {
691  case ROID_EDGE: SideNormal<ReferenceEdge,2>(normalOut, side, vCornerCoords); return;
692  case ROID_TRIANGLE: SideNormal<ReferenceTriangle,2>(normalOut, side, vCornerCoords); return;
693  case ROID_QUADRILATERAL: SideNormal<ReferenceQuadrilateral,2>(normalOut, side, vCornerCoords); return;
694  default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 2.");
695  }
696 }
697 
698 template <>
699 inline void SideNormal<3>(ReferenceObjectID roid, MathVector<3>& normalOut, int side, const MathVector<3>* vCornerCoords)
700 {
701  switch(roid)
702  {
703  case ROID_EDGE: SideNormal<ReferenceEdge,3>(normalOut, side, vCornerCoords); return;
704  case ROID_TRIANGLE: SideNormal<ReferenceTriangle,3>(normalOut, side, vCornerCoords); return;
705  case ROID_QUADRILATERAL: SideNormal<ReferenceQuadrilateral,3>(normalOut, side, vCornerCoords); return;
706  case ROID_TETRAHEDRON: SideNormal<ReferenceTetrahedron,3>(normalOut, side, vCornerCoords); return;
707  case ROID_PYRAMID: SideNormal<ReferencePyramid,3>(normalOut, side, vCornerCoords); return;
708  case ROID_PRISM: SideNormal<ReferencePrism,3>(normalOut, side, vCornerCoords); return;
709  case ROID_HEXAHEDRON: SideNormal<ReferenceHexahedron,3>(normalOut, side, vCornerCoords); return;
710  case ROID_OCTAHEDRON: SideNormal<ReferenceOctahedron,3>(normalOut, side, vCornerCoords); return;
711  default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 3.");
712  }
713 }
714 
717 // ElementSideRayIntersection
720 
721 // wrapper class to distinguish reference dimesion
722 template <typename TRefElem, int TWorldDim, int TRefDim = TRefElem::dim>
724 {
725  static bool apply( size_t& sideOut,
726  MathVector<TWorldDim>& GlobalIntersectionPointOut,
727  MathVector<TRefElem::dim>& LocalIntersectionPoint,
728  const MathVector<TWorldDim>& From, const MathVector<TWorldDim>& Direction,
729  bool bPositiv, const MathVector<TWorldDim>* vCornerCoords)
730  {
731  UG_THROW("Not implemented.");
732  return false;
733  }
734 };
735 
736 // specialization for 2d
737 template <typename TRefElem>
738 struct ElementSideRayIntersectionWrapper<TRefElem, 2, 2>
739 {
740  static bool apply( size_t& sideOut,
741  MathVector<2>& GlobalIntersectionPointOut,
742  MathVector<TRefElem::dim>& LocalIntersectionPoint,
743  const MathVector<2>& From, const MathVector<2>& Direction,
744  bool bPositiv, const MathVector<2>* vCornerCoords)
745  {
746  static const TRefElem& rRefElem = Provider<TRefElem>::get();
747 
748  // reference dimension
749  const int dim = TRefElem::dim;
750 
751  // parameters
752  number bc = 0., t = 0.;
753  size_t p0 = 0, p1 = 0;
754 
755  // find side
756  for(sideOut = 0; sideOut < rRefElem.num(dim-1); ++sideOut)
757  {
758  // get corners
759  p0 = rRefElem.id(dim-1, sideOut, 0, 0);
760  p1 = rRefElem.id(dim-1, sideOut, 0, 1);
761 
762  // if match: break
763  if(RayLineIntersection2d( GlobalIntersectionPointOut, bc, t,
764  vCornerCoords[p0], vCornerCoords[p1],
765  From, Direction))
766  {
767  if(bPositiv && t >= 0.0) break;
768  else if(!bPositiv && t <= 0.0) break;
769  }
770  }
771  // if not found
772  if(sideOut >= rRefElem.num(dim-1))
773  UG_THROW("ElementSideRayIntersection: no cut side found.");
774 
775  // Compute local intersection
776  VecScaleAdd(LocalIntersectionPoint, bc, rRefElem.corner(p1), 1.-bc, rRefElem.corner(p0));
777 
778  // true if found
779  return true;
780  }
781 };
782 
783 // specialization for 3d
784 template <typename TRefElem>
785 struct ElementSideRayIntersectionWrapper<TRefElem, 3, 3>
786 {
787  static bool apply( size_t& sideOut,
788  MathVector<3>& GlobalIntersectionPointOut,
789  MathVector<TRefElem::dim>& LocalIntersectionPoint,
790  const MathVector<3>& From, const MathVector<3>& Direction,
791  bool bPositiv, const MathVector<3>* vCornerCoords)
792  {
793  static const TRefElem& rRefElem = Provider<TRefElem>::get();
794 
795  // reference dimension
796  const int dim = TRefElem::dim;
797 
798  // parameters
799  number bc0 = 0., bc1 = 0., t = 0.;
800  size_t p0 = 0, p1 = 0, p2 = 0;
801 
802  // find side
803  for(sideOut = 0; sideOut < rRefElem.num(dim-1); ++sideOut)
804  {
805  // get corners
806  p0 = rRefElem.id(dim-1, sideOut, 0, 0);
807  p1 = rRefElem.id(dim-1, sideOut, 0, 1);
808  p2 = rRefElem.id(dim-1, sideOut, 0, 2);
809 
810  // if match: break
811  if(RayTriangleIntersection( GlobalIntersectionPointOut, bc0, bc1, t,
812  vCornerCoords[p0], vCornerCoords[p1], vCornerCoords[p2],
813  From, Direction))
814  {
815  if(bPositiv && t >= 0.0) break;
816  else if(!bPositiv && t <= 0.0) break;
817  }
818 
819  // second triangle (only if 4 corners)
820  if(rRefElem.num(dim-1, sideOut, 0) == 3) continue;
821 
822  // get corner number 4
823  p1 = rRefElem.id(dim-1, sideOut, 0, 3);
824 
825  // if match: break
826  if(RayTriangleIntersection( GlobalIntersectionPointOut, bc0, bc1, t,
827  vCornerCoords[p0], vCornerCoords[p1], vCornerCoords[p2],
828  From, Direction))
829  {
830  if(bPositiv && t >= 0.0) break;
831  else if(!bPositiv && t <= 0.0) break;
832  }
833  }
834 
835  // if not found
836  if(sideOut >= rRefElem.num(dim-1))
837  UG_THROW("ElementSideRayIntersection: no cut side found.");
838 
839  // Compute local intersection
840  VecScaleAdd(LocalIntersectionPoint,
841  (1.-bc0-bc1), rRefElem.corner(p0),
842  bc0, rRefElem.corner(p1),
843  bc1, rRefElem.corner(p2));
844 
845  // true if found
846  return true;
847  }
848 };
849 
850 
853 
869 template <typename TRefElem, int TWorldDim>
870 bool ElementSideRayIntersection( size_t& sideOut,
871  MathVector<TWorldDim>& GlobalIntersectionPointOut,
872  MathVector<TRefElem::dim>& LocalIntersectionPoint,
873  const MathVector<TWorldDim>& From, const MathVector<TWorldDim>& Direction,
874  bool bPositiv, const MathVector<TWorldDim>* vCornerCoords)
875 {
876  UG_ASSERT(VecTwoNorm(Direction) > 0, "Direction must be non-zero vector.");
878  apply(sideOut, GlobalIntersectionPointOut, LocalIntersectionPoint,
879  From, Direction, bPositiv, vCornerCoords);
880 }
881 
882 
885 // ElementSideRayIntersection
888 
889 // wrapper class to distinguish reference dimesion
890 template <int TDim, int TWorldDim>
892 {
893  static bool apply( size_t& sideOut, number& bc,
894  MathVector<TWorldDim>& GlobalIntersectionPointOut,
895  MathVector<TDim>& LocalIntersectionPoint,
896  const MathVector<TWorldDim>& From, const MathVector<TWorldDim>& Direction,
897  bool bPositiv, const MathVector<TWorldDim>* vCornerCoords)
898  {
899  UG_THROW("Not implemented.");
900  return false;
901  }
902 };
903 
904 // specialization for 2d
905 template <>
907 {
908  static bool apply( size_t& sideOut, number& bc,
909  MathVector<2>& GlobalIntersectionPointOut,
910  MathVector<2>& LocalIntersectionPoint,
911  const MathVector<2>& From, const MathVector<2>& Direction,
912  bool bPositiv, const MathVector<2>* vCornerCoords)
913  {
915 
916  // reference dimension
917  static const int dim = 2;
918 
919  // parameters
920  bc = 0.;
921  number t = 0.;
922  size_t p0 = 0, p1 = 0;
923 
924  // find side
925  for(sideOut = 0; sideOut < rRefElem.num(0); ++sideOut)
926  {
927  // get corners
928  p0 = rRefElem.id(dim-1, sideOut, 0, 0);
929  p1 = rRefElem.id(dim-1, sideOut, 0, 1);
930 
931  // if match: break
932  if(RayLineIntersection2d( GlobalIntersectionPointOut, bc, t,
933  vCornerCoords[p0], vCornerCoords[p1],
934  From, Direction))
935  {
936  // skip if one root-point scvf
937  if(fabs(t) <= std::numeric_limits<number>::epsilon() * 10)
938  continue;
939 
940  // upwind / downwind switch
941  if(bPositiv && t >= 0.0) break;
942  else if(!bPositiv && t <= 0.0) break;
943  }
944  }
945 
946  // if not found
947  if(sideOut >= rRefElem.num(0))
948  UG_THROW("Side not found.");
949 
950  // Compute local intersection
951  VecScaleAdd(LocalIntersectionPoint, bc, rRefElem.corner(p1), 1.-bc, rRefElem.corner(p0));
952 
953  // parameter of intersection should loop always from center to edgeMidpoint
954  // thus, for side 2 this is correct, but for side 1 we have to invert direction
955  if(sideOut == 1) bc = 1. - bc;
956 
957  // true if found on scvf
958  if(sideOut == 1 || sideOut == 2) return true;
959  // false if found on element corner
960  else return false;
961  }
962 };
963 
965 // SCVFofSCVRayIntersection
986 template <int TDim, int TWorldDim>
987 bool SCVFofSCVRayIntersection( size_t& sideOut, number& bc,
988  MathVector<TWorldDim>& GlobalIntersectionPointOut,
989  MathVector<TDim>& LocalIntersectionPoint,
990  const MathVector<TWorldDim>& Root, const MathVector<TWorldDim>& Direction,
991  bool bPositiv, const MathVector<TWorldDim>* vCornerCoords)
992 {
993  UG_ASSERT(VecTwoNorm(Direction) > 0, "Direction must be non-zero vector.");
995  apply(sideOut, bc, GlobalIntersectionPointOut, LocalIntersectionPoint,
996  Root, Direction, bPositiv, vCornerCoords);
997 }
998 
999 
1000 
1004 
1005 
1006 template <typename TVector>
1007 inline void ComputeElementExtensionsSqForEdges(const TVector* vCornerCoords, TVector &ext)
1008 {
1009  VecElemProd(ext, vCornerCoords[0], vCornerCoords[1]);
1010 }
1011 
1012 
1013 template <int TWorldDim, int ncorners>
1015 {
1016  // compute center
1017  MathVector<TWorldDim> mid = 0.0;
1018  for (int i=ncorners-1; i>=0; --i){
1019  VecAppend(mid, vCornerCoords[i]);
1020  }
1021  VecScale(mid, mid, 1.0/ncorners);
1022 
1023  // compute
1024  ext = 0.0;
1026  for (int i=ncorners-1; i>=0; --i){
1027  VecSubtract(aux, mid, vCornerCoords[i]);
1028  VecElemProd(aux, aux, aux);
1029  VecAppend(ext, aux);
1030  }
1031  VecScale(ext, ext, 1.0/ncorners);
1032 }
1033 
1035 // extensions of an element
1037 
1038 
1039 template <int dim>
1040 inline void ElementExtensionsSq(ReferenceObjectID roid, MathVector<dim>& ext, const MathVector<dim>* vCornerCoords);
1041 
1042 template <>
1043 inline void ElementExtensionsSq<1>(ReferenceObjectID roid, MathVector<1>& ext, const MathVector<1>* vCornerCoords)
1044 {
1045  switch(roid)
1046  {
1047  case ROID_VERTEX: ext = 0; return;
1048  case ROID_EDGE: ComputeElementExtensionsSqForEdges(vCornerCoords,ext); return;
1049  default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 1.");
1050  }
1051 }
1052 
1053 template <>
1054 inline void ElementExtensionsSq<2>(ReferenceObjectID roid, MathVector<2>& ext, const MathVector<2>* vCornerCoords)
1055 {
1056  switch(roid)
1057  {
1058  case ROID_VERTEX: ext = 0; return;
1059  case ROID_EDGE: ComputeElementExtensionsSqForEdges(vCornerCoords,ext); return;
1060  case ROID_TRIANGLE: ComputeElementExtensionsSq<2,3>(vCornerCoords,ext); return;
1061  case ROID_QUADRILATERAL: ComputeElementExtensionsSq<2,4>(vCornerCoords,ext); return;
1062  default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 2.");
1063  }
1064 }
1065 
1066 template <>
1067 inline void ElementExtensionsSq<3>(ReferenceObjectID roid, MathVector<3>& ext, const MathVector<3>* vCornerCoords)
1068 {
1069  switch(roid)
1070  {
1071  case ROID_VERTEX: ext = 0; return;
1072  case ROID_EDGE: ComputeElementExtensionsSqForEdges(vCornerCoords,ext); return;
1073  case ROID_TRIANGLE: ComputeElementExtensionsSq<3,3>(vCornerCoords,ext); return;
1074  case ROID_QUADRILATERAL: ComputeElementExtensionsSq<3,4>(vCornerCoords,ext); return;
1075  case ROID_TETRAHEDRON: ComputeElementExtensionsSq<3,4>(vCornerCoords,ext); return;
1076  case ROID_PYRAMID: ComputeElementExtensionsSq<3,5>(vCornerCoords,ext); return;
1077  case ROID_PRISM: ComputeElementExtensionsSq<3,6>(vCornerCoords,ext); return;
1078  case ROID_HEXAHEDRON: ComputeElementExtensionsSq<3,8>(vCornerCoords,ext); return;
1079  case ROID_OCTAHEDRON: ComputeElementExtensionsSq<3,6>(vCornerCoords,ext); return;
1080  default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 3.");
1081  }
1082 }
1083 
1084 
1085 } // end namespace ug
1086 
1087 #endif /* __H__UG__LIB_DISC__COMMON__GEOMETRY_UTIL__ */
const MathVector< dim > & corner(size_t i) const
coordinates of reference corner (i = 0 ... num(0))
Definition: reference_element.h:192
a mathematical Vector with N entries.
Definition: math_vector.h:97
static TClass & get()
returns a singleton based on the identifier
Definition: provider.h:54
size_t num(int dim) const
returns the number of geometric objects of dim
Definition: reference_element.h:95
ReferenceObjectID roid() const
returns the reference object id
Definition: reference_element.h:76
int id(int dim_i, size_t i, int dim_j, size_t j) const
id of object j in dimension dim_j of obj i in dimension dim_i
Definition: reference_element.h:127
static const DimReferenceElement< dim > & get(ReferenceObjectID roid)
returns a dimension dependent Reference Element
Definition: reference_element.h:280
Definition: reference_element.h:445
Class for computing integral properties of geometric objects types in lists.
Definition: element_list_traits.h:60
static const int dim
#define UG_ASSERT(expr, msg)
Definition: assert.h:70
#define UG_CATCH_THROW(msg)
Definition: error.h:64
#define UG_THROW(msg)
Definition: error.h:57
double number
Definition: types.h:124
bool RayLineIntersection2d(vector_t &vOut, number &bcOut, number &tOut, const vector_t &p0, const vector_t &p1, const vector_t &vFrom, const vector_t &vDir, number sml=0)
calculates the intersection of a ray with a Line in 2d
Definition: math_util_impl.hpp:428
bool RayTriangleIntersection(vector_t &vOut, number &bc1Out, number &bc2Out, number &tOut, const vector_t &p0, const vector_t &p1, const vector_t &p2, const vector_t &vFrom, const vector_t &vDir, const number small=SMALL)
calculates the intersection of a ray with a triangle
Definition: math_util_impl.hpp:506
void VecScaleAdd(vector_t &vOut, typename vector_t::value_type s1, const vector_t &v1, typename vector_t::value_type s2, const vector_t &v2)
Scales two Vectors, adds them and returns the sum in a third vector.
Definition: math_vector_functions_common_impl.hpp:265
void VecNormalize(vector_t &vOut, const vector_t &v)
scales a vector_t to unit length
Definition: math_vector_functions_common_impl.hpp:501
void VecSubtract(vector_t &vOut, const vector_t &v1, const vector_t &v2)
subtracts v2 from v1 and stores the result in a vOut
Definition: math_vector_functions_common_impl.hpp:226
void VecAppend(vector_t &vOut, const vector_t &v1)
adds a MathVector<N> to a second one
Definition: math_vector_functions_common_impl.hpp:72
vector_t::value_type VecDistance(const vector_t &v1, const vector_t &v2)
returns the distance of two vector_ts.
Definition: math_vector_functions_common_impl.hpp:375
void VecScale(vector_t &vOut, const vector_t &v, typename vector_t::value_type s)
scales a MathVector<N>
Definition: math_vector_functions_common_impl.hpp:252
vector_t::value_type VecTwoNorm(const vector_t &v)
Definition: math_vector_functions_common_impl.hpp:577
void VecCross(vector_t &vOut, const vector_t &v1, const vector_t &v2)
calculates the cross product of two Vectors of dimension 3. It makes no sense to use VecCross for vec...
Definition: math_vector_functions_common_impl.hpp:437
vector_t::value_type VecDot(const vector_t &v1, const vector_t &v2)
returns the dot-product of two vector_ts
Definition: math_vector_functions_common_impl.hpp:385
the ug namespace
void SideNormal< 1 >(ReferenceObjectID roid, MathVector< 1 > &normalOut, int side, const MathVector< 1 > *vCornerCoords)
Definition: geometry_util.h:677
number ElementSize< ReferenceQuadrilateral, 3 >(const MathVector< 3 > *vCornerCoords)
Volume of a Quadrilateral in 3d.
Definition: geometry_util.h:176
void SideNormal(MathVector< TWorldDim > &normalOut, int side, const MathVector< TWorldDim > *vCornerCoords)
Normal to a side of an Element in a given Dimension.
Definition: geometry_util.h:642
ReferenceObjectID
these ids are used to identify the shape of a geometric object.
Definition: grid_base_objects.h:74
@ ROID_TETRAHEDRON
Definition: grid_base_objects.h:80
@ ROID_QUADRILATERAL
Definition: grid_base_objects.h:79
@ ROID_PYRAMID
Definition: grid_base_objects.h:83
@ ROID_PRISM
Definition: grid_base_objects.h:82
@ ROID_EDGE
Definition: grid_base_objects.h:77
@ ROID_OCTAHEDRON
Definition: grid_base_objects.h:84
@ ROID_HEXAHEDRON
Definition: grid_base_objects.h:81
@ ROID_TRIANGLE
Definition: grid_base_objects.h:78
@ ROID_VERTEX
Definition: grid_base_objects.h:76
void ElementNormal< 1 >(ReferenceObjectID roid, MathVector< 1 > &normalOut, const MathVector< 1 > *vCornerCoords)
Definition: geometry_util.h:596
number ElementSize< 1 >(ReferenceObjectID roid, const MathVector< 1 > *vCornerCoords)
Definition: geometry_util.h:374
number ElementSize< 3 >(ReferenceObjectID roid, const MathVector< 3 > *vCornerCoords)
Definition: geometry_util.h:398
void ElementNormal< ReferenceQuadrilateral, 3 >(MathVector< 3 > &normalOut, const MathVector< 3 > *vCornerCoords)
Normal to a Quadrilateral in 3d.
Definition: geometry_util.h:579
number ElementSize< ReferencePyramid, 3 >(const MathVector< 3 > *vCornerCoords)
Volume of a Pyramid in 3d.
Definition: geometry_util.h:235
number ElementSize< ReferenceEdge, 1 >(const MathVector< 1 > *vCornerCoords)
Volume of a Line in 1d.
Definition: geometry_util.h:67
number ElementSize< ReferenceTetrahedron, 3 >(const MathVector< 3 > *vCornerCoords)
Volume of a Tetrahedron in 3d.
Definition: geometry_util.h:209
void ElementNormal(MathVector< TWorldDim > &normalOut, const MathVector< TWorldDim > *vCornerCoords)
Normal to an Element in a given Dimension.
void ElementNormal< ReferenceTriangle, 3 >(MathVector< 3 > &normalOut, const MathVector< 3 > *vCornerCoords)
Normal to a Triangle in 3d.
Definition: geometry_util.h:556
void SideNormal< 3 >(ReferenceObjectID roid, MathVector< 3 > &normalOut, int side, const MathVector< 3 > *vCornerCoords)
Definition: geometry_util.h:699
number ElementSize< ReferenceEdge, 2 >(const MathVector< 2 > *vCornerCoords)
Volume of a Line in 2d.
Definition: geometry_util.h:81
number ElementSize< 2 >(ReferenceObjectID roid, const MathVector< 2 > *vCornerCoords)
Definition: geometry_util.h:385
void ElementNormal< 3 >(ReferenceObjectID roid, MathVector< 3 > &normalOut, const MathVector< 3 > *vCornerCoords)
Definition: geometry_util.h:617
number ElementSize< ReferenceOctahedron, 3 >(const MathVector< 3 > *vCornerCoords)
Volume of an Octahedron in 3d.
Definition: geometry_util.h:345
void ComputeElementExtensionsSq(const MathVector< TWorldDim > *vCornerCoords, MathVector< TWorldDim > &ext)
Definition: geometry_util.h:1014
number ElementSize< ReferenceTriangle, 2 >(const MathVector< 2 > *vCornerCoords)
Volume of a Triangle in 2d.
Definition: geometry_util.h:118
bool SCVFofSCVRayIntersection(size_t &sideOut, number &bc, MathVector< TWorldDim > &GlobalIntersectionPointOut, MathVector< TDim > &LocalIntersectionPoint, const MathVector< TWorldDim > &Root, const MathVector< TWorldDim > &Direction, bool bPositiv, const MathVector< TWorldDim > *vCornerCoords)
Definition: geometry_util.h:987
void ElementExtensionsSq< 1 >(ReferenceObjectID roid, MathVector< 1 > &ext, const MathVector< 1 > *vCornerCoords)
Definition: geometry_util.h:1043
void ElementNormal< ReferenceEdge, 2 >(MathVector< 2 > &normalOut, const MathVector< 2 > *vCornerCoords)
Normal to a Line in 2d.
Definition: geometry_util.h:500
void ElementExtensionsSq(ReferenceObjectID roid, MathVector< dim > &ext, const MathVector< dim > *vCornerCoords)
number ElementSize< ReferenceHexahedron, 3 >(const MathVector< 3 > *vCornerCoords)
Volume of a Hexahedron in 3d.
Definition: geometry_util.h:295
number ElementSize< ReferenceTriangle, 3 >(const MathVector< 3 > *vCornerCoords)
Volume of a Triangle in 3d.
Definition: geometry_util.h:135
void ElementNormal< ReferenceEdge, 3 >(MathVector< 3 > &normalOut, const MathVector< 3 > *vCornerCoords)
Normal to a Line in 3d.
Definition: geometry_util.h:524
void ElementNormal< ReferenceVertex, 2 >(MathVector< 2 > &normalOut, const MathVector< 2 > *vCornerCoords)
Normal to a Point in 2d.
Definition: geometry_util.h:454
number ElementSize< ReferencePrism, 3 >(const MathVector< 3 > *vCornerCoords)
Volume of a Prism in 3d.
Definition: geometry_util.h:260
void ElementNormal< ReferenceVertex, 1 >(MathVector< 1 > &normalOut, const MathVector< 1 > *vCornerCoords)
Normal to a Point in 1d.
Definition: geometry_util.h:436
number ElementSize< ReferenceQuadrilateral, 2 >(const MathVector< 2 > *vCornerCoords)
Volume of a Quadrilateral in 2d.
Definition: geometry_util.h:157
number ElementSize< ReferenceEdge, 3 >(const MathVector< 3 > *vCornerCoords)
Volume of a Line in 3d.
Definition: geometry_util.h:95
void ElementNormal< ReferenceVertex, 3 >(MathVector< 3 > &normalOut, const MathVector< 3 > *vCornerCoords)
Normal to a Point in 3d.
Definition: geometry_util.h:478
void SideNormal< 2 >(ReferenceObjectID roid, MathVector< 2 > &normalOut, int side, const MathVector< 2 > *vCornerCoords)
Definition: geometry_util.h:687
void ElementExtensionsSq< 3 >(ReferenceObjectID roid, MathVector< 3 > &ext, const MathVector< 3 > *vCornerCoords)
Definition: geometry_util.h:1067
void ComputeElementExtensionsSqForEdges(const TVector *vCornerCoords, TVector &ext)
Extension of an element (in a given dimension)
Definition: geometry_util.h:1007
void VecElemProd(vector_t &vOut, const vector_t &v1, const vector_t &v2)
component-wise product: vOut_i = v1_i*v2_i
Definition: math_vector_functions_common_impl.hpp:651
void ElementNormal< 2 >(ReferenceObjectID roid, MathVector< 2 > &normalOut, const MathVector< 2 > *vCornerCoords)
Definition: geometry_util.h:606
bool ElementSideRayIntersection(size_t &sideOut, MathVector< TWorldDim > &GlobalIntersectionPointOut, MathVector< TRefElem::dim > &LocalIntersectionPoint, const MathVector< TWorldDim > &From, const MathVector< TWorldDim > &Direction, bool bPositiv, const MathVector< TWorldDim > *vCornerCoords)
ElementSideRayIntersection.
Definition: geometry_util.h:870
void ElementExtensionsSq< 2 >(ReferenceObjectID roid, MathVector< 2 > &ext, const MathVector< 2 > *vCornerCoords)
Definition: geometry_util.h:1054
number ElementSize(const MathVector< TWorldDim > *vCornerCoords)
Volume of an Element in a given Dimension.
static bool apply(size_t &sideOut, MathVector< 2 > &GlobalIntersectionPointOut, MathVector< TRefElem::dim > &LocalIntersectionPoint, const MathVector< 2 > &From, const MathVector< 2 > &Direction, bool bPositiv, const MathVector< 2 > *vCornerCoords)
Definition: geometry_util.h:740
static bool apply(size_t &sideOut, MathVector< 3 > &GlobalIntersectionPointOut, MathVector< TRefElem::dim > &LocalIntersectionPoint, const MathVector< 3 > &From, const MathVector< 3 > &Direction, bool bPositiv, const MathVector< 3 > *vCornerCoords)
Definition: geometry_util.h:787
Definition: geometry_util.h:724
static bool apply(size_t &sideOut, MathVector< TWorldDim > &GlobalIntersectionPointOut, MathVector< TRefElem::dim > &LocalIntersectionPoint, const MathVector< TWorldDim > &From, const MathVector< TWorldDim > &Direction, bool bPositiv, const MathVector< TWorldDim > *vCornerCoords)
Definition: geometry_util.h:725
static bool apply(size_t &sideOut, number &bc, MathVector< 2 > &GlobalIntersectionPointOut, MathVector< 2 > &LocalIntersectionPoint, const MathVector< 2 > &From, const MathVector< 2 > &Direction, bool bPositiv, const MathVector< 2 > *vCornerCoords)
Definition: geometry_util.h:908
Definition: geometry_util.h:892
static bool apply(size_t &sideOut, number &bc, MathVector< TWorldDim > &GlobalIntersectionPointOut, MathVector< TDim > &LocalIntersectionPoint, const MathVector< TWorldDim > &From, const MathVector< TWorldDim > &Direction, bool bPositiv, const MathVector< TWorldDim > *vCornerCoords)
Definition: geometry_util.h:893
Definition: domain_traits.h:53