1 /**
2 * UGENE - Integrated Bioinformatics Tools.
3 * Copyright (C) 2008-2021 UniPro <ugene@unipro.ru>
4 * http://ugene.net
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #include "GeomUtils.h"
23
24 namespace U2 {
25
26 QScopedPointer<QVector<Vector3D>> GeodesicSphere::elementarySphere(nullptr);
27 int GeodesicSphere::currentDetailLevel = 1;
28
GeodesicSphere(const Vector3D & center,float radius,int detaillevel)29 GeodesicSphere::GeodesicSphere(const Vector3D ¢er, float radius, int detaillevel) {
30 if (elementarySphere.isNull() || currentDetailLevel != detaillevel) {
31 elementarySphere.reset(createGeodesicSphere(detaillevel));
32 currentDetailLevel = detaillevel;
33 }
34
35 QVector<Vector3D> normals;
36 vertices.resize(elementarySphere->count());
37 std::copy(elementarySphere->begin(), elementarySphere->end(), vertices.begin());
38
39 int size = vertices.count();
40 for (int i = 0; i < size; ++i) {
41 Vector3D &vertex = vertices[i];
42 vertex.normalize();
43 normals.append(vertex);
44 vertex *= radius;
45 vertex += center;
46 }
47
48 for (int i = 0; i < size; i += 3) {
49 Face face;
50 face.v[0] = vertices.at(i);
51 face.v[1] = vertices.at(i + 1);
52 face.v[2] = vertices.at(i + 2);
53
54 face.n[0] = normals.at(i);
55 face.n[1] = normals.at(i + 1);
56 face.n[2] = normals.at(i + 2);
57
58 faces.append(face);
59 }
60 }
61
interpolate(const Vector3D & v1,const Vector3D & v2,const Vector3D & v3,QVector<Vector3D> * v,int detailLevel)62 void GeodesicSphere::interpolate(const Vector3D &v1, const Vector3D &v2, const Vector3D &v3, QVector<Vector3D> *v, int detailLevel) {
63 if (0 == detailLevel) {
64 v->append(v1);
65 v->append(v2);
66 v->append(v3);
67 return;
68 }
69
70 Vector3D nv1((v1.x + v2.x) / 2, (v1.y + v2.y) / 2, (v1.z + v2.z) / 2);
71 Vector3D nv2((v2.x + v3.x) / 2, (v2.y + v3.y) / 2, (v2.z + v3.z) / 2);
72 Vector3D nv3((v3.x + v1.x) / 2, (v3.y + v1.y) / 2, (v3.z + v1.z) / 2);
73 interpolate(nv1, nv2, nv3, v, detailLevel - 1);
74 interpolate(v1, nv1, nv3, v, detailLevel - 1);
75 interpolate(nv1, v2, nv2, v, detailLevel - 1);
76 interpolate(nv3, nv2, v3, v, detailLevel - 1);
77 }
78
createGeodesicSphere(int detailLevel)79 QVector<Vector3D> *GeodesicSphere::createGeodesicSphere(int detailLevel) {
80 QVector<Vector3D> base;
81 base.resize(24);
82
83 // up
84 base[0] = Vector3D(-1.0f, 0.0f, 0.0f);
85 base[1] = Vector3D(0.0f, 1.0f, 0.0f);
86 base[2] = Vector3D(0.0f, 0.0f, -1.0f);
87
88 base[3] = Vector3D(0.0f, 0.0f, -1.0f);
89 base[4] = Vector3D(0.0f, 1.0f, 0.0f);
90 base[5] = Vector3D(1.0f, 0.0f, 0.0f);
91
92 base[6] = Vector3D(1.0f, 0.0f, 0.0f);
93 base[7] = Vector3D(0.0f, 1.0f, 0.0f);
94 base[8] = Vector3D(0.0f, 0.0f, 1.0f);
95
96 base[9] = Vector3D(0.0f, 0.0f, 1.0f);
97 base[10] = Vector3D(0.0f, 1.0f, 0.0f);
98 base[11] = Vector3D(-1.0f, 0.0f, 0.0f);
99
100 // down
101 base[12] = Vector3D(-1.0f, 0.0f, 0.0f);
102 base[13] = Vector3D(0.0f, 0.0f, -1.0f);
103 base[14] = Vector3D(0.0f, -1.0f, 0.0f);
104
105 base[15] = Vector3D(0.0f, 0.0f, -1.0f);
106 base[16] = Vector3D(1.0f, 0.0f, 0.0f);
107 base[17] = Vector3D(0.0f, -1.0f, 0.0f);
108
109 base[18] = Vector3D(1.0f, 0.0f, 0.0f);
110 base[19] = Vector3D(0.0f, 0.0f, 1.0f);
111 base[20] = Vector3D(0.0f, -1.0f, 0.0f);
112
113 base[21] = Vector3D(0.0f, 0.0f, 1.0f);
114 base[22] = Vector3D(-1.0f, 0.0f, 0.0f);
115 base[23] = Vector3D(0.0f, -1.0f, 0.0f);
116
117 QVector<Vector3D> *v = new QVector<Vector3D>();
118 for (int i = 0; i < 24; i += 3) {
119 interpolate(base.at(i), base.at(i + 1), base.at(i + 2), v, detailLevel);
120 }
121
122 return v;
123 }
124
125 } // namespace U2
126