/*-----------------------------------------------------------------------------
        File:           UgGeomInterferCheck.c
        Description:    Interference Checking of Parts and Assemblies
 
            PTC             File
   Date   Version   Author  Vers  Comment
--------- -------  -------- ----- ---------------------------------------------
04-dec-97 H-02-02   Stefan   $$1  setup
-----------------------------------------------------------------------------*/

/*---------------------- Pro/Develop Includes ------------------------*/
#include        "prodevelop.h"
#include        "user_wchar_t.h"
#include        "proincludes.h"
#include        "select3d.h"
#include        "prographics.h"
#include        "user_error.h"
#include        "pro_interf.h"

/*---------------------- Pro/Toolkit Includes ------------------------*/
#include <ProToolkit.h>
#include "ProMdl.h"
#include "ProUtil.h"

/*---------------------- Function Prototypes -------------------------*/
ProError user_surf_clear ();
ProError user_dist_manifolds ();
ProError user_part_interference ();
ProError user_global_interference ();
int user_dump_interferences ();
int user_dump_mdl();

/*------------------------- External Data ----------------------------*/
extern char *user_gen_filename();  


/*================================================================*\
FUNCTION  : user_surf_clear
PURPOSE   : Computes the clearance between two surfaces.
\*================================================================*/
ProError user_surf_clear ()
{
    int 	status;
    int         interf;
    double      distance, coord[2][3];
    Select3d   *sel;
    ProFileName msg_fil;

    ProStringToWstring( msg_fil, "msg_uggeom.txt" );
    while (1)
    {
        status = ProMessageDisplay (msg_fil, "USER Select a face");
	ERROR_CHECK("user_surf_clear","ProMessageDisplay",status);
        if (pro_select ("face", 2, &sel, 0, 0) <= 1) 
            return (PRO_TK_GENERAL_ERROR);

/*----------------------------------------------------------------*\
        Computes the clearance between the two selected surfaces.
\*----------------------------------------------------------------*/
        status = pro_compute_clearance (sel, PRO_SURFACE_CLEARANCE, &distance,
                                        &interf, coord);
   	ERROR_CHECK("user_surf_clear","pro_compute_clearance",(status <=0));

        status = ProMessageDisplay (msg_fil, "USER Distance is %0(5.3)f", &distance);
	ERROR_CHECK("user_surf_clear","ProMessageDisplay",status);

        if (interf)
	{
            status = ProMessageDisplay (msg_fil, "USER Interference exists");
	    ERROR_CHECK("user_surf_clear","ProMessageDisplay",status);
	}
    }
    return (PRO_TK_NO_ERROR);
}

/*================================================================*\
FUNCTION  : user_dist_manifolds
PURPOSE   : Computes the critical distance between two objects.
\*================================================================*/
ProError user_dist_manifolds ()
{
    int          status, old_color;
    Select3d    *sel;
    double       uvpar[2][2], xyz[2][3], distance;
    ProFileName msg_fil;

    ProStringToWstring( msg_fil, "msg_uggeom.txt" );
   
    status = ProMessageDisplay (msg_fil, "USER %0s", "Select two entities");
    ERROR_CHECK("user_dist_manifolds","ProMessageDisplay",status);

    if (pro_select ("point,edge,curve,surface", 2, &sel, 0, 0) < 2)
        return (PRO_TK_GENERAL_ERROR);

/*----------------------------------------------------------------*\
    Compute the distance between the two manifolds.
\*----------------------------------------------------------------*/
    status = pro_dist_manifolds (&sel[0], &sel[1], uvpar, xyz,
             &distance);
    ERROR_CHECK("user_dist_manifolds","pro_dist_manifolds",(status <=0));

    if (status)
    {
        status = ProMessageDisplay (msg_fil, "USER Distance is %0(5.3)f", 
				&distance);
	ERROR_CHECK("user_dist_manifolds","ProMessageDisplay",status);
    }
    else
    {
        status = ProMessageDisplay (msg_fil, "USER %0s", 
					"No min/max distances found");
	ERROR_CHECK("user_dist_manifolds","ProMessageDisplay",status);
    }
    return (PRO_TK_NO_ERROR);
}

/*================================================================*\
FUNCTION  : user_part_interference
PURPOSE   : Computes the interference between two parts.
\*================================================================*/
ProError user_part_interference ()
{
    int		  status;
    Select3d     *sel;
    Prohandle    *intf_surfs;
    int           n_surfs, i;
    wchar_t       w_str[5];
    char          str[100], a_str[5];
    double        volume;
    FILE         *fp;
    char          fname[PRODEV_NAME_SIZE+4];
    wchar_t       w_fname[PRODEV_NAME_SIZE+4];
    Prohandle	  p_model;
    ProFileName msg_fil;

    p_model = pro_get_current_object();
    ERROR_CHECK("user_part_interference","pro_get_current_object",
			(p_model == NULL));
    if (p_model == NULL) return (PRO_TK_E_NOT_FOUND);

    ProStringToWstring( msg_fil, "msg_uggeom.txt" );
    status = ProMessageDisplay (msg_fil, "USER %0s", "Select two parts");
    ERROR_CHECK("user_part_interference","ProMessageDisplay",status);

    if (pro_select ("part", 2, &sel, 0, 0) <= 1)
        return (PRO_TK_GENERAL_ERROR);

/*----------------------------------------------------------------*\
    Compute the interference between the two parts.
\*----------------------------------------------------------------*/
    status = pro_compute_interference (sel, 0, &intf_surfs, 
        &n_surfs);
    ERROR_CHECK("user_part_interference","pro_compute_interference",
		(status != PRODEV_NO_ERROR));
    if (status != PRODEV_NO_ERROR)
        return (PRO_TK_GENERAL_ERROR);

    if (n_surfs == 0)
    {
        status = ProMessageDisplay (msg_fil, "USER %0s", 
				"No interference was detected.");
	ERROR_CHECK("user_part_interference","ProMessageDisplay",status);
        return (PRO_TK_NO_ERROR);
    }

    sprintf (str, "%d interference surfaces found. Display? [Y]:",
         n_surfs);
    status = ProMessageDisplay (msg_fil,"USER %0s", str);
    ERROR_CHECK("user_part_interference","ProMessageDisplay",status);

    if (!ProMessageStringRead (4, w_str))
    {
        ProWstringToString (a_str, w_str);
        if (a_str[0] != 'y' || a_str[0] != 'Y')
            return (PRO_TK_NO_ERROR);
    }

    user_gen_filename (p_model, ".intf", fname);
    if ((fp = fopen (fname, "w")) == NULL)
        return (PRO_TK_GENERAL_ERROR);
    fprintf (fp, "Interference in ");
    user_dump_mdl (fp, p_model);
    fprintf (fp, "\n\n");

/*----------------------------------------------------------------*\
    Compute the interference volume.
\*----------------------------------------------------------------*/
    status = pro_compute_volume (intf_surfs, n_surfs, &volume);
    ERROR_CHECK("user_part_interference","pro_compute_volume",
		(status <=0));
    user_dump_interferences (fp, sel, volume);

/*----------------------------------------------------------------*\
    Highlight the interference regions.
\*----------------------------------------------------------------*/
    status = pro_display_interf_volume (intf_surfs, n_surfs,
          EDGE_HIGHLITE_COLOR);
    ERROR_CHECK("user_part_interference","pro_display_interf_volume",
		(status <=0));

    sprintf (str, "Total Interference Volume = %lf", volume);
    status = ProMessageDisplay (msg_fil, "USER %0s", str);
    ERROR_CHECK("user_part_interference","ProMessageDisplay",status);

/*----------------------------------------------------------------*\
    Release the memory for the interference volume.
\*----------------------------------------------------------------*/
    status = pro_interference_volume_release (intf_surfs, n_surfs);
    ERROR_CHECK("user_part_interference","pro_interference_volume_release",
		(status <=0));
    fclose (fp);

    ProStringToWstring (w_fname, fname);
    status = ProInfoWindowDisplay (w_fname, NULL, NULL);
    ERROR_CHECK("user_part_interference","ProInfoWindowDisplay",status);

    return (PRO_TK_NO_ERROR);
}

/*================================================================*\
FUNCTION  : user_global_interference
PURPOSE   : Computes the global interference within an assembly.
\*================================================================*/
ProError user_global_interference ()
{
    int 		   status;
    Select3d              *sel;
    Prohandle            **intf_part_surfs;
    int                    n_intf_parts, *n_part_surfs, i;
    Interference_parts    *intf_parts;
    wchar_t                w_str[5];
    char                   str[100], a_str[5];
    double                 volume;
    FILE                  *fp;
    char                   fname[PRODEV_NAME_SIZE+4];
    wchar_t                w_fname[PRODEV_NAME_SIZE+4];
    ProFileName            msg_fil;
    Prohandle 		   p_model;

    ProStringToWstring( msg_fil, "msg_uggeom.txt" );

    p_model = pro_get_current_object();
    ERROR_CHECK("user_global_interference","pro_get_current_object",
                        (p_model == NULL));
    if (p_model == NULL) return (PRO_TK_E_NOT_FOUND);

/*----------------------------------------------------------------*\
    Compute the interference within the assembly.
\*----------------------------------------------------------------*/
    status = pro_compute_global_interference (p_model, 0, &n_intf_parts,
          &intf_parts, &intf_part_surfs, &n_part_surfs);
    ERROR_CHECK("user_global_interference","pro_compute_global_interference",
		(status <=0));

    if (status != PRODEV_NO_ERROR)
        return (PRO_TK_GENERAL_ERROR);

    if (n_intf_parts == 0)
    {
       status = ProMessageDisplay (msg_fil, "USER %0s", 
				"No interference was detected.");
           ERROR_CHECK("user_global_interference","ProMessageDisplay",status);
    }

    sprintf (str, 
     "%d interfering part pairs found. Display interference pair volumes? [Y]:",
     n_intf_parts);

    ProMessageDisplay (msg_fil, "USER %0s", str);
    if (!ProMessageStringRead (4, w_str))
    {
        ProWstringToString (a_str, w_str);
        if (a_str[0] != 'y' || a_str[0] != 'Y')
            return (PRO_TK_NO_ERROR);
    }
    user_gen_filename (p_model, ".intf", fname);
    if ((fp = fopen (fname, "w")) == NULL)
        return (PRO_TK_GENERAL_ERROR);
    fprintf (fp, "Interference in ");
    user_dump_mdl (fp, p_model);
    fprintf (fp, "\n\n");
    for (i = 0; i < n_intf_parts; i++)
    {

/*----------------------------------------------------------------*\
        Compute the interference volumes.
\*----------------------------------------------------------------*/
        status = pro_compute_volume (intf_part_surfs[i],
              n_part_surfs[i], &volume);
	ERROR_CHECK("user_global_interference","pro_compute_volume",
			(status <=0));
        user_dump_interferences (fp,
              (Select3d *)&(intf_parts[i].part1_sel), volume);

/*----------------------------------------------------------------*\
        Highlight the interference regions.
\*----------------------------------------------------------------*/
        status = pro_display_interf_volume (intf_part_surfs[i],
              n_part_surfs[i], EDGE_HIGHLITE_COLOR);
	ERROR_CHECK("user_global_interference","pro_display_interf_volume",
			(status <=0));

        sprintf (str, "Interference pair %d of %d: Volume = %0.2lf: \
            Continue? [y]:", i+1, n_intf_parts, volume);
        status = ProMessageDisplay (msg_fil, "USER %0s", str);
	ERROR_CHECK("user_global_interference","ProMessageDisplay",status);

        if (!ProMessageStringRead (4, w_str))
        {
            ProWstringToString (a_str, w_str);
            if (a_str[0] != 'y' || a_str[0] != 'Y')
            {
                fclose (fp);
                status = pro_interference_volume_release(
                      intf_part_surfs[i], n_part_surfs[i]);
                return (PRO_TK_NO_ERROR);
            }
        }

/*----------------------------------------------------------------*\
        Release the memory for the interference volume.
\*----------------------------------------------------------------*/
        status = pro_interference_volume_release (intf_part_surfs[i], 
              n_part_surfs[i]);
    }
    fclose (fp);

    ProStringToWstring (w_fname, fname);
    status = ProInfoWindowDisplay (w_fname, NULL, NULL);
    ERROR_CHECK("user_global_interference","ProInfoWindowDisplay",status);

    return (PRO_TK_NO_ERROR);
}


/*================================================================*\
FUNCTION  : user_dump_interferences
PURPOSE   : Writes the interference information into a file.
\*================================================================*/
int user_dump_interferences (fp, intf, volume)
FILE          *fp;
Select3d       intf[];
double         volume;
{
    int m;
    
    fprintf (fp, "Interfering Parts:\n");
    fprintf (fp, "\t ");
    user_dump_mdl (fp, intf[0].part_ptr);
    fprintf (fp, "\tmemb_id_tab[");
    for (m = 0; m < intf[0].memb_num; m++)
    {
        fprintf (fp, "%d", intf[0].memb_id_tab[m]);
        if (m < intf[0].memb_num-1)
            fprintf (fp, ",");
    }
    fprintf (fp, "]\n");
    fprintf (fp, "\t ");
    user_dump_mdl (fp, intf[1].part_ptr);
    fprintf (fp, "\tmemb_id_tab[");
    for (m = 0; m < intf[1].memb_num; m++)
    {
        fprintf (fp, "%d", intf[1].memb_id_tab[m]);
        if (m < intf[1].memb_num-1)
            fprintf (fp, ",");
    }
    fprintf (fp, "]\n");
    fprintf (fp, "\tInterfering Volume: %0.2lf\n\n", volume);
    return(0);
}

int user_dump_mdl (fp, p_model)
FILE          *fp;
Prohandle      p_model;
{
    ProMdldata           info;
    char                 name[80], type[10];

    if (p_model == NULL)
        return (0);
    ProMdlDataGet (p_model, &info);
    fprintf (fp, "%s.%s:", ProWstringToString (name, info.name),
        ProWstringToString (type, info.type));
    return (0);
}
