/***************************************************************************/
/* File:         simple-structure.c
 * Status:       03-nov-2010, wlm.
 * Functie:      Voorbeelden van:
 *               - gebruik van structures
 ***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MAXPOINTS       10        /* maximal number of points       */

/*=========================================================================*/

struct point {      /* defines a structure point with x and y value */
  float x;
  float y;
};
struct rect {       /* defines a structure rect: This contains allows storage of */
  struct point pt1; /* lower-left and upper-right coordinates of a rectangular   */
  struct point pt2;
};
struct points_definition {
  struct point * pt;
  int n;
};

float distance ( struct point pt1, struct point pt2){       /* function to calculate the distance between two points */

   return ( sqrt( (pt1.x - pt2.x) * (pt1.x - pt2.x) +
                  (pt1.y - pt2.y) * (pt1.y - pt2.y)   ) );
}

struct point makepoint ( float x, float y) {                /* function to place (x,y) value in the structure point  */

  struct point temp;
  temp.x = x;
  temp.y = y;
  return temp;
}

void simple_place ( void ) {
  float x, y;
  struct point xy;

  printf ("Simple pointer use\n");
  for ( x = -5 ; x <= 5 ; x++ ) {                     /* Simple placing points and print results, result lost  */
     y = 2. * x;
     xy = makepoint(x, y);
     printf ("Defined points: (%5.1f,%5.1f)\n",xy.x,xy.y);
  }
}

void place_and_store ( struct point * xy, int i) {
  struct point temp;
  float x, y;

  x = i;
  y = 2. * x;
  temp = makepoint(x, y);
  xy->x = temp.x;
  xy->y = temp.y;
}

struct points_definition place_store_and_return ( void ) {  /* Placing points, results stored and returned. Print results  */
  struct point * xy_ptr;
  struct points_definition xy_points;
  int n = MAXPOINTS - 2;
  n = n /2;
  n = 2 * n;   /* to make sure n is even */
  int i, j;
  float x, y;

  xy_ptr = (struct point * ) malloc ( (MAXPOINTS + 1 ) * sizeof( struct point) );  /* Allocate space for MAXPOINTS + 1 points (x,y) value */
  if ( xy_ptr == NULL ) {                                                          /* Check if succesfull */
     fprintf (stderr, "Error: No space allocated for (x,y) values in simple_place_store\n");
     exit(10);
  }
  xy_points.pt = xy_ptr;
  xy_points.n  = n;

  printf ("Simple pointer use with storage\n");
  for ( i = - n / 2, j = 0 ; i <= n /2  ; i++, j++ ) {             /* Simple placing points and print results, result stored  */
     x = i;
     y = 2. * x;
     xy_ptr[j] = makepoint(x, y);
     printf ("Defined points: (%5.1f,%5.1f), distance to (0,0) = %7.3f\n",xy_ptr[j].x,xy_ptr[j].y,
                                                            distance(xy_ptr[j], makepoint(0,0)) );
  }
  return xy_points;
}


void place_store_and_fill ( struct point xy[], int n) {
/* This definition is identical: void place_store_and_fill ( struct point * xy, int n) */
  struct point temp;
  int i, j;
  float x, y;

  for ( i = - n / 2, j = 0 ; i <= n /2  ; i++, j++ ) {
     x = i;
     y = 2. * x;
     temp = makepoint(x, y);
     xy[j].x = temp.x;
     xy[j].y = temp.y;
  }
}

int main ()
{
  struct point * main_xy;
  struct points_definition main_def_xy;
  int i, j;
  int n = MAXPOINTS;
  n = n /2;
  n = 2 * n;   /* to make sure n is even */

/***********   I   *****************************************************************************/

  simple_place();

 /***********************************************************************************************/

  main_xy = (struct point * ) malloc ( (MAXPOINTS + 1 ) * sizeof( struct point) );
  if ( main_xy == NULL ) {
     fprintf (stderr, "Error: No space allocated for (x,y) values in main\n");
     exit(10);
  }
  printf ("Pointer use with storage, element by element\n");
/************   II  ****************************************************************************/
  for ( i = - n / 2, j = 0 ; i <= n /2  ; i++, j++ ) {
     place_and_store( &main_xy[j], i);
     printf ("Defined points: (%5.1f,%5.1f), distance to (0,0) = %7.3f\n",main_xy[j].x,main_xy[j].y,
                                                            distance(main_xy[j], makepoint(0,0)) );
  }
/***********************************************************************************************/

/************   III   **************************************************************************/
  main_def_xy = place_store_and_return();             /* Placing points, results stored and returned. Print results  */
  for ( i = - main_def_xy.n / 2, j = 0 ; i <= main_def_xy.n /2  ; i++, j++ ) {
      printf ("                (%5.1f,%5.1f)\n",main_def_xy.pt[j].x, main_def_xy.pt[j].y);
  }
/***********************************************************************************************/

/*************   IV   **************************************************************************/
  printf ("Pointer use with storage, direct fill of all elements\n");
  place_store_and_fill( main_xy, n);
  for ( i = - n / 2, j = 0 ; i <= n /2  ; i++, j++ ) {
     printf ("Defined points: (%5.1f,%5.1f), distance to (0,0) = %7.3f\n",main_xy[j].x,main_xy[j].y,
                                                            distance(main_xy[j], makepoint(0,0)) );
  }
/***********************************************************************************************/

  return (0);
}
