1 /*
2 * ***************************************************************************
3 * GAMER = < Geometry-preserving Adaptive MeshER >
4 * Copyright (C) 2007-2010 -- Michael Holst and Johan Hake
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * ***************************************************************************
20 */
21
22 /* ***************************************************************************
23 * File: SurfaceMesh.C < ... >
24 *
25 * Author: Johan Hake (hake.dev@gmail.com)
26 *
27 * Purpose: Create and destroy SurfaceMesh data
28 * ****************************************************************************
29 */
30
31 #include <gamer/biom.h>
32 #include "gamercf.h"
33
34 /*
35 * ***************************************************************************
36 * Routine: SurfaceMesh_ctor
37 *
38 * Author: Johan Hake (hake.dev@gmail.com)
39 *
40 * Purpose: Create a surface mesh instance
41 * ***************************************************************************
42 */
SurfaceMesh_ctor(unsigned int num_vertices,unsigned int num_faces)43 SurfaceMesh* SurfaceMesh_ctor(unsigned int num_vertices, unsigned int num_faces)
44 {
45 // Allocate memory and initialize variables
46 SurfaceMesh* surfmesh= (SurfaceMesh*)malloc(sizeof(SurfaceMesh));
47 surfmesh->nv = num_vertices;
48 surfmesh->nf = num_faces;
49 surfmesh->vertex = (FLTVECT*)malloc(sizeof(FLTVECT)*surfmesh->nv);
50 surfmesh->face = (INT3VECT*)malloc(sizeof(INT3VECT)*surfmesh->nf);
51 surfmesh->neighbor = NULL;
52 surfmesh->neighbor_list = NULL;
53 surfmesh->avglen = 0.;
54 surfmesh->min[0] = 0.; surfmesh->min[1] = 0.; surfmesh->min[2] = 0.;
55 surfmesh->max[0] = 0.; surfmesh->max[1] = 0.; surfmesh->max[2] = 0.;
56 surfmesh->nvm = 0;
57 surfmesh->nfm = 0;
58 surfmesh->vertex_markers = NULL;
59 surfmesh->face_markers = NULL;
60
61 return surfmesh;
62 }
63
64 /*
65 * ***************************************************************************
66 * Routine: SurfaceMesh_dtor
67 *
68 * Author: Johan Hake (hake.dev@gmail.com)
69 *
70 * Purpose: Release memory from a SurfaceMesh instance
71 * ***************************************************************************
72 */
SurfaceMesh_dtor(SurfaceMesh * surfmesh)73 void SurfaceMesh_dtor(SurfaceMesh* surfmesh)
74 {
75 // Relase data memory
76 SurfaceMesh_releaseData(surfmesh);
77
78 // Release memory for the SurfaceMesh struct
79 free(surfmesh);
80 }
81
82 /*
83 * ***************************************************************************
84 * Routine: SurfaceMesh_releaseData
85 *
86 * Author: Johan Hake (hake.dev@gmail.com)
87 *
88 * Purpose: Release data memory from a SurfaceMesh instance
89 * ***************************************************************************
90 */
SurfaceMesh_releaseData(SurfaceMesh * surfmesh)91 void SurfaceMesh_releaseData(SurfaceMesh* surfmesh)
92 {
93 // Free allocated memory
94 free(surfmesh->vertex);
95 free(surfmesh->face);
96
97 // Destroy neighbor_list
98 SurfaceMesh_destroyNeighborlist(surfmesh);
99
100 // Destroy marker lists
101 SurfaceMesh_destroyVertexMarkers(surfmesh);
102 SurfaceMesh_destroyFaceMarkers(surfmesh);
103
104 }
105
106 /*
107 * ***************************************************************************
108 * SubRoutine: SurfaceMesh_createVertexMarkers
109 *
110 * Author: Johan Hake (hake.dev@gmail.com)
111 *
112 * Purpose: Create an array for vertex markers
113 * ***************************************************************************
114 */
SurfaceMesh_createVertexMarkers(SurfaceMesh * surfmesh)115 void SurfaceMesh_createVertexMarkers(SurfaceMesh* surfmesh)
116 {
117 if (surfmesh->vertex_markers != NULL)
118 SurfaceMesh_destroyVertexMarkers(surfmesh);
119 surfmesh->vertex_markers = (int*)malloc(sizeof(int)*surfmesh->nv);
120 surfmesh->nvm = surfmesh->nv;
121 }
122
123 /*
124 * ***************************************************************************
125 * SubRoutine: SurfaceMesh_destroyVertexMarkers
126 *
127 * Author: Johan Hake (hake.dev@gmail.com)
128 *
129 * Purpose: Release memory for vertex markers
130 * ***************************************************************************
131 */
SurfaceMesh_destroyVertexMarkers(SurfaceMesh * surfmesh)132 void SurfaceMesh_destroyVertexMarkers(SurfaceMesh* surfmesh)
133 {
134 if (surfmesh->vertex_markers != NULL)
135 free(surfmesh->vertex_markers);
136 surfmesh->nvm = 0;
137 }
138
139 /*
140 * ***************************************************************************
141 * SubRoutine: SurfaceMesh_resetVertexMarkers
142 *
143 * Author: Johan Hake (hake.dev@gmail.com)
144 *
145 * Purpose: Reset vertex markers and initialize them to 0
146 * ***************************************************************************
147 */
SurfaceMesh_resetVertexMarkers(SurfaceMesh * surfmesh)148 void SurfaceMesh_resetVertexMarkers(SurfaceMesh* surfmesh)
149 {
150
151 // If the number of vertex markers are less than the number of vertices
152 // (re)create vertex_markers
153 if (surfmesh->nvm < surfmesh->nv)
154 SurfaceMesh_createVertexMarkers(surfmesh);
155
156 // Initialize the markers
157 for (int n = 0; n < surfmesh->nv; n++)
158 surfmesh->vertex_markers[n] = 0;
159
160 }
161
162 /*
163 * ***************************************************************************
164 * SubRoutine: SurfaceMesh_createFaceMarkers
165 *
166 * Author: Johan Hake (hake.dev@gmail.com)
167 *
168 * Purpose: Create an array for face markers
169 * ***************************************************************************
170 */
SurfaceMesh_createFaceMarkers(SurfaceMesh * surfmesh)171 void SurfaceMesh_createFaceMarkers(SurfaceMesh* surfmesh)
172 {
173 if (surfmesh->face_markers != NULL)
174 SurfaceMesh_destroyFaceMarkers(surfmesh);
175 surfmesh->face_markers = (int*)malloc(sizeof(int)*surfmesh->nf);
176 surfmesh->nfm = surfmesh->nf;
177 }
178
179 /*
180 * ***************************************************************************
181 * SubRoutine: SurfaceMesh_destroyFaceMarkers
182 *
183 * Author: Johan Hake (hake.dev@gmail.com)
184 *
185 * Purpose: Release memory for face markers
186 * ***************************************************************************
187 */
SurfaceMesh_destroyFaceMarkers(SurfaceMesh * surfmesh)188 void SurfaceMesh_destroyFaceMarkers(SurfaceMesh* surfmesh)
189 {
190 if (surfmesh->face_markers != NULL)
191 free(surfmesh->face_markers);
192 surfmesh->nfm = 0;
193 }
194
195 /*
196 * ***************************************************************************
197 * SubRoutine: SurfaceMesh_resetFaceMarkers
198 *
199 * Author: Johan Hake (hake.dev@gmail.com)
200 *
201 * Purpose: Reset face markers and initialize them to 0
202 * ***************************************************************************
203 */
SurfaceMesh_resetFaceMarkers(SurfaceMesh * surfmesh)204 void SurfaceMesh_resetFaceMarkers(SurfaceMesh* surfmesh)
205 {
206 // If the number of face markers are less than the number of vertices
207 // (re)create face_markers
208 if (surfmesh->nfm < surfmesh->nf)
209 SurfaceMesh_createFaceMarkers(surfmesh);
210
211 // Initialize the markers
212 for (int n = 0; n < surfmesh->nf; n++)
213 surfmesh->face_markers[n] = 0;
214
215 }
216
217 /*
218 * ***************************************************************************
219 * SubRoutine: SurfaceMesh_createNeighborList
220 *
221 * Author: Zeyun Yu (zeyun.yu@gmail.com) and Johan Hake (hake.dev@gmail.com)
222 *
223 * Purpose: Create a neigbor list from a surface mesh
224 * ***************************************************************************
225 */
SurfaceMesh_createNeighborlist(SurfaceMesh * surfmesh)226 void SurfaceMesh_createNeighborlist(SurfaceMesh* surfmesh)
227 {
228
229 int m,n,a0,b0;
230 int a,b,c;
231 NPNT3 *first_ngr,*second_ngr,*tmp_ngr;
232 NPNT3 **neighbor_list;
233
234 // Destroy any exsisting neigborlist
235 SurfaceMesh_destroyNeighborlist(surfmesh);
236
237 // Create an array of NPNT3, used to store
238 neighbor_list = (NPNT3 **)malloc(sizeof(NPNT3 *)*surfmesh->nv);
239
240 // Initialize the neighbor list
241 for (n = 0; n < surfmesh->nv; n++)
242 neighbor_list[n] = NULL;
243
244 // Iterate over the faces and collect line segments (a, b) and its connection
245 // to a face (c). Save the line segment so it forms a counter clockwise triangle
246 // with the origin vertex
247 for (n = 0; n < surfmesh->nf; n++) {
248 a = surfmesh->face[n].a;
249 b = surfmesh->face[n].b;
250 c = surfmesh->face[n].c;
251
252 first_ngr = (NPNT3 *)malloc(sizeof(NPNT3));
253 first_ngr->a = b;
254 first_ngr->b = c;
255 first_ngr->c = n;
256 first_ngr->next = neighbor_list[a];
257 neighbor_list[a] = first_ngr;
258
259 first_ngr = (NPNT3 *)malloc(sizeof(NPNT3));
260 first_ngr->a = c;
261 first_ngr->b = a;
262 first_ngr->c = n;
263 first_ngr->next = neighbor_list[b];
264 neighbor_list[b] = first_ngr;
265
266 first_ngr = (NPNT3 *)malloc(sizeof(NPNT3));
267 first_ngr->a = a;
268 first_ngr->b = b;
269 first_ngr->c = n;
270 first_ngr->next = neighbor_list[c];
271 neighbor_list[c] = first_ngr;
272
273 }
274
275 // Order the neighbors so they are connected counter clockwise
276 for (n = 0; n < surfmesh->nv; n++) {
277 first_ngr = neighbor_list[n];
278 c = first_ngr->a;
279 while (first_ngr != NULL) {
280 a = first_ngr->a;
281 b = first_ngr->b;
282
283 second_ngr = first_ngr->next;
284 while (second_ngr != NULL) {
285 a0 = second_ngr->a;
286 b0 = second_ngr->b;
287 if (a0==b && b0!=a) {
288 tmp_ngr = first_ngr;
289 while (tmp_ngr != NULL) {
290 if (tmp_ngr->next == second_ngr) {
291 tmp_ngr->next = second_ngr->next;
292 break;
293 }
294 tmp_ngr = tmp_ngr->next;
295 }
296 tmp_ngr = first_ngr->next;
297 first_ngr->next = second_ngr;
298 second_ngr->next = tmp_ngr;
299 break;
300 }
301 second_ngr = second_ngr->next;
302 }
303 if (first_ngr->next == NULL) {
304 if (first_ngr->b != c)
305 {
306 printf("some polygons are not closed, Vertices: %d-%d\n ", first_ngr->b, c);
307 printf("(%f,%f,%f)\n", surfmesh->vertex[first_ngr->b].x,
308 surfmesh->vertex[first_ngr->b].y,
309 surfmesh->vertex[first_ngr->b].z);
310 printf("(%f,%f,%f)\n", surfmesh->vertex[c].x,
311 surfmesh->vertex[c].y,
312 surfmesh->vertex[c].z);
313 }
314 }
315
316 first_ngr = first_ngr->next;
317 }
318 }
319
320 // Attach the neigborlist to the surfmesh
321 surfmesh->neighbor_list = neighbor_list;
322 }
323
324 /*
325 * ***************************************************************************
326 * SubRoutine: SurfaceMesh_destroyNeighborlist
327 *
328 * Author: Johan Hake (hake.dev@gmail.com)
329 *
330 * Purpose: Release memory from a neigborlist
331 * ***************************************************************************
332 */
SurfaceMesh_destroyNeighborlist(SurfaceMesh * surfmesh)333 void SurfaceMesh_destroyNeighborlist(SurfaceMesh* surfmesh)
334 {
335 unsigned int n;
336 NPNT3* first_ngr = NULL;
337 NPNT3* tmp_ngr = NULL;
338
339 if (surfmesh->neighbor_list != NULL)
340 {
341 // Release the single neighbors
342 for (n = 0; n < surfmesh->nv; n++) {
343 first_ngr = surfmesh->neighbor_list[n];
344 while (first_ngr != NULL)
345 {
346 tmp_ngr = first_ngr->next;
347 free(first_ngr);
348 first_ngr = tmp_ngr;
349 }
350 }
351
352 // Free the array of pointers
353 free(surfmesh->neighbor_list);
354 surfmesh->neighbor_list = NULL;
355 }
356 }
357
358 /*
359 * ***************************************************************************
360 * SubRoutine: SurfaceMesh_getCenterRadius
361 *
362 * Author: Johan Hake (hake.dev@gmail.com)
363 *
364 * Purpose: Return the center and radius of SurfaceMesh
365 * ***************************************************************************
366 */
SurfaceMesh_getCenterRadius(SurfaceMesh * surfmesh)367 ATOM SurfaceMesh_getCenterRadius(SurfaceMesh* surfmesh)
368 {
369 ATOM data;
370 int i;
371
372 // Get the center and radius of the molecular surface mesh
373 float mol_center_x = 0;
374 float mol_center_y = 0;
375 float mol_center_z = 0;
376 float distance;
377
378 for (i=0; i<surfmesh->nv; i++) {
379 mol_center_x += surfmesh->vertex[i].x;
380 mol_center_y += surfmesh->vertex[i].y;
381 mol_center_z += surfmesh->vertex[i].z;
382 }
383 if (surfmesh->nv > 0) {
384 data.x = (float)(mol_center_x/(double)surfmesh->nv);
385 data.y = (float)(mol_center_y/(double)surfmesh->nv);
386 data.z = (float)(mol_center_z/(double)surfmesh->nv);
387 }
388 else {
389 printf("no atoms found ....\n");
390 exit(0);
391 }
392
393 data.radius = 0;
394 for (i=0; i < surfmesh->nv; i++) {
395 distance = sqrt((surfmesh->vertex[i].x-data.x)*(surfmesh->vertex[i].x-data.x)+
396 (surfmesh->vertex[i].y-data.y)*(surfmesh->vertex[i].y-data.y)+
397 (surfmesh->vertex[i].z-data.z)*(surfmesh->vertex[i].z-data.z));
398 if (distance > data.radius)
399 data.radius = distance;
400 }
401
402 return data;
403 }
404
SurfaceMesh_translate(SurfaceMesh * surfmesh,float dx,float dy,float dz)405 void SurfaceMesh_translate(SurfaceMesh* surfmesh, float dx, float dy, float dz){
406 int i;
407 for (i=0; i<surfmesh->nv; i++){
408 surfmesh->vertex[i].x += dx;
409 surfmesh->vertex[i].y += dy;
410 surfmesh->vertex[i].z += dz;
411 }
412 }
413
SurfaceMesh_scale(SurfaceMesh * surfmesh,float scale_x,float scale_y,float scale_z)414 void SurfaceMesh_scale(SurfaceMesh* surfmesh, float scale_x,
415 float scale_y, float scale_z){
416 int i;
417 for (i=0; i<surfmesh->nv; i++){
418 surfmesh->vertex[i].x *= scale_x;
419 surfmesh->vertex[i].y *= scale_y;
420 surfmesh->vertex[i].z *= scale_z;
421 }
422 }
423
SurfaceMesh_scale(SurfaceMesh * surfmesh,float scale)424 void SurfaceMesh_scale(SurfaceMesh* surfmesh, float scale){
425 SurfaceMesh_scale(surfmesh, scale, scale, scale);
426 }
427
SurfaceMesh_centeralize(SurfaceMesh * surfmesh)428 void SurfaceMesh_centeralize(SurfaceMesh* surfmesh){
429 ATOM center = SurfaceMesh_getCenterRadius(surfmesh);
430 SurfaceMesh_translate(surfmesh, -center.x, -center.y, -center.z);
431 }
432