/*
	Copyright (c) 2024 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved.
*/


/*--------------------------------------------------------------------*\
Pro/TOOLKIT includes
\*--------------------------------------------------------------------*/
#include <ProToolkit.h>
#include <ProObjects.h>
#include <ProAnalysis.h>
#include <ProModelitem.h>
#include <ProMessage.h>
#include <ProArray.h>
#include <ProPoint.h>
#include <ProDtmPnt.h>
#include <ProUtil.h>
#include <ProEdge.h>
#include <ProEdgedata.h>

#include <TestAnalysis.h>

#define UV_FREQ 1

typedef ProUvParam ProUvParam2[2];

static ProFileName analysis_msgfile; 

/*--------------------------------------------------------------------*\
  Application includes
\*--------------------------------------------------------------------*/

static void XyzDataEval(Surfacedata_t *data, ProUvParam uv, ProVector xyz);

/*====================================================================*\
  FUNCTION : ProTestSurfaceUiAction()
  PURPOSE  : Callback for UI action of analysis feature
\*====================================================================*/
ProError ProTestSurfaceUiAction (
				 ProAnalysis analysis)
{
  Surfacedata_t *data;
  ProError err = PRO_TK_NO_ERROR;
  ProSelection *sel = NULL;
  int n_sel;
  ProGeomitem feature;
  ProSurface pln_surface;
  ProSrftype surface_type;
  FILE *fp;

  data = (Surfacedata_t *)calloc(1, sizeof(Surfacedata_t));
  sel = (ProSelection *)calloc(1, sizeof(ProSelection));

  TEST_CALL_REPORT ("ProAnalysisUiAction()====", 
		    "ProTestSurfaceUiAction()", err, err != PRO_TK_NO_ERROR);

  /*--------------------------------------------------------------------*\
  Ask the user to select a surface. 
  \*--------------------------------------------------------------------*/

  ProStringToWstring (analysis_msgfile, (char *)"analysis_msg.txt");

  ProMessageDisplay (analysis_msgfile, (char *)"USER Select a surface feature");

  if (ProSelect ((char *)"surface", 1, NULL, NULL, NULL, NULL, &sel, &n_sel) 
      != PRO_TK_NO_ERROR || n_sel < 0)
    return (PRO_TK_USER_ABORT);
    

  err = ProSelectionModelitemGet(*sel, &feature);
  TEST_CALL_REPORT ("ProSelectionModelitemGet()", 
		    "ProTestSurfaceUiAction()", err, err != PRO_TK_NO_ERROR);
  
  if ( err != PRO_TK_NO_ERROR )
    return err; 
    

  err = ProGeomitemToSurface (&feature, &pln_surface);
  TEST_CALL_REPORT ("ProGeomitemToSurface()", 
		    "ProTestSurfaceUiAction()", err, err != PRO_TK_NO_ERROR);

  /*--------------------------------------------------------------------*\
  Verify the selection of a surface feature.
  \*--------------------------------------------------------------------*/
  err = ProSurfaceTypeGet (pln_surface, &surface_type);
  TEST_CALL_REPORT ("ProSurfaceTypeGet()", 
		    "ProTestSurfaceUiAction()", err, err != PRO_TK_NO_ERROR);   
  /*--------------------------------------------------------------------*\
  Get the pointer to the data stored for this analysis feature,
  and set the surface in it.
  \*--------------------------------------------------------------------*/
  err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
  TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
		    "ProTestSurfaceUiAction()", err, err != PRO_TK_NO_ERROR);
  if (err != PRO_TK_NO_ERROR)
    return(PRO_TK_USER_ABORT);

  memcpy (&data->surface, &feature, sizeof (ProGeomitem));
  
  err = ProAnalysisInfoSet(analysis, data);
  TEST_CALL_REPORT ("ProAnalysisInfoSet()", 
		    "ProTestSurfaceInfoallocAction()", err, err != PRO_TK_NO_ERROR);
  
  return(PRO_TK_NO_ERROR);

    
}

/*====================================================================*\
FUNCTION : ProTestSurfaceDimsAction()
PURPOSE  : Create dimentions
\*====================================================================*/
ProError ProTestSurfaceDimsAction(
				  ProAnalysis analysis,
				  double **dims)
{
  Surfacedata_t *data;
  ProError err = PRO_TK_NO_ERROR;
  FILE *fp;

  TEST_CALL_REPORT ("ProAnalysisDimsAction()====", 
		    "ProTestSurfaceDimsAction()", err, err != PRO_TK_NO_ERROR);

  /*---------------------------------------------------------*\
  Get the analysis data for this structure
  \*---------------------------------------------------------*/
  err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
  TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
		    "ProTestSurfaceDimsAction()", err, err != PRO_TK_NO_ERROR);
  if (err != PRO_TK_NO_ERROR)
    return(PRO_TK_USER_ABORT);
    
  return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestSurfaceInfoallocAction()
PURPOSE  : Callback to allocate application data needed to describe
		the analysis feature
\*====================================================================*/
ProError ProTestSurfaceInfoallocAction(
				       ProAnalysis analysis)
{
  Surfacedata_t *data;
  ProError err = PRO_TK_NO_ERROR;

  TEST_CALL_REPORT ("ProAnalysisInfoallocAction()====", 
		    "ProTestSurfaceInfoallocAction()", err, err != PRO_TK_NO_ERROR);
  /*--------------------------------------------------------------------*\
  Allocate a data structure
  \*--------------------------------------------------------------------*/
  data = (Surfacedata_t*)calloc(1, sizeof(Surfacedata_t));
  if (data == NULL)
    return PRO_TK_USER_ABORT;

  /*--------------------------------------------------------------------*\
  Put the data pointer into the analysis
  \*--------------------------------------------------------------------*/
  err = ProAnalysisInfoSet(analysis, (ProAppData)data);
  TEST_CALL_REPORT ("ProAnalysisInfoSet()", 
		    "ProTestSurfaceInfoallocAction()", err, err != PRO_TK_NO_ERROR);

  return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestSurfaceInfofreeAction()
PURPOSE  : Callback to free the application data
\*====================================================================*/
ProError ProTestSurfaceInfofreeAction(
				      ProAnalysis analysis)
{
  Surfacedata_t *data;
  ProError err = PRO_TK_NO_ERROR;

  TEST_CALL_REPORT ("ProAnalysisInfofreeAction()====", 
		    "ProTestSurfaceInfofreeAction()", err, err != PRO_TK_NO_ERROR);
  /*--------------------------------------------------------------------*\
  Get the data pointer from the analysis
  \*--------------------------------------------------------------------*/
  err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
  TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
		    "ProTestSurfaceInfofreeAction()", err, err != PRO_TK_NO_ERROR);
  if (err != PRO_TK_NO_ERROR)
    return(PRO_TK_GENERAL_ERROR);

 /*--------------------------------------------------------------------*\
  Free the data
  \*--------------------------------------------------------------------*/
  free (data);

  /*--------------------------------------------------------------------*\
  Set the data pointer in the analysis to NULL
  \*--------------------------------------------------------------------*/
  err = ProAnalysisInfoSet (analysis, NULL);
  TEST_CALL_REPORT ("ProAnalysisInfoSet()", 
		    "ProTestSurfaceInfofreeAction()", err, err != PRO_TK_NO_ERROR);

  return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestSurfaceCompcheckAction()
PURPOSE  : Callback to tell Pro/E whether computation can be performed
		in this analysis feature
\*====================================================================*/
ProError ProTestSurfaceCompcheckAction(
				       ProAnalysis analysis)
{
  ProError err = PRO_TK_NO_ERROR;

  TEST_CALL_REPORT ("ProAnalysisCompcheckAction()====", 
		    "ProTestSurfaceCompcheckAction()", err, err != PRO_TK_NO_ERROR);
  
  return PRO_TK_NO_ERROR;
}

/*====================================================================*\
FUNCTION : ProTestSurfaceComputeAction()
PURPOSE  : Callback to perform the analysis feature computation
\*====================================================================*/
ProError ProTestSurfaceComputeAction(
				     ProAnalysis analysis)
{
  ProError err = PRO_TK_NO_ERROR;
  double offset;
  Surfacedata_t *s_data;
  ProSurface *pln_surface = NULL;
  ProGeomitemdata *surf_data = NULL;
  FILE *fp;

  s_data = (Surfacedata_t *)calloc(1, sizeof(Surfacedata_t));
  pln_surface = (ProSurface *)calloc(1, sizeof(ProSurface));

  surf_data = (ProGeomitemdata *)calloc(1, sizeof(ProGeomitemdata));

  TEST_CALL_REPORT ("ProAnalysisComputeAction====)", 
		    "ProTestSurfaceComputeAction()", err, err != PRO_TK_NO_ERROR);

  /*--------------------------------------------------------------------*\
  Get the application data from the analysis
  \*--------------------------------------------------------------------*/
  err = ProAnalysisInfoGet (analysis, (ProAppData*)&s_data);
  TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
		    "ProTestSurfaceComputeAction()", err, err != PRO_TK_NO_ERROR);
  if (err != PRO_TK_NO_ERROR)
    return(PRO_TK_GENERAL_ERROR);

  err = ProGeomitemToSurface (&s_data->surface, pln_surface);
  TEST_CALL_REPORT ("ProGeomitemToSurface()", 
		    "ProTestSurfaceComputeAction()", err, err != PRO_TK_NO_ERROR);
  
  err = ProSurfaceDataGet(*pln_surface, &surf_data);
  TEST_CALL_REPORT ("ProSurfaceDataGet()", 
		    "ProTestSurfaceComputeAction()", err, err != PRO_TK_NO_ERROR);

  s_data->surf_data = *(surf_data->data.p_surface_data);

  err = ProAnalysisInfoSet (analysis, s_data);
  TEST_CALL_REPORT ("ProAnalysisInfoSet()", 
		    "ProTestSurfaceComputeAction()", err, err != PRO_TK_NO_ERROR);

  return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestSurfaceDisplayAction()
PURPOSE  : Callback to display the results of the analysis computation
\*====================================================================*/
ProError ProTestSurfaceDisplayAction(
				     ProAnalysis analysis)
{
  Surfacedata_t *data;
  ProUvParam  min_uv, max_uv, uv;
  double u_incr, v_incr;
  ProVector xyz;
  ProPoint3d **pnt_arr, **pnt_arr1;
  ProVector pos;
  ProError err = PRO_TK_NO_ERROR;
  ProEnttype type;
  int i, j, k, num, n_pnt;
  FILE *fp;
  

  TEST_CALL_REPORT ("ProAnalysisDisplayAction()====", 
		    "ProTestSurfaceDisplayAction()", err, err != PRO_TK_NO_ERROR);
 
  /*--------------------------------------------------------------------*\
  Get the application data from the analysis
  \*--------------------------------------------------------------------*/
  err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
  TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
		    "ProTestSurfaceDisplayAction()", err, err != PRO_TK_NO_ERROR);
  if (err != PRO_TK_NO_ERROR)
    return(PRO_TK_GENERAL_ERROR);

  return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestSurfaceOutputAction()
PURPOSE  : Callback to write textual information about the result of
		the computation
\*====================================================================*/
ProError ProTestSurfaceOutputAction(
				    ProAnalysis analysis,
				    ProLine **lines)
{
  Surfacedata_t *data;
  ProError err = PRO_TK_NO_ERROR;
  ProCharLine buff;
  ProLine line;
  FILE *fp;

  TEST_CALL_REPORT ("ProAnalysisOutputAction()====", 
		    "ProTestSurfaceOutputAction()", err, err != PRO_TK_NO_ERROR);

  /*--------------------------------------------------------------------*\
  Get the application data from the analysis
  \*--------------------------------------------------------------------*/
  err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
  TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
		    "ProTestSurfaceOutputAction()", err, err != PRO_TK_NO_ERROR);
  if (err != PRO_TK_NO_ERROR)
    return(PRO_TK_GENERAL_ERROR);
  
  TEST_CALL_REPORT ("ProAnalysisOutputAction()====", 
		    "ProTestSurfaceOutputAction()", err, err != PRO_TK_NO_ERROR);

  return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestSurfaceSavecheckAction()
PURPOSE  : Callback to tell Pro/E whether the analysis application
		data can be saved
\*====================================================================*/
ProError ProTestSurfaceSavecheckAction(
    ProAnalysis analysis)
{
  return (PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestSurfaceInfosaveAction()
PURPOSE  : Callback to tell Pro/E what element references are required
		by the analysis feature
\*====================================================================*/
ProError ProTestSurfaceInfosaveAction(
    ProAnalysis analysis,
    ProFeature  *feature,
    ProSelection **references)
{
  ProError err = PRO_TK_NO_ERROR;
  Surfacedata_t *data;
  ProGeomitem surface;
  ProSelection sel;
  FILE *fp;
  
  TEST_CALL_REPORT ("ProAnalysisInfosaveAction()====", 
        "ProTestSurfaceInfoSaveAction()", err, err != PRO_TK_NO_ERROR);

  /*--------------------------------------------------------------------*\
  Get the application data from the analysis
  \*--------------------------------------------------------------------*/
  err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
  TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
		    "ProTestSurfaceInfosaveAction()", err, 
		    err != PRO_TK_NO_ERROR);
  if (err != PRO_TK_NO_ERROR)
    return(PRO_TK_GENERAL_ERROR);

  /*--------------------------------------------------------------------*\
  Output the reference to the surface
  \*--------------------------------------------------------------------*/
  /*err = ProGeomitemFeatureGet(&(data->surface), &surface);*/
  err = ProSelectionAlloc (NULL, &data->surface, &sel);
  TEST_CALL_REPORT ("ProSelectionAlloc()", 
		    "ProTestSurfaceInfosaveAction()", err, 
		    err != PRO_TK_NO_ERROR);
  
  err = ProArrayObjectAdd((ProArray*)references, -1, 1, &sel);
  TEST_CALL_REPORT ("ProArrayObjectAdd()", 
		    "ProTestSurfaceInfosaveAction()", err, 
		    err != PRO_TK_NO_ERROR);
  
  return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestSurfaceInforetrieveAction()
PURPOSE  : Callback to get the references Pro/E has stored with the
		analysis feature
\*====================================================================*/
ProError ProTestSurfaceInforetrieveAction(
    ProAnalysis analysis,
    ProFeature *feature,
    ProSelection *references)
{
  Surfacedata_t *data;
  ProSurface pln_surface = NULL;
  ProGeomitemdata *surf_data = NULL;
  ProError err = PRO_TK_NO_ERROR;
  FILE *fp;


  TEST_CALL_REPORT ("ProAnalysisInforetrieveAction()====", 
		    "ProTestSurfaceInforetrieveAction()", 
		    err, err != PRO_TK_NO_ERROR);
  
  surf_data = (ProGeomitemdata *)calloc(1, sizeof(ProGeomitemdata));

  err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
  TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
		    "ProTestSurfaceInforetrieveAction()", err, 
		    err != PRO_TK_NO_ERROR);
  if (err != PRO_TK_NO_ERROR)
    return(PRO_TK_GENERAL_ERROR);

    
  /*--------------------------------------------------------------------*\
  Copy the first reference to the application as the surface data structure
  \*--------------------------------------------------------------------*/
  err = ProSelectionModelitemGet(references[0], &data->surface);
  TEST_CALL_REPORT ("ProSelectionModelitemGet()", 
		    "ProTestSurfaceInforetrieveAction()", 
		    err, err != PRO_TK_NO_ERROR);
  
  err = ProGeomitemToSurface (&data->surface, &pln_surface);
  TEST_CALL_REPORT ("ProGeomitemToSurface()", 
		    "ProTestSurfaceComputeAction()", err, 
		    err != PRO_TK_NO_ERROR);
  
  err = ProSurfaceDataGet(pln_surface, &surf_data);
  TEST_CALL_REPORT ("ProSurfaceDataGet()", 
		    "ProTestSurfaceComputeAction()", err, err != PRO_TK_NO_ERROR);

  data->surf_data = *(surf_data->data.p_surface_data);

  err = ProAnalysisInfoSet (analysis, data);
  TEST_CALL_REPORT ("ProAnalysisInfoSet()", 
		    "ProTestSurfaceComputeAction()", err, err != PRO_TK_NO_ERROR);
  
  err = ProTestSurfaceDisplayAction(analysis);
  TEST_CALL_REPORT ("ProTestSurfaceDisplayAction()", 
		    "ProTestSurfaceComputeAction()", err, err != PRO_TK_NO_ERROR);

  if (surf_data != NULL)
  {
    err = ProGeomitemdataFree (&surf_data);
    TEST_CALL_REPORT ("ProGeomitemdataFree()", 
		    "ProTestSurfaceComputeAction()", err, err != PRO_TK_NO_ERROR);
  }

  return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestSurfaceInfocopyAction()
PURPOSE  : 
\*====================================================================*/
ProError ProTestSurfaceInfocopyAction(
    ProAnalysis from,
    ProAnalysis to)
{
    Surfacedata_t *fdata, *tdata;
    ProError err = PRO_TK_NO_ERROR;

    TEST_CALL_REPORT ("ProAnalysisInfocopyAction()", 
        "ProTestSurfaceInfocopyAction()", 
        err, err != PRO_TK_NO_ERROR);
   
    err = ProAnalysisInfoGet (from, (ProAppData*)&fdata);
    TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
        "ProTestSurfaceInfocopyAction()", 
        err, err != PRO_TK_NO_ERROR);
    if (err != PRO_TK_NO_ERROR)
        return(PRO_TK_GENERAL_ERROR);
    err = ProAnalysisInfoGet (to  , (ProAppData*)&tdata);
    TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
        "ProTestSurfaceInfocopyAction()", 
        err, err != PRO_TK_NO_ERROR);
    if (err != PRO_TK_NO_ERROR)
        return(PRO_TK_GENERAL_ERROR);

    memcpy(&tdata->surface, &fdata->surface, sizeof(ProGeomitem)); 

    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestSurfaceResultAction()
PURPOSE  : Callback to give Pro/E the feature parameters and geometry
		that the analysis feature must contain
\*====================================================================*/
ProError ProTestSurfaceResultAction(
				    ProAnalysis analysis,
				    ProBoolean names_only,
				    ProAnalysisParameter **parameters,
				    ProAnalysisGeomitem  **geometry)
{
  Surfacedata_t *data;
  ProSrftype type;
  ProVector xyz_min, xyz_max;
  ProUvParam min_uv, max_uv;
  ProSurfaceOrient orient;
  int *edge_ids, *surf_id;
  ProEdgeDir *dir;
  ProModelitem p_handle;
  ProEdge edge, *edge_neigh;
  ProSurface *surf_neigh;
  ProAnalysisGeomitem geomitem;
  ProAnalysisParameter param;
  ProUvParam uv[2], uvd1[2], uvd2[2], *uv_array;
  ProError err = PRO_TK_NO_ERROR;
  int num, i, j, n, id;
  double t;
  FILE *fp;
  ProSurfacedata  *temp_data;
  
  TEST_CALL_REPORT ("ProAnalysisResultAction====()", 
		    "ProTestSurfaceResultAction()", 
		    err, err != PRO_TK_NO_ERROR);

  /*--------------------------------------------------------------------*\
     Get the application data from the analysis
  \*--------------------------------------------------------------------*/
  err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
  TEST_CALL_REPORT ("ProAnalysisInfoGet()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
  if (err != PRO_TK_NO_ERROR)
    return(PRO_TK_GENERAL_ERROR);

  ProStringToWstring (param.name,(char *)"SURFACE");
  param.create = PRO_B_TRUE;
  ProStringToWstring (param.description,(char *)"Wireframe of Cyl Surf");
  param.values = NULL;

  /*---------------------------------------------------------------------*\
     Copy values from the surface data structure to the analysis surface 
     data structure
  \*---------------------------------------------------------------------*/
     
  ProStringToWstring (geomitem.name,(char *)"SURFACE");
  geomitem.create = PRO_B_TRUE;
  geomitem.type = PRO_ANALYSIS_SURFACE;

  err = ProArrayAlloc(1, sizeof(ProAnalysisEntity), 1, (ProArray *)&geomitem.shapes);
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
  
  err = ProAnalysissrfdataAlloc (&(geomitem.shapes[0].surface));
  TEST_CALL_REPORT ("ProAnalysissrfdataAlloc()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);

  
  err = ProArrayAlloc (1, sizeof(ProSurfacedata), 1, (ProArray *)&geomitem.shapes[0].surface->pro_surface);
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProTestSurfaceResultAction()", err, 
		    err != PRO_TK_NO_ERROR);
		    
  err = ProSurfacedataAlloc (&temp_data);
  
  err = ProSurfacedataInit(data->surf_data.type,
			   data->surf_data.uv_min,
			   data->surf_data.uv_max,
			   data->surf_data.orient,
			   &data->surf_data.srf_shape,
			   data->surf_data.id,
			   temp_data);
  TEST_CALL_REPORT ("ProSurfacedataInit()",
		    "ProTestSurfaceResultAction()", err, 
		    err != PRO_TK_NO_ERROR);
  
  err = ProSurfacedataGet(&data->surf_data, NULL, min_uv, max_uv, NULL, NULL, NULL);
  TEST_CALL_REPORT ("ProSurfacedataGet()", 
		    "ProTestSurfaceDisplayAction()", err, 
		    err != PRO_TK_NO_ERROR); 

  XyzDataEval(data, min_uv, xyz_min);
  XyzDataEval(data, max_uv, xyz_max);
  for (i=0; i<3; i++)
    {
      temp_data->xyz_min[i] = xyz_min[i];
      temp_data->xyz_max[i] = xyz_max[i];
    }

  
  err = ProSurfacedataContourArraySet(temp_data, data->surf_data.contour_arr);
  TEST_CALL_REPORT ("ProSurfacedataContourArraySet()",
		    "ProTestSurfaceResultAction()", err, 
		    err != PRO_TK_NO_ERROR);
  
  memcpy (&geomitem.shapes[0].surface->pro_surface[0], temp_data, 
	  sizeof(ProSurfacedata));
  
  /*-----------------------------------------------------------------*\
     Provide the edge data to the analysis surface
  \*-----------------------------------------------------------------*/

  err = ProArrayAlloc(2, sizeof(int), 2, (ProArray *)&surf_id);
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
  
  err = ProArrayAlloc(2, sizeof(ProEdgeDir), 2, (ProArray *)&dir);
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
  
  err = ProArrayAlloc(2, sizeof(ProSurface), 2, (ProArray *)&surf_neigh);
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
  
  err = ProArrayAlloc(2, sizeof(ProEdge), 2, (ProArray *)&edge_neigh);
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
    
  err = ProContourdataEdgeIdArrayGet(data->surf_data.contour_arr, &edge_ids);
  TEST_CALL_REPORT ("ProContourdataEdgeIdArrayGet()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
    
  err = ProArraySizeGet((ProArray)edge_ids, &n);
  TEST_CALL_REPORT ("ProArraySizeGet()",
		    "ProTestSurfaceResultAction()", err, 
		    err != PRO_TK_NO_ERROR);
  
  fp = PTApplsUnicodeFopen("out.txt", "w");
  ProTKPrintf("ProSrftype Surface Type =  %d\n", data->surf_data.type );

  ProTKFprintf(fp, "Surface Type =  %d\n", data->surf_data.type );
  ProTKFprintf(fp, "The array size is  %3d\n", n);
  
  err = ProArrayAlloc(n, sizeof(ProEdgedata), 1,
		      (ProArray *)&geomitem.shapes[0].surface->edge_data);
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProTestSurfaceResultAction()", 
		    err, err != PRO_TK_NO_ERROR);
 
  for (i=0; i<n; i++)
    { 
      err = ProModelitemInit(data->surface.owner, edge_ids[i], PRO_EDGE, &p_handle);
      TEST_CALL_REPORT ("ProModelitemInit()",
			"ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
	
      err = ProGeomitemToEdge(&p_handle, &edge);
      TEST_CALL_REPORT ("ProGeomitemToEdge()",
			"ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
      
      err = ProEdgeNeighborsGet(edge, &edge_neigh[0], &edge_neigh[1], &surf_neigh[0], &surf_neigh[1]);
      TEST_CALL_REPORT ("ProEdgeNeighbourGet()",
			"ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
      
      ProTKFprintf ( fp, "Edge ID under process = %d\n", edge_ids[i] ); 
      {
	ProError err_dir1, err_dir2, err_id1, err_id2; 

	if ( surf_neigh[0] != NULL )
	  {
	    err_dir1 = ProEdgeDirGet(edge, surf_neigh[0], (int *)&dir[0]);
	    err = err_dir1; 
	    TEST_CALL_REPORT ("ProEdgeDirGet()",
			      "ProTestSurfaceResultAction()", err, 
			      err != PRO_TK_NO_ERROR);
	    
	    err_id1 = ProSurfaceIdGet(surf_neigh[0], &surf_id[0]);
	    err = err_id1; 
	    TEST_CALL_REPORT ("ProSurfaceIdGet()",
			      "ProTestSurfaceResultAction()", err, 
			      err != PRO_TK_NO_ERROR);
	  }
	else
	  {
	    ProTKFprintf ( fp, " surf_neigh[0] == NULL\n" ); 
	    dir[0] 		= (ProEdgeDir)-1; 
	    surf_id[0] 	= 0; 
	  }
	
	if ( surf_neigh[1] != NULL )
	  {
	    err_dir2 = ProEdgeDirGet(edge, surf_neigh[1], (int *)&dir[1]);
	    err = err_dir2; 
	    TEST_CALL_REPORT ("ProEdgeDirGet()",
			      "ProTestSurfaceResultAction()", err, 
			      err != PRO_TK_NO_ERROR);
      
      
	    err_id2 = ProSurfaceIdGet(surf_neigh[1], &surf_id[1]);
	    err = err_id2; 
	    TEST_CALL_REPORT ("ProSurfaceIdGet()",
			      "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
	  }
	else
	  {
	    ProTKFprintf ( fp, " surf_neigh[1] == NULL\n" ); 
	    dir[1] 		= (ProEdgeDir)-1; 
	    surf_id[1] 	= 0; 
	  }
      }
      
      for (j=0; j<2; j++)
	{
          ProTKFprintf ( fp, " surf_id[%d] = %d\n", j, surf_id[j] ); 
          ProTKFprintf ( fp, " dir    [%d] = %d\n", j, dir[j] ); 

	  geomitem.shapes[0].surface->edge_data[i].surf_ids[j] = surf_id[j];
	  geomitem.shapes[0].surface->edge_data[i].directions[j] = dir[j];
	}

      geomitem.shapes[0].surface->edge_data[i].id = edge_ids[i];
      
      /*provide the uv values for the edges*/
      
      err = ProArrayAlloc(UV_FREQ+1, sizeof(ProUvParam2), 1, 
	       (ProArray *)&geomitem.shapes[0].surface->edge_data[i].uv_points);
      TEST_CALL_REPORT ("ProArrayAlloc()",
			"ProTestSurfaceResultAction()", err, 
			err != PRO_TK_NO_ERROR);
      
      for (j=0; j<=UV_FREQ; j++)
	{
	  t = (double)(1.0/UV_FREQ) * (double)j;
	  err = ProEdgeUvdataEval(edge, t, uv, uvd1, uvd2);
	  TEST_CALL_REPORT ("ProEdgeUvdataEval()",
			    "ProTestSurfaceResultAction()", 
			    err, err != PRO_TK_NO_ERROR);
	    
	  geomitem.shapes[0].surface->edge_data[i].uv_points[j][0][0] = uv[0][0];
	  geomitem.shapes[0].surface->edge_data[i].uv_points[j][0][1] = uv[0][1];
	  geomitem.shapes[0].surface->edge_data[i].uv_points[j][1][0] = uv[1][0];
	  geomitem.shapes[0].surface->edge_data[i].uv_points[j][1][1] = uv[1][1];
	}
    } /* for i / numbers of edges */ 
	
  /* Passing back the vaues to Pro/E via geometry & paramters array */ 

  ProArrayAlloc (0, sizeof(ProAnalysisGeomitem), 1, (ProArray*)geometry);
  err = ProArrayObjectAdd((ProArray*)geometry, PRO_VALUE_UNUSED, 
			    1, &geomitem);
  TEST_CALL_REPORT ("ProArrayObjectAdd()",
		      "ProTestSurfaceResultAction()", err, 
		    err != PRO_TK_NO_ERROR);

  ProArrayAlloc (0, sizeof(ProAnalysisParameter), 1, (ProArray*)parameters);
  err = ProArrayObjectAdd((ProArray*)parameters, PRO_VALUE_UNUSED, 
			    1, &param);
  TEST_CALL_REPORT ("ProArrayObjectAdd()",
		    "ProTestSurfaceResultAction()", err, 
		    err != PRO_TK_NO_ERROR);
      	    
  fclose(fp);

  ProArrayFree ((ProArray *)&surf_id); 
  ProArrayFree ((ProArray *)&dir);
  ProArrayFree ((ProArray *)&surf_neigh);
  ProArrayFree ((ProArray *)&edge_neigh);

  return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestNURBSSurfaceResultAction()
PURPOSE  : Callback to give Pro/E the feature parameters and
geometry that the analysis feature must contain
\*====================================================================*/
ProError ProTestNURBSSurfaceResultAction(
                                    ProAnalysis analysis,
                                    ProBoolean names_only,
                                    ProAnalysisParameter **parameters,
                                    ProAnalysisGeomitem  **geometry)
{
  Surfacedata_t *data;
  ProSrftype type;
  ProVector xyz_min, xyz_max;
  ProUvParam min_uv, max_uv;
  ProSurfaceOrient orient;
  int *edge_ids, *surf_id;
  ProEdgeDir *dir;
  ProModelitem p_handle;
  ProEdge edge, *edge_neigh;
  ProSurface *surf_neigh;
  ProAnalysisGeomitem geomitem;
  ProAnalysisParameter param;
  ProUvParam uv[2], uvd1[2], uvd2[2], *uv_array;
  ProError err = PRO_TK_NO_ERROR;
  int num, i, j, n, id;
  double t;
  FILE *fp;
  ProSurface nurb_surface; 
  ProSurfacedata  *temp_data;
  
  TEST_CALL_REPORT ("ProAnalysisResultAction====()", 
		    "ProTestSurfaceResultAction()", 
		    err, err != PRO_TK_NO_ERROR);

  /*--------------------------------------------------------------------*\
     Get the application data from the analysis
  \*--------------------------------------------------------------------*/
  err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
  TEST_CALL_REPORT ("ProAnalysisInfoGet()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
  if (err != PRO_TK_NO_ERROR)
    return(PRO_TK_GENERAL_ERROR);

  ProStringToWstring (param.name,(char *)"SURFACE");
  param.create = PRO_B_TRUE;
  ProStringToWstring (param.description,(char *)"Wireframe of Cyl Surf");
  param.values = NULL;

  /*---------------------------------------------------------------------*\
     Copy values from the surface data structure to the analysis surface 
     data structure
  \*---------------------------------------------------------------------*/
     
  ProStringToWstring (geomitem.name,(char *)"SURFACE");
  geomitem.create = PRO_B_TRUE;
  geomitem.type = PRO_ANALYSIS_SURFACE;

  err = ProArrayAlloc(1, sizeof(ProAnalysisEntity), 1, (ProArray *)&geomitem.shapes);
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
  
  err = ProAnalysissrfdataAlloc (&(geomitem.shapes[0].surface));
  TEST_CALL_REPORT ("ProAnalysissrfdataAlloc()",
		    "ProTestNURBSSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
  
  err = ProArrayAlloc (1, sizeof(ProSurfacedata), 1, (ProArray *)&geomitem.shapes[0].surface->pro_surface);
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProTestSurfaceResultAction()", err, 
		    err != PRO_TK_NO_ERROR);

  err = ProGeomitemToSurface ( &data->surface, &nurb_surface );
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProGeomitemToSurface()", err, 
		    err != PRO_TK_NO_ERROR);

  err = ProSurfaceToNURBS ( nurb_surface, &temp_data );
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProSurfaceToNURBS()", err, 
		    err != PRO_TK_NO_ERROR);


  err = ProSurfacedataContourArraySet(temp_data, data->surf_data.contour_arr);
  TEST_CALL_REPORT ("ProSurfacedataContourArraySet()",
		    "ProTestSurfaceResultAction()", err, 
		    err != PRO_TK_NO_ERROR);

  
  memcpy (&geomitem.shapes[0].surface->pro_surface[0], temp_data, 
	  sizeof(ProSurfacedata));
  
  /*-----------------------------------------------------------------*\
     Provide the edge data to the analysis surface
  \*-----------------------------------------------------------------*/

  err = ProArrayAlloc(2, sizeof(int), 2, (ProArray *)&surf_id);
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
  
  err = ProArrayAlloc(2, sizeof(ProEdgeDir), 2, (ProArray *)&dir);
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
  
  err = ProArrayAlloc(2, sizeof(ProSurface), 2, (ProArray *)&surf_neigh);
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
  
  err = ProArrayAlloc(2, sizeof(ProEdge), 2, (ProArray *)&edge_neigh);
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
    
  err = ProContourdataEdgeIdArrayGet(data->surf_data.contour_arr, &edge_ids);
  TEST_CALL_REPORT ("ProContourdataEdgeIdArrayGet()",
		    "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
    
  err = ProArraySizeGet((ProArray)edge_ids, &n);
  TEST_CALL_REPORT ("ProArraySizeGet()",
		    "ProTestSurfaceResultAction()", err, 
		    err != PRO_TK_NO_ERROR);
  
  fp = PTApplsUnicodeFopen("out.txt", "w");
  ProTKPrintf("ProSrftype Surface Type =  %d\n", data->surf_data.type );
 
  ProTKFprintf(fp, "Surface Type =  %d\n", data->surf_data.type );
  ProTKFprintf(fp, "The array size is  %3d\n", n);
  
  err = ProArrayAlloc(n, sizeof(ProEdgedata), 1,
		      (ProArray *)&geomitem.shapes[0].surface->edge_data);
  TEST_CALL_REPORT ("ProArrayAlloc()",
		    "ProTestSurfaceResultAction()", 
		    err, err != PRO_TK_NO_ERROR);
 
  for (i=0; i<n; i++)
    { 
      err = ProModelitemInit(data->surface.owner, edge_ids[i], PRO_EDGE, &p_handle);
      TEST_CALL_REPORT ("ProModelitemInit()",
			"ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
	
      err = ProGeomitemToEdge(&p_handle, &edge);
      TEST_CALL_REPORT ("ProGeomitemToEdge()",
			"ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
      
      err = ProEdgeNeighborsGet(edge, &edge_neigh[0], &edge_neigh[1], &surf_neigh[0], &surf_neigh[1]);
      TEST_CALL_REPORT ("ProEdgeNeighbourGet()",
			"ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
      
      ProTKFprintf ( fp, "Edge ID under process = %d\n", edge_ids[i] ); 
      {
	ProError err_dir1, err_dir2, err_id1, err_id2; 

	if ( surf_neigh[0] != NULL )
	  {
	    err_dir1 = ProEdgeDirGet(edge, surf_neigh[0], (int *)&dir[0]);
	    err = err_dir1; 
	    TEST_CALL_REPORT ("ProEdgeDirGet()",
			      "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);

	    err_id1 = ProSurfaceIdGet(surf_neigh[0], &surf_id[0]);
	    err = err_id1; 
	    TEST_CALL_REPORT ("ProSurfaceIdGet()",
			      "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
	  }
	else
	  {
	    ProTKFprintf ( fp, " surf_neigh[0] == NULL\n" ); 
	    dir[0] 		= (ProEdgeDir)-1; 
	    surf_id[0] 	= 0; 
	  }
      
	if ( surf_neigh[1] != NULL )
	  {
	    err_dir2 = ProEdgeDirGet(edge, surf_neigh[1], (int *)&dir[1]);
	    err = err_dir2; 
	    TEST_CALL_REPORT ("ProEdgeDirGet()",
			      "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
      
      
	    err_id2 = ProSurfaceIdGet(surf_neigh[1], &surf_id[1]);
	    err = err_id2; 
	    TEST_CALL_REPORT ("ProSurfaceIdGet()",
			      "ProTestSurfaceResultAction()", err, err != PRO_TK_NO_ERROR);
	  }
	else
	  {
	    ProTKFprintf ( fp, " surf_neigh[1] == NULL\n" ); 
	    dir[1] 		= (ProEdgeDir)-1; 
	    surf_id[1] 	= 0; 
	  }
      }
      
      for (j=0; j<2; j++)
	{
          ProTKFprintf ( fp, " surf_id[%d] = %d\n", j, surf_id[j] ); 
          ProTKFprintf ( fp, " dir    [%d] = %d\n", j, dir[j] ); 

	  geomitem.shapes[0].surface->edge_data[i].surf_ids[j] = surf_id[j];
	  geomitem.shapes[0].surface->edge_data[i].directions[j] = dir[j];
	}

      geomitem.shapes[0].surface->edge_data[i].id = edge_ids[i];
      
      /*provide the uv values for the edges*/
      
      err = ProArrayAlloc(UV_FREQ+1, sizeof(ProUvParam2), 1, 
	       (ProArray *)&geomitem.shapes[0].surface->edge_data[i].uv_points);
      TEST_CALL_REPORT ("ProArrayAlloc()",
			"ProTestSurfaceResultAction()", err, 
			err != PRO_TK_NO_ERROR);
      
      for (j=0; j<=UV_FREQ; j++)
	{
	  t = (double)(1.0/UV_FREQ) * (double)j;
	  err = ProEdgeUvdataEval(edge, t, uv, uvd1, uvd2);
	  TEST_CALL_REPORT ("ProEdgeUvdataEval()",
			    "ProTestSurfaceResultAction()", 
			    err, err != PRO_TK_NO_ERROR);
	    
	  geomitem.shapes[0].surface->edge_data[i].uv_points[j][0][0] = uv[0][0];
	  geomitem.shapes[0].surface->edge_data[i].uv_points[j][0][1] = uv[0][1];
	  geomitem.shapes[0].surface->edge_data[i].uv_points[j][1][0] = uv[1][0];
	  geomitem.shapes[0].surface->edge_data[i].uv_points[j][1][1] = uv[1][1];
	}
      }
	
  /* Passing back the vaues to Pro/E via geometry & paramters array */ 

  ProArrayAlloc (0, sizeof(ProAnalysisGeomitem), 1, (ProArray*)geometry);
  err = ProArrayObjectAdd((ProArray*)geometry, PRO_VALUE_UNUSED, 
			    1, &geomitem);
  TEST_CALL_REPORT ("ProArrayObjectAdd()",
		      "ProTestSurfaceResultAction()", err, 
		    err != PRO_TK_NO_ERROR);

  ProArrayAlloc (0, sizeof(ProAnalysisParameter), 1, (ProArray*)parameters);
  err = ProArrayObjectAdd((ProArray*)parameters, PRO_VALUE_UNUSED, 
			    1, &param);
  TEST_CALL_REPORT ("ProArrayObjectAdd()",
		    "ProTestSurfaceResultAction()", err, 
		    err != PRO_TK_NO_ERROR);
      	    
  fclose(fp);

  ProArrayFree ((ProArray *)&surf_id); 
  ProArrayFree ((ProArray *)&dir);
  ProArrayFree ((ProArray *)&surf_neigh);
  ProArrayFree ((ProArray *)&edge_neigh);

  return(PRO_TK_NO_ERROR);

}



/*=====================================================================*\
FUNCTION : XyzDataEval
PURPOSE  : Subroutine to be used to calculate the xyz values of a surface 
           offset by the distance equal to the new radius increment
\*=====================================================================*/
void XyzDataEval(Surfacedata_t *data, ProUvParam uv, ProVector xyz)
{
  ProVector vec1, vec2, vec3;
  Pro3dPnt origin;
  int i;
  
  for (i=0; i<3; i++)
    {
      vec1[i] = data->surf_data.srf_shape.plane.e1[i];
      vec2[i] = data->surf_data.srf_shape.plane.e2[i];
      vec3[i] = data->surf_data.srf_shape.plane.e3[i];
      origin[i] = data->surf_data.srf_shape.plane.origin[i];
      xyz[i] = uv[0]*vec1[i] + uv[1]*vec2[i] + origin[i];
		    
    }
}