/*====================================================================*\
FILE    : UgSweepCreate.c
PURPOSE : ProTk  User Guide
	  Example of creating a sweep feature 

HISTORY..
DATE      BUILD   AUTHOR   MODIFICATIONS
06-Jan-98 H-03-36 Steve    $$1  Created 
16-Jan-98 H-03-37 Steve    $$2  Make sure sec method element is specified
20-Jan-98 H-03-37 Steve    $$3  Make sure sec method defined for x-sect
\*====================================================================*/
/*---------------------- Pro/Toolkit Includes ------------------------*/
#include <ProToolkit.h>
#include <ProMdl.h>
#include <ProElement.h>
#include <ProFeatType.h>
#include <ProFeatForm.h>
#include <ProSweep.h>
#include <ProFeature.h>
#include <ProSection.h>
#include <ProSecdim.h>
 
/*---------------------- Pro/Develop Includes ------------------------*/

/*---------------------- Application Includes ------------------------*/
#include <TestError.h>

/*---------------------- Application Typedefs ------------------------*/
typedef struct element_data
{
    ProElement parent_element;
    ProElemId elem_id;
    ProValueData value_data;
} UgElemdata;

/*---------------------- Prototypes ----------------------------------*/
ProError UgFeatElemAdd(UgElemdata *elem,ProElement *added_elem);
ProError UgFeatElemValueGet(ProElement tree, ProElempathItem *path, int size, 
			    ProValueData *elem_val);
ProError UgSectionRegenerate(ProSection section);
ProError UgSweepSpineSktCreate(ProSection section);
ProError UgSweepSectSktCreate(ProSection section);
ProError UgFeatElemRemove(ProElement tree, ProElempathItem *path, int size);
ProError UgFeatElemAddSecMethod(ProElement std_sec_elem);

/*====================================================================*\
Function: UgBaseSweepProtrCreate
Purpose: Example to demonstrate creation of first feature sweep protrusion
\*====================================================================*/
int UgBaseSweepProtrCreate(ProPart part )
{
    ProError err;
    UgElemdata elem_data;
    ProFeature feature;
    ProErrorlist ftcr_errs;
    ProElement elem,elem_tree;
    ProSelection part_sel;
    ProModelitem part_mdlitem;
    ProFeatureCreateOptions ftcropts[] = {PRO_FEAT_CR_INCOMPLETE_FEAT};
    ProElempathItem sect_path[] = {{PRO_ELEM_PATH_ITEM_TYPE_ID,
				    PRO_E_SWEEP_SECTION}};
    ProElempathItem spine_skt_path[] = {{PRO_ELEM_PATH_ITEM_TYPE_ID,
					 PRO_E_SWEEP_SPINE},
                                        {PRO_ELEM_PATH_ITEM_TYPE_ID,
					 PRO_E_SKETCHER}};
    ProElempathItem sect_skt_path[] = {{PRO_ELEM_PATH_ITEM_TYPE_ID,
					 PRO_E_SWEEP_SECTION},
                                        {PRO_ELEM_PATH_ITEM_TYPE_ID,
					 PRO_E_SKETCHER}};
    ProValueData spine_skt_val, sect_skt_val;

    if (part == NULL)
    {
	err = ProMdlCurrentGet((ProMdl *)&part);
	ERROR_CHECK("ProMdlCurrentGet","UgBaseSweepProtrCreate",err);
    }
/*--------------------------------------------------------------------*\
Initialize element tree
\*--------------------------------------------------------------------*/
    err = ProElementAlloc(PRO_E_FEATURE_TREE,&elem_tree);
    ERROR_CHECK("ProElementAlloc","UgBaseSweepProtrCreate",err);

/*--------------------------------------------------------------------*\
Add feature type element to the tree
\*--------------------------------------------------------------------*/
    elem_data.parent_element = elem_tree;
    elem_data.elem_id = PRO_E_FEATURE_TYPE;
    elem_data.value_data.type = PRO_VALUE_TYPE_INT;
    elem_data.value_data.v.i = PRO_FEAT_FIRST_FEAT;
    err = UgFeatElemAdd(&elem_data,&elem);

/*--------------------------------------------------------------------*\
Add feature form element to the tree
\*--------------------------------------------------------------------*/
    elem_data.parent_element = elem_tree;
    elem_data.elem_id = PRO_E_FEATURE_FORM;
    elem_data.value_data.type = PRO_VALUE_TYPE_INT;
    elem_data.value_data.v.i = PRO_SWEEP;
    err = UgFeatElemAdd(&elem_data,&elem);

/*--------------------------------------------------------------------*\
Add section method for the spine section 
\*--------------------------------------------------------------------*/
    elem_data.parent_element = elem_tree;
    elem_data.elem_id = PRO_E_SWEEP_SPINE;
    elem_data.value_data.type = -1;
    elem_data.value_data.v.i = 0;
    err = UgFeatElemAdd(&elem_data,&elem);
    err = UgFeatElemAddSecMethod(elem);

/*--------------------------------------------------------------------*\
Add section method for the sweep section 
\*--------------------------------------------------------------------*/
    elem_data.parent_element = elem_tree;
    elem_data.elem_id = PRO_E_SWEEP_SECTION;
    elem_data.value_data.type = -1;
    elem_data.value_data.v.i = 0;
    err = UgFeatElemAdd(&elem_data,&elem);
    err = UgFeatElemAddSecMethod(elem);

/*--------------------------------------------------------------------*\
Create incomplete feature to initialize spine sketch handle
\*--------------------------------------------------------------------*/
    err = ProMdlToModelitem((ProMdl)part,&part_mdlitem);
    ERROR_CHECK("ProMdlToModelitem","UgBaseSweepProtrCreate",err);
    err = ProSelectionAlloc(NULL,&part_mdlitem,&part_sel);
    ERROR_CHECK("ProSelectionAlloc","UgBaseSweepProtrCreate",err);
    err = ProFeatureCreate(part_sel,elem_tree,ftcropts,1,&feature,
			   &ftcr_errs);
    ERROR_CHECK("ProFeatureCreate","UgBaseSweepProtrCreate",err);
    err = ProElementFree(&elem_tree);
    ERROR_CHECK("ProElementFree","UgBaseSweepProtrCreate",err);

/*--------------------------------------------------------------------*\
Retrieve initialized element tree from the proe data base
\*--------------------------------------------------------------------*/
    err = ProFeatureElemtreeCreate(&feature,&elem_tree);
    ERROR_CHECK("ProFeatureElemtreeCreate","UgBaseSweepProtrCreate",err);
/*--------------------------------------------------------------------*\
Get the spine sketch handle from the element tree
\*--------------------------------------------------------------------*/
    err = UgFeatElemValueGet(elem_tree,spine_skt_path,2,&spine_skt_val);

/*--------------------------------------------------------------------*\
Create sweep spine
\*--------------------------------------------------------------------*/
    err = UgSweepSpineSktCreate((ProSection)spine_skt_val.v.p);

/*--------------------------------------------------------------------*\
Remove sweep section element tree to avoid unitialized data 
\*--------------------------------------------------------------------*/
    err = UgFeatElemRemove(elem_tree,sect_path,1);

/*--------------------------------------------------------------------*\
Add section method for the sweep x-section 
\*--------------------------------------------------------------------*/
    elem_data.parent_element = elem_tree;
    elem_data.elem_id = PRO_E_SWEEP_SECTION;
    elem_data.value_data.type = -1;
    elem_data.value_data.v.i = 0;
    err = UgFeatElemAdd(&elem_data,&elem);
    err = UgFeatElemAddSecMethod(elem);

/*--------------------------------------------------------------------*\
Redefine feature as incomplete to add spine and initialize section sketch
\*--------------------------------------------------------------------*/
    err = ProFeatureRedefine(NULL,&feature,elem_tree,ftcropts,1,
			     &ftcr_errs);
    ERROR_CHECK("ProFeatureRedefine","UgBaseSweepProtrCreate",err);
    err = ProElementFree(&elem_tree);
    ERROR_CHECK("ProElementFree","UgBaseSweepProtrCreate",err);

/*--------------------------------------------------------------------*\
Retrieve initialized element tree from the proe data base
\*--------------------------------------------------------------------*/
    err = ProFeatureElemtreeCreate(&feature,&elem_tree);
    ERROR_CHECK("ProFeatureElemtreeCreate","UgBaseSweepProtrCreate",err);

/*--------------------------------------------------------------------*\
Get the section sketch handle from the element tree
\*--------------------------------------------------------------------*/
    err = UgFeatElemValueGet(elem_tree,sect_skt_path,2,&sect_skt_val);

/*--------------------------------------------------------------------*\
Create sweep section sketch
\*--------------------------------------------------------------------*/
    err = UgSweepSectSktCreate((ProSection)sect_skt_val.v.p);

/*--------------------------------------------------------------------*\
Redefine feature to create complete feature
\*--------------------------------------------------------------------*/
    ftcropts[0] = PRO_FEAT_CR_NO_OPTS;
    err = ProFeatureRedefine(NULL,&feature,elem_tree,ftcropts,1,
			     &ftcr_errs);
    ERROR_CHECK("ProFeatureRedefine","UgBaseSweepProtrCreate",err);
    err = ProElementFree(&elem_tree);
    ERROR_CHECK("ProElementFree","UgBaseSweepProtrCreate",err);

    return(err);
}
/*====================================================================*\
Function: UgFeatElemAdd
Purpose: Adds a generic feature element to the element tree
\*====================================================================*/
ProError UgFeatElemAdd(UgElemdata *elem,ProElement *added_elem)
{
    ProValue value;
    ProElement element;
    ProError err;
     
    if (elem->value_data.type != -1)
    {
        err = ProValueAlloc(&value);
        ERROR_CHECK("ProValueAlloc","UgFeatElemAdd", err);
	err = ProValueDataSet(value,&elem->value_data);
	ERROR_CHECK("ProValueDataSet","UgFeatElemAdd",err);
    }

    err = ProElementAlloc(elem->elem_id,&element);
    ERROR_CHECK("ProElementAlloc","UgFeatElemAdd",err);
    if (elem->value_data.type != -1)
    {
        err = ProElementValueSet(element,value);
	ERROR_CHECK("ProElementValueSet","UgFeatElemAdd",err);
    }

    err = ProElemtreeElementAdd(elem->parent_element,NULL,element);
    ERROR_CHECK("ProElemtreeElementAdd","UgFeatElemAdd",err);
    
    *added_elem = element;

    return(err);
}
/*====================================================================*\
Function: UgFeatElemAddSecMethod
Purpose: adds necessary elements below PRO_E_STD_SECTION elem to 
	 specify sec method element
\*====================================================================*/
ProError UgFeatElemAddSecMethod(ProElement std_sec_elem)
{
    ProElement elem;
    UgElemdata elem_data;
    ProError err;

    elem_data.parent_element = std_sec_elem;
    elem_data.elem_id = PRO_E_STD_SEC_SETUP;
    elem_data.value_data.type = -1;
    elem_data.value_data.v.i = 0;
    err = UgFeatElemAdd(&elem_data,&elem);

    elem_data.parent_element = elem;
    elem_data.elem_id = PRO_E_STD_SEC_METHOD;
    elem_data.value_data.type = PRO_VALUE_TYPE_INT;
    elem_data.value_data.v.i = PRO_SEC_SKETCH;
    err = UgFeatElemAdd(&elem_data,&elem);

    return(0);
}
/*====================================================================*\
Function: UgFeatElemValueGet
Purpose: Gets a feature element from the element tree
\*====================================================================*/
ProError UgFeatElemValueGet(ProElement tree, ProElempathItem *path, int size, 
			    ProValueData *elem_val)
{
    ProElempath elem_path;
    ProElement elem;
    ProValue value;
    ProError err;

    err = ProElempathAlloc(&elem_path);
    ERROR_CHECK("ProElempathAlloc","UgFeatElemGet",err);

    err = ProElempathDataSet(elem_path,path,size);
    ERROR_CHECK("ProElempathDataSet","UgFeatElemGet",err);

    err = ProElemtreeElementGet(tree,elem_path,&elem);
    ERROR_CHECK("ProElemtreeElementGet","UgFeatElemValueGet",err);

    err = ProElementValueGet(elem,&value);
    ERROR_CHECK("ProElementValueGet","UgFeatElemValueGet",err);

    err = ProValueDataGet(value,elem_val);
    ERROR_CHECK("ProValueDataGet","UgFeatElemValueGet",err);

    return(err);
}
/*====================================================================*\
Function: UgFeatElemRemove
Purpose: Removes a feature element from the element tree
\*====================================================================*/
ProError UgFeatElemRemove(ProElement tree, ProElempathItem *path, int size)
{
    ProElempath elem_path;
    ProElement elem;
    ProError err;

    err = ProElempathAlloc(&elem_path);
    ERROR_CHECK("ProElempathAlloc","UgFeatElemGet",err);

    err = ProElempathDataSet(elem_path,path,size);
    ERROR_CHECK("ProElempathDataSet","UgFeatElemGet",err);

    err = ProElemtreeElementGet(tree,elem_path,&elem);
    ERROR_CHECK("ProElemtreeElementGet","UgFeatElemValueGet",err);

    err = ProElemtreeElementRemove(tree,elem_path,&elem);
    ERROR_CHECK("ProElemtreeElementRemove","UgFeatElemRemove",err);

    err = ProElementFree(&elem);
    ERROR_CHECK("ProElementFree","UgFeatElemRemove",err);

    return(err);
}
/*====================================================================*\
Function: UgSweepSpineSktCreate
Purpose: Creates a spine sketch for a sweep first feature
\*====================================================================*/
ProError UgSweepSpineSktCreate(ProSection section)
{
    Pro2dSplinedef spline;
    Pro2dPnt pnt_ar[] = {{0.0,0.0},{5.0,5.0},{10.0,-5.0},{15.0,2.0}};
    int spl_id, dim_id;
    Pro2dPnt place_pnt = {7.5,0.0};
    ProSectionPointType pnt_types[] = {PRO_ENT_START,PRO_ENT_END};
    int ent_ids[2];
    ProError err;

    spline.type = PRO_2D_SPLINE;
    spline.tangency_type = PRO_2D_SPLINE_TAN_NONE;
    spline.n_points = 4;
    spline.point_arr = pnt_ar;
    spline.start_tang_angle = 0.0;
    spline.end_tang_angle = 0.0;

    err = ProSectionEntityAdd(section,(Pro2dEntdef *)&spline,&spl_id);
    ERROR_CHECK("ProSecitonEntityAdd","UgSweepSpineSktCreate",err);

    ent_ids[0] = ent_ids[1] = spl_id;
    err = ProSecdimCreate(section,ent_ids,pnt_types,2,
			  PRO_TK_DIM_PNT_PNT_HORIZ,place_pnt,&dim_id);
    ERROR_CHECK("ProSecdimCreate","UgSweepSpineSktCreate",err);

    ent_ids[0] = ent_ids[1] = spl_id;
    err = ProSecdimCreate(section,ent_ids,pnt_types,2,
			  PRO_TK_DIM_PNT_PNT_VERT,place_pnt,&dim_id);
    ERROR_CHECK("ProSecdimCreate","UgSweepSpineSktCreate",err);

    err = UgSectionRegenerate(section);

    return(err);
}
/*====================================================================*\
Function: UgSweepSectSktCreate
Purpose: Creates a section sketch for a constant section sweep
\*====================================================================*/
ProError UgSweepSectSktCreate(ProSection section)
{
    ProError err;
    Pro2dCircledef circle;
    int circle_id;
    ProSectionPointType pnt_types[] = {PRO_ENT_WHOLE};
    Pro2dPnt place_pnt = {0.0,0.0};
    int dim_id;
    ProIntlist ids;
    int n_ids;

    err = ProSectionEntityIdsGet(section,&ids,&n_ids);
    ERROR_CHECK("ProSectionEntityIdsGet","UgSweepSectSktCreate",err);

    printf("Number of section entities: %d\n",n_ids);

    circle.type = PRO_2D_CIRCLE;
    circle.center[0] = circle.center[1] = 0.0;
    circle.radius = 1.0;
    err = ProSectionEntityAdd(section,(Pro2dEntdef *)&circle,&circle_id);
    ERROR_CHECK("ProSecitonEntityAdd","UgSweepSectSktCreate",err);

/*--------------------------------------------------------------------*\
Dimension section and add location dimensions if necessary; Section can
be dimensioned with respect to the construction entities created by 
default (i.e. xy centerlines) although not needed here since the circle is
placed at the origin.
\*--------------------------------------------------------------------*/
    err = ProSecdimCreate(section,&circle_id,pnt_types,1,
			  PRO_TK_DIM_DIA,place_pnt,&dim_id);
    ERROR_CHECK("ProSecdimCreate","UgSweepSectSktCreate",err);

    err = UgSectionRegenerate(section);
    
    return(err);
}
/*====================================================================*\
Function: UgSectionRegenerate
Purpose: Regenerate a section
\*====================================================================*/
ProError UgSectionRegenerate(ProSection section)
{
    ProWSecerror sec_errs;
    ProError err;

    err = ProSecerrorAlloc(&sec_errs);
    ERROR_CHECK("ProSecerrorAlloc","UgSectionRegenerate",err);

    err = ProSectionSolve(section,&sec_errs);
    ERROR_CHECK("ProSectionSolve","UgSectionRegenerate",err);

    err = ProSecerrorFree(&sec_errs);
    ERROR_CHECK("ProSecerrorFree","UgSectionRegenerate",err);

    err = ProSecerrorAlloc(&sec_errs);
    ERROR_CHECK("ProSecerrorAlloc","UgSectionRegenerate",err);

    err = ProSectionRegenerate(section,&sec_errs);
    ERROR_CHECK("ProSectionRegenerate","UgSectionRegenerate",err);

    err = ProSecerrorAlloc(&sec_errs);
    ERROR_CHECK("ProSecerrorAlloc","UgSectionRegenerate",err);

    return(err);
}
