File: gridTriangleCenter.h

package info (click to toggle)
groops 0%2Bgit20250907%2Bds-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 11,140 kB
  • sloc: cpp: 135,607; fortran: 1,603; makefile: 20
file content (191 lines) | stat: -rw-r--r-- 6,387 bytes parent folder | download | duplicates (2)
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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/***********************************************/
/**
* @file gridTriangleCenter.h
*
* @brief Triangle grid (center points).
* @see Grid
*
* @author Torsten Mayer-Guerr
* @date 2002-05-31
*
*/
/***********************************************/

#ifndef __GROOPS_GRIDTRIANGLECENTER__
#define __GROOPS_GRIDTRIANGLECENTER__

// Latex documentation
#ifdef DOCSTRING_Grid
static const char *docstringGridTriangleCenter = R"(
\subsection{TriangleCenter}
The points of the zeroth level are located at the centers of the icosahedron triangles.
To achieve a finer grid, each of the triangles is divided into four smaller triangles by
connecting the midpoints of the triangle edges. The refined grid points are again located
at the center of the triangles. Subsequently, the triangles can be further densified up to
the desired level of densification $n$, which is defined by \config{level}.

The number of global grid points for a certain level can be determined by
\begin{equation}\label{eq:numberCenter}
I=20\cdot 4^n.
\end{equation}
Thus the quantity of grid points depends exponentially on the level $n$, as with
every additional level the number of grid points quadruplicates.
)";
#endif

/***********************************************/

#include "base/import.h"
#include "config/config.h"
#include "classes/border/border.h"
#include "classes/grid/grid.h"

/***** CLASS ***********************************/

/** @brief Triangle grid (center points).
* @ingroup gridGroup
* @see Grid */
class GridTriangleCenter : public GridBase
{
public:
  GridTriangleCenter(Config &config);
};

/***********************************************/

class Triangle
{
  Vector3d p1, p2, p3; // Eckpunkte
  public:
    Triangle() {}
    Triangle(Vector3d _p1, Vector3d _p2, Vector3d _p3) : p1(_p1), p2(_p2), p3(_p3) {}
    // Durch Halbieren der Seiten 4 neue Dreiecke erzeugen
    void divide(Triangle &d1, Triangle &d2, Triangle &d3, Triangle &d4) const;
    // Schwerpunkt des Dreiecks
    Vector3d center() const {return normalize(p1+p2+p3);}
    // Flaeche des Dreiecks
    Double   area() const;
};

/***********************************************/

inline void Triangle::divide(Triangle &d1, Triangle &d2, Triangle &d3, Triangle &d4) const
{
  Vector3d p12 = normalize(p1+p2);
  Vector3d p23 = normalize(p2+p3);
  Vector3d p31 = normalize(p3+p1);

  d1 = Triangle(p1, p12, p31);
  d2 = Triangle(p2, p23, p12);
  d3 = Triangle(p3, p31, p23);
  d4 = Triangle(p12,p23, p31);
}

/***********************************************/

inline Double Triangle::area() const
{
  Vector3d e1 = normalize(crossProduct(p1,p2));
  Vector3d e2 = normalize(crossProduct(p2,p3));
  Vector3d e3 = normalize(crossProduct(p3,p1));

  Double w1 = PI-std::acos(inner(e1,e2));
  Double w2 = PI-std::acos(inner(e2,e3));
  Double w3 = PI-std::acos(inner(e3,e1));

  return w1+w2+w3-PI;
}

/***********************************************/

// Einen Vector von Dreiecken unterteilen
// und 4mal soviel kleinere Dreiecke zurueckliefern
inline std::vector<Triangle> divide(const std::vector<Triangle> &triangle)
{
  std::vector<Triangle> small(4*triangle.size());

  for(UInt i=0; i<triangle.size(); i++)
    triangle.at(i).divide(small.at(4*i), small.at(4*i+1), small.at(4*i+2), small.at(4*i+3));

  return small;
}

/***********************************************/
/***********************************************/

inline GridTriangleCenter::GridTriangleCenter(Config &config)
{
  try
  {
    UInt      level;
    Double    a, f;
    BorderPtr border;

    readConfig(config, "level",             level,      Config::MUSTSET,  "",                     "division of icosahedron, point count = 5*4**(n+1)");
    readConfig(config, "R",                 a,          Config::DEFAULT,  STRING_DEFAULT_GRS80_a, "major axsis of the ellipsoid/sphere");
    readConfig(config, "inverseFlattening", f,          Config::DEFAULT,  STRING_DEFAULT_GRS80_f, "flattening of the ellipsoid, 0: sphere");
    readConfig(config, "border",            border,     Config::DEFAULT,  "",                     "");
    if(isCreateSchema(config)) return;

    // Create global icosaedron grid
    // ----------------------------
    // 12 vertexes of icosaedron
    std::vector<Vector3d> p0(12);
    Double phi  = PI/2.0-acos((cos(72*DEG2RAD)+cos(72*DEG2RAD)*cos(72*DEG2RAD))/(sin(72*DEG2RAD)*sin(72*DEG2RAD)));
    p0.at(0)  = polar(Angle(  0.0*DEG2RAD), Angle( 90*DEG2RAD), 1.0);
    p0.at(1)  = polar(Angle(  0.0*DEG2RAD), Angle( phi), 1.0);
    p0.at(2)  = polar(Angle( 72.0*DEG2RAD), Angle( phi), 1.0);
    p0.at(3)  = polar(Angle(144.0*DEG2RAD), Angle( phi), 1.0);
    p0.at(4)  = polar(Angle(216.0*DEG2RAD), Angle( phi), 1.0);
    p0.at(5)  = polar(Angle(288.0*DEG2RAD), Angle( phi), 1.0);
    p0.at(6)  = polar(Angle( 36.0*DEG2RAD), Angle(-phi), 1.0);
    p0.at(7)  = polar(Angle(108.0*DEG2RAD), Angle(-phi), 1.0);
    p0.at(8)  = polar(Angle(180.0*DEG2RAD), Angle(-phi), 1.0);
    p0.at(9)  = polar(Angle(252.0*DEG2RAD), Angle(-phi), 1.0);
    p0.at(10) = polar(Angle(324.0*DEG2RAD), Angle(-phi), 1.0);
    p0.at(11) = polar(Angle(  0.0*DEG2RAD), Angle(-90*DEG2RAD), 1.0);

    // 3 vertexes of 20 triangles
    const UInt tri[20][3] = {{0,1,2},{0,2,3},{0,3,4},{0,4,5},{0,5,1},
                             {2,1,6},{3,2,7},{4,3,8},{5,4,9},{1,5,10},
                             {6,7,2},{7,8,3},{8,9,4},{9,10,5},{10,6,1},
                             {11,7,6},{11,8,7},{11,9,8},{11,10,9},{11,6,10}};

    // create triangles of the icosahedron
    std::vector<Triangle> triangle(20);
    for(UInt i=0; i<20; i++)
      triangle.at(i) = Triangle(p0.at(tri[i][0]), p0.at(tri[i][1]), p0.at(tri[i][2]));

    // divide triangles
    for(UInt i=0; i<level; i++)
      triangle = divide(triangle);

    // create points
    Ellipsoid ellipsoid(a,f);
    for(UInt i=0; i<triangle.size(); i++)
    {
      Vector3d point = triangle.at(i).center();
      // from sphere to ellipsoidal surface
      Double r = ellipsoid.b()/sqrt(1-ellipsoid.e()*ellipsoid.e()*cos(point.phi())*cos(point.phi()));
      point *= r;

      Angle  L,B;
      Double h;
      ellipsoid(point, L,B,h);

      if(border->isInnerPoint(L,B))
      {
        points.push_back(point);
        areas.push_back(triangle.at(i).area());
      }
    }
  }
  catch(std::exception &e)
  {
    GROOPS_RETHROW(e)
  }
}

/***********************************************/

#endif /* __GROOPS__ */