intersect_clipper.h
Go to the documentation of this file.
1 /*
2 This file is part of the Ristra portage project.
3 Please see the license file at the root of this repository, or at:
4  https://github.com/laristra/portage/blob/master/LICENSE
5 */
6 
7 #ifndef PORTAGE_INTERSECT_INTERSECTCLIPPER_H_
8 #define PORTAGE_INTERSECT_INTERSECTCLIPPER_H_
9 
10 #include <iostream>
11 #include <cmath>
12 #include <cfloat>
13 #include <algorithm>
14 
15 // portage includes
16 #include "portage/intersect/clipper.hpp"
18 #include "wonton/support/Point.h"
19 
20 namespace Portage {
21 
27 inline
28 std::vector<double> areaAndMomentPolygon(std::vector<Wonton::Point<2>> const& poly){
29  double area = 0;
30  double cx = 0;
31  double cy = 0;
32  std::vector <double> ret;
33 
34  int lastIndex = poly.size()-1;
35 
36  for(int i=0; i < lastIndex; i++){
37  double a = (poly[i][0]*poly[i+1][1]-poly[i+1][0]*poly[i][1]);
38  area+=a;
39  cx+= (poly[i][0]+poly[i+1][0])*a;
40  cy+= (poly[i][1]+poly[i+1][1])*a;
41  }
42 
43  //close the polygon
44  double a = poly[lastIndex][0]*poly[0][1] - poly[0][0]*poly[lastIndex][1];
45  area+= a;
46  cx+= (poly[lastIndex][0]+poly[0][0])*a;
47  cy+= (poly[lastIndex][1]+poly[0][1])*a;
48  ret.emplace_back(.5*area);
49  ret.emplace_back(cx/6.);
50  ret.emplace_back(cy/6.);
51  return ret;
52 }
53 
64 template <typename SourceMeshType, typename TargetMeshType=SourceMeshType> class IntersectClipper
65 {
66 
67 public:
68 
70 typedef std::vector<Wonton::Point<2>> Poly;
72 typedef std::pair<double, Wonton::Point<2>> Moment;
73 
75 IntersectClipper(const SourceMeshType &s, const TargetMeshType &t):sourceMeshWrapper(s), targetMeshWrapper(t){}
76 
83 std::vector<std::vector<double> > operator() (const int cellA, const int cellB) const {
84  Poly polyA, polyB;
85  sourceMeshWrapper.cell_get_coordinates(cellA, &polyA);
86  targetMeshWrapper.cell_get_coordinates(cellB, &polyB);
87  double max_size_poly = 0;
88  max_size_poly = IntersectClipper::updateMaxSize(polyA, max_size_poly);
89  max_size_poly = IntersectClipper::updateMaxSize(polyB, max_size_poly);
90 
91  const ClipperLib::Path intPolyA = IntersectClipper::convertPoly2int(polyA, max_size_poly);
92  const ClipperLib::Path intPolyB = IntersectClipper::convertPoly2int(polyB, max_size_poly);
93 
94  //Make clipper aware of polyA and polyB
95  ClipperLib::Clipper clpr;
96  clpr.AddPath(intPolyA, ClipperLib::ptSubject, true);
97  clpr.AddPath(intPolyB, ClipperLib::ptClip, true);
98 
99  //Compute the intersection of all paths which have been added to clipper (in this case
100  //polyA and polyB; use the Even-Odd winding rule in case of self-intersecting polygons
101  //For more information on the winding rules see:
102  //http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Types/PolyFillType.htm
103  ClipperLib::Paths solution;
104  clpr.Execute(ClipperLib::ctIntersection, solution,
105  ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd);
106 
107  std::vector<std::vector<Wonton::Point<2>>> intersectionList;
108  for(auto const &i: solution){
109  std::vector<Wonton::Point<2>> poly;
110  for(auto const &j: i){
111  //Build list of intersections and convert back to doubles
112  poly.emplace_back(integer2real(j.X, max_size_poly), integer2real(j.Y, max_size_poly));
113  }
114  intersectionList.emplace_back(poly);
115  }
116  std::vector<std::vector<double>> moments;
117  for(auto const &i: intersectionList){
118  moments.emplace_back(areaAndMomentPolygon(i));
119  }
120  return moments;
121 }
122 
124 IntersectClipper() = default;
125 
127 IntersectClipper(const IntersectClipper &) = delete;
128 
130 IntersectClipper & operator = (const IntersectClipper &) = delete;
131 
132 
133 private:
134 
135 //We must use the same max size for all the polygons, so the number we are looking for is the maximum value in the set--all the X and Y values will be converted using this value
136 static double updateMaxSize( const std::vector<Wonton::Point<2>> poly, double max_size_poly){
137  for(auto const &i: poly){
138  double m = std::max(std::abs(i[0]), std::abs(i[1]));
139  if (m > max_size_poly) max_size_poly = m;
140  }
141  return max_size_poly;
142 }
143 
154 static long real2integer(double a, const double max_size){
155  int exp;
156 
157  // We want to move the decimal point of the floating point number so that the last digit given is before the decimal point.
158  // The alogrithm is to find the exponent (in the floating point representation) of the largest number in the polygons (either X or Y coordinate).
159  //Multiply by the power of two which is number of digits in mantissa (in this case, 53) - exponent
160  //lrint, then rounds to an integer
161 
162  //Compute the exponent
163  frexp(max_size, &exp);
164  //Size of long must be >= size double
165  return lrint(ldexp(a, DBL_MANT_DIG-exp));
166 }
167 
173 static double integer2real(long a, const double max_size){
174  int exp;
175  frexp(max_size, &exp);
176  return ldexp(a, exp-DBL_MANT_DIG);
177 }
178 
179 //Convert an entire polygon (specifiied as a std::vector<Wonton::Point>) to a std::vector<IntPoint>
180 static std::vector<ClipperLib::IntPoint> convertPoly2int(std::vector<Wonton::Point<2>> poly, double max_size_poly){
181  std::vector<ClipperLib::IntPoint> intpoly(poly.size());
182  std::transform(poly.begin(), poly.end(), intpoly.begin(), [max_size_poly](Wonton::Point<2> point){
183  return ClipperLib::IntPoint(real2integer(point[0], max_size_poly), real2integer(point[1], max_size_poly));});
184  return intpoly;
185 }
186 
187 private:
188 const SourceMeshType &sourceMeshWrapper;
189 const TargetMeshType &targetMeshWrapper;
190 
191 }; // class IntersectClipper
192 
193 } // namespace Portage
194 
195 #endif // PORTAGE_INTERSECT_INTERSECTCLIPPER_H_
std::vector< T > vector
Definition: portage.h:238
OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryFunction op)
Definition: portage.h:250
std::pair< double, Wonton::Point< 2 > > Moment
Alias to provide volume and centroid.
Definition: intersect_clipper.h:72
IntersectClipper()=default
Default constructor.
std::vector< std::vector< double > > operator()(const int cellA, const int cellB) const
Intersect two cells and return the first two moments.
Definition: intersect_clipper.h:83
2-D intersection algorithm for arbitrary convex and non-convex polyhedra
Definition: intersect_clipper.h:64
IntersectClipper(const SourceMeshType &s, const TargetMeshType &t)
Constructor taking a source mesh s and a target mesh t.
Definition: intersect_clipper.h:75
IntersectClipper & operator=(const IntersectClipper &)=delete
Assignment operator (disabled)
Definition: coredriver.h:42
std::vector< double > areaAndMomentPolygon(std::vector< Wonton::Point< 2 >> const &poly)
Return the area and moment of the polygon.
Definition: intersect_clipper.h:28
std::vector< Wonton::Point< 2 > > Poly
Alias for a collection of Points.
Definition: intersect_clipper.h:70