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