19#ifndef GEOMETRIC_OBJECTS_HH_
20#define GEOMETRIC_OBJECTS_HH_
27#include <boost/array.hpp>
28#include <boost/utility/enable_if.hpp>
29#include <dune/common/fvector.hh>
30#include <dune/grid/common/genericreferenceelements.hh>
32#include "tools/linalg/scalarproducts.hh"
40 template <
class Scalar,
int dim>
50 template <
class Scalar,
int dim>
64 template <
class Scalar,
int dim>
88 template <
class Scalar,
int dim>
97 init(e[0], e[1], e[2], e[3]);
102 init(p0, p1, p2, p3);
118 struct BoundingBoxContainsImpl{
119 template <
class Array,
class Coordinate>
120 static bool apply(Array
const& array, Coordinate
const& x)
122 return (BoundingBoxContainsImpl<dim-1>::apply(array, x) && array[dim-1].first<=x[dim-1] && array[dim-1].second>=x[dim-1]);
127 struct BoundingBoxContainsImpl<1>{
128 template <
class Array,
class Coordinate>
129 static bool apply(Array
const& array, Coordinate
const& x)
131 return (array[0].first <= x[0] && array[0].second >= x[0]);
135 template <
class Scalar,
int dim,
int id>
136 struct BoundingBoxGetCornersImpl
138 template <
class Array>
139 static void apply(std::vector<Point<Scalar,dim> > &corners, Array
const& array)
141 size_t offset = (size_t)(corners.size()/pow(2,
id+1));
144 for(
size_t i=0; i<corners.size(); ++i)
146 if( (i-changes*offset)==offset )
152 if(first) corners[i][id] = array[id].first;
153 else corners[i][id] = array[id].second;
155 BoundingBoxGetCornersImpl<Scalar,dim,id+1>::apply(corners, array);
159 template <
class Scalar,
int dim>
160 struct BoundingBoxGetCornersImpl<Scalar,dim,dim>
162 template <
class Array>
163 static void apply(std::vector<Point<Scalar,dim> > &corners, Array
const& array){}
167 template <
class Scalar,
int dim,
int id>
168 struct BoundingBoxGetEdgesImpl
170 template <
class Array>
171 static void apply(std::vector<Line<Scalar,dim> > &edges, Array
const& array,
int indexOffset)
173 int localNumberOfEdges = pow(2,dim-1);
174 for(
int edge=0; edge<localNumberOfEdges; ++edge)
176 Point<Scalar,dim> start, end;
177 start[id] = array[id].first;
178 end[id] = array[id].second;
180 for(
int i=0; i<dim; ++i)
184 insert(start, end, array[i].first, i);
189 if(i==1) insert(start, end, array[i].second, i);
190 if(i==2) insert(start, end, array[i].first, i);
195 if(i==1) insert(start, end, array[i].first, i);
196 if(i==2) insert(start, end, array[i].second, i);
201 if(i==1) insert(start, end, array[i].second, i);
202 if(i==2) insert(start, end, array[i].second, i);
206 edges[edge] = Line<Scalar,dim>(start,end);
208 BoundingBoxGetEdgesImpl<Scalar,dim,id+1>::apply(edges, array, localNumberOfEdges);
212 static void insert(Point<Scalar,dim>& start, Point<Scalar,dim>& end, Scalar value,
int index)
214 start[index] = value, end[index] = value;
218 template <
class Scalar,
int dim>
219 struct BoundingBoxGetEdgesImpl<Scalar,dim,dim>
221 template <
class Array>
222 static void apply(std::vector<Line<Scalar,dim> >&, Array
const&,
int){};
225 template <
int v1,
int v2>
227 static bool const value=v1<v2;
230 template <
int v1,
int v2>
232 static int const value = v1-v2;
237 static int const value = val-1;
240 template <
class Scalar,
int dim,
int dimMinusCodim>
241 struct GetCodimTypeImpl;
243 template <
class Scalar,
int dim>
244 struct GetCodimTypeImpl<Scalar,dim,0>{
245 typedef typename boost::enable_if<MyLess<0,dim>, Point<Scalar,dim> >::type type;
248 template <
class Scalar,
int dim>
249 struct GetCodimTypeImpl<Scalar,dim,1>{
250 typedef typename boost::enable_if<MyLess<1,dim>, Line<Scalar,dim> >::type type;
253 template <
class Scalar,
int dim>
254 struct GetCodimTypeImpl<Scalar,dim,2>{
255 typedef typename boost::enable_if<MyLess<2,dim>, Rectangle<Scalar,dim> >::type type;
258 template <
class Scalar,
int dim,
int codim>
260 typedef typename GetCodimTypeImpl<Scalar,dim,dim-codim>::type type;
263 template <
class Scalar,
int dim,
int dimMinusCodim>
264 struct CodimBaseImpl{};
266 template <
class Scalar,
int dim>
267 struct CodimBaseImpl<Scalar,dim,2>
269 template <
class Array>
270 std::vector<
typename GetCodimType<Scalar,dim,dim-2>::type > getFaces(Array
const& array)
const
272 std::vector<Rectangle<Scalar,3> > faces(6);
273 std::vector<Point<Scalar,3> > corners=CodimBaseImpl<Scalar,dim,0>::getCorners(array);
274 faces[0] = Rectangle<Scalar,3>(corners[0], corners[2], corners[3], corners[1]);
275 faces[1] = Rectangle<Scalar,3>(corners[4], corners[6], corners[7], corners[5]);
276 faces[2] = Rectangle<Scalar,3>(corners[0], corners[4], corners[6], corners[2]);
277 faces[3] = Rectangle<Scalar,3>(corners[1], corners[5], corners[7], corners[3]);
278 faces[4] = Rectangle<Scalar,3>(corners[0], corners[4], corners[5], corners[1]);
279 faces[5] = Rectangle<Scalar,3>(corners[2], corners[6], corners[7], corners[3]);
284 template <
class Scalar,
int dim>
285 struct CodimBaseImpl<Scalar,dim,1>
287 template <
class Array>
288 std::vector<Line<Scalar,dim> > getEdges(Array
const& array)
const
290 if(dim==0)
return std::vector<Line<Scalar,dim> >();
293 for(
int i=1; i<dim; ++i) numEdges = 2*numEdges + pow(2,i);
295 std::vector<Line<Scalar,dim> > edges(numEdges);
296 BoundingBoxGetEdgesImpl<Scalar,dim, 0>::apply(edges, array, 0);
301 template <
class Scalar,
int dim>
302 struct CodimBaseImpl<Scalar, dim, 0>
304 template <
class Array>
305 static std::vector<Point<Scalar,dim> > getCorners(Array
const& array)
307 std::vector<Point<Scalar,dim> > corners(pow(2,dim));
308 BoundingBoxGetCornersImpl<Scalar,dim,0>::apply(corners, array);
313 template <
class Scalar,
int dim,
int codim>
314 struct CodimBase :
public CodimBaseImpl<Scalar,dim,dim-codim>,
public CodimBase<Scalar,dim,codim-1>{};
316 template <
class Scalar,
int dim>
317 struct CodimBase<Scalar,dim,0>{};
321 template <
class Scalar,
int dimension>
322 struct BoundingBox :
public CodimBase<Scalar,dimension,dimension>{
323 static int const dim=dimension;
326 for(
int i=0; i<
dim; ++i)
coord[i].first =
coord[i].second = 0;
336 for(
int i=0; i<
dim; ++i)
coord[i].first =
coord[i].second = x[i];
339 template <
class Coordinate>
342 for(
int i=0; i<
dim; ++i)
344 if(
coord[i].first > x[i])
coord[i].first = x[i];
345 if(
coord[i].second < x[i])
coord[i].second = x[i];
349 std::ostream&
print(std::ostream &stream)
const
351 stream <<
"BoundingBox: ";
352 for(
int i=0; i<
dim-1; ++i)
353 stream <<
coord[i].first <<
" - " <<
coord[i].second <<
" | ";
358 template <
class Coordinate>
361 return BoundingBoxContainsImpl<dim>::apply(
coord, x);
372 template <
class Scalar,
int dim>
383 template <
class Coordinate>
422 std::vector<Line<Scalar,dim> >
edges;
423 std::vector<Rectangle<Scalar,dim> >
faces;
430 template <
class Scalar,
int dim>
441 template <
class Scalar,
int dim>
455 template <
class Scalar,
int dim>
460 template <
class Position>
466 template <
class Position>
469 return (x-
center).two_norm();
477 template <
class Scalar,
int dim,
class Metric>
480 template <
class Scalar,
int dim,
class Metric>
483 template <
class Scalar,
int dim,
class Metric>
486 template <
class Scalar,
int dim,
class Metric>
489 template <
class Scalar,
int dim,
class Metric>
492 template <
class Scalar,
int dim,
class Metric>
495 template <
class Scalar,
int dim,
class Metric>
498 template <
class Scalar,
int dim,
class Metric>
501 template <
class Scalar,
int dim,
class Metric>
504 template <
class Scalar,
int dim,
class Metric>
507 namespace ImplementationDetail{
509 template <
class FirstObject,
class SecondObject,
class Scalar,
int dim,
class ScalarProduct>
512 template <
class Scalar,
int dim,
class ScalarProduct>
518 return line.
start + scalarProduct(point-line.
start, direction)*direction;
522 template <
class Scalar,
int dim,
class ScalarProduct>
530 return rectangle.
corners[0] + scalarProduct(vec, dir1)*dir1 + scalarProduct(vec, dir2)*dir2;
534 template <
class Metric,
class Scalar,
int dim,
class FirstObject,
class SecondObject>
537 template <
class Metric,
class Scalar,
int dim>
542 return metric(firstPoint-secondPoint);
546 template <
class Metric,
class Scalar,
int dim>
553 Scalar length = distance<Metric>(line.
start, line.
end);
554 if(0 < a && a < length)
return distance<Metric>(point,projectedPoint,metric);
555 if(a <= 0)
return distance<Metric>(point, line.
start,metric);
556 return distance<Metric>(point, line.
end,metric);
562 template <
class Metric,
class Scalar,
int dim>
569 Point<Scalar,dim> projectedPoint =
ProjectionImpl<Point<Scalar,dim>,
Rectangle<Scalar,dim>, Scalar,dim,
typename Metric::ScalarProduct>::apply(point, rectangle, a, b);
570 Scalar l0 = distance<Metric>(rectangle.
corners[0], rectangle.
corners[1], metric),
571 l1 = distance<Metric>(rectangle.
corners[0], rectangle.
corners[3], metric);
572 if(0 < a && a < l0 && 0 < b && b < l1)
return distance<Metric>(point, projectedPoint, metric);
576 if(b <= 0)
return distance<Metric>(point, rectangle.
corners[0], metric);
577 if(b >= l1)
return distance<Metric>(point, rectangle.
corners[3], metric);
578 return distance<Metric>(point,
Edge(rectangle.
corners[0], rectangle.
corners[3]), metric);
582 if(b <= 0)
return distance<Metric>(point, rectangle.
corners[1], metric);
583 if(b >= l1)
return distance<Metric>(point, rectangle.
corners[2], metric);
584 return distance<Metric>(point,
Edge(rectangle.
corners[1], rectangle.
corners[2]), metric);
586 if(b <= 0)
return distance<Metric>(point,
Edge(rectangle.
corners[0], rectangle.
corners[1]), metric);
587 return distance<Metric>(point,
Edge(rectangle.
corners[2], rectangle.
corners[3]), metric);
591 template <
class Metric,
class Scalar,
int dim>
596 Scalar distanceToCenter = distance<Metric>(point, ball.
center, metric);
597 return (distanceToCenter < ball.
radius) ? 0 : distanceToCenter-ball.
radius;
601 template <
class Metric,
class Scalar,
int dim>
607 int distanceToCenter = distance<Metric>(ball.
center, line, metric);
608 return (distanceToCenter < ball.
radius) ? 0 : distanceToCenter - ball.
radius;
612 template <
class Metric,
class Scalar,
int dim>
617 Scalar distanceToCenter = distance<Metric>(ball.
center, rectangle, metric);
618 return (distanceToCenter < ball.
radius) ? 0 : distanceToCenter - ball.
radius;
622 template <
class Metric,
class Scalar,
int dim>
630 std::vector<Point<Scalar,dim> >
const& corners =
boundingBox.getCorners();
631 for(
size_t cornerId=0; cornerId<corners.size(); ++cornerId)
633 Scalar tmp = distance<Metric>(ball, corners[cornerId], metric);
634 if(tmp > 0) result =
std::min(tmp,result);
else return 0;
637 std::vector<Line<Scalar,dim> >
const edges =
boundingBox.getEdges();
638 for(
size_t edgeId=0; edgeId<edges.size(); ++edgeId)
640 Scalar tmp = distance<Metric>(ball, edges[edgeId], metric);
641 if(tmp > 0) result =
std::min(tmp, result);
else return 0;
644 std::vector<Rectangle<Scalar,dim> >
const faces =
boundingBox.getFaces();
645 for(
size_t faceId=0; faceId<faces.size(); ++faceId)
647 Scalar tmp = distance<Metric>(ball, faces[faceId], metric);
648 if(tmp > 0) result =
std::min(tmp, result);
else return 0;
692 template <
class Metric,
class Scalar,
int dim,
class FirstObject,
class SecondObject>
695 template <
class Metric,
class Scalar,
int dim>
718 template <
class Scalar,
int dim,
class FirstObject,
class SecondObject,
class ScalarProduct>
719 FirstObject
projectFirstOnSecond(FirstObject
const& first, SecondObject
const& second, ScalarProduct
const& scalarProduct = ScalarProduct())
724 template <
class Scalar,
int dim,
class Metric>
730 template <
class Scalar,
int dim,
class Metric>
736 template <
class Scalar,
int dim,
class Metric>
742 template <
class Scalar,
int dim,
class Metric>
748 template <
class Scalar,
int dim,
class Metric>
754 template <
class Scalar,
int dim,
class Metric>
760 template <
class Scalar,
int dim,
class Metric>
766 template <
class Scalar,
int dim,
class Metric>
772 template <
class Scalar,
int dim,
class Metric>
778 template <
class Scalar,
int dim,
class Metric>
784 template <
class Scalar,
int dim,
class Metric>
790 template <
class Scalar,
int dim,
class Metric>
796 template <
class Scalar,
int dim,
class Metric>
802 template <
class Scalar,
int dim,
class Metric>
808 template <
class Scalar,
int dim,
class Metric>
814 template <
class Scalar,
int dim,
class Metric>
827 template <
class Scalar,
int dim,
class Metric>
Dune::FieldVector< Scalar, dim > Base
Point(Dune::FieldVector< Scalar, dim > const &p)
Dune::FieldVector< T, n > min(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise minimum.
std::pair< Dune::FieldVector< double, Cell::dimension >, Dune::FieldVector< double, Cell::dimension > > boundingBox(Cell const &cell)
Computes the bounding box of a cell.
Scalar intersects(Ball< Scalar, dim > const &ball, BoundingBox< Scalar, dim > const &boundingBox, Metric const &metric=Metric())
FirstObject projectFirstOnSecond(FirstObject const &first, SecondObject const &second, ScalarProduct const &scalarProduct=ScalarProduct())
Scalar distance(Point< Scalar, dim > const &first, Point< Scalar, dim > const &second)
bool contains(Position const &x) const
Ball(Dune::FieldVector< Scalar, dim > &c, Scalar r)
Scalar distanceFromCenter(Position const &x) const
Dune::FieldVector< Scalar, dim > center
BoundingBox(BoundingBox const &boundingBox)
std::ostream & print(std::ostream &stream) const
Dune::FieldVector< std::pair< Scalar, Scalar >, dim > coord
BoundingBox(typename Point< Scalar, dim >::Base const &x)
bool contains(Coordinate const &x) const
void update(Coordinate const &x)
friend std::ostream & operator<<(std::ostream &stream, BoundingBox< Scalar, dim > const &boundingBox)
static void init(BB &boundingBox)
BoundingBox< Scalar, dim > BB
static void initFaces(BB &boundingBox)
static void initCorners(BB &boundingBox)
static void initEdges(BB &boundingBox)
FastBoundingBox< Scalar, dim > BB
static void initFaces(BB &boundingBox)
static void initCorners(BB &boundingBox)
static void initEdges(BB &boundingBox)
static void init(BB &boundingBox)
std::vector< Line< Scalar, dim > > edges
BoundingBox< Scalar, dim > Base
FastBoundingBox(FastBoundingBox const &boundingBox)
FastBoundingBox(Coordinate const &x)
std::vector< Rectangle< Scalar, dim > > faces
std::vector< Point< Scalar, dim > > corners
std::vector< Point< Scalar, dim > > const & getStoredCorners() const
std::vector< Line< Scalar, dim > > const & getStoredEdges() const
std::vector< Rectangle< Scalar, dim > > const & getStoredFaces() const
static Scalar apply(Ball< Scalar, dim > const &ball, Rectangle< Scalar, dim > const &rectangle, Metric metric)
static Scalar apply(Ball< Scalar, dim > const &ball, Line< Scalar, dim > const &line, Metric metric)
static Scalar apply(Ball< Scalar, dim > const &ball, BoundingBox< Scalar, dim > const &boundingBox, Metric metric)
static Scalar apply(Ball< Scalar, dim > const &ball, Point< Scalar, dim > const &point, Metric metric)
static Scalar apply(Point< Scalar, dim > const &point, Line< Scalar, dim > const &line, Metric metric)
static Scalar apply(Point< Scalar, dim > const &firstPoint, Point< Scalar, dim > const &secondPoint, Metric metric)
static Scalar apply(Point< Scalar, dim > const &point, Rectangle< Scalar, dim > const &rectangle, Metric metric)
static bool apply(Ball< Scalar, dim > const &ball, BoundingBox< Scalar, dim > const &boundingBox, Metric metric)
static Point< Scalar, dim > apply(Point< Scalar, dim > const &point, Rectangle< Scalar, dim > const &rectangle, Scalar &a, Scalar &b, ScalarProduct const scalarProduct)
static Point< Scalar, dim > apply(Point< Scalar, dim > const &point, Line< Scalar, dim > const &line, Scalar &a, ScalarProduct const scalarProduct)
Line(Point< Scalar, dim > const &s, Point< Scalar, dim > const &e)
Point< Scalar, dim > start
Rectangle(boost::array< Point< Scalar, dim >, 4 > const &e)
Rectangle(Point< Scalar, dim > const &p0, Point< Scalar, dim > const &p1, Point< Scalar, dim > const &p2, Point< Scalar, dim > const &p3)
boost::array< Point< Scalar, dim >, 4 > corners
Triangle(Vertex const &v1, Vertex const &v2, Vertex const &v3)
boost::array< Vertex, 3 > corners
Point< Scalar, dim > Vertex