Goosefoot Mesher - CGAL
proximity_domain_3.h
1 #ifndef PROXIMITY_DOMAIN_3_H
2 #define PROXIMITY_DOMAIN_3_H
3 
4 #include "mesher_cgal.h"
5 
6 #include <vtkImageData.h>
7 #include <vtkXMLImageDataWriter.h>
8 #include <CGAL/AABB_tree.h>
9 #include <CGAL/AABB_traits.h>
10 #include <CGAL/AABB_face_graph_triangle_primitive.h>
11 
12 typedef K::Iso_cuboid_3 Iso_cuboid;
13 
14 typedef CGAL::AABB_face_graph_triangle_primitive<Polyhedron> Primitive;
15 typedef CGAL::AABB_traits<K, Primitive> Traits;
16 typedef CGAL::AABB_tree<Traits> Tree;
17 
18 namespace mesherCGAL {
19  template <typename Gt, typename Index_>
21  {
22  public:
23  typedef typename Gt::FT FT;
24  typedef typename Gt::Point_3 Point_3;
25  typedef Index_ Index;
26 
27  private:
28  // Map to store field values
29  int minx, miny, minz, nx, ny, nz;
30  FT length_scale;
31  CGAL::Max<FT> max_;
32  CGAL::Min<FT> min_;
33 
34  public:
36  Proximity_domain_field_3(Tree* tree, double near_cl, double far_cl, std::vector< std::unique_ptr<Zone> >& zones, float zone_radius, float centre_radius,
37  const Point* centre, Tree* needle_tree, float granularity, const Iso_cuboid& bbox, bool solid_zones) :
38  max_(CGAL::Max<FT>()), min_(CGAL::Min<FT>()),
39  tree_(tree), near_cl_(near_cl), far_cl_(far_cl), zones_(zones), zone_radius_(zone_radius),
40  centre_radius_(centre_radius),
41  centre_(centre), needle_tree_(needle_tree), granularity_(granularity),
42  bbox_(bbox), checks_(0), total_checks_(0), values_size_(0), solid_zones_(solid_zones)
43  {
44  max_dist[0] = 0.; max_dist[1] = 0.; max_dist[2] = 0.;
45 
46  minx = (int)(bbox.xmin()/granularity_); nx = 1 + (int)(bbox.xmax()/granularity_) - minx;
47  miny = (int)(bbox.ymin()/granularity_); ny = 1 + (int)(bbox.ymax()/granularity_) - miny;
48  minz = (int)(bbox.zmin()/granularity_); nz = 1 + (int)(bbox.zmax()/granularity_) - minz;
49  length_scale = std::pow(bbox.volume(), 1./3);
50 
51  std::cout << "Bounding Box coordinates: "
52  << "[" << bbox.xmin() << ", " << bbox.ymin() << ", " << bbox.zmin() << "] -> "
53  << "[" << bbox.xmax() << ", " << bbox.ymax() << ", " << bbox.zmax() << "]"
54  << std::endl;
55  std::cout << "Length scale: " << length_scale << std::endl;
56  std::cout << "CL bitmap: "
57  << "[" << minx << ", " << miny << ", " << minz << "] + "
58  << "[" << nx << ", " << ny << ", " << nz << "]"
59  << std::endl;
60  std::cout << "Array size: " << nx * ny * nz << std::endl;
61 
62  //visualization_create_structured_grid(minx, miny, minz, nx, ny, nz, granularity_);
63 
64  values_ = (FT*)calloc(sizeof(FT), nx*ny*nz);
65  dists_ = (FT*)calloc(sizeof(FT), nx*ny*nz);
66  max_cl_ = -1.;
67  }
68  //RMV : insert destructor to clear values_ allocations
69 
70  /* http://www.vtk.org/Wiki/VTK/Examples/Cxx/ImageData/IterateImageData */
71  void output_characteristic_lengths(std::string filename)
72  {
73  vtkSmartPointer<vtkImageData> imageData = vtkSmartPointer<vtkImageData>::New();
74  imageData->SetDimensions(nx, ny, nz);
75  imageData->SetNumberOfScalarComponents(2);
76  imageData->SetScalarTypeToDouble();
77  imageData->SetSpacing(granularity_, granularity_, granularity_);
78  imageData->SetOrigin(minx * granularity_, miny * granularity_, minz * granularity_);
79 
80  for (int z = 0 ; z < nz ; z++)
81  for (int y = 0 ; y < ny ; y++)
82  for (int x = 0 ; x < nx ; x++) {
83  double *pix = static_cast<double*>(imageData->GetScalarPointer(x, y, z));
84  int ix = nx*(ny*z + y) + x;
85  pix[0] = values_[ix] > 1e-20 ? values_[ix] : -1.0;
86  pix[1] = dists_[ix] > 1e-20 ? dists_[ix] : -2.0;
87  }
88 
89  vtkSmartPointer<vtkXMLImageDataWriter> imageWriter = vtkSmartPointer<vtkXMLImageDataWriter>::New();
90  imageWriter->SetInput(imageData);
91  imageWriter->SetFileName(filename.c_str());
92  imageWriter->Update();
93  imageWriter->Write();
94  }
95 
96  FT to_cl(FT closest_cl, FT dist) const
97  {
98  FT scaling = 1;
99 
100  if (dist <= 4 * closest_cl * closest_cl + 1e-10)
101  scaling = 0;
102  else
103  scaling *= pow((dist - closest_cl * closest_cl * 4)/(length_scale * length_scale * 0.25), 0.5);
104 
105  return (far_cl_ - (far_cl_-closest_cl)*(exp(-scaling) - exp(-1)) / (1 - exp(-1)));
106  }
107 
109  FT operator()(const Point_3& q, const int , const Index& ) const
110  {
111  Point_3 p(
112  min_(max_(q.x(), bbox_.xmin()), bbox_.xmax()),
113  min_(max_(q.y(), bbox_.ymin()), bbox_.ymax()),
114  min_(max_(q.z(), bbox_.zmin()), bbox_.zmax())
115  );
116  int x = (int)(p.x()/granularity_);
117  int y = (int)(p.y()/granularity_);
118  int z = (int)(p.z()/granularity_);
119  //int ix = nx*(ny*(min_(max_(z - minz, 0), nz - 1)) + min_(max_(y - miny, 0), ny - 1)) + min_(max_(x - minx, 0), nx - 1);
120  int ix = nx*(ny*(z - minz) + y - miny) + x - minx;
121 
122  FT cl = values_[ix];
123 
124  checks_++;
125 
126  if ( checks_ % 10000 == 0 ) {
127  total_checks_ += checks_;
128  std::cout << "Cached " << values_size_
129  << " blocks (miss rate " << values_size_*100./total_checks_
130  << "%) - max. cl: " << max_cl_
131  << " - max. distances from key points/surfaces: " << max_dist[0]
132  << " " << max_dist[1] << " " << max_dist[2] << std::endl;
133  checks_ = 0;
134 
135  //if (values_.size() > 0) {
136  // typename Values::const_iterator i = values_.begin();
137  // char filename[200];
138  // sprintf(filename, "/tmp/points.%06d.txt", total_checks_);
139  // FILE* f = fopen(filename, "w");
140  // fprintf(f, "x,y,z\n");
141  // for ( ; i != values_.end() ; ++i ) {
142  // const std::vector<int> &curtup = (i->first);
143  // fprintf(f, "%d, %d, %d\n", curtup[0], curtup[1], curtup[2]);
144  // }
145  // fclose(f);
146  //}
147  }
148 
149  if ( cl > 1e-20 ) {
150  return cl;
151  }
152 
153  /* Everywhere dist appears, it is squared */
154  FT scaling = 1., dist = -1.;
155  FT closest_cl = near_cl_;
156 
157  if (tree_ != NULL) {
158  FT tree_dist = tree_->squared_distance(p);
159  if (dist < 0 || tree_dist < dist) {
160  dist = tree_dist;
161  closest_cl = near_cl_;
162  }
163  //max_dist[0] = CGAL::max(max_dist[0], tree_dist);
164  }
165 
166  FT needle_dist = 0.;
167  if (needle_tree_ != NULL) {
168  needle_dist = needle_tree_->squared_distance(p);
169  //needle_dist = CGAL::min(needle_dist - near_cl_ * 2, 0.0); /* Introduce near_cl region around needle */
170  if (dist < 0 || needle_dist < dist) {
171  dist = needle_dist;
172  closest_cl = near_cl_;
173  }
174 
175  }
176 
177  for (auto&& zone : zones_) {
178  FT zone_dist = -1;
179  if (solid_zones_ && zone->is_container() && zone->contains(p)) {
180  zone_dist = 0;
181  }
182  else if (zone->has_tree()) {
183  zone_dist = zone->squared_distance(p);
184  if (zone_dist > zone_radius_ * zone_radius_)
185  zone_dist = zone_dist + zone_radius_ * zone_radius_ - 2. * sqrt(zone_dist) * zone_radius_;
186  else zone_dist = 0.;
187  if (zone_dist < 0) zone_dist = 0.;
188  }
189  //zone_dist = CGAL::min(zone_dist - near_cl_ * 2, 0.0); /* Introduce near_cl region around zone */
190  if (zone_dist >= 0 && (dist < 0 || (to_cl(closest_cl, dist) > to_cl(zone->get_cl(), zone_dist)))) {
191  dist = zone_dist;
192  closest_cl = zone->get_cl();
193  }
194  }
195 
196  if (centre_ != NULL) {
197  FT centre_dist = squared_distance(*centre_, p);
198  if (centre_dist > centre_radius_ * centre_radius_)
199  centre_dist = centre_dist + centre_radius_ * centre_radius_ - 2. * sqrt(centre_dist) * centre_radius_;
200  else centre_dist = 0.;
201  if (centre_dist < 0) centre_dist = 0.;
202  if (dist < 0 || to_cl(closest_cl, dist) > to_cl(near_cl_, centre_dist)) {
203  dist = centre_dist;
204  closest_cl = near_cl_;
205  }
206  }
207 
208  if (dist < 0) {
209  cl = far_cl_;
210  } else {
211  //if (dist <= 4 * closest_cl * closest_cl + 1e-10)
212  // scaling = 0;
213  //else
214  // scaling *= pow((dist - closest_cl * closest_cl * 4)/(length_scale * length_scale * 0.25), 0.5);
215  cl = CGAL::min(far_cl_, to_cl(closest_cl, dist));
216  if (cl > max_cl_) max_cl_ = cl;
217  }
218 
219  //if (zone_pips_ != NULL) {
220  // int zone = -1;
221  // BOOST_FOREACH(const zone_pip_map::value_type& zone_pair, *zone_pips_) {
222  // if ((*zone_pair.second)(p)) {
223  // zone = zone_pair.first;
224  // break;
225  // }
226  // }
227  // if (zone > -1 && zone_cls_[zone] < cl) {
228  // cl = zone_cls_[zone];
229  // if (zone_cls_[zone] < 0.01)
230  // std::cout << "*" << std::endl;
231  // }
232  //}
233 
234  //FT scaling = CGAL::min(10*needle_dist/length_scale, 4.) * (1 / (.1 + dist/length_scale));
235  //printf("[%lf %lf %lf]\n", needle_dist, dist, length_scale);
236 
237  //cl = CGAL::min(far_cl_, (far_cl_ - (far_cl_-near_cl_)*exp(-scaling)));
238  values_size_++;
239 
240  values_[ix] = cl;
241  dists_[ix] = dist;
242  //visualization_set_allocation_order(ix, values_size_, cl, needle_dist, p.x(), p.y(), p.z());
243 
244  return cl;
245  }
246 
247  mutable float max_cl_;//RMV
248  private:
249  Tree* tree_;
250  mutable FT* values_;
251  mutable FT* dists_;
252  FT near_cl_, far_cl_;
253  std::vector< std::unique_ptr<Zone> >& zones_;
254  FT zone_radius_, centre_radius_;
255  const Point* centre_;
256  Tree* needle_tree_;
257  FT granularity_;
258  const Iso_cuboid& bbox_;
259  mutable int checks_, total_checks_, values_size_;
260  mutable FT max_dist[3];
261  bool solid_zones_;
262  };
263 }
264 
265 #endif
Definition: proximity_domain_3.h:20
Proximity_domain_field_3(Tree *tree, double near_cl, double far_cl, std::vector< std::unique_ptr< Zone > > &zones, float zone_radius, float centre_radius, const Point *centre, Tree *needle_tree, float granularity, const Iso_cuboid &bbox, bool solid_zones)
Constructor.
Definition: proximity_domain_3.h:36
Definition: implicit_zone_function.h:17
Definition: write_c3t3_to_gmsh_file.h:50
FT operator()(const Point_3 &q, const int, const Index &) const
Returns size.
Definition: proximity_domain_3.h:109