/****************************************************************************/
/*                                                                          */
/*  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_mea_main.c
 *	      Author:  Hui Chen
 *		Date:  Dec. 7, 1991
 * 	 Description:  This file contains mea_main(),
 *		       which calls
 *		       different routines depending on the inputs 
 *		       to do the measurement.
 *		       It is device-independent.
 * Modification History:
 * 
 *	who?		when?		why?
 * -----------------------------------------------
 *
 */


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

/****************************************/
/*					
/*	Procedure Name:  mea_main
/*	  Return Value:  none
/*     Input Variables:  none 
/*    Output Variables:  none
/*    Update Variables:  none 
/*    Global Variables:  none
/*     	   Description:  This routine calls
/*		         different routines depending on the inputs 
/*		         to do the measurement.
 */

void mea_main()
{
	extern int voxel_method();
	extern float s_cell1();
	extern void cell_methed2();
	extern float v_voxel_method();
	extern float v_cell1();
	extern void v_cell_methed2();
	extern int mea_valid_seed();
	extern void mea_tracking();
	extern void mea_clean_list();
	extern int s_seed_voxel();
	extern float s_seed_cell1();
	extern void s_seed_cell2();
	extern float v_seed_voxel();
	extern float v_seed_cell1();
	extern void v_seed_cell2();
	extern float mea_distance();
	extern void output_mea_result();

	extern C_World		world;
	extern C_MeaInfo	mea_info;
	int		xsize;		/* x resolution of data array	*/
	int		ysize;		/* y resolution of data array	*/
	int		zsize;		/* z resolution of data array	*/
	int		low;		/* low threshold value used for */
					/* segmentation			*/
	int		high;		/* high threshold value used for */
					/* segmentation			*/
	C_Voxel_8bit		*data;	/* pointer to raw data array	*/
	float		result_u;
	float		f_result;
	int		i_result;

	C_MeaVoxelList	*mea_surface_voxels[C_MEA_HASH_MAX];

	float	rx, ry, rz;
	int	mea_volume;
	int 	seedx, seedy, seedz;

	mea_volume = mea_info.mea_volume;

	if ((mea_info.mea_tool == C_SURFACE_SEED) || 
	    (mea_info.mea_tool == C_VOLUME_SEED)) { 
	    mea_volume = mea_info.seed1.volume_index;
	    seedx = mea_info.seed1.seed.x;
	    seedy = mea_info.seed1.seed.y;
	    seedz = mea_info.seed1.seed.z;
	}

	switch (world.volume[mea_volume]->data_type) {
        case C_SCALAR_DATA_8BIT :
	    switch (world.volume[mea_volume]->data.scalar_data_8bit->seg_type) {
            case C_ISO_SURFACE :
		data = world.volume[mea_volume]->data.scalar_data_8bit->scalar_data;
		xsize = world.volume[mea_volume]->x_size_voxels; 
		ysize = world.volume[mea_volume]->y_size_voxels;
		zsize = world.volume[mea_volume]->z_size_voxels;
		low = world.volume[mea_volume]->data.scalar_data_8bit->seg.isovalue;
		high=255;
		rx = world.volume[mea_volume]->x_size_units/(float)world.volume[mea_volume]->x_size_voxels;
		ry = world.volume[mea_volume]->y_size_units/(float)world.volume[
mea_volume]->y_size_voxels;
		rz = world.volume[mea_volume]->z_size_units/(float)world.volume[
mea_volume]->z_size_voxels;
		mea_info.low = low;
		mea_info.high = high;

		switch (mea_info.mea_tool) {
		case C_SURFACE: /* surface measurement without a seed point option */
	   	   if (mea_info.mea_method == C_VOXEL_METHOD) {
	     	      i_result = voxel_method(data,xsize,ysize,zsize,low,high,rx,ry,rz);
		      result_u = i_result * ((rx*ry+ry*rz+rx*rz)/3.);
		      world.volume[mea_volume]->mea_values[0][0].flag = C_MEA_VALID;
		      world.volume[mea_volume]->mea_values[0][0].value_voxels = i_result;
		      world.volume[mea_volume]->mea_values[0][0].value_units = result_u;
		      output_mea_result(result_u, i_result);
		   }
		   else {
	     	      if (C_VOXEL_SIZE <= 256) { 
	        	f_result = s_cell1(data,xsize,ysize,zsize,
					   low,high,rx,ry,rz);
		        world.volume[mea_volume]->mea_values[0][mea_info.mea_method].flag = C_MEA_VALID;
		        world.volume[mea_volume]->mea_values[0][mea_info.mea_method].value_units = f_result;
		        output_mea_result(f_result, 0);
		      }
	     	      else {   
	        	cell_method2(data,xsize,ysize,zsize,low,high,rx,ry,rz);
		      }
		   }
		   break;	
		case C_SURFACE_SEED: /* surface measurement with a seed point option */
		   if (mea_valid_seed(data,xsize,ysize,zsize,low,high,
					seedx, seedy, seedz)) {
		      mea_tracking(mea_info.mea_method, mea_surface_voxels, 
			data, xsize,ysize,zsize,low,high,seedx,seedy,seedz);
		      mea_clean_list(mea_surface_voxels, data);
	   	      if (mea_info.mea_method == C_VOXEL_METHOD) {
	     	         i_result = s_seed_voxel(mea_surface_voxels,data,
					xsize,ysize,zsize,low,high,rx,ry,rz);
		         result_u = i_result * ((rx*ry+ry*rz+rx*rz)/3.);
		         output_mea_result(result_u, i_result);
		      }
		      else {
	     	         if (C_VOXEL_SIZE <= 256) { 
	           	   f_result = s_seed_cell1(mea_surface_voxels,data,
					xsize,ysize,zsize,low,high,rx,ry,rz);
		           output_mea_result(f_result, 0);
		         }
	     	         else {  
	        	   s_seed_cell2(mea_surface_voxels,data,
					xsize,ysize,zsize,low,high,rx,ry,rz);
		         }
		      }
		   }
		   break;	
		case C_VOLUME: /* volume measurement without a seed point option */
	   	   if (mea_info.mea_method == C_VOXEL_METHOD) {
	     	      f_result = v_voxel_method(data,xsize,ysize,zsize,low,high,rx,ry,rz);
		      result_u = f_result * rx*ry*rz;
		      i_result = (int) f_result;
		      world.volume[mea_volume]->mea_values[1][0].flag = C_MEA_VALID;
		      world.volume[mea_volume]->mea_values[1][0].value_voxels = i_result;
		      world.volume[mea_volume]->mea_values[1][0].value_units = result_u;
		      output_mea_result(result_u, i_result);
		   }
		   else {
	     	      if (C_VOXEL_SIZE <= 256) { 
	        	f_result = v_cell1(data,xsize,ysize,zsize,
					   low,high,rx,ry,rz);
		        world.volume[mea_volume]->mea_values[1][mea_info.mea_method].flag = C_MEA_VALID;
		        world.volume[mea_volume]->mea_values[1][mea_info.mea_method].value_units = f_result;
		        output_mea_result(f_result, 0);
		      }
	     	      else { 
	        	v_cell_method2(data,xsize,ysize,zsize,low,high,rx,ry,rz);
		      }
		   }
		   break;	
		case C_VOLUME_SEED: /* volume measurement with a seed point option */
		   if (mea_valid_seed(data,xsize,ysize,zsize,low,high,
					seedx, seedy, seedz)) {
		      mea_tracking(mea_info.mea_method, mea_surface_voxels, 
			data, xsize,ysize,zsize,low,high,seedx,seedy,seedz);
		      mea_clean_list(mea_surface_voxels, data);
	   	      if (mea_info.mea_method == C_VOXEL_METHOD) {
	     	         f_result = v_seed_voxel(mea_surface_voxels,data,
					xsize,ysize,zsize,low,high,rx,ry,rz);
		         result_u = f_result * rx*ry*rz;
		         i_result = (int) f_result;
		         output_mea_result(result_u, i_result);
		      }
		      else {
	     	         if (C_VOXEL_SIZE <= 256) { 
	           	   f_result = v_seed_cell1(mea_surface_voxels,data,
					xsize,ysize,zsize,low,high,rx,ry,rz);
		           output_mea_result(f_result, 0);
		         }
	     	         else {  
	        	   v_seed_cell2(mea_surface_voxels,data,
					xsize,ysize,zsize,low,high,rx,ry,rz);
		         }
		      }
		   }
		   break;	
		case C_DISTANCE:
		   break;	
		default:
		   printf("invalid tool choice. \n");
		   break;	
		}
		break;
	    case C_SCALAR_OPACITY :
		C_error_message("Scan data segmentation type is C_OPACITY_ARRAY!!!\n");
                break;
	    case C_SCALAR_GRADIENT_OPACITY :
		C_error_message("Scan data segmentation type is C_OPACITY_ARRAY!!!\n");
                break;
	    default:
		C_error_message("Invalid scan data segmentation type!!!\n");
                break;
	    }
            break;
	case C_GEOMETRIC_DATA :
            C_error_message("Volume data type is C_GEOMETRIC_DATA!!!\n");
            break;
	default:
            C_error_message("Invalid volume data type!!!\n");
            break;
	}

}
