/****************************************************************************/
/*                                                                          */
/*  VolVis is a volume visualization system for investigating, manipulating */
/*  and rendering geometric and volumetric data.                            */
/*                                                                          */
/*  Copyright (C) 1993 by the Research Foundation of the State University   */
/*                            of New York                                   */
/*                                                                          */
/*  This program is free software; you can redistribute it and/or modify    */
/*  it under the terms of the GNU General Public License as published by    */
/*  the Free Software Foundation; either version 1, or (at your option)     */
/*  any later version.                                                      */
/*                                                                          */
/*  This program is distributed in the hope that it will be useful,         */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of          */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           */
/*  GNU General Public License for more details.                            */
/*                                                                          */
/*  You should have received a copy of the GNU General Public License       */
/*  along with this program; if not, write to the Free Software             */
/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
/*                                                                          */
/*  For information on VolVis, contact us at:                               */
/*                                                                          */
/*                volvis@cs.sunysb.edu                         (email)      */
/*                                                                          */
/*                Lisa Sobierajski & Ricardo Avila             (US Mail)    */
/*                Department of Computer Science                            */
/*                State University of New York at Stony Brook               */
/*                Stony Brook, New York  11794-4400                         */
/*                                                                          */
/****************************************************************************/




/*
 *			File: C_pick_seed.c
 *		      Author: Hui Chen
 *			Date: 10/22/92
 *		 Description: Floating Point Ray Caster
 *	Modification History:
 *
 *		Who?		When?		Why?
 *	--------------------------------------------------------------------
 *
 */

#include <stdio.h>
#include <math.h>	/* For ftan() 	*/

#include "C_volvis.h"
#include "C_measure.h"

extern	C_World		world;
extern	C_View		view;

/****** Get Rid Of These !!!!!!! ******/
#define	MAX_STEP		400	/* Number Of Steps Along A Ray 	*/
#define	X_STEP_DISTANCE		1.0	/* Distance To Step Along X	*/
#define	Y_STEP_DISTANCE		1.0	/* Distance To Step Along Y	*/
#define	Z_STEP_DISTANCE		1.0	/* Distance To Step Along Z	*/
#define NORMAL_DIST		0.5	/* Distance To Sample For Normal */

C_SeedPoint	seed_point;

int C_pick_cast_ray( ray_origin, ray_direction, world )
C_FPosition             ray_origin;	/* Origin Of Ray */
C_FVector               ray_direction;	/* Direction Of Ray */
C_World                 *world;		/* Data To Send Ray Through 	*/
{
	int		step_count;		/* Ray Step Loop	*/
	int		vloop;			/* World Volumes Loop	*/
	C_FPosition	step_position;		/* Position along Ray 	*/
	C_FPosition	new_position;		/* Transformed Position */
	C_IPosition	new_iposition;		/* Transf. Integer Posit. */
	C_Volume	*volume;		/* Volume Pointer	*/
	C_Volume	*intersect_volume;	/* Volume Intersected	*/
	float		intersect_dist;		/* Distance Along Ray Until */
						/* Intersection Found	*/
	C_Voxel		*dptr;			/* Pointer To Scalar Data */
	int		xstep,			/* Offsets In Volume Data */
			ystep,
			zstep;
	int		xshift,			/* Shifts in Float to Integer */
			yshift,
			zshift;
	C_Voxel		seg_low,		/* Low Segmentation Val */
			seg_high;		/* High Segmentation Val */
	C_ScalarData_8bit	*scan_dptr;		/* Ptr To Scan Data */

	/* Initialize Starting Position Of Ray */
	step_position.x	= ray_origin.x;
	step_position.y	= ray_origin.y;
	step_position.z	= ray_origin.z;

	/* Optimize This OUT of Ray Casting LATER!!! */
	ray_direction.x	*= X_STEP_DISTANCE;
	ray_direction.y	*= Y_STEP_DISTANCE;
	ray_direction.z	*= Z_STEP_DISTANCE;

	/* Loop Through Each Sample Point Along The Ray */
	step_count = MAX_STEP;
	intersect_volume = NULL;

	while( step_count-- )
	{
	   /* Loop Through Each Volume In The World & Look For Intersection */
	   for( vloop=0; (vloop < world->num_volumes); vloop++ )
	   {
	      /* Check If An Intersection Was Found */
	      if( intersect_volume != NULL )
	      {
		/* To Simplify References */
		volume = world->volume[vloop];

		/* Check If INSIDE The Current Volume */
		C_transform_fposition(  &(step_position), &(new_position),
					&(volume->wtol_voxels) );

		if( 	(new_position.x >= 0.0) && 
			(new_position.y >= 0.0) && 
			(new_position.z >= 0.0) && 
			(new_position.x < volume->x_size_voxels-1) && 
			(new_position.y < volume->y_size_voxels-1) && 
			(new_position.z < volume->z_size_voxels-1)    )
		{
		   /* Initialize Data Stepping Offsets */
		   xstep = 1;
		   ystep = volume->x_size_voxels;
		   zstep = volume->x_size_voxels * volume->y_size_voxels;

		   new_iposition.x = (int)(new_position.x);
		   new_iposition.y = (int)(new_position.y);
		   new_iposition.z = (int)(new_position.z);

		   if (new_iposition.x < new_position.x)
			xshift = 1;
		   else if (new_iposition.x > new_position.x)
			xshift = -1;
		   else
			xshift = 0;

		   if (new_iposition.y < new_position.y)
			yshift = 1;
		   else if (new_iposition.y > new_position.y)
			yshift = -1;
		   else
			yshift = 0;

		   if (new_iposition.z < new_position.z)
			zshift = 1;
		   else if (new_iposition.z > new_position.z)
			zshift = -1;
		   else
			zshift = 0;

		   scan_dptr = volume->data.scalar_data_8bit;
		   dptr      = 	scan_dptr->scalar_data  +  
		   	        zstep*new_iposition.z   +
				ystep*new_iposition.y   +
				xstep*new_iposition.x;

		   seg_low  = scan_dptr->seg.simp_range->low;
		   seg_high = scan_dptr->seg.simp_range->high;

		   if ((C_In_Range(*dptr, seg_low, seg_high)) && 
		       (C_On_Surface(dptr, seg_low, seg_high, 
					xstep, ystep, zstep))) {
			intersect_volume = volume;
			step_count = 0;
			seed_point.volume_index = vloop;
			seed_point.seed.x = new_iposition.x;
			seed_point.seed.y = new_iposition.y;
			seed_point.seed.z = new_iposition.z;
		   }
		   else if ((C_In_Range(*(dptr+xshift*xstep), seg_low, seg_high)) &&
                            (C_On_Surface((dptr+xshift*xstep), seg_low, seg_high,
                                          xstep, ystep, zstep))) { 
			intersect_volume = volume;
			step_count = 0;
			seed_point.volume_index = vloop;
			seed_point.seed.x = new_iposition.x + xshift;
			seed_point.seed.y = new_iposition.y;
			seed_point.seed.z = new_iposition.z;
		   }
		   else if ((C_In_Range(*(dptr+yshift*ystep), seg_low, seg_high)) &&
                            (C_On_Surface((dptr+yshift*ystep), seg_low, seg_high,
                                          xstep, ystep, zstep))) { 
			intersect_volume = volume;
			step_count = 0;
			seed_point.volume_index = vloop;
			seed_point.seed.x = new_iposition.x;
			seed_point.seed.y = new_iposition.y + yshift;
			seed_point.seed.z = new_iposition.z;
		   }
		   else if ((C_In_Range(*(dptr+xshift*xstep+yshift*ystep), seg_low, seg_high)) &&
                            (C_On_Surface((dptr+xshift*xstep+yshift*ystep), seg_low, seg_high,
                                          xstep, ystep, zstep))) { 
			intersect_volume = volume;
			step_count = 0;
			seed_point.volume_index = vloop;
			seed_point.seed.x = new_iposition.x + xshift;
			seed_point.seed.y = new_iposition.y + yshift;
			seed_point.seed.z = new_iposition.z;
		   }
		   else if ((C_In_Range(*(dptr+zshift*zstep), seg_low, seg_high)) &&
                            (C_On_Surface((dptr+zshift*zstep), seg_low, seg_high,
                                          xstep, ystep, zstep))) { 
			intersect_volume = volume;
			step_count = 0;
			seed_point.volume_index = vloop;
			seed_point.seed.x = new_iposition.x;
			seed_point.seed.y = new_iposition.y;
			seed_point.seed.z = new_iposition.z + zshift;
		   }
		   else if ((C_In_Range(*(dptr+xshift*xstep+zshift*zstep), seg_low, seg_high)) &&
                            (C_On_Surface((dptr+xshift*xstep+zshift*zstep), seg_low, seg_high,
                                          xstep, ystep, zstep))) { 
			intersect_volume = volume;
			step_count = 0;
			seed_point.volume_index = vloop;
			seed_point.seed.x = new_iposition.x + xshift;
			seed_point.seed.y = new_iposition.y;
			seed_point.seed.z = new_iposition.z + zshift;
		   }
		   else if ((C_In_Range(*(dptr+yshift*ystep+zshift*zstep), seg_low, seg_high)) &&
                            (C_On_Surface((dptr+yshift*ystep+zshift*zstep), seg_low, seg_high,
                                          xstep, ystep, zstep))) { 
			intersect_volume = volume;
			step_count = 0;
			seed_point.volume_index = vloop;
			seed_point.seed.x = new_iposition.x;
			seed_point.seed.y = new_iposition.y + yshift;
			seed_point.seed.z = new_iposition.z + zshift;
		   }
		   else if ((C_In_Range(*(dptr+xshift*xstep+yshift*ystep+zshift*zstep), seg_low, seg_high)) &&
                            (C_On_Surface((dptr+xshift*xstep+yshift*ystep+zshift*zstep), seg_low, seg_high,
                                          xstep, ystep, zstep))) { 
			intersect_volume = volume;
			step_count = 0;
			seed_point.volume_index = vloop;
			seed_point.seed.x = new_iposition.x + xshift;
			seed_point.seed.y = new_iposition.y + yshift;
			seed_point.seed.z = new_iposition.z + zshift;
		   }
		} 
	      }
	   }
	   /* Advance Position Along Ray */
	   step_position.x	+= ray_direction.x;
	   step_position.y	+= ray_direction.y;
	   step_position.z	+= ray_direction.z;
	}
	/* Check If An Intersection Was Found */
	if ( intersect_volume != NULL ) {
	   printf("Seed point found!!!\n");
	   return(1);
	}
	else {
	   printf("Seed point NOT found!!!\n");
	   return(0);
	}
}

