Hermes2D  2.0
linearizer_base.cpp
1 // This file is part of Hermes2D.
2 //
3 // Copyright 2009 Ivo Hanak <hanak@byte.cz>
4 // Copyright 2005-2008 Jakub Cerveny <jakub.cerveny@gmail.com>
5 // Copyright 2005-2008 Lenka Dubcova <dubcova@gmail.com>
6 // Copyright 2005-2008 Pavel Solin <solin@unr.edu>
7 //
8 // Hermes2D is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation, either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // Hermes2D is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with Hermes2D. If not, see <http://www.gnu.org/licenses/>.
20 
21 #include "linearizer_base.h"
22 namespace Hermes
23 {
24  namespace Hermes2D
25  {
26  namespace Views
27  {
28  Quad2DLin g_quad_lin;
29 
30  Quad2DLin::Quad2DLin()
31  {
32  max_order[0] = max_order[1] = 1;
33  num_tables[0] = num_tables[1] = 2;
34  tables = lin_tables;
35  np = lin_np;
36  };
37 
38  LinearizerBase::LinearizerBase(bool auto_max) : auto_max(auto_max), del_slot(-1), empty(true)
39  {
40  tris = NULL;
41  tri_markers = NULL;
42  edges = NULL;
43  edge_markers = NULL;
44  hash_table = NULL;
45  info = NULL;
46  max = -1e100;
47 
48  vertex_count = triangle_count = edges_count = this->vertex_size = this->triangle_size = this->edges_size = 0;
49 
50  pthread_mutexattr_t attr;
51  pthread_mutexattr_init(&attr);
52  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
53  pthread_mutex_init(&data_mutex, &attr);
54  pthread_mutexattr_destroy(&attr);
55  }
56 
58  {
59  return this->empty;
60  }
61 
63  {
64  if(tris != NULL)
65  {
66  ::free(tris);
67  tris = NULL;
69  tri_markers = NULL;
70  }
71  if(edges != NULL)
72  {
73  ::free(edges);
74  edges = NULL;
76  edge_markers = NULL;
77  }
78  this->empty = true;
79  }
80 
81  LinearizerBase::~LinearizerBase()
82  {
83 
84  pthread_mutex_destroy(&data_mutex);
85  }
86 
87  void LinearizerBase::lock_data() const
88  {
89  pthread_mutex_lock(&data_mutex);
90  }
91 
92  void LinearizerBase::unlock_data() const
93  {
94  pthread_mutex_unlock(&data_mutex);
95  }
96 
97  void LinearizerBase::process_edge(int iv1, int iv2, int marker)
98  {
99  int mid = peek_vertex(iv1, iv2);
100  if(mid != -1)
101  {
102  process_edge(iv1, mid, marker);
103  process_edge(mid, iv2, marker);
104  }
105  else
106  add_edge(iv1, iv2, marker);
107  }
108 
109  void LinearizerBase::regularize_triangle(int iv0, int iv1, int iv2, int mid0, int mid1, int mid2, int marker)
110  {
111  // count the number of hanging mid-edge vertices
112  int n = 0;
113  if(mid0 >= 0) n++;
114  if(mid1 >= 0) n++;
115  if(mid2 >= 0) n++;
116  if(n == 3)
117  {
118  // three hanging vertices: split into four triangles
119  regularize_triangle(iv0, mid0, mid2, peek_vertex(iv0, mid0), -1, peek_vertex(mid2, iv0), marker);
120  regularize_triangle(mid0, iv1, mid1, peek_vertex(mid0, iv1), peek_vertex(iv1, mid1), -1, marker);
121  regularize_triangle(mid2, mid1, iv2, -1, peek_vertex(mid1, iv2), peek_vertex(iv2, mid2), marker);
122  regularize_triangle(mid0, mid1, mid2, -1, -1, -1, marker);
123  }
124  else if(n == 2)
125  {
126  // two hanging vertices: split into three triangles
127  if(mid0 < 0)
128  {
129  regularize_triangle(iv0, iv1, mid1, peek_vertex(iv0, iv1), peek_vertex(iv1, mid1), -1, marker);
130  regularize_triangle(mid2, iv0, mid1, peek_vertex(mid2, iv0), -1, -1, marker);
131  regularize_triangle(mid2, mid1, iv2, -1, peek_vertex(mid1, iv2), peek_vertex(iv2, mid2), marker);
132  }
133  else if(mid1 < 0)
134  {
135  regularize_triangle(iv1, iv2, mid2, peek_vertex(iv1, iv2), peek_vertex(iv2, mid2), -1, marker);
136  regularize_triangle(mid0, iv1, mid2, peek_vertex(mid0, iv1), -1, -1, marker);
137  regularize_triangle(mid0, mid2, iv0, -1, peek_vertex(mid2, iv0), peek_vertex(iv0, mid0), marker);
138  }
139  else
140  {
141  regularize_triangle(iv2, iv0, mid0, peek_vertex(iv2, iv0), peek_vertex(iv0, mid0), -1, marker);
142  regularize_triangle(mid1, iv2, mid0, peek_vertex(mid1, iv2), -1, -1, marker);
143  regularize_triangle(mid1, mid0, iv1, -1, peek_vertex(mid0, iv1), peek_vertex(iv1, mid1), marker);
144  }
145  }
146  else if(n == 1)
147  {
148  // one hanging vertex: split into two triangles
149  if(mid0 >= 0)
150  {
151  regularize_triangle(iv0, mid0, iv2, peek_vertex(iv0, mid0), -1, peek_vertex(iv2, iv0), marker);
152  regularize_triangle(mid0, iv1, iv2, peek_vertex(mid0, iv1), peek_vertex(iv1, iv2), -1, marker);
153  }
154  else if(mid1 >= 0)
155  {
156  regularize_triangle(iv1, mid1, iv0, peek_vertex(iv1, mid1), -1, peek_vertex(iv0, iv1), marker);
157  regularize_triangle(mid1, iv2, iv0, peek_vertex(mid1, iv2), peek_vertex(iv2, iv0), -1, marker);
158  }
159  else
160  {
161  regularize_triangle(iv2, mid2, iv1, peek_vertex(iv2, mid2), -1, peek_vertex(iv1, iv2), marker);
162  regularize_triangle(mid2, iv0, iv1, peek_vertex(mid2, iv0), peek_vertex(iv0, iv1), -1, marker);
163  }
164  }
165  else
166  {
167  // no hanging vertices: produce a single triangle
168  add_triangle(iv0, iv1, iv2, marker);
169  }
170  }
171 
172  void LinearizerBase::add_edge(int iv1, int iv2, int marker)
173  {
174 #pragma omp critical(realloc_edges)
175  {
176  if(edges_count >= edges_size)
177  {
178  edges = (int2*) realloc(edges, sizeof(int2) * (edges_size * 1.5));
179  edge_markers = (int*) realloc(edge_markers, sizeof(int) * (edges_size = edges_size * 1.5));
180  }
181  edges[edges_count][0] = iv1;
182  edges[edges_count][1] = iv2;
183  edge_markers[edges_count++] = marker;
184  }
185  }
186 
187  int LinearizerBase::peek_vertex(int p1, int p2)
188  {
189  // search for a vertex with parents p1, p2
190  if(p1 > p2) std::swap(p1, p2);
191  int index = hash(p1, p2);
192  int i = hash_table[index];
193  while (i >= 0)
194  {
195  if(info[i][0] == p1 && info[i][1] == p2) return i;
196  i = info[i][2];
197  }
198  return -1;
199  }
200 
201  void LinearizerBase::add_triangle(int iv0, int iv1, int iv2, int marker)
202  {
203  int index;
204 #pragma omp critical(realloc_triangles)
205  {
206  if(this->del_slot >= 0) // reuse a slot after a deleted triangle
207  {
208  index = this->del_slot;
209  del_slot = -1;
210  }
211  {
212  if(triangle_count >= triangle_size)
213  {
214  tris = (int3*) realloc(tris, sizeof(int3) * (triangle_size * 2));
215  tri_markers = (int*) realloc(tri_markers, sizeof(int) * (triangle_size = triangle_size * 2));
216  }
217  index = triangle_count++;
218 
219  tris[index][0] = iv0;
220  tris[index][1] = iv1;
221  tris[index][2] = iv2;
222  tri_markers[index] = marker;
223  }
224  }
225  }
226 
227  int LinearizerBase::hash(int p1, int p2)
228  {
229  return (984120265*p1 + 125965121*p2) & (vertex_size - 1);
230  }
231 
232  void LinearizerBase::set_max_absolute_value(double max_abs)
233  {
234  if(max_abs < 0.0)
235  this->warn("Setting of maximum absolute value in Linearizer with a negative value");
236  else
237  {
238  this->auto_max = false;
239  this->max = max_abs;
240  }
241  return;
242  }
243 
244  double LinearizerBase::get_min_value() const
245  {
246  return min_val;
247  }
248 
249  double LinearizerBase::get_max_value() const
250  {
251  return max_val;
252  }
253 
254  void LinearizerBase::calc_aabb(double* x, double* y, int stride, int num, double* min_x, double* max_x, double* min_y, double* max_y)
255  {
256  *min_x = *max_x = *x;
257  *min_y = *max_y = *y;
258 
259  uint8_t* ptr_x = (uint8_t*)x;
260  uint8_t* ptr_y = (uint8_t*)y;
261  for(int i = 0; i < num; i++, ptr_x += stride, ptr_y += stride)
262  {
263  *min_x = std::min(*min_x, *((double*)ptr_x));
264  *min_y = std::min(*min_y, *((double*)ptr_y));
265  *max_x = std::max(*max_x, *((double*)ptr_x));
266  *max_y = std::max(*max_y, *((double*)ptr_y));
267  }
268  }
269 
270  int3* LinearizerBase::get_triangles()
271  {
272  return this->tris;
273  }
274  int* LinearizerBase::get_triangle_markers()
275  {
276  return this->tri_markers;
277  }
278  int LinearizerBase::get_num_triangles()
279  {
280  return this->triangle_count;
281  }
282  int2* LinearizerBase::get_edges()
283  {
284  return this->edges;
285  }
286  int* LinearizerBase::get_edge_markers()
287  {
288  return this->edge_markers;
289  }
290  int LinearizerBase::get_num_edges()
291  {
292  return this->edges_count;
293  }
294  }
295  }
296 }