Exemple #1
0
static void generate_small_random_rotation( struct transf * t )
{
  int i;
  double sine_azimuth, cos_azimuth, sine_inclin, cos_inclin, rana, rani;

  rana = unit_random( &seed);
  rani = 2 * unit_random( &seed) - 1;
/*
rana = rani = 0;
*/

  sine_azimuth = ROTATION_SINE_AZIMUTH * rana * rotation_factor;
  cos_azimuth = sqrt( 1 - sine_azimuth * sine_azimuth );
  sine_inclin = ROTATION_SINE_INCLIN * rana * rotation_factor;
  cos_inclin = sqrt( 1 - sine_inclin * sine_inclin );

  /* now compute the transformation */
  t->matrix[0][0] =  cos_azimuth;
  t->matrix[0][1] = sine_azimuth;
  t->matrix[0][2] = 0;
  t->matrix[1][0] = - sine_azimuth *  cos_inclin;
  t->matrix[1][1] =    cos_azimuth *  cos_inclin;
  t->matrix[1][2] =                  sine_inclin;
  t->matrix[2][0] =   sine_azimuth * sine_inclin;
  t->matrix[2][1] = -  cos_azimuth * sine_inclin;
  t->matrix[2][2] =                   cos_inclin;
  /* and no translation component */
  for ( i=0 ; i<3 ; i++ ) t->matrix[i][3] = 0;

  return;
}
Exemple #2
0
/* Create a random ball-shaped object
   */
static void create_hull( int npts, REAL (*pts)[DIM], VertexID * rings)
{
   int i, num_vertices, num_rings;
   double azimuth, sine_inclin, cosine_inclin, radius;
   double (* input_points)[DIM];
   double input_array[MAX_POINTS][3];

   if ( rings==0 ) /* then no hill-climbing */
     input_points = pts;
   else
     input_points = input_array;

   /* Compute each of the required points independently.  Each point is
      classified by a radius, and azimuth, and an inclination.  The
      azimuth is like an angle of longitude on the Earth's surface, and
      is choosen from a uniform random variable ranging from 0 to 2pi.
      However as circles of latitude get shorter as we approach the poles,
      we wish to bias the angles of inclination (which measures angle out
      of the equatorial plane) towards the lower absolute values.  Using
      an inverse sinusoidal function provides the correct bias.
      */
   for ( i=0 ; i<npts ; i++ )
   {
      azimuth = 2 * M_PI * unit_random( &seed);
      /* we don't need the inclination as an angle, so derive the sine
         and cosine of it directly */
      sine_inclin = 2 * unit_random( &seed) -1;
      cosine_inclin = sqrt( 1 - sine_inclin * sine_inclin );
      radius = MEAN_RADIUS;

      input_points[i][0] = radius * cosine_inclin * cos( azimuth );
      input_points[i][1] = radius * cosine_inclin * sin( azimuth );
      input_points[i][2] = radius * sine_inclin;
      }

   if ( rings==0 ) /* then no hill-climbing */
     return;

   /* Otherwise, call the convex-hull routine */
   num_vertices = sac_qhull( npts, input_points, pts, &num_rings,
			     rings, (int *) 0, (double (*)[4]) 0);

   return;
   }
Exemple #3
0
/* Compute an initial random shift for a hull
   */      
static void generate_initial_random_shift( REAL pts[DIM])
{
   double ran;
   int d;
        
   for ( d=0 ; d<3 ; d++ )
   {
      ran = unit_random( &seed) - 0.5;
      pts[d] = TRANSLATION_WIDTH * ran * translation_factor;
      }

   return;
   }
Exemple #4
0
/* Add a random translation component to the vector given
   */      
static void add_delta_random_shift( REAL pts[DIM])
{
   double ran, fact;
   int d;
        
   ran = unit_random( &seed);
   fact = 1 + ran * ran;

   for ( d=0 ; d<3 ; d++ )
   {
      pts[d] += TRANSLATION_SPEED * fact *
	shift_factor * delta_vector[d];
      }

   return;
   }
Exemple #5
0
/* Create a random ball-shaped object
   */
static void create_polyball( int npts, REAL (*pts)[DIM], VertexID * rings)
{
  double s, c, z, xyr;
  double radius;
  int p, q, r;
  int i, v, lower, upper, slice, firstv, nextv, nextr, lastv;

  double sines[MAX_POINTS], cosines[MAX_POINTS];

  radius = MEAN_RADIUS *
         ( 1.0 - RADIUS_RATIO*radius_factor / 2.0 
	   + RADIUS_RATIO*radius_factor * unit_random( &seed) );

  (void) compute_sizes( npts, & p, & q, & r);
  /* debugging statements 
    fprintf( stderr, "%d = %d * %d + %d\n", npts, p, q, r);
    first_time1 = 0;
  */

  /* Force generation of blocks if n==8 */
  if ( npts==8 ) { p = 4; q = 2; r = 0; }
  /**/

  /* `normal' vertices are indexed in the range [firstv, lastv] (inclusive) */
  firstv = ( r==2 ) ? 1 : 0;
  lastv = ( r>0 ) ? npts-2 : npts-1;

  /* compute vertex coordinates */

  /* bottom vertex, if it exists */
  if ( r==2 ) {
     pts[0][0] = pts[0][1] = 0;
     pts[0][2] = - radius;
   }

  /* normal vertices */

  /* cache sines and cosines first */
   sines[0] = 0;	cosines[0] = 1;
   s = sin( 2*M_PI / p );   c = cos( 2*M_PI / p );
   for ( i = 1 ; i < p ; i++ ) {
       sines[i] = cosines[i-1]*s + sines[i-1]*c;
     cosines[i] = cosines[i-1]*c - sines[i-1]*s;
   }

   nextv = firstv;
   for ( slice=1 ; slice<=q ; slice++ ) {
     z = radius * ((double) 2*slice - ( q+1) ) / (q+1);
     xyr = sqrt( radius * radius - z * z );
     for ( i = 0 ; i < p ; i++ ) {
       pts[nextv][0] = xyr * cosines[i];
       pts[nextv][1] = xyr *   sines[i];
       pts[nextv][2] = z;
       nextv++;
     }
   }

  /* top vertex, if it exists */
  if ( r>0 ) {
     pts[npts-1][0] = pts[npts-1][1] = 0;
     pts[npts-1][2] = radius;
   }
   
  if ( rings==0 ) /* then no hill-climbing */
     return;

   /* otherwise set up the edge lists.
      We process them in vertex number order.
      */
   nextr = npts;

   if ( r==2 ) { /* then form an entry for the first, bottom vertex */
     rings[0] = nextr;
     for ( i=0 ; i<p ; i++ )
       rings[nextr++] = i+1;
     rings[nextr++] = TERMINATOR;
   }

   /* now the `normal' vertices */
   for ( v=firstv ; v<=lastv ; v++ ) {
     rings[v] = nextr;
     slice = (v+p-firstv)/p;
     rings[v] = nextr;
     lower = v-p;
     if ( lower<firstv )
       lower = ( r==2 ) ? 0 : -1;
     if ( lower>=0 )
       rings[nextr++] = lower;
     rings[nextr++] = ( ((v+p+1-firstv)/p)==slice ) ? v+1 : v+1-p;
     upper = v+p;
     if ( upper>lastv )
       upper = ( r>0 ) ? npts-1 : -1;
     if ( upper>=0 )
       rings[nextr++] = upper;
     rings[nextr++] = ( ((v+p-1-firstv)/p)==slice ) ? v-1 : v-1+p;
     rings[nextr++] = TERMINATOR;
     }

   if ( r>0 ) { /* then form an entry for the last, top vertex */
     rings[npts-1] = nextr;
     for ( i=0 ; i<p ; i++ )
       rings[nextr++] = lastv - i;
     rings[nextr++] = TERMINATOR;
   }


   return;
   }
int main(int argc, char *argv[])
{
  double background = 0.0;            // Value in the background of the image
  unsigned oversampling = 100;        // How much to oversample in X and Y within each pixel
  unsigned width = 101;               // Width of the image
  unsigned height= 101;               // Height of the image
  double start_x = 75;                // Where to start the bead at
  double start_y = 50;                // Where to start the bead at
  unsigned frames = 120;              // How many frames to write
  const char *basename = "moving_spot";
  SPOT_TYPE spot_type = DISC;         // Type of spot to use.
  double disc_value = 65535;          // Pixel value within a disc
  double disc_radius = 10;            // Radius of a disc in pixels
  double cone_value = 65535;          // Maximum pixel value within a cone
  double cone_radius = 10;            // Radius of a cone in pixels
  double gaussian_value;              // Maximum pixel value obtained by the Gaussian
  double gaussian_std;                // Standard deviation of a Gaussian
  double rod_value = 65535;           // Pixel value within a rod
  double rod_radius = 65535;          // Raidus of a rod in pixels
  double rod_length = 65535;          // Length of a rod in pixels
  MOTION_TYPE motion_type = CIRCLE;
  double circle_radius = 25;          // Radius of circular motion
  double circle_speed = 3;            // Speed of moving around the circle in degrees/second
  double spiral_size = 1;             // Larger numbers make a looser spiral
  double spiral_speed = 1;            // Speed of moving around the spiral
  int random_seed = 1;                 // Seed for random number generator
  double random_step = 1;              // Maximum magnitude of noise step
  double random_angle = 1;             // Maximum degrees of angle change
  bool verbose = false;               // Print out info along the way?

  int	realparams = 0;
  int	i;
  i = 1;
  while (i < argc) {
    if (!strncmp(argv[i], "-background", strlen("-background"))) {
          if (++i > argc) { Usage(argv[0]); }
	  background = 65535 * atof(argv[i]); // Scale 1 becomes maximum pixel value
    } else if (!strncmp(argv[i], "-oversampling", strlen("-oversampling"))) {
          if (++i > argc) { Usage(argv[0]); }
	  oversampling = atoi(argv[i]);
    } else if (!strncmp(argv[i], "-imagesize", strlen("-imagesize"))) {
          if (++i > argc) { Usage(argv[0]); }
	  width = atoi(argv[i]);
          if (++i > argc) { Usage(argv[0]); }
	  height = atoi(argv[i]);
    } else if (!strncmp(argv[i], "-start", strlen("-start"))) {
          if (++i > argc) { Usage(argv[0]); }
	  start_x = atof(argv[i]);
          if (++i > argc) { Usage(argv[0]); }
	  start_y = atof(argv[i]);
    } else if (!strncmp(argv[i], "-frames", strlen("-frames"))) {
          if (++i > argc) { Usage(argv[0]); }
	  frames = atoi(argv[i]);
    } else if (!strncmp(argv[i], "-disc", strlen("-disc"))) {
          if (++i > argc) { Usage(argv[0]); }
	  disc_value = 65535 * atof(argv[i]);   // Scale so 1 becomes maximum pixel value
          if (++i > argc) { Usage(argv[0]); }
	  disc_radius = atof(argv[i]);
          spot_type = DISC;
    } else if (!strncmp(argv[i], "-cone", strlen("-cone"))) {
          if (++i > argc) { Usage(argv[0]); }
	  cone_value = 65535 * atof(argv[i]);   // Scale 1 becomes maximum pixel value
          if (++i > argc) { Usage(argv[0]); }
	  cone_radius = atof(argv[i]);
          spot_type = CONE;
    } else if (!strncmp(argv[i], "-gaussian", strlen("-gaussian"))) {
          if (++i > argc) { Usage(argv[0]); }
	  gaussian_value = 65535 * atof(argv[i]);   // Scale 1 becomes maximum pixel value
          if (++i > argc) { Usage(argv[0]); }
	  gaussian_std = atof(argv[i]);
          spot_type = GAUSSIAN;
    } else if (!strncmp(argv[i], "-rod", strlen("-rod"))) {
          if (++i > argc) { Usage(argv[0]); }
	  rod_value = 65535 * atof(argv[i]);   // Scale 1 becomes maximum pixel value
          if (++i > argc) { Usage(argv[0]); }
	  rod_radius = atof(argv[i]);
          if (++i > argc) { Usage(argv[0]); }
	  rod_length = atof(argv[i]);
          spot_type = ROD;
    } else if (!strncmp(argv[i], "-circle", strlen("-circle"))) {
          if (++i > argc) { Usage(argv[0]); }
	  circle_radius = atof(argv[i]);   
          if (++i > argc) { Usage(argv[0]); }
	  circle_speed = atof(argv[i]);
          motion_type = CIRCLE;
    } else if (!strncmp(argv[i], "-spiral", strlen("-spiral"))) {
          if (++i > argc) { Usage(argv[0]); }
	  spiral_size = atof(argv[i]);   
          if (++i > argc) { Usage(argv[0]); }
	  spiral_speed = atof(argv[i]);
          motion_type = SPIRAL;
    } else if (!strncmp(argv[i], "-random", strlen("-random"))) {
          if (++i > argc) { Usage(argv[0]); }
	  random_seed = atoi(argv[i]);   
          if (++i > argc) { Usage(argv[0]); }
	  random_step = atof(argv[i]);
          if (++i > argc) { Usage(argv[0]); }
	  random_angle = atof(argv[i]);
          motion_type = RANDOM;
          srand(random_seed);
    } else if (!strncmp(argv[i], "-v", strlen("-v"))) {
          verbose = true;
    } else if (argv[i][0] == '-') {	// Unknown flag
	  Usage(argv[0]);
    } else switch (realparams) {		// Non-flag parameters
      case 0:
          basename = argv[i];
          realparams++;
          break;
      default:
	  Usage(argv[0]);
    }
    i++;
  }
  if (realparams > 1) {
    Usage(argv[0]);
  }

  if (verbose) { printf("Version %s\n", version); }

  const unsigned MAX_NAME = 2048;
  char filename[MAX_NAME];
  if (strlen(basename) > MAX_NAME - strlen(".0000.tif")) {
    fprintf(stderr,"Base file name too long\n");
    return -1;
  }

  //------------------------------------------------------------------------------------
  // Open the CSV file that will record the motion and put the header information into it.
  FILE  *g_csv_file = NULL;		  //< File to save data in with .csv extension
  char *csvname = new char[strlen(basename)+5];	// Remember the closing '\0'
  if (csvname == NULL) {
    fprintf(stderr, "Out of memory when allocating CSV file name\n");
    return -1;
  }
  sprintf(csvname, "%s.csv", basename);
  if ( NULL == (g_csv_file = fopen(csvname, "w")) ) {
    fprintf(stderr,"Cannot open CSV file for writing: %s\n", csvname);
  } else {
    fprintf(g_csv_file, "FrameNumber,Spot ID,X,Y,Z,Radius,Orientation (if meaningful)\n");
  }
  delete [] csvname;

  //------------------------------------------------------------------------------------
  // Generate images matching the requested motion and disc types, with the
  // specified geometries, and write them to files.

  unsigned frame;
  for (frame = 0; frame < frames; frame++) {
    double x = start_x, y = start_y, angle = 0;

    // Find out where we should be based on the motion type
    switch (motion_type) {
      case CIRCLE:
        // Subtracting 1 from the cos() value so that we start at the
        // correct location, not one radius away from it.
        x = start_x + circle_radius * (cos(frame * circle_speed * M_PI/180) - 1);
        y = start_y + circle_radius * sin(frame * circle_speed * M_PI/180);
        angle = (90 - frame * circle_speed);
        break;
      case SPIRAL:
        x = start_x + spiral_size * exp(frame/32.0) * sin(frame * spiral_speed * M_PI/180);
        y = start_y + spiral_size * exp(frame/32.0) * cos(frame * spiral_speed * M_PI/180);
        angle = (90 - frame * spiral_speed);
        break;
      case RANDOM:
		if (frame != 0) {
          x += random_step * unit_random();
          y += random_step * unit_random();
		  angle += random_angle * unit_random();
		}
    }

    // Flip the image in Y because the write function is going to flip it again
    // for us before saving the image.
    double flip_y = (height - 1) - y;

    // Make the appropriate image based on the bead type
    image_wrapper *bead;
    double        radius;   // Used for logging
    switch (spot_type) {
    case DISC:
      bead = new disc_image(0, width-1, 0, height-1,
                            background, 0.0,
                            x, flip_y, disc_radius,
                            disc_value,
                            oversampling);
      radius = disc_radius;
      angle = 0.0;
      break;

    case CONE:
      bead = new cone_image(0, width-1, 0, height-1,
                            background, 0.0,
                            x, flip_y, cone_radius,
                            cone_value,
                            oversampling);
      radius = cone_radius;
      angle = 0.0;
      break;

    case GAUSSIAN:
      // Figure out the volume that will make the Gaussian have a maximum value
      // equal to gaussian_value.  The volume under the curve is equal to
      // std^2 * 2 * PI; this is divided by to make it unit volume, so we need
      // to multiply by this to get back to unit height and then multiply again
      // by the value we want.
      bead = new Integrated_Gaussian_image(0, width-1, 0, height-1,
                                           background, 0.0,
                                           x, flip_y, gaussian_std,
                                           gaussian_value * gaussian_std*gaussian_std * 2 * M_PI,
                                           oversampling);
      radius = gaussian_std;
      break;

    case ROD:
      bead = new rod_image(0, width-1, 0, height-1,
                            background, 0.0,
                            x, flip_y, rod_radius,
                            rod_length, angle * M_PI/180, rod_value,
                            oversampling);
      radius = rod_radius;
      break;
    }

    // Write the image to file whose name is the base name with
    // the frame number and .tif added.
    sprintf(filename, "%s.%04d.tif", basename, frame);
    if (verbose) { printf("Writing %s:\n", filename); }
    bead->write_to_grayscale_tiff_file(filename, 0, 1.0, 0.0, true);

    // Write the information about the current bead to the CSV file, in a format
    // that matches the header description.  We DO NOT flip y in this report.
    fprintf(g_csv_file, "%d,0,%lg,%lg,0,%lg,%lg\n", frame, x,y, radius, angle);

    // Clean up things allocated for this frame.
    delete bead;
  }

  // Clean up things allocated for the whole sequence
  if (g_csv_file) { fclose(g_csv_file); g_csv_file = NULL; };
  return 0;
}