Trisurf Monte Carlo simulator
Samo Penic
2014-06-13 ad4e7069f10b80446be8d13eba28a03c2c642a3b
src/cross-section.c
@@ -1,7 +1,7 @@
#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:
@@ -12,12 +12,12 @@
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;
   ts_uint i, j,k,l;
   ts_double pp,Dsq; // distance from the plane squared
   ts_double ppn; // 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_double ppn1; // distance from the plane squared of a neighbor
   ts_vertex *vtx;
   ts_uint ntria=0; // number triangles
   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];
@@ -26,13 +26,31 @@
      Dsq=pp*pp/(a*a+b*b+c*c);
      if(Dsq<vesicle->dmax){
         for(j=0;j<vtx->neigh_no;j++){
            ppn=vtx->neigh[j]->x*a+vtx->neigh[j]->y*b+vtx->neigh[j]->z*c+d;
            if(pp*ppn<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);
            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
               //find triangle that belongs to the two vertices
               ntria=0;
               for(k=0;k<vtx->tristar_no;k++){
                  if(vtx->tristar[k]->vertex[0]==vtx && ( vtx->tristar[k]->vertex[1]==vtx->neigh[j] || vtx->tristar[k]->vertex[2]==vtx->neigh[j]) ){
                     //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) { //there should be 2 triangles. of course, all some of them will be doubled.
                  fprintf(stderr,"ntria=%u\n",ntria);
                  fatal ("Error in mesh. 2 triangles not found",123123);
               } */
               //find the two intersections (in general) to form a intersection line
               for(l=0;l<ntria;l++){
               //we add intersection line between two points for each of the triangles found above.
                  add_crosssection_point(pts,a,b,c,d,tria[l]->vertex[0], tria[l]->vertex[1]);
                  add_crosssection_point(pts,a,b,c,d,tria[l]->vertex[0], tria[l]->vertex[2]);
                  add_crosssection_point(pts,a,b,c,d,tria[l]->vertex[1], tria[l]->vertex[2]);
               }
            }
         }
      }
@@ -41,3 +59,53 @@
}
ts_bool add_crosssection_point(ts_coord_list *pts, ts_double a, ts_double b, ts_double c, ts_double d, ts_vertex *vtx1, ts_vertex *vtx2){
   ts_double pp=vtx1->x*a+vtx1->y*b+vtx1->z*c+d;
   ts_double pp2=vtx2->x*a+vtx1->y*b+vtx2->z*c+d;
   if(pp*pp2<=0){
   ts_double u=pp/(a*(vtx1->x-vtx2->x)+b*(vtx1->y-vtx2->y)+c*(vtx1->z-vtx2->z));
   add_coord(pts, vtx1->x+u*(vtx2->x - vtx1->x),
      vtx1->y+u*(vtx2->y - vtx1->y),
      vtx1->z+u*(vtx2->z - vtx1->z),
      TS_COORD_CARTESIAN);
   return TS_SUCCESS;
   } else {
   return TS_FAIL;
   }
}
/** 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_RGB24, 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;
}
ts_bool save_crossection_snapshot(ts_coord_list *pts, ts_uint timestepno){
   char filename[255];
       sprintf(filename,"timestep_%.6u.png",timestepno);
   crossection_to_png(pts,filename);
   return TS_SUCCESS;
}