File: Bubbles.cpp

package info (click to toggle)
gmsh 4.8.4%2Bds2-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 87,812 kB
  • sloc: cpp: 378,014; ansic: 99,669; yacc: 7,216; python: 6,680; java: 3,486; lisp: 659; lex: 621; perl: 571; makefile: 470; sh: 440; xml: 415; javascript: 113; pascal: 35; modula3: 32
file content (174 lines) | stat: -rw-r--r-- 5,405 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// Gmsh - Copyright (C) 1997-2021 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// issues on https://gitlab.onelab.info/gmsh/gmsh/issues.

#include <stdlib.h>
#include "GmshGlobal.h"
#include "GModel.h"
#include "MTriangle.h"
#include "Numeric.h"
#include "Bubbles.h"
#include "OS.h"

StringXNumber BubblesOptions_Number[] = {
  {GMSH_FULLRC, "ShrinkFactor", nullptr, 0.},
};

StringXString BubblesOptions_String[] = {
  {GMSH_FULLRC, "OutputFile", nullptr, "bubbles.geo"}};

extern "C" {
GMSH_Plugin *GMSH_RegisterBubblesPlugin() { return new GMSH_BubblesPlugin(); }
}

std::string GMSH_BubblesPlugin::getHelp() const
{
  return "Plugin(Bubbles) constructs a geometry consisting of "
         "`bubbles' inscribed in the Voronoi of an input triangulation. "
         "`ShrinkFactor' allows to change the size of the bubbles. "
         "The plugin expects a triangulation in the `z = 0' plane to exist "
         "in the current model.\n\n"
         "Plugin(Bubbles) creates one `.geo' file.";
}

int GMSH_BubblesPlugin::getNbOptions() const
{
  return sizeof(BubblesOptions_Number) / sizeof(StringXNumber);
}

StringXNumber *GMSH_BubblesPlugin::getOption(int iopt)
{
  return &BubblesOptions_Number[iopt];
}

int GMSH_BubblesPlugin::getNbOptionsStr() const
{
  return sizeof(BubblesOptions_String) / sizeof(StringXString);
}

StringXString *GMSH_BubblesPlugin::getOptionStr(int iopt)
{
  return &BubblesOptions_String[iopt];
}

static double myangle(double c[3], double p[3])
{
  double v[3] = {1, 0, 0};
  double n[3] = {0, 0, 1};
  if(fabs(c[0] - p[0]) < 1e-12 && fabs(c[1] - p[1]) < 1e-12 &&
     fabs(c[2] - p[2]) < 1e-12)
    return 0.;
  return angle_plan(c, v, p, n);
}

class compareAngle {
private:
  SPoint3 v;

public:
  compareAngle(const SPoint3 &vv) : v(vv) {}
  bool operator()(const SPoint3 &b1, const SPoint3 &b2)
  {
    double p1[3] = {b1.x(), b1.y(), b1.z()};
    double p2[3] = {b2.x(), b2.y(), b2.z()};
    double c[3] = {v.x(), v.y(), v.z()};

    return myangle(c, p1) < myangle(c, p2);
  }
};

PView *GMSH_BubblesPlugin::execute(PView *v)
{
  double shrink = (double)BubblesOptions_Number[0].def;
  std::string fileName = BubblesOptions_String[0].def;

  FILE *fp = Fopen(fileName.c_str(), "w");
  if(!fp) {
    Msg::Error("Could not open output file '%s'", fileName.c_str());
    return v;
  }

  GModel *m = GModel::current();

  int p = m->getMaxElementaryNumber(0) + 1;
  int l = m->getMaxElementaryNumber(1) + 1;
  int s = m->getMaxElementaryNumber(2) + 1;
  int ll = s, ps = 1;

  SBoundingBox3d bbox = m->bounds();
  double lc = norm(SVector3(bbox.max(), bbox.min())) / 100;
  fprintf(fp, "lc = %g;\n", lc);

  for(auto vit = m->firstVertex(); vit != m->lastVertex(); vit++)
    (*vit)->writeGEO(fp, "lc");

  for(auto eit = m->firstEdge(); eit != m->lastEdge(); eit++)
    (*eit)->writeGEO(fp);

  for(auto fit = m->firstFace(); fit != m->lastFace(); fit++) {
    (*fit)->writeGEO(fp);
    fprintf(fp, "Delete { Surface {%d}; }\n", (*fit)->tag());

    int sbeg = s;
    int llbeg = ll;

    // compute vertex-to-triangle_barycenter map
    std::map<MVertex *, std::vector<SPoint3> > v2t;
    for(std::size_t i = 0; i < (*fit)->triangles.size(); i++)
      for(int j = 0; j < 3; j++)
        v2t[(*fit)->triangles[i]->getVertex(j)].push_back(
          (*fit)->triangles[i]->barycenter());

    // add boundary vertices in map to get cells "closer" to the boundary
    for(auto it = v2t.begin(); it != v2t.end(); it++) {
      MVertex *v = it->first;
      if(v->onWhat() && v->onWhat()->dim() < 2)
        it->second.push_back(
          SPoint3(it->first->x(), it->first->y(), it->first->z()));
    }

    for(auto it = v2t.begin(); it != v2t.end(); it++) {
      if(it->second.size() > 2) {
        // get barycenter of cell boundary points and order them
        SPoint3 bc;
        for(std::size_t i = 0; i < it->second.size(); i++) bc += it->second[i];
        bc *= 1. / (double)it->second.size();
        compareAngle comp(bc);
        std::sort(it->second.begin(), it->second.end(), comp);
        // shrink cells
        if(shrink) {
          for(std::size_t i = 0; i < it->second.size(); i++) {
            double dir[3] = {it->second[i].x() - bc.x(),
                             it->second[i].y() - bc.y(),
                             it->second[i].z() - bc.z()};
            it->second[i][0] -= shrink * dir[0];
            it->second[i][1] -= shrink * dir[1];
            it->second[i][2] -= shrink * dir[2];
          }
        }
        // create b-spline bounded surface for each cell
        int nump = it->second.size();
        for(int i = 0; i < nump; i++) {
          SPoint3 &b(it->second[i]);
          fprintf(fp, "Point(%d) = {%.16g, %.16g, %.16g, lc};\n", p++, b.x(),
                  b.y(), b.z());
        }
        fprintf(fp, "BSpline(%d) = {", l++);
        for(int i = nump - 1; i >= 0; i--) fprintf(fp, "%d,", p - i - 1);
        fprintf(fp, "%d};\n", p - nump);
        fprintf(fp, "Line Loop(%d) = {%d};\n", ll++, l - 1);
        fprintf(fp, "Plane Surface(%d) = {%d};\n", s++, ll - 1);
      }
    }
    fprintf(fp, "Physical Surface(%d) = {%d:%d};\n", ps++, sbeg, s - 1);

    fprintf(fp, "Plane Surface(%d) = {%d, %d:%d};\n", s++, (*fit)->tag(), llbeg,
            ll - 1);
    fprintf(fp, "Physical Surface(%d) = {%d};\n", ps++, s - 1);
  }

  fclose(fp);

  return v;
}