File: gridTriangleVertex.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-- 7,148 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 gridTriangleVertex.h
*
* @brief Triangle grid (Vertcies)
* @see Grid
*
* @author Torsten Mayer-Guerr
* @date 2002-05-31
*
*/
/***********************************************/

#ifndef __GROOPS_GRIDTRIANGLEVERTEX__
#define __GROOPS_GRIDTRIANGLEVERTEX__

// Latex documentation
#ifdef DOCSTRING_Grid
static const char *docstringGridTriangleVertex = R"(
\subsection{TriangleVertex}
The zeroth level of densification
coincides with the 12 icosahedron vertices, as displayed in the upper left part
of Fig.~\ref{fig:triangle_grid}. Then, depending on the envisaged densification,
each triangle edge is divided into $n$ parts, illustrated in the upper right
part of Fig.~\ref{fig:triangle_grid}. The new nodes on the edges are then connected
by arcs of great circles parallel to the triangle edges. The intersections of
each three corresponding parallel lines become nodes of the densified grid as well.
As in case of a spherical triangle those three connecting lines do not exactly
intersect in one point, the center of the resulting triangle is used as location
for the new node (lower left part of Fig.~\ref{fig:triangle_grid}). The lower right
side of Fig.~\ref{fig:triangle_grid} finally shows the densified triangle vertex
grid for a level of $n=3$. The number of grid points in dependence of the chosen
level of densification can be calculated by
\begin{equation}\label{eq:numberVertex}
I=10\cdot(n+1)^2+2.
\end{equation}

\fig{!hb}{0.6}{icogrid}{fig:triangle_grid}{TriangleVertex grid.}
)";
#endif

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

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

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

/** @brief Triangle grid (Vertcies).
* @ingroup gridGroup
* @see Grid */
class GridTriangleVertex : public GridBase
{
  static void divideEdge(Vector3d p1, Vector3d p2, UInt level, std::vector<Vector3d> &points);
  static void divideTriangle(Vector3d p1, Vector3d p2, Vector3d p3, UInt level, std::vector<Vector3d> &points);

public:
  GridTriangleVertex(Config &config);
};

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

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

    readConfig(config, "level",             level,      Config::MUSTSET,  "",                     "division of icosahedron, point count = 10*(n+1)**2+2");
    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}};

    // start and end vertex of 30 edges
    const UInt edge[30][2] = {{0,1},{0,2},{0,3},{0,4},{0,5},
                              {1,2},{2,3},{3,4},{4,5},{5,1},
                              {1,6},{2,7},{3,8},{4,9},{5,10},
                              {6,2},{7,3},{8,4},{9,5},{10,1},
                              {6,7},{7,8},{8,9},{9,10},{10,6},
                              {11,6},{11,7},{11,8},{11,9},{11,10}};

    // divides edges
    for(UInt i=0; i<30; i++)
      divideEdge(p0.at(edge[i][0]), p0.at(edge[i][1]), level, p0);

    // create inner points
    for(UInt i=0; i<20; i++)
      divideTriangle( p0.at(tri[i][0]), p0.at(tri[i][1]), p0.at(tri[i][2]), level, p0);

    // p0 contain now the global point distribution on unit sphere

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

      Angle  L,B;
      Double h;
      ellipsoid(p0.at(i), L,B,h);

      if(border->isInnerPoint(L,B))
      {
        points.push_back(p0.at(i));
        areas.push_back(4*PI / p0.size());
      }
    }
  }
  catch(std::exception &e)
  {
    GROOPS_RETHROW(e)
  }
}

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

// Erzeugt level gleichabstandige Punkte zwischen Anfpkt und Endpkt
inline void GridTriangleVertex::divideEdge(Vector3d p1, Vector3d p2, UInt level, std::vector<Vector3d> &points)
{
  Double psi = acos(inner(p1, p2))/(level+1);

  Vector3d pPerpendicular = normalize(crossProduct(crossProduct(p1, p2), p1));

  for(UInt i=1; i<=level; i++)
    points.push_back( cos(i*psi)*p1 + sin(i*psi)*pPerpendicular );
}

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

// Innere Punkte im Dreieck erzeugen
inline void GridTriangleVertex::divideTriangle(Vector3d p1, Vector3d p2, Vector3d p3, UInt level, std::vector<Vector3d> &points)
{
  std::vector<Vector3d> edge1, edge2, edge3;

  divideEdge(p1, p2, level, edge1);
  divideEdge(p2, p3, level, edge2);
  divideEdge(p3, p1, level, edge3);

  // innere punkte erzeugen
  for(UInt i=1; i<level; i++)
    for(UInt k=0; k<i; k++)
    {
      // Verbindungsgraden erzeugen
      Vector3d line13 = crossProduct(edge1.at(i),     edge3.at(level-1-i));
      Vector3d line12 = crossProduct(edge1.at(i-1-k), edge2.at(level-i+k));
      Vector3d line23 = crossProduct(edge2.at(k),     edge3.at(level-1-k));

      // Geraden schneiden (Schnittpunkt)
      Vector3d p1 = normalize(crossProduct(line13, line12));
      Vector3d p2 = normalize(crossProduct(line23, line13));
      Vector3d p3 = normalize(crossProduct(line23, line12));

      // Punkte mitteln
      Vector3d pMean = normalize(p1 + p2 + p3);
      points.push_back( -pMean );
    }
}

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

#endif /* __GROOPS__ */