/*
Copyright (c) 2019 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved.
*/
/*--------------------------------------------------------------------*\
Pro/TOOLKIT includes
\*--------------------------------------------------------------------*/
#include "ProToolkit.h"
#include "ProObjects.h"
#include "ProAxis.h"
#include "ProCsys.h"
#include "ProGraphic.h"
#include "ProDisplist.h"
#include "ProGeomitem.h"
#include "ProMenu.h"
#include "ProMessage.h"
#include "ProPoint.h"
#include "ProSelection.h"
#include "ProSolid.h"
#include "ProUtil.h"
#include "ProWindows.h"
#include "ProEdge.h"
/*--------------------------------------------------------------------*\
System includes
\*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*\
Application includes
\*--------------------------------------------------------------------*/
#include "TestError.h"
/*--------------------------------------------------------------------*\
Application macros
\*--------------------------------------------------------------------*/
#define DSPL1_ID 115
#define DSPL2_ID (DSPL1_ID+1)
#ifdef MSGFIL
#undef MSGFIL
#endif
#define MSGFIL msgfil
#define COPY3D(a, b) memcpy(a, b, 3*sizeof(double))
/*--------------------------------------------------------------------*\
Application data types
\*--------------------------------------------------------------------*/
typedef struct tag_hit_list
{
Pro3dPnt origin;
int n_hits;
Pro3dPnt *p_pnt;
ProBoolean *to_front;
} Hit_list;
/*--------------------------------------------------------------------*\
Application global/external data
\*--------------------------------------------------------------------*/
static ProFileName msgfil;
/*--------------------------------------------------------------------*\
Function prototypes
\*--------------------------------------------------------------------*/
int ProTestSolidRay(ProAppData data, int value);
int ProUtilDeleteRay(ProAppData data, int value);
static int CreateRays(ProModelitem *, ProRay *);
static int CreateRaysFromPoint(ProModelitem *, ProRay *);
static int CreateRaysFromEdgeEnd(ProModelitem *, ProRay *);
static int CreateRaysFromCsys(ProModelitem *, ProRay *);
static int CreateRaysFromAxis(ProModelitem *, ProRay *);
static int TransfRays(ProSelection, ProRay *, int);
static int CreateHitList(ProSolid, ProRay*, Hit_list *);
static int CreateDispList(Hit_list *, int *, int *);
/*=============================================================*\
Function: ProTestRay
Purpose: To initiate the user's options
\*=============================================================*/
int ProTestRay (void *data, int dummy)
{
/* Declare external functions */
int m_id, action;
ProError status;
ProStringToWstring (msgfil,(char*) "gen_msg.txt");
status = ProMenuFileRegister((char*)"TkRay",(char*) "tkray.mnu", &m_id);
TEST_CALL_REPORT("ProMenuFileRegister()", "ProTestRay()",
status, status !=PRO_TK_NO_ERROR);
if (status != PRO_TK_NO_ERROR) return (-1);
status = ProMenubuttonActionSet((char*)"TkRay",(char*) "-Ray Inter Demo",
(ProMenubuttonAction)ProTestSolidRay, NULL, 0);
TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestRay()",
status, status !=PRO_TK_NO_ERROR);
if (status != PRO_TK_NO_ERROR) return (-1);
status = ProMenubuttonActionSet((char*)"TkRay",(char*) "-Ray Del",
(ProMenubuttonAction)ProUtilDeleteRay, NULL, 0);
TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestRay()",
status, status !=PRO_TK_NO_ERROR);
if (status != PRO_TK_NO_ERROR) return (-1);
status = ProMenubuttonActionSet((char*)"TkRay",(char*) "-Done",
(ProMenubuttonAction)ProMenuDelete, NULL, 0);
TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestRay()",
status, status !=PRO_TK_NO_ERROR);
if (status != PRO_TK_NO_ERROR) return (-1);
status = ProMenubuttonActionSet((char*)"TkRay",(char*) "TkRay",
(ProMenubuttonAction)ProMenuDelete, NULL, 0);
TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestRay()",
status, status !=PRO_TK_NO_ERROR);
if (status != PRO_TK_NO_ERROR) return (-1);
status = ProMenuCreate(PROMENUTYPE_MAIN,(char*) "TkRay", NULL);
status = ProMenuProcess((char*)"TkRay", &action);
return(0);
}
/*=============================================================*\
Function: ProTestSolidRay
Purpose: main test ProSolidRayIntersectionCompute() function
\*=============================================================*/
int ProTestSolidRay(ProAppData data, int value)
{
ProSelection *p_sel;
ProModelitem modelitem;
ProRay rays[3];
ProSolid model;
int n_ray, n_sel, i, mode;
ProError status;
Hit_list h_list[3];
ProAsmcomppath comp_path;
ProMessageDisplay(MSGFIL, (char*)"TEST %0s", "Select Csys, Axis or Datum Point");
status = ProSelect((char*)"point,axis,csys,edge_end", 1, NULL, NULL, NULL, NULL,
&p_sel, &n_sel);
if (status != PRO_TK_NO_ERROR)
return (0);
status = ProSelectionModelitemGet(p_sel[0], &modelitem);
TEST_CALL_REPORT("ProSelectionModelitemGet()", "ProTestSolidRay()",
status, status != PRO_TK_NO_ERROR);
status = ProSelectionModelitemGet(p_sel[0], &modelitem);
TEST_CALL_REPORT("ProSelectionModelitemGet()", "ProTestSolidRay()",
status, status != PRO_TK_NO_ERROR);
status = ProSelectionAsmcomppathGet(p_sel[0], &comp_path);
TEST_CALL_REPORT("ProSelectionAsmcomppathGet()", "ProTestSolidRay()",
status, status != PRO_TK_NO_ERROR);
model=(comp_path.owner)!=NULL?comp_path.owner:(ProSolid)modelitem.owner;
n_ray = CreateRays(&modelitem, rays);
if (n_ray == -1) return (-1);
TransfRays(p_sel[0], rays, n_ray);
for (i=0; i<n_ray; i++)
{
CreateHitList(model, rays+i, h_list+i);
}
ProUtilDeleteRay(NULL, 0);
mode=0;
status = ProDisplist3dCreate( DSPL1_ID, (ProDisplistCallback)CreateDispList, (void *)h_list,
(void *)&n_ray, (void *)&mode, NULL, NULL, NULL );
TEST_CALL_REPORT("ProDisplist3dCreate()", "ProTestSolidRay()",
status, status != PRO_TK_NO_ERROR);
mode=1;
status = ProDisplist3dCreate( DSPL2_ID, (ProDisplistCallback)CreateDispList, (void *)h_list,
(void *)&n_ray, (void *)&mode, NULL, NULL, NULL);
TEST_CALL_REPORT("ProDisplist3dCreate()", "ProTestSolidRay()",
status, status != PRO_TK_NO_ERROR);
for (i=0; i<n_ray; i++)
{
free(h_list[i].p_pnt);
free(h_list[i].to_front);
}
status = ProWindowRepaint(PRO_VALUE_UNUSED);
TEST_CALL_REPORT("ProWindowRepaint()", "ProTestSolidRay()",
status, status != PRO_TK_NO_ERROR);
return (0);
}
/*=============================================================*\
Function: ProUtilDeleteRay
Purpose: to delete application's display list
\*=============================================================*/
int ProUtilDeleteRay(ProAppData data, int value)
{
ProError status;
status = ProDisplist3dDelete( DSPL1_ID );
TEST_CALL_REPORT("ProDisplist3dDelete()", "ProUtilDeleteRay()",
status, status != PRO_TK_NO_ERROR && status != PRO_TK_E_NOT_FOUND);
status = ProDisplist3dDelete( DSPL2_ID );
TEST_CALL_REPORT("ProDisplist3dDelete()", "ProUtilDeleteRay()",
status, status != PRO_TK_NO_ERROR && status != PRO_TK_E_NOT_FOUND);
status = ProWindowRepaint(PRO_VALUE_UNUSED);
TEST_CALL_REPORT("ProWindowRepaint()", "ProUtilDeleteRay()",
status, status != PRO_TK_NO_ERROR && status != PRO_TK_E_NOT_FOUND);
return (0);
}
/*=============================================================*\
Function: CreateRays
Purpose: to fill ProRays structure
Return : # of rays, -1 if unsuccessfull
\*=============================================================*/
static int CreateRays(
ProModelitem *mod_item, /* In : user's selection */
ProRay *rays) /* Out: the filled ray structure */
{
int ret;
switch (mod_item->type)
{
case PRO_EDGE_END:
case PRO_EDGE_START:
ret = CreateRaysFromEdgeEnd (mod_item, rays) == 0 ? 3 : -1;
break;
case PRO_POINT:
ret = CreateRaysFromPoint(mod_item, rays) == 0 ? 3 : -1;
break;
case PRO_CSYS:
ret = CreateRaysFromCsys(mod_item, rays) == 0 ? 3 : -1;
break;
case PRO_AXIS:
ret = CreateRaysFromAxis(mod_item, rays) == 0 ? 1 : -1;
break;
default :
ret =-1;
}
return (ret);
}
/*=============================================================*\
Function: CreateRaysFromEdgeEnd
Purpose: to fill ProRays structure
Return : 0 if successfull, -1 if unsuccessfull
\*=============================================================*/
static int CreateRaysFromEdgeEnd(
ProModelitem *mod_item, /* In : user's selection */
ProRay *rays) /* Out: the filled ray structure */
{
ProEdge edge;
ProError status;
double edge_param;
ProVector xyz, der1, der2, dir;
rays[0].dir_vector[0] = rays[1].dir_vector[1] = 1.0;
rays[2].dir_vector[2] = 1.0;
rays[0].dir_vector[1] = rays[0].dir_vector[2] = 0.0;
rays[1].dir_vector[0] = rays[1].dir_vector[2] = 0.0;
rays[2].dir_vector[0] = rays[2].dir_vector[1] = 0.0;
status = ProEdgeInit((ProSolid)mod_item->owner, mod_item->id, &edge);
TEST_CALL_REPORT("ProEdgeInit()", "CreateRaysFromEdgeEnd()", status,
status != PRO_TK_NO_ERROR);
if (status!=PRO_TK_NO_ERROR)
return (-1);
edge_param = 1.0 * (mod_item->type == PRO_EDGE_END);
ProEdgeXyzdataEval (edge, edge_param, xyz, der1, der2, dir);
COPY3D (rays[0].start_point, xyz);
COPY3D(rays[1].start_point, rays[0].start_point);
COPY3D(rays[2].start_point, rays[0].start_point);
return (0);
}
/*=============================================================*\
Function: CreateRaysFromPoint
Purpose: to fill ProRays structure
Return : 0 if successfull, -1 if unsuccessfull
\*=============================================================*/
static int CreateRaysFromPoint(
ProModelitem *mod_item, /* In : user's selection */
ProRay *rays) /* Out: the filled ray structure */
{
ProPoint pnt;
ProError status;
rays[0].dir_vector[0] = rays[1].dir_vector[1] = 1.0;
rays[2].dir_vector[2] = 1.0;
rays[0].dir_vector[1] = rays[0].dir_vector[2] = 0.0;
rays[1].dir_vector[0] = rays[1].dir_vector[2] = 0.0;
rays[2].dir_vector[0] = rays[2].dir_vector[1] = 0.0;
status = ProPointInit((ProSolid)mod_item->owner, mod_item->id, &pnt);
TEST_CALL_REPORT("ProPointInit()", "CreateRaysFromPoint()", status,
status != PRO_TK_NO_ERROR);
if (status!=PRO_TK_NO_ERROR)
return (-1);
status = ProPointCoordGet(pnt, rays[0].start_point);
TEST_CALL_REPORT("ProPointCoordGet()", "CreateRaysFromPoint()", status,
status != PRO_TK_NO_ERROR);
if (status!=PRO_TK_NO_ERROR)
return (-1);
COPY3D(rays[1].start_point, rays[0].start_point);
COPY3D(rays[2].start_point, rays[0].start_point);
return (0);
}
/*=============================================================*\
Function: CreateRaysFromCsys
Purpose: to fill ProRays structure
Return : 0 if successfull, -1 if unsuccessfull
\*=============================================================*/
static int CreateRaysFromCsys(
ProModelitem *mod_item, /* In : user's selection */
ProRay *rays) /* Out: the filled ray structure */
{
ProError status;
ProCsys csys;
ProGeomitemdata *geomdata;
status = ProCsysInit((ProSolid)mod_item->owner, mod_item->id, &csys);
TEST_CALL_REPORT("ProCsysInit()", "CreateRaysFromCsys()", status,
status != PRO_TK_NO_ERROR);
if (status!=PRO_TK_NO_ERROR)
return (-1);
status = ProCsysDataGet(csys, &geomdata);
TEST_CALL_REPORT("ProCsysDataGet()", "CreateRaysFromCsys()", status,
status != PRO_TK_NO_ERROR);
if (status!=PRO_TK_NO_ERROR)
return (-1);
COPY3D(rays[0].start_point, geomdata->data.p_csys_data->origin);
COPY3D(rays[1].start_point, rays[0].start_point);
COPY3D(rays[2].start_point, rays[0].start_point);
COPY3D(rays[0].dir_vector, geomdata->data.p_csys_data->x_vector);
COPY3D(rays[1].dir_vector, geomdata->data.p_csys_data->y_vector);
COPY3D(rays[2].dir_vector, geomdata->data.p_csys_data->z_vector);
status = ProGeomitemdataFree(&geomdata);
TEST_CALL_REPORT("ProGeomitemdataFree()", "CreateRaysFromCsys()", status,
status != PRO_TK_NO_ERROR);
return (0);
}
/*=============================================================*\
Function: CreateRaysFromAsys
Purpose: to fill ProRays structure
Return : 0 if successfull, -1 if unsuccessfull
\*=============================================================*/
static int CreateRaysFromAxis(
ProModelitem *mod_item, /* In : user's selection */
ProRay *rays) /* Out: the filled ray structure */
{
ProError status;
ProAxis axis;
ProGeomitemdata *geomdata;
status = ProAxisInit((ProSolid)mod_item->owner, mod_item->id, &axis);
TEST_CALL_REPORT("ProAxisInit()", "CreateRaysFromAxis()", status,
status != PRO_TK_NO_ERROR);
if (status!=PRO_TK_NO_ERROR)
return (-1);
status = ProAxisDataGet(axis, &geomdata);
TEST_CALL_REPORT("ProAxisDataGet()", "CreateRaysFromAxis()", status,
status != PRO_TK_NO_ERROR);
if (status!=PRO_TK_NO_ERROR)
return (-1);
COPY3D(rays[0].start_point, geomdata->data.p_curve_data->line.end1);
COPY3D(rays[0].dir_vector, geomdata->data.p_curve_data->line.end2);
rays[0].dir_vector[0] -= rays[0].start_point[0];
rays[0].dir_vector[1] -= rays[0].start_point[1];
rays[0].dir_vector[2] -= rays[0].start_point[2];
return (0);
}
/*=============================================================*\
Function: TransfRays
Purpose: to transform ray's origin and direction to top
level assembly csys
\*=============================================================*/
static int TransfRays(
ProSelection sel, /* In : the user's selection structure */
ProRay *rays, /* In, Out : the array of ProRay structures */
int n_ray) /* In : # of rays*/
{
ProMatrix trf;
ProError status;
ProAsmcomppath comp_path;
ProVector pnt;
int i;
status = ProSelectionAsmcomppathGet(sel, &comp_path);
TEST_CALL_REPORT("ProSelectionAsmcomppathGet()", "TransfRays()",
status, status != PRO_TK_NO_ERROR);
if (comp_path.owner==NULL) return (0);
status = ProAsmcomppathTrfGet(&comp_path, PRO_B_TRUE, trf);
TEST_CALL_REPORT("ProAsmcomppathTrfGet()", "TransfRays()",
status, status != PRO_TK_NO_ERROR);
for (i=0; i<n_ray; i++)
{
status = ProPntTrfEval(rays[i].start_point, trf, pnt);
TEST_CALL_REPORT("ProPntTrfEval()", "TransfRays()",
status, status != PRO_TK_NO_ERROR);
COPY3D(rays[i].start_point, pnt);
status = ProVectorTrfEval(rays[i].dir_vector, trf, rays[i].dir_vector);
TEST_CALL_REPORT("ProVectorTrfEval()", "TransfRays()",
status, status != PRO_TK_NO_ERROR);
}
return (0);
}
/*=============================================================*\
Function: CreateHitList
Purpose: generate hit list for one ray
\*=============================================================*/
static int CreateHitList(
ProSolid model, /* In : The model */
ProRay* ray, /* In : ray */
Hit_list *h_list) /* In : The hit list, user's memory */
{
ProError status;
int n_hits, i;
ProSelection *p_sel;
ProAsmcomppath comp_path;
double depth;
ProPoint3d pnt;
ProMode mode;
ProMatrix trf = { {1.0, 0.0, 0.0, 0.0},
{0.0, 1.0, 0.0, 0.0},
{0.0, 0.0, 1.0, 0.0},
{0.0, 0.0, 0.0, 1.0} };
h_list->p_pnt = NULL;
h_list->to_front = NULL;
h_list->n_hits =0;
status = ProSolidRayIntersectionCompute(model, -1, ray, &p_sel, &n_hits);
TEST_CALL_REPORT("ProSolidRayIntersectionCompute()", "CreateHitList()",
status, status != PRO_TK_NO_ERROR && status != PRO_TK_E_NOT_FOUND);
if (status != PRO_TK_NO_ERROR)
return (-1);
COPY3D(h_list->origin, ray->start_point);
h_list->n_hits = n_hits;
h_list->p_pnt = (Pro3dPnt *)calloc(n_hits, sizeof(Pro3dPnt));
h_list->to_front = (ProBoolean *)calloc(n_hits, sizeof(ProBoolean));
for (i=0; i<n_hits; i++)
{
status = ProSelectionDepthGet(p_sel[i], &depth);
TEST_CALL_REPORT("ProSelectionDepthGet()", "CreateHitList()",
status, status != PRO_TK_NO_ERROR);
h_list->to_front[i] = (ProBoolean)(depth>=0);
status = ProSelectionAsmcomppathGet(p_sel[i], &comp_path);
TEST_CALL_REPORT("ProSelectionAsmcomppathGet()", "CreateHitList()",
status, status != PRO_TK_NO_ERROR);
status = ProModeCurrentGet(&mode);
TEST_CALL_REPORT("ProModeCurrentGet()", "CreateHitList()",
status, status != PRO_TK_NO_ERROR);
if(mode == PRO_MODE_ASSEMBLY)
{
status = ProAsmcomppathTrfGet(&comp_path, PRO_B_TRUE, trf);
TEST_CALL_REPORT("ProAsmcomppathTrfGet()", "CreateHitList()",
status, status != PRO_TK_NO_ERROR);
}
status = ProSelectionPoint3dGet(p_sel[i], pnt);
TEST_CALL_REPORT("ProSelectionPoint3dGet()", "CreateHitList()",
status, status != PRO_TK_NO_ERROR);
status = ProPntTrfEval(pnt, trf, h_list->p_pnt[i]);
TEST_CALL_REPORT("ProPntTrfEval()", "CreateHitList()",
status, status != PRO_TK_NO_ERROR);
}
return (0);
}
/*=============================================================*\
Function: CreateDispList
Purpose: generate display list
\*=============================================================*/
static int CreateDispList(
Hit_list *p_list, /*In : the hit list array */
int *n_list, /*In : n_list[0] contains number of lists in p_list */
int *mode) /*In : mode[0]==0 behind origin
mode[0]==1 front origin */
{
int i, l;
ProError status;
ProColor keep_color, letter_color, highlite_color;
double radius;
ProMdl model;
Pro3dPnt points[2];
TEST_CALL_REPORT("ProDisplistCallback()", "CreateDispList()", (ProError)0, 0);
status = ProMdlCurrentGet (&model);
TEST_CALL_REPORT("ProMdlCurrentGet()", "CreateDispList()", status,
status != PRO_TK_NO_ERROR);
status = ProSolidOutlineGet ((ProSolid)model, points);
TEST_CALL_REPORT("ProSolidOutlineGet()", "CreateDispList()", status,
status != PRO_TK_NO_ERROR);
radius = 0.3*(points[1][0] - points[0][0])/100.0;
highlite_color.method = PRO_COLOR_METHOD_TYPE;
highlite_color.value.type = PRO_COLOR_HIGHLITE;
letter_color.method = PRO_COLOR_METHOD_TYPE;
letter_color.value.type = PRO_COLOR_LETTER;
status = ProGraphicsColorModify(mode[0] ? &letter_color :
&highlite_color, &keep_color);
TEST_CALL_REPORT("ProGraphicsColorModify()", "CreateDispList()", status,
status != PRO_TK_NO_ERROR);
for (l=0; l<n_list[0]; l++)
{
for (i=0; i<p_list[l].n_hits; i++)
{
if (mode[0] ^ (p_list[l].to_front[i]==PRO_B_TRUE)) continue;
ProGraphicsPenPosition(p_list[l].origin);
ProGraphicsLineDraw(p_list[l].p_pnt[i]);
ProGraphicsCircleDraw(p_list[l].p_pnt[i], radius);
}
}
status = ProGraphicsColorModify(&keep_color, NULL);
TEST_CALL_REPORT("ProGraphicsColorModify()", "CreateDispList()", status,
status != PRO_TK_NO_ERROR);
return (0);
}