int define_Computed_field_type_integration(Parse_state *state,
	void *field_modify_void,void *computed_field_integration_package_void)
/*******************************************************************************
LAST MODIFIED : 24 August 2006

DESCRIPTION :
Converts <field> into type COMPUTED_FIELD_INTEGRATION (if it is not already)
and allows its contents to be modified.
==============================================================================*/
{
	int return_code = 1;
	ENTER(define_Computed_field_type_integration);
	Computed_field_modify_data *field_modify = reinterpret_cast<Computed_field_modify_data *>(field_modify_void);
	USE_PARAMETER(computed_field_integration_package_void);
	if (state && field_modify)
	{
		cmzn_region_id region = field_modify->get_region();
		cmzn_mesh_id mesh = 0;
		cmzn_field_id coordinate_field = 0;
		cmzn_field_id integrand = 0;
		int magnitude_coordinates_flag = 0;
		int seed_element_identifier = 0;
		float time_update = 0;
		if ((NULL != field_modify->get_field()) &&
			Computed_field_is_type_integration(field_modify->get_field()))
		{
			cmzn_element_id seed_element;
			return_code = Computed_field_get_type_integration(field_modify->get_field(),
				&mesh, &seed_element, &integrand, &magnitude_coordinates_flag, &coordinate_field);
			if (seed_element)
			{
				seed_element_identifier = cmzn_element_get_identifier(seed_element);
				cmzn_element_destroy(&seed_element);
			}
		}
		if (coordinate_field)
		{
			ACCESS(Computed_field)(coordinate_field);
		}
		if (integrand)
		{
			ACCESS(Computed_field)(integrand);
		}
		else
		{
			/* Make a default integrand of one */
			double value = 1.0;
			// use temporary field module to supply different defaults
			cmzn_fieldmodule *temp_field_module = cmzn_region_get_fieldmodule(region);
			cmzn_fieldmodule_set_field_name(temp_field_module, "constant_1.0");
			integrand = Computed_field_create_constant(temp_field_module,
				/*number_of_components*/1, &value);
			if (NULL == integrand)
			{
				display_message(ERROR_MESSAGE,
					"define_Computed_field_type_integration.  Unable to create constant integrand");
				return_code = 0;
			}
			cmzn_fieldmodule_destroy(&temp_field_module);
		}
		char *group_name = 0;

		Option_table *option_table = CREATE(Option_table)();
		/* coordinate */
		Set_Computed_field_conditional_data set_coordinate_field_data;
		set_coordinate_field_data.computed_field_manager = field_modify->get_field_manager();
		set_coordinate_field_data.conditional_function = Computed_field_has_up_to_3_numerical_components;
		set_coordinate_field_data.conditional_function_user_data = 0;
		Option_table_add_Computed_field_conditional_entry(option_table, "coordinate",
			&coordinate_field, &set_coordinate_field_data);
		/* integrand */
		Set_Computed_field_conditional_data set_integrand_field_data;
		set_integrand_field_data.computed_field_manager = field_modify->get_field_manager();
		set_integrand_field_data.conditional_function = Computed_field_is_scalar;
		set_integrand_field_data.conditional_function_user_data = 0;
		Option_table_add_Computed_field_conditional_entry(option_table, "integrand",
			&integrand, &set_integrand_field_data);
		/* magnitude_coordinates|no_magnitude_coordinates */
		Option_table_add_switch(option_table, "magnitude_coordinates", "no_magnitude_coordinates",
			&magnitude_coordinates_flag);
		// mesh
		Option_table_add_mesh_entry(option_table, "mesh", region, &mesh);
		/* region - legacy group name */
		Option_table_add_string_entry(option_table, "region", &group_name, " GROUP_NAME(DEPRECATED)");
		/* seed_element */
		Option_table_add_int_non_negative_entry(option_table, "seed_element",
			&seed_element_identifier);
		/* update_time_integration */
		Option_table_add_entry(option_table,"update_time_integration",
			&time_update, NULL, set_float);
		return_code = Option_table_multi_parse(option_table,state);
		DESTROY(Option_table)(&option_table);

		if (return_code && !mesh)
		{
			int dimension = FE_region_get_highest_dimension(cmzn_region_get_FE_region(region));
			mesh = cmzn_fieldmodule_find_mesh_by_dimension(field_modify->get_field_module(), dimension);
			if (group_name)
			{
				cmzn_field_id group_field = cmzn_fieldmodule_find_field_by_name(field_modify->get_field_module(), group_name);
				cmzn_field_group_id group = cmzn_field_cast_group(group_field);
				cmzn_field_element_group_id element_group = cmzn_field_group_get_field_element_group(group, mesh);
				cmzn_mesh_destroy(&mesh);
				mesh = cmzn_mesh_group_base_cast(cmzn_field_element_group_get_mesh_group(element_group));
				cmzn_field_element_group_destroy(&element_group);
				cmzn_field_group_destroy(&group);
				cmzn_field_destroy(&group_field);
			}
		}
		if (return_code && !mesh)
		{
			display_message(ERROR_MESSAGE, "You must specify a mesh.");
			return_code = 0;
		}
		if (return_code && !coordinate_field)
		{
			display_message(ERROR_MESSAGE, "You must specify a coordinate field.");
			return_code = 0;
		}
		if (return_code && !integrand)
		{
			display_message(ERROR_MESSAGE, "You must specify an integrand field.");
			return_code = 0;
		}
		cmzn_element_id seed_element = 0;
		if (return_code)
		{
			seed_element = cmzn_mesh_find_element_by_identifier(mesh, seed_element_identifier);
			if (!seed_element)
			{
				display_message(ERROR_MESSAGE, "Could not find seed_element %d in mesh.", seed_element_identifier);
				return_code = 0;
			}
		}
		if (return_code)
		{
			if (time_update && (NULL != field_modify->get_field()) &&
				Computed_field_is_type_integration(field_modify->get_field()))
			{
				display_message(ERROR_MESSAGE,
					"The update_time_integration code has not been updated"
					"with the latest changes.");
				return_code=0;
			}
			else
			{
				return_code = field_modify->update_field_and_deaccess(
					Computed_field_create_integration(field_modify->get_field_module(),
						mesh, seed_element, integrand, magnitude_coordinates_flag, coordinate_field));
			}
		}
		if (group_name)
		{
			DEALLOCATE(group_name);
		}
		cmzn_element_destroy(&seed_element);
		cmzn_mesh_destroy(&mesh);
		cmzn_field_destroy(&coordinate_field);
		cmzn_field_destroy(&integrand);
	}
	else
	{
		display_message(ERROR_MESSAGE,
			"define_Computed_field_type_integration.  Invalid argument(s)");
		return_code=0;
	}
	LEAVE;

	return (return_code);
}
int define_Computed_field_type_compose(struct Parse_state *state,
	void *field_modify_void, void *computed_field_compose_package_void)
/*******************************************************************************
LAST MODIFIED : 24 August 2006

DESCRIPTION :
Converts <field> into type COMPUTED_FIELD_COMPOSE (if it is not
already) and allows its contents to be modified.
==============================================================================*/
{
	int return_code;
	Computed_field_compose_package *computed_field_compose_package;
	Computed_field_modify_data *field_modify;
	struct Option_table *find_option_table, *option_table,
		*out_of_bounds_option_table;
	struct Set_Computed_field_conditional_data set_calculate_values_field_data,
		set_find_element_xi_field_data, set_texture_coordinates_field_data;

	ENTER(define_Computed_field_type_compose);
	if (state && (field_modify=(Computed_field_modify_data *)field_modify_void) &&
		(computed_field_compose_package =
			(Computed_field_compose_package *)
			computed_field_compose_package_void))
	{
		return_code = 1;
		Cmiss_mesh_id mesh = 0;
		char *search_group_name = 0;
		Cmiss_field_id calculate_values_field = 0;
		Cmiss_field_id find_element_xi_field = 0;
		Cmiss_field_id texture_coordinates_field = 0;
		char find_nearest_flag = 0;
		char find_exact_flag = 0;
		char use_point_five_when_out_of_bounds_flag = 0;
		char fail_when_out_of_bounds_flag = 0;
		int use_point_five_when_out_of_bounds = 0;
		int element_dimension = 0;
		/* Maintain the existing behaviour as the default */
		int find_nearest = 0;
		/* get valid parameters for composite field */
		if (field_modify->get_field())
		{
			Computed_field_compose* compose_core =
				dynamic_cast<Computed_field_compose*>(field_modify->get_field()->core);
			if (compose_core)
			{
				return_code = compose_core->get_type(
					&calculate_values_field, &find_element_xi_field,
					&texture_coordinates_field, &mesh,
					&find_nearest, &use_point_five_when_out_of_bounds);
				if (mesh)
				{
					Cmiss_mesh_access(mesh);
					element_dimension = Cmiss_mesh_get_dimension(mesh);
				}
			}
		}
		if (return_code)
		{
			/* must access objects for set functions */
			if (calculate_values_field)
			{
				ACCESS(Computed_field)(calculate_values_field);
			}
			if (find_element_xi_field)
			{
				ACCESS(Computed_field)(find_element_xi_field);
			}
			if (texture_coordinates_field)
			{
				ACCESS(Computed_field)(texture_coordinates_field);
			}

			option_table = CREATE(Option_table)();
			Option_table_add_help(option_table,
				"The value of a compose field is found by evaluating the <texture_coordinates_field>, "
				"then searching for matching values of the <find_element_xi_field> in the elements of "
				"the <mesh> (alternatively specified by <group> and <element_dimension>) and then "
				"finally evaluating the <calculate_values_field> at this found location.  You can "
				"specify the outcome if the matching values cannot be found in the mesh with "
				"<use_point_five_when_out_of_bounds> or <fail_when_out_of_bounds>.  See examples "
				"a/resample_texture or a/create_slices where the compose field is used to find the "
				"equivalent coordinate in another element to evaluate a texture.");
			/* calculate_values_field */
			set_calculate_values_field_data.computed_field_manager =
				field_modify->get_field_manager();
			set_calculate_values_field_data.conditional_function =
				Computed_field_has_numerical_components;
			set_calculate_values_field_data.conditional_function_user_data =
				(void *)NULL;
			Option_table_add_entry(option_table, "calculate_values_field",
				&calculate_values_field, &set_calculate_values_field_data,
				set_Computed_field_conditional);
			Option_table_add_int_positive_entry(option_table,"element_dimension",
				&element_dimension);
			/* find_element_xi_field */
			set_find_element_xi_field_data.computed_field_manager =
				field_modify->get_field_manager();
			set_find_element_xi_field_data.conditional_function =
				Computed_field_has_numerical_components;
			set_find_element_xi_field_data.conditional_function_user_data =
				(void *)NULL;
			Option_table_add_entry(option_table, "find_element_xi_field",
				&find_element_xi_field, &set_find_element_xi_field_data,
				set_Computed_field_conditional);
			find_option_table=CREATE(Option_table)();
			Option_table_add_char_flag_entry(find_option_table,"find_nearest",
				&find_nearest_flag);
			Option_table_add_char_flag_entry(find_option_table,"find_exact",
				&find_exact_flag);
			Option_table_add_suboption_table(option_table, find_option_table);
			/* group */
			Option_table_add_string_entry(option_table, "group",
				 &search_group_name, " GROUP_NAME");
			// mesh
			Option_table_add_mesh_entry(option_table, "mesh", field_modify->get_region(), &mesh);
			/* texture_coordinates_field */
			set_texture_coordinates_field_data.computed_field_manager =
				field_modify->get_field_manager();
			set_texture_coordinates_field_data.conditional_function =
				Computed_field_has_numerical_components;
			set_texture_coordinates_field_data.conditional_function_user_data =
				(void *)NULL;
			Option_table_add_entry(option_table, "texture_coordinates_field",
				&texture_coordinates_field, &set_texture_coordinates_field_data,
				set_Computed_field_conditional);
			out_of_bounds_option_table=CREATE(Option_table)();
			/* use_point_five_when_out_of_bounds */
			Option_table_add_char_flag_entry(out_of_bounds_option_table,
				"use_point_five_when_out_of_bounds",
				&use_point_five_when_out_of_bounds_flag);
			Option_table_add_char_flag_entry(out_of_bounds_option_table,
				"fail_when_out_of_bounds",
				&fail_when_out_of_bounds_flag);
			Option_table_add_suboption_table(option_table, out_of_bounds_option_table);
			return_code = Option_table_multi_parse(option_table, state);

			if (return_code && !mesh)
			{
				mesh = Cmiss_field_module_find_mesh_by_dimension(
					field_modify->get_field_module(), element_dimension);
				if (search_group_name)
				{
					Cmiss_field_id group_field = Cmiss_field_module_find_field_by_name(field_modify->get_field_module(), search_group_name);
					Cmiss_field_group_id group = Cmiss_field_cast_group(group_field);
					Cmiss_field_element_group_id element_group = Cmiss_field_group_get_element_group(group, mesh);
					Cmiss_mesh_destroy(&mesh);
					mesh = Cmiss_mesh_group_base_cast(Cmiss_field_element_group_get_mesh(element_group));
					Cmiss_field_element_group_destroy(&element_group);
					Cmiss_field_group_destroy(&group);
					Cmiss_field_destroy(&group_field);
				}
			}
			if (return_code && !mesh)
			{
				display_message(ERROR_MESSAGE, "You must specify a mesh (or element_dimension and optional group).");
				return_code = 0;
			}
			if (return_code)
			{
				if (find_nearest_flag && find_exact_flag)
				{
					display_message(ERROR_MESSAGE,
						"Specify only one of find_nearest and find_exact");
					return_code = 0;
				}
				if (find_nearest_flag)
				{
					find_nearest = 1;
				}
				else if (find_exact_flag)
				{
					find_nearest = 0;
				}
				if (use_point_five_when_out_of_bounds_flag &&
					fail_when_out_of_bounds_flag)
				{
					display_message(ERROR_MESSAGE,
						"Specify only one of use_point_five_when_out_of_bounds "
						"and fail_when_out_of_bounds");
					return_code = 0;
				}
				if (use_point_five_when_out_of_bounds_flag)
				{
					use_point_five_when_out_of_bounds = 1;
				}
				else if (fail_when_out_of_bounds_flag)
				{
					use_point_five_when_out_of_bounds = 0;
				}
			}
			if (return_code)
			{
				return_code = field_modify->update_field_and_deaccess(
					Computed_field_create_compose(field_modify->get_field_module(),
						texture_coordinates_field, find_element_xi_field,
						calculate_values_field, mesh,
						find_nearest, use_point_five_when_out_of_bounds));
			}
			if (!return_code)
			{
				if ((!state->current_token) ||
					(strcmp(PARSER_HELP_STRING, state->current_token)&&
						strcmp(PARSER_RECURSIVE_HELP_STRING, state->current_token)))
				{
					/* error */
					display_message(ERROR_MESSAGE,
						"define_Computed_field_type_compose.  Failed");
				}
			}
			Cmiss_mesh_destroy(&mesh);
			if (calculate_values_field)
			{
				DEACCESS(Computed_field)(&calculate_values_field);
			}
			if (find_element_xi_field)
			{
				DEACCESS(Computed_field)(&find_element_xi_field);
			}
			if (search_group_name)
			{
				DEALLOCATE(search_group_name);
			}
			if (texture_coordinates_field)
			{
				DEACCESS(Computed_field)(&texture_coordinates_field);
			}
			DESTROY(Option_table)(&option_table);
		}
	}
	else
	{
		display_message(ERROR_MESSAGE,
			"define_Computed_field_type_compose.  Invalid argument(s)");
		return_code = 0;
	}
	LEAVE;

	return (return_code);
} /* define_Computed_field_type_compose */
int define_Computed_field_type_xi_texture_coordinates(Parse_state *state,
	void *field_modify_void,void *computed_field_integration_package_void)
/*******************************************************************************
LAST MODIFIED : 24 August 2006

DESCRIPTION :
Converts <field> into type COMPUTED_FIELD_XI_TEXTURE_COORDINATES (if it is not already)
and allows its contents to be modified.
==============================================================================*/
{
	int return_code = 1;
	ENTER(define_Computed_field_type_xi_texture_coordinates);
	Computed_field_modify_data *field_modify = reinterpret_cast<Computed_field_modify_data *>(field_modify_void);
	USE_PARAMETER(computed_field_integration_package_void);
	if (state && field_modify)
	{
		cmzn_region_id region = field_modify->get_region();
		cmzn_mesh_id mesh = 0;
		int seed_element_identifier = 0;
		char *group_name = 0;

		Option_table *option_table = CREATE(Option_table)();
		// mesh
		Option_table_add_mesh_entry(option_table, "mesh", region, &mesh);
		/* region - legacy group name */
		Option_table_add_string_entry(option_table, "region", &group_name, " GROUP_NAME(OBSOLETE)");
		/* seed_element */
		Option_table_add_int_non_negative_entry(option_table, "seed_element",
			&seed_element_identifier);
		return_code = Option_table_multi_parse(option_table,state);
		DESTROY(Option_table)(&option_table);

		if (return_code && !mesh)
		{
			int dimension = FE_region_get_highest_dimension(cmzn_region_get_FE_region(region));
			mesh = cmzn_fieldmodule_find_mesh_by_dimension(field_modify->get_field_module(), dimension);
			if (group_name)
			{
				cmzn_field_id group_field = cmzn_fieldmodule_find_field_by_name(field_modify->get_field_module(), group_name);
				cmzn_field_group_id group = cmzn_field_cast_group(group_field);
				cmzn_field_element_group_id element_group = cmzn_field_group_get_field_element_group(group, mesh);
				cmzn_mesh_destroy(&mesh);
				mesh = cmzn_mesh_group_base_cast(cmzn_field_element_group_get_mesh_group(element_group));
				cmzn_field_element_group_destroy(&element_group);
				cmzn_field_group_destroy(&group);
				cmzn_field_destroy(&group_field);
			}
		}
		if (return_code && !mesh)
		{
			display_message(ERROR_MESSAGE, "Must specify mesh.");
			return_code = 0;
		}
		cmzn_element_id seed_element = 0;
		if (return_code)
		{
			seed_element = cmzn_mesh_find_element_by_identifier(mesh, seed_element_identifier);
			if (!seed_element)
			{
				display_message(ERROR_MESSAGE, "Could not find seed_element %d in mesh.", seed_element_identifier);
				return_code = 0;
			}
		}
		// use temporary field module to supply different defaults
		cmzn_field_id coordinate_field = FIRST_OBJECT_IN_MANAGER_THAT(Computed_field)(
			Computed_field_is_type_xi_coordinates, (void *)NULL,
			field_modify->get_field_manager());
		if (coordinate_field)
		{
			ACCESS(Computed_field)(coordinate_field);
		}
		else
		{
			if ((!state->current_token) ||
				(strcmp(PARSER_HELP_STRING, state->current_token)&&
					strcmp(PARSER_RECURSIVE_HELP_STRING, state->current_token)))
			{
				display_message(ERROR_MESSAGE,
					"define_Computed_field_type_xi_texture_coordinates.  xi field not found");
			}
			return_code = 0;
		}
		double value = 1.0;
		cmzn_fieldmodule *temp_field_module = cmzn_region_get_fieldmodule(region);
		cmzn_fieldmodule_set_field_name(temp_field_module, "constant_1.0");
		Computed_field *integrand = Computed_field_create_constant(temp_field_module,
			/*number_of_components*/1, &value);
		cmzn_fieldmodule_destroy(&temp_field_module);
		if (NULL == integrand)
		{
			display_message(ERROR_MESSAGE,
				"define_Computed_field_type_xi_texture_coordinates.  Unable to create constant field");
			return_code = 0;
		}
		if (return_code)
		{
			return_code = field_modify->update_field_and_deaccess(
				Computed_field_create_integration(field_modify->get_field_module(),
					mesh, seed_element, integrand, /*magnitude_coordinates*/0, coordinate_field));
		}
		if (group_name)
		{
			DEALLOCATE(group_name);
		}
		cmzn_element_destroy(&seed_element);
		cmzn_mesh_destroy(&mesh);
		cmzn_field_destroy(&coordinate_field);
		cmzn_field_destroy(&integrand);
	}
	else
	{
		display_message(ERROR_MESSAGE,
			"define_Computed_field_type_xi_texture_coordinates.  Invalid argument(s)");
		return_code=0;
	}
	LEAVE;

	return (return_code);
}