Trisurf Monte Carlo simulator
Samo Penic
2014-06-13 a61c001cd35ff70a314ef417c4beda9c7e68d3ad
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
#include<general.h>
#include<cross-section.h>
#include<coord.h>
#include<cairo/cairo.h>
/** @brief Calculates cross-section of vesicle with plane.
 *
 * Function returns points of cross-section of vesicle with plane. Plane is described with equation $ax+by+cz+d=0$. Algorithm extracts coordinates of each vertex of a vesicle and then:
 *
 * if a distance of point to plane (given by equation $D=\frac{ax_0+by_0+cz_0+d}{\sqrt{a^2+b^2+c^2}}$, where $x_0$, $y_0$ and $z_0$ are coordinates of a given vertex) is less than maximal allowed distance between vertices {\tt sqrt(vesicle->dmax)} than vertex is a candidate for crossection calculation.
 *
 */
ts_coord_list *get_crossection_with_plane(ts_vesicle *vesicle,ts_double a,ts_double b,ts_double c, ts_double d){
 
 
    ts_uint i, j,k;
    ts_double pp,Dsq; // distance from the plane squared
    ts_double ppn1,ppn2; // distance from the plane squared of a neighbor
    ts_double u; //factor to scale vector from first vector to the second to get intersection
    ts_vertex *vtx;
    ts_uint ntria=0; // number triangles
    ts_uint cnt=0;
    ts_triangle *tria[2]; // list of triangles
    ts_coord_list *pts=init_coord_list();
    for(i=0;i<vesicle->vlist->n;i++){
        vtx=vesicle->vlist->vtx[i];
 
        pp=vtx->x*a+vtx->y*b+vtx->z*c+d;
        Dsq=pp*pp/(a*a+b*b+c*c);
        if(Dsq<vesicle->dmax){
            for(j=0;j<vtx->neigh_no;j++){
                ppn1=vtx->neigh[j]->x*a+vtx->neigh[j]->y*b+vtx->neigh[j]->z*c+d;
                if(pp*ppn1<=0){ //the combination of vertices are good candidates for a crossection
/*                    u=pp/(a*(vtx->x-vtx->neigh[j]->x)+b*(vtx->y-vtx->neigh[j]->y)+c*(vtx->z-vtx->neigh[j]->z));
                    add_coord(pts, vtx->x+u*(vtx->neigh[j]->x - vtx->x),
                            vtx->y+u*(vtx->neigh[j]->y - vtx->y),        
                            vtx->z+u*(vtx->neigh[j]->z - vtx->z),
                            TS_COORD_CARTESIAN);        
 
*/
                    //find triangle that belongs to the two vertices
                    cnt=0;
                    ntria=0;
                    for(k=0;k<vtx->tristar_no;k++){
                        if(vtx->tristar[k]->vertex[1]==vtx->neigh[j] && vtx->tristar[k]->vertex[0]==vtx){ 
                            //triangle found.
                            tria[ntria]=vtx->tristar[k];
                            ntria++;
                        }
                    }
                    // if ntria !=1 there is probably something wrong I would say...
                    if(ntria==0) continue;
                    if(ntria!=1) {
                        fprintf(stderr,"ntria=%u\n",ntria);
                        fatal ("Error in mesh. 1 triangle not found",123123);
                    }
                    //find the two intersections (in general) to form a intersection line
                    /* we dont know which vertex is which, so we need to recalculate all previously calculated values*/
                    pp=vtx->x*a+vtx->y*b+vtx->z*c+d;
                    ppn1=vtx->neigh[j]->x*a+vtx->neigh[j]->y*b+vtx->neigh[j]->z*c+d;
 
                    u=pp/(a*(vtx->x-vtx->neigh[j]->x)+b*(vtx->y-vtx->neigh[j]->y)+c*(vtx->z-vtx->neigh[j]->z));
                    add_coord(pts, vtx->x+u*(vtx->neigh[j]->x - vtx->x),
                            vtx->y+u*(vtx->neigh[j]->y - vtx->y),        
                            vtx->z+u*(vtx->neigh[j]->z - vtx->z),
                            TS_COORD_CARTESIAN);
                    ppn2=tria[0]->vertex[2]->x*a+tria[0]->vertex[2]->y*b+tria[0]->vertex[2]->z*c+d;    
                    cnt++;
                    //two more tries to find anothen pair of vertices, one above and one below the intersection plane */    
                    if(pp*ppn2<=0) {
                        u=pp/(a*(vtx->x-tria[0]->vertex[2]->x)+b*(vtx->y-tria[0]->vertex[2]->y)+c*(vtx->z-tria[0]->vertex[2]->z));
                        add_coord(pts, vtx->x+u*(tria[0]->vertex[2]->x - vtx->x),
                            vtx->y+u*(tria[0]->vertex[2]->y - vtx->y),        
                            vtx->z+u*(tria[0]->vertex[2]->z - vtx->z),
                            TS_COORD_CARTESIAN);    
                        cnt++;
                    }
 
                    if(ppn2*ppn1<=0) {
                        u=ppn1/(a*(vtx->neigh[j]->x-tria[0]->vertex[2]->x)+b*(vtx->neigh[j]->y-tria[0]->vertex[2]->y)+c*(vtx->neigh[j]->z-tria[0]->vertex[2]->z));
                        add_coord(pts, vtx->neigh[j]->x+u*(tria[0]->vertex[2]->x - vtx->neigh[j]->x),
                            vtx->neigh[j]->y+u*(tria[0]->vertex[2]->y - vtx->neigh[j]->y),        
                            vtx->neigh[j]->z+u*(tria[0]->vertex[2]->z - vtx->neigh[j]->z),
                            TS_COORD_CARTESIAN);    
                        cnt++;
 
                    }
 
 
                    if(cnt!=2){
                        fprintf(stderr,"Hey, cnt=%u",cnt);
                    }
                }
            }
        }
    }
    return pts;
}
 
 
/** Saves calculated crossection as a png image */
ts_bool crossection_to_png(ts_coord_list *pts, char *filename){
 
    cairo_surface_t *surface;
    cairo_t *cr;
    ts_uint i;
    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1800, 1800);
    cr = cairo_create (surface);
    cairo_rectangle(cr, 0.0, 0.0, 1800,1800);
    cairo_set_source_rgb(cr, 0.3, 0.3, 0.3);
    cairo_fill(cr);
    cairo_set_line_width (cr, 5.0/30.0);
    cairo_translate(cr, 900,900);
    cairo_scale (cr, 30, 30);
    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
 
    for(i=0;i<pts->n;i+=2){
        cairo_move_to(cr, pts->coord[i]->e1, pts->coord[i]->e2);
        cairo_line_to(cr, pts->coord[i+1]->e1, pts->coord[i+1]->e2);
    }
    cairo_stroke(cr);
    cairo_surface_write_to_png (surface,filename);
    cairo_surface_finish (surface);    
    return TS_SUCCESS;
}