gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
SmoothData.cpp
Go to the documentation of this file.
1 // Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 
6 #include <stdio.h>
7 #include "SmoothData.h"
8 #include "Numeric.h"
9 #include "OS.h"
10 
11 // Basic coordinate-based floting point value averager
12 
13 double xyzv::eps = 1.e-12;
14 
15 xyzv::xyzv(const xyzv &other)
16 {
17  x = other.x;
18  y = other.y;
19  z = other.z;
20  scaleValue = other.scaleValue; // Added by Trevor Strickler 07/10/2013
21  scale_numvals = other.scale_numvals; // Added by Trevor Strickler 07/10/2013
22  nbvals = other.nbvals;
24  if(other.vals && other.nbvals) {
25  vals = new double[other.nbvals];
26  for(int i = 0; i < nbvals; i++) vals[i] = other.vals[i];
27  }
28  else
29  vals = nullptr;
30 }
31 
32 xyzv &xyzv::operator=(const xyzv &other)
33 {
34  if(this != &other) {
35  x = other.x;
36  y = other.y;
37  z = other.z;
38  scaleValue = other.scaleValue; // Added by Trevor Strickler 07/10/2013
39  scale_numvals = other.scale_numvals; // Added by Trevor Strickler 07/10/2013
40  nbvals = other.nbvals;
42  if(other.vals && other.nbvals) {
43  vals = new double[other.nbvals];
44  for(int i = 0; i < nbvals; i++) vals[i] = other.vals[i];
45  }
46  }
47  return *this;
48 }
49 
50 void xyzv::update(int n, double *v)
51 {
52  if(!vals) {
53  vals = new double[n];
54  for(int i = 0; i < n; i++) vals[i] = 0.0;
55  nbvals = n;
56  nboccurrences = 0;
57  }
58  else if(nbvals != n)
59  return; // error
60  double x1 = (double)(nboccurrences) / (double)(nboccurrences + 1);
61  double x2 = 1. / (double)(nboccurrences + 1);
62  for(int i = 0; i < nbvals; i++) vals[i] = (x1 * vals[i] + x2 * v[i]);
63  nboccurrences++;
64 }
65 
66 // Added by Trevor Strickler
67 void xyzv::scale_update(double scale_inp)
68 {
69  if(std::abs(1.0 - scale_inp) <= eps) scale_inp = 1.0;
70  if(scale_inp != 1.0 || scaleValue != 1.0) {
71  double x1 = (double)(scale_numvals) / (double)(scale_numvals + 1);
72  double x2 = 1.0 / (double)(scale_numvals + 1);
73  scaleValue = (x1 * scaleValue + x2 * scale_inp);
74  }
75  if(std::abs(1.0 - scaleValue) <= eps) scaleValue = 1.0;
76  scale_numvals++;
77 }
78 
79 void smooth_data::add(double x, double y, double z, int n, double *vals)
80 {
81  xyzv xyz(x, y, z);
82  auto it = c.find(xyz);
83  if(it == c.end()) {
84  xyz.update(n, vals);
85  c.insert(xyz);
86  }
87  else {
88  // we can do this because we know that it will not destroy the set
89  // ordering
90  xyzv *p = (xyzv *)&(*it);
91  p->update(n, vals);
92  }
93 }
94 
95 // added by Trevor Strickler
96 void smooth_data::add_scale(double x, double y, double z, double scale_val)
97 {
98  xyzv xyz(x, y, z);
99  auto it = c.find(xyz);
100  if(it == c.end()) {
101  xyz.scale_update(scale_val);
102  c.insert(xyz);
103  }
104  else {
105  // we can do this because we know that it will not destroy the set
106  // ordering
107  xyzv *p = (xyzv *)&(*it);
108  p->scale_update(scale_val);
109  }
110 }
111 
112 bool smooth_data::get(double x, double y, double z, int n, double *vals) const
113 {
114  auto it = c.find(xyzv(x, y, z));
115  if(it == c.end()) return false;
116  for(int k = 0; k < n; k++) vals[k] = it->vals[k];
117  return true;
118 }
119 
120 // added by Trevor Strickler
121 bool smooth_data::get_scale(double x, double y, double z, double *scale_val) const
122 {
123  auto it = c.find(xyzv(x, y, z));
124  if(it == c.end()) return false;
125  (*scale_val) = it->scaleValue;
126  return true;
127 }
128 
130 {
131  auto it = c.begin();
132  while(it != c.end()) {
133  if(it->nbvals == 3) norme(it->vals);
134  it++;
135  }
136 }
137 
138 bool smooth_data::exportview(const std::string &filename) const
139 {
140  FILE *fp = Fopen(filename.c_str(), "w");
141  if(!fp) return false;
142  fprintf(fp, "View \"data\" {\n");
143  auto it = c.begin();
144  while(it != c.end()) {
145  switch(it->nbvals) {
146  case 1:
147  fprintf(fp, "SP(%.16g,%.16g,%.16g){%.16g};\n", it->x, it->y, it->z,
148  it->vals[0]);
149  break;
150  case 3:
151  fprintf(fp, "VP(%.16g,%.16g,%.16g){%.16g,%.16g,%.16g};\n", it->x, it->y,
152  it->z, it->vals[0], it->vals[1], it->vals[2]);
153  break;
154  }
155  it++;
156  }
157  fprintf(fp, "};\n");
158  fclose(fp);
159  return true;
160 }
161 
162 // Normal smoother
163 
164 float xyzn::eps = 1.e-6F;
165 
166 float xyzn::angle(int i, char nx, char ny, char nz)
167 {
168  // returns the angle (in [-180,180]) between the ith normal stored
169  // at point xyz and the new normal nx,ny,nz
170  double a[3] = {char2float(n[i].nx), char2float(n[i].ny), char2float(n[i].nz)};
171  double b[3] = {char2float(nx), char2float(ny), char2float(nz)};
172  norme(a);
173  norme(b);
174 
175  double c[3];
176  prodve(a, b, c);
177 
178  double const cosc = prosca(a, b);
179  double const sinc = std::sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]);
180  double const angplan = myatan2(sinc, cosc);
181  return (float)(angplan * 180. / M_PI);
182 }
183 
184 void xyzn::update(char nx, char ny, char nz, float tol)
185 {
186  // just ignore it if we have more than 100 clusters
187  if(n.size() > 100) return;
188 
189  // we average by clusters of normals separated by tol; the result of
190  // the averaging depends on the order in which we average (since we
191  // store the average value as the cluster center as we go), but it
192  // seems to work very nicely in practice (and it's faster than
193  // storing everyting and averaging at the end)
194  for(std::size_t i = 0; i < n.size(); i++) {
195  if(tol >= 180. || std::abs(angle(i, nx, ny, nz)) < tol) {
196  // just ignore it if we have more than 100 contributions to a
197  // single point...
198  if(n[i].nb < 100) {
199  float c1 = (float)(n[i].nb) / (float)(n[i].nb + 1);
200  float c2 = 1.0F / (float)(n[i].nb + 1);
201  n[i].nx = (char)(c1 * n[i].nx + c2 * nx);
202  n[i].ny = (char)(c1 * n[i].ny + c2 * ny);
203  n[i].nz = (char)(c1 * n[i].nz + c2 * nz);
204  n[i].nb++;
205  }
206  return;
207  }
208  }
209 
210  // create a new cluster
211  nnb nn = {nx, ny, nz, 0};
212  n.push_back(nn);
213 }
214 
215 void smooth_normals::add(double x, double y, double z, double nx, double ny,
216  double nz)
217 {
218  xyzn xyz((float)x, (float)y, (float)z);
219  auto it = c.find(xyz);
220  if(it == c.end()) {
221  xyz.update(float2char((float)nx), float2char((float)ny),
222  float2char((float)nz), tol);
223  c.insert(xyz);
224  }
225  else {
226  // we can do this because we know that it will not destroy the set
227  // ordering
228  xyzn *p = (xyzn *)&(*it);
229  p->update(float2char((float)nx), float2char((float)ny),
230  float2char((float)nz), tol);
231  }
232 }
233 
234 bool smooth_normals::get(double x, double y, double z, double &nx, double &ny,
235  double &nz) const
236 {
237  auto it =
238  c.find(xyzn((float)x, (float)y, (float)z));
239 
240  if(it == c.end()) return false;
241 
242  xyzn *p = (xyzn *)&(*it);
243  for(std::size_t i = 0; i < p->n.size(); i++) {
244  if(std::abs(p->angle(i, float2char((float)nx), float2char((float)ny),
245  float2char((float)nz))) < tol) {
246  nx = char2float(p->n[i].nx);
247  ny = char2float(p->n[i].ny);
248  nz = char2float(p->n[i].nz);
249  break;
250  }
251  }
252  return true;
253 }
xyzv::update
void update(int n, double *v)
Definition: SmoothData.cpp:50
xyzn::angle
float angle(int i, char n0, char n1, char n2)
Definition: SmoothData.cpp:166
smooth_normals::tol
float tol
Definition: SmoothData.h:102
xyzv::scale_numvals
int scale_numvals
Definition: SmoothData.h:22
F
#define F
Definition: DefaultOptions.h:23
OS.h
float2char
char float2char(float f)
Definition: Numeric.cpp:452
c
static double c(int i, int j, fullMatrix< double > &CA, const std::vector< SPoint3 > &P, const std::vector< SPoint3 > &Q)
Definition: discreteFrechetDistance.cpp:15
nnb
Definition: SmoothData.h:73
xyzv::xyzv
xyzv(double xx, double yy, double zz)
Definition: SmoothData.h:24
smooth_data::get
bool get(double x, double y, double z, int n, double *vals) const
Definition: SmoothData.cpp:112
smooth_data::add
void add(double x, double y, double z, int n, double *vals)
Definition: SmoothData.cpp:79
char2float
float char2float(char c)
Definition: Numeric.cpp:464
xyzv::operator=
xyzv & operator=(const xyzv &other)
Definition: SmoothData.cpp:32
smooth_normals::add
void add(double x, double y, double z, double nx, double ny, double nz)
Definition: SmoothData.cpp:215
Fopen
FILE * Fopen(const char *f, const char *mode)
Definition: OS.cpp:273
xyzv::vals
double * vals
Definition: SmoothData.h:16
xyzv
Definition: SmoothData.h:15
xyzn::update
void update(char n0, char n1, char n2, float tol)
Definition: SmoothData.cpp:184
myatan2
double myatan2(double a, double b)
Definition: Numeric.cpp:12
Numeric.h
xyzv::y
double y
Definition: SmoothData.h:16
smooth_normals::c
std::set< xyzn, lessthanxyzn > c
Definition: SmoothData.h:103
prosca
double prosca(double const a[3], double const b[3])
Definition: Numeric.h:112
smooth_data::add_scale
void add_scale(double x, double y, double z, double scale_val)
Definition: SmoothData.cpp:96
prodve
void prodve(double a[3], double b[3], double c[3])
Definition: Numeric.h:105
xyzn::n
std::vector< nnb > n
Definition: SmoothData.h:80
smooth_data::normalize
void normalize()
Definition: SmoothData.cpp:129
xyzv::x
double x
Definition: SmoothData.h:16
smooth_data::c
std::set< xyzv, lessthanxyzv > c
Definition: SmoothData.h:55
xyzv::z
double z
Definition: SmoothData.h:16
smooth_normals::get
bool get(double x, double y, double z, double &nx, double &ny, double &nz) const
Definition: SmoothData.cpp:234
xyzn
Definition: SmoothData.h:78
z
const double z
Definition: GaussQuadratureQuad.cpp:56
xyzv::scaleValue
double scaleValue
Definition: SmoothData.h:21
xyzn::eps
static float eps
Definition: SmoothData.h:81
smooth_data::exportview
bool exportview(const std::string &filename) const
Definition: SmoothData.cpp:138
xyzv::eps
static double eps
Definition: SmoothData.h:23
smooth_data::get_scale
bool get_scale(double x, double y, double z, double *scale_val) const
Definition: SmoothData.cpp:121
xyzv::scale_update
void scale_update(double scale_val)
Definition: SmoothData.cpp:67
norme
double norme(double a[3])
Definition: Numeric.h:123
xyzv::nboccurrences
int nboccurrences
Definition: SmoothData.h:18
xyzv::nbvals
int nbvals
Definition: SmoothData.h:17
c1
const double c1
Definition: GaussQuadratureHex.cpp:16
SmoothData.h