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 &center, 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