b2api
B2000++ API Reference Manual, VERSION 4.6
 
Loading...
Searching...
No Matches
b2find_coinciding_points.H
1//------------------------------------------------------------------------
2// b2find_coinciding_points.H --
3//
4// Find coinciding points.
5//
6// written by Thomas Ludwig
7//
8// Copyright (c) 2016
9// SMR Engineering & Development SA
10// 2502 Bienne, Switzerland
11//
12// All Rights Reserved. Proprietary source code. The contents of
13// this file may not be disclosed to third parties, copied or
14// duplicated in any form, in whole or in part, without the prior
15// written permission of SMR.
16//------------------------------------------------------------------------
17
18#ifndef _B2_FIND_COINCIDING_POINTS_H_
19#define _B2_FIND_COINCIDING_POINTS_H_
20
21#include <algorithm>
22#include <cassert>
23#include <cmath>
24#include <cstdint>
25#include <vector>
26
27namespace {
28
29struct Signature {
30 uint64_t d[3];
31
32 bool operator==(const Signature& o) const {
33 return d[0] == o.d[0] && d[1] == o.d[1] && d[2] == o.d[2];
34 }
35
36 bool operator!=(const Signature& o) const {
37 return d[0] != o.d[0] || d[1] != o.d[1] || d[2] != o.d[2];
38 }
39
40 bool operator<(const Signature& o) const {
41 return (
42 d[0] < o.d[0]
43 || (d[0] == o.d[0] && (d[1] < o.d[1] || (d[1] == o.d[1] && d[2] < o.d[2]))));
44 }
45};
46
47struct Point {
48 size_t index;
49 Signature signature;
50
51 bool operator<(const Point& o) const {
52 return (signature < o.signature || (signature == o.signature && index < o.index));
53 }
54};
55
56} // namespace
57
58namespace b2000 {
59
90template <typename T = uint64_t>
92 const double delta, const bool delta_relative, const size_t n, const double* coor,
93 std::vector<size_t>& coincide) {
94 assert(delta > 0);
95
96 coincide.clear();
97
98 // Special case.
99 if (n == 0) { return; }
100
101 coincide.reserve(n);
102 for (size_t i = 0; i != n; ++i) { coincide.push_back(i); }
103
104 // Get axis-aligned bounding box.
105 assert(n > 0);
106 double bb_min[3] = {coor[0], coor[1], coor[2]};
107 double bb_max[3] = {coor[0], coor[1], coor[2]};
108 for (size_t i = 3; i != 3 * n; ++i) {
109 size_t j = i % 3;
110 if (coor[i] < bb_min[j]) { bb_min[j] = coor[i]; }
111 if (coor[i] > bb_max[j]) { bb_max[j] = coor[i]; }
112 }
113
114 // Calculate the maximum distance in each direction by which two
115 // "coinciding" points may be separated.
116 double delta_abs = delta;
117 if (delta_relative) {
118 const double bb_extent[3] = {
119 bb_max[0] - bb_min[0], bb_max[1] - bb_min[1], bb_max[2] - bb_min[2]};
120
121 const double bb_extent_max = std::max(bb_extent[0], std::max(bb_extent[1], bb_extent[2]));
122
123 delta_abs = bb_extent_max * delta;
124 }
125 const double delta_abs_2 = delta_abs * delta_abs;
126
127 // The size of the boxes must be twice as large.
128 const double box_size = 2 * delta_abs;
129
130 std::vector<Point> points(n, Point());
131
132 // First pass.
133 double box_start_a[3] = {bb_min[0], bb_min[1], bb_min[2]};
134 for (size_t i = 0; i != n; ++i) {
135 Point& p = points[i];
136 p.index = i;
137 for (int j = 0; j != 3; ++j) {
138 p.signature.d[j] = T((coor[3 * i + j] - box_start_a[j]) / box_size);
139 }
140 }
141 std::sort(points.begin(), points.end());
142 for (size_t i = 0; i + 1 < n;) {
143 const size_t j = i++;
144 for (; i < n; ++i) {
145 if (points[i].signature != points[j].signature) { break; }
146 const size_t ii = points[i].index;
147 const size_t jj = points[j].index;
148 const double* ci = &coor[3 * ii];
149 const double* cj = &coor[3 * jj];
150 const double d[3] = {ci[0] - cj[0], ci[1] - cj[1], ci[2] - cj[2]};
151 if (coincide[ii] == ii && d[0] * d[0] + d[1] * d[1] + d[2] * d[2] < delta_abs_2) {
152 coincide[ii] = coincide[jj];
153 }
154 }
155 }
156
157 // Second pass with offset boxes.
158 double box_start_b[3] = {
159 bb_min[0] + 0.5 * box_size, bb_min[1] + 0.5 * box_size, bb_min[2] + 0.5 * box_size};
160 for (size_t i = 0; i != n; ++i) {
161 Point& p = points[i];
162 p.index = i;
163 for (int j = 0; j != 3; ++j) {
164 p.signature.d[j] = T((coor[3 * i + j] - box_start_b[j]) / box_size);
165 }
166 }
167 std::sort(points.begin(), points.end());
168 for (size_t i = 0; i + 1 < n;) {
169 const size_t j = i++;
170 for (; i < n; ++i) {
171 if (points[i].signature != points[j].signature) { break; }
172 const size_t ii = points[i].index;
173 const size_t jj = points[j].index;
174 const double* ci = &coor[3 * ii];
175 const double* cj = &coor[3 * jj];
176 const double d[3] = {ci[0] - cj[0], ci[1] - cj[1], ci[2] - cj[2]};
177 if (coincide[ii] == ii && d[0] * d[0] + d[1] * d[1] + d[2] * d[2] < delta_abs_2) {
178 coincide[ii] = coincide[jj];
179 }
180 }
181 }
182
183 // Resolve transitive relations due to the second pass.
184 for (size_t i = 0; i != n; ++i) { coincide[i] = coincide[coincide[i]]; }
185}
186
218template <typename T = uint64_t>
220 const double delta, const bool delta_relative, const size_t n, const double* coor,
221 std::vector<std::pair<size_t, size_t> >& coincide) {
222 coincide.clear();
223
224 std::vector<size_t> vcoincide;
225 find_coinciding_points<T>(delta, delta_relative, n, coor, vcoincide);
226
227 assert(vcoincide.size() == n);
228 coincide.reserve(n);
229 for (size_t i = 0; i != n; ++i) {
230 coincide.push_back(std::pair<size_t, size_t>(vcoincide[i], i));
231 }
232 std::sort(coincide.begin(), coincide.end());
233}
234
235} // namespace b2000
236
237#endif /* _B2_FIND_COINCIDING_POINTS_H_ */
bool operator==(const csda< T1 > &a, const csda< T2 > &b)
Comparison of two csda numbers is performed on the real part only.
Definition b2csda.H:226
bool operator!=(const csda< T1 > &a, const csda< T2 > &b)
Comparison of two csda numbers is performed on the real part only.
Definition b2csda.H:244
bool operator<(const csda< T1 > &a, const csda< T2 > &b)
Comparison of two csda numbers is performed on the real part only.
Definition b2csda.H:262
Definition b2beam_cross_sections.H:102
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32
void find_coinciding_points(const double delta, const bool delta_relative, const size_t n, const double *coor, std::vector< size_t > &coincide)
Definition b2find_coinciding_points.H:91