9 #include <unordered_map>
16 #if defined(HAVE_QUADMESHINGTOOLS)
17 #include "qmtMeshGeometryOptimization.h"
18 #include "qmtMeshUtils.h"
50 if(fabs(
dot(t1, t2)) > 0.95) {
54 else if(fabs(
dot(t1, t2)) > 0.5) {
62 static void printLabelling(
const char *fn,
PolyMesh *pm,
63 std::unordered_map<PolyMesh::Vertex *, int> &_labels)
66 FILE *
f = fopen(fn,
"w");
67 fprintf(
f,
"View \"labels\"{\n");
69 fprintf(
f,
"SP(%g,%g,%g){%d};\n",
v->position.x(),
v->position.y(),
70 v->position.z(), _labels[
v]);
84 for(
auto face : pm->
faces) {
93 if((l0 == 0 && l1 == 0 && l2 == 0) || (l0 == 1 && l1 == 1 && l2 == 1))
98 fprintf(
f,
"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%d,%d,%d};\n",
104 fprintf(
f,
"SQ(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g){%d,%d,%d,%d};\n",
145 Msg::Debug(
"Quadrangulation of face %d using Bipartite Labelling", faceTag);
147 printf(
"%d Quadrangulation of face\n", faceTag);
149 printf(
"%d Transfer to Half Edge done\n", faceTag);
150 if(result == -1)
return;
151 std::queue<PolyMesh::Vertex *> _queue;
152 std::unordered_map<PolyMesh::Vertex *, int> _labels;
153 std::unordered_map<PolyMesh::Vertex *, SVector3> _dirs;
161 if(_labels[
v] == -1 && pm->
degree(
v) == -1) {
164 bool currentLabel =
true;
165 _labels[
v] = currentLabel;
167 size_t nodeCount = 0;
173 if(_labels[he->
v] != -1)
break;
174 currentLabel = !currentLabel;
175 _labels[he->
v] = currentLabel;
181 if(nodeCount % 2 != 0) {
182 Msg::Warning(
"Bipartite algorithm requires an even numer of boundary"
183 " vertices on every edge loop that bounds face %d. This "
184 "loop has %d nodes and some triangles will remain.",
190 printf(
"%d Initial labelling done\n", faceTag);
192 while(!_queue.empty()) {
194 auto v = _queue.front();
196 bool currentLabel = _labels[
v];
200 computeNaturalCross(
v, n, t1, t2);
203 double dot_max = 0.0;
209 if(_labels[he->
next->
v] == -1) {
210 double dd = std::max(fabs(
dot(t1, t)), fabs(
dot(t2, t)));
218 if(best && dot_max > 0.9) {
222 _dirs[best->
next->
v] = best->
d();
223 _labels[best->
next->
v] = !currentLabel;
224 _queue.push(best->
next->
v);
232 std::vector<std::pair<double, PolyMesh::HalfEdge *> > bests;
236 double dd = -std::max(fabs(
dot(t1, t)), fabs(
dot(t2, t)));
237 bests.push_back(std::make_pair(dd, he));
240 }
while(he !=
v->he);
242 std::sort(bests.begin(), bests.end());
245 for(
auto it : bests) {
246 if(count++ > 3)
break;
248 if(_labels[best->
next->
v] == -1) {
250 _dirs[best->
next->
v] = best->
d();
251 _labels[best->
next->
v] = !currentLabel;
252 _queue.push(best->
next->
v);
259 printf(
"%d internal labelling done\n", faceTag);
262 bool changed =
false;
263 printLabelling(
"labelling_initial.pos", pm, _labels);
269 int myIndex = _labels[
v];
270 if(myIndex == -1) { _labels[
v] = myIndex = 1; }
271 int oppositeIndex = (myIndex == 1) ? 0 : 1;
274 l.push_back(_labels[he->
next->
v]);
276 }
while(he !=
v->he);
277 int nbInvalidBefore = 0;
278 int nbInvalidAfter = 0;
279 for(
size_t i = 0; i < l.size(); i++) {
281 int i1 = l[(i + 1) % l.size()];
282 if(i0 == i1 && i0 == myIndex) nbInvalidBefore++;
283 if(i0 == i1 && i0 == oppositeIndex) nbInvalidAfter++;
285 if(nbInvalidBefore > nbInvalidAfter) {
287 _labels[
v] = oppositeIndex;
293 printLabelling(
"labelling_final.pos", pm, _labels);
295 printf(
"%d optimum labelling done\n", faceTag);
299 for(
auto he : pm->
hedges) {
305 int l0 = _labels[v0];
306 int l1 = _labels[v1];
307 int l2 = _labels[v2];
308 int l3 = _labels[v3];
309 if(l0 == l1 && l0 == l2 && l0 == l3) {
315 else if(l0 == l1 && l0 == l2) {
324 printf(
"%d steiner points added\n", faceTag);
326 printLabelling(
"labelling_final_split.pos", pm, _labels);
328 for(
auto he : pm->
hedges) {
329 if(he->
v !=
nullptr && he->
opposite !=
nullptr) {
332 int l0 = _labels[v0];
333 int l1 = _labels[v1];
339 printLabelling(
"labelling_final_split_quad.pos", pm, _labels);
341 printf(
"%d quads created\n", faceTag);
345 printf(
"%d 2 gmsh done\n", faceTag);
360 Msg::Error(
"This requires quad meshing tools");