cgma
|
00001 //------------------------------------------------------------------------- 00002 // Filename : FacetSurface.hpp 00003 // 00004 // Purpose : 00005 // 00006 // Special Notes : 00007 // 00008 // Creator : David R. White 00009 // 00010 // Creation Date : 06/06/00 00011 // 00012 // Owner : David R. White 00013 //------------------------------------------------------------------------- 00014 00015 #ifndef SURFACE_Facet_HPP 00016 #define SURFACE_Facet_HPP 00017 00018 #include "CubitDefines.h" 00019 #include "Surface.hpp" 00020 #include "FacetAttribSet.hpp" 00021 #include <map> 00022 00023 class TopologyEntity; 00024 class RefVolume; 00025 class RefFace; 00026 class RefVolume; 00027 class FacetEvalTool; 00028 class FacetShell; 00029 class FacetAttrib; 00030 00031 class FacetBody; 00032 class FacetLump; 00033 class FacetLoop; 00034 class FacetCoEdge; 00035 class FacetCurve; 00036 class FacetPoint; 00037 class CubitFacetEdge; 00038 class CubitFacet; 00039 class CubitPoint; 00040 class CubitTransformMatrix; 00041 class CubitEvaluator; 00042 class CubitEvaluatorData; 00043 class SphereEvaluatorData; 00044 class CylinderEvaluatorData; 00045 00046 class FacetSurface : public Surface 00047 { 00048 00049 private: 00050 //CubitSense sense_; 00051 //- The sense of the RefFace that owns this Surface with respect 00052 //- to the positive sense of the first FACE in FACEPtrList_. 00053 //- When a Surface is first constructed, this value is arbitrarily 00054 //- set to CUBIT_FORWARD. 00055 //- In the case of Surfaces, the normal is used in determining 00056 //- the relative sense value. 00057 //- MJP NOTE: 00058 //- Not only does the RefFace have a sense wrt its Surface, but each 00059 //- Facet FACE has a sense wrt its underlying "surface" object. 00060 00061 //sjowen FacetEvalTool *facetEvalTool; 00062 FacetEvalTool *facetEvalTool; 00063 //For topology traversals we need to have connections to the 00064 //entitities connected to this surface. From these we can get the rest. 00065 DLIList<LoopSM*> myLoops; 00066 DLIList<ShellSM*> myShells; 00067 00068 FacetAttribSet attribSet; 00069 //List of FacetAttrib*'s instead of CubitSimpleAttribs 00070 00071 // the sense of the surface with respect to the shells in the myShells list 00072 CubitSense myShellSense; 00073 00074 CubitEvaluator *myEvaluator; 00075 00076 protected: 00077 00078 public : 00079 00080 FacetSurface(FacetEvalTool *facet_eval_tool_ptr, 00081 DLIList<ShellSM*> &shellsms,DLIList<LoopSM*> &loopsms ); 00082 //I- facet_eval_tool pointer 00083 //I- A pointer to the set of facets that define this surface. 00084 00085 FacetSurface(FacetEvalTool *facet_eval_tool_ptr, 00086 CubitSense sense, 00087 CubitSense shell_sense0, 00088 CubitBoolean use_facets, 00089 DLIList<LoopSM*> &loopsms ); 00090 00091 00092 FacetSurface( const CylinderEvaluatorData *cylinder_data, 00093 FacetEvalTool *facet_tool, 00094 DLIList<ShellSM*> &shellsms, 00095 DLIList<LoopSM*> &loopsms ); 00096 //- Constructor used to create a faceted surface representing a cylinder. 00097 //I- eval_data - radius, base, etc. of cylinder. 00098 //I- facet_eval_tool_ptr - evaluator to evaluate directly on facets. 00099 //I- shellsms - the shells in this facet model 00100 //I- loopsms - the loops in this facet model. 00101 00102 FacetSurface( const SphereEvaluatorData *eval_data, 00103 FacetEvalTool *facet_eval_tool_ptr, 00104 DLIList<ShellSM*> &shellsms, 00105 DLIList<LoopSM*> &loopsms ); 00106 //- Constructor used to create a faceted surface representing a sphere. 00107 //I- eval_data - radius, center, etc. of sphere. 00108 //I- facet_eval_tool_ptr - evaluator to evaluate directly on facets. 00109 //I- shellsms - the shells in this facet model 00110 //I- loopsms - the loops in this facet model. 00111 00112 virtual ~FacetSurface() ; 00113 //- The destructor 00114 00115 void add_shell(ShellSM *shell_ptr) 00116 {myShells.append(shell_ptr);} 00117 00118 CubitStatus remove_shell(FacetShell* shell_ptr); 00119 00120 void disconnect_all_loops(); 00121 00122 inline bool has_parent_shell() { return myShells.size() > 0; } 00123 00124 //CubitSense get_relative_surface_sense(); 00125 //- Return the relative surface sense. (see below) 00126 00127 virtual void append_simple_attribute_virt(const CubitSimpleAttrib&); 00128 //R void 00129 //I 00130 //I- 00131 //I- that is to be appended to this OSME object. 00132 //- The purpose of this function is to append a 00133 //- attribute to the OSME. The is attached to each of the 00134 //- underlying solid model entities this one points to. 00135 00136 virtual void remove_simple_attribute_virt(const CubitSimpleAttrib&); 00137 //R void 00138 //I CubitSimpleAttrib* 00139 //I- A reference to a CubitSimpleAttrib object which is the object 00140 //I- that is to be removed to this OSME object. 00141 //- The purpose of this function is to remove a simple 00142 //- attribute from the OSME. The attribute is attached to each of the 00143 //- underlying solid model entities this one points to. 00144 00145 virtual void remove_all_simple_attribute_virt(); 00146 //R void 00147 //I- 00148 //- The purpose of this function is to remove all simple 00149 //- attributes from the OSME. 00150 00151 virtual CubitStatus get_simple_attribute(DLIList<CubitSimpleAttrib>&); 00152 virtual CubitStatus get_simple_attribute(const CubitString& name, 00153 DLIList<CubitSimpleAttrib>&); 00154 //R CubitSimpleAttrib* 00155 //R- the returned cubit simple attribute. 00156 //- The purpose of this function is to get the attributes 00157 //- of the geometry entity. The name is attached to the underlying solid 00158 //- model entity(ies) this one points to. 00159 //- MJP Note: 00160 //- This is the code that implements the requirement that names 00161 //- of VGI Entities propagate across solid model boolean 00162 //- operations. The success of this relies, of course, on the underlying 00163 //- solid modeler being able to propagate attributes across 00164 //- such operations on its entities. If it cannot, then "names" 00165 //- of VGI entities will not propagate. 00166 00167 virtual CubitBox bounding_box() const ; 00168 // see comments in GeometryEntity.hpp 00169 00170 virtual GeometryQueryEngine* 00171 get_geometry_query_engine() const; 00172 //R GeometryQueryEngine* 00173 //R- A pointer to the geometric modeling engine associated with 00174 //R- the object. 00175 //- This function returns a pointer to the geometric modeling engine 00176 //- associated with the object. 00177 00178 // Added by CAT 00179 virtual CubitStatus get_point_normal( CubitVector& , 00180 CubitVector& ); 00181 //- Only valid for planar surfaces 00182 //- Finds the underlying plane's origin and normal vector 00183 //- Returns CubitFailure if not a plane. The origin and normal 00184 //- are returned directly from the underlying format for a plane. 00185 00186 virtual CubitStatus closest_point_uv_guess( 00187 CubitVector const& location, 00188 double &u, double &v, 00189 CubitVector* closest_location = NULL, 00190 CubitVector* unit_normal = NULL ); 00191 00192 00193 virtual void closest_point_trimmed(CubitVector from_point, 00194 CubitVector& point_on_surface); 00195 //R void 00196 //I CubitVector 00197 //I- point from which to find closest point on trimmed surface 00198 //O CubitVector 00199 //O- point on trimmed surface closest to passed-in point 00200 //- This function finds the closest point on a TRIMMED surface to the 00201 //- passed-in point. 00202 00203 virtual CubitStatus closest_point_along_vector(CubitVector& from_point, 00204 CubitVector& along_vector, 00205 CubitVector& point_on_surface); 00206 00207 00208 virtual CubitStatus closest_point( 00209 CubitVector const& location, 00210 CubitVector* closest_location = NULL, 00211 CubitVector* unit_normal_ptr = NULL, 00212 CubitVector* curvature1_ptr = NULL, 00213 CubitVector* curvature2_ptr = NULL); 00214 //R CubitStatus 00215 //R- CUBIT_SUCCESS/FAILURE 00216 //I location 00217 //I- The point to which the closest point on the surface is desired. 00218 //O closest_location 00219 //O- The point on the Surface, closest to the 00220 //O- input location (which might not be on the Surface). This is 00221 //O- input as a reference so that the function can modify its 00222 //O- contents. 00223 //O unit_normal_ptr 00224 //O- The normal (represented as a unit vector) at the closest_location. 00225 //O- If this pointer is NULL, the normal is not returned. 00226 //O curvature1_ptr 00227 //O- The first principal curvature of the surface at closest_location. 00228 //O- If this pointer is NULL, this curvature is not returned. 00229 //O curvature2_ptr 00230 //O- The second principal curvature of the surface at closest_location. 00231 //O- If this pointer is NULL, this curvature is not returned. 00232 //- This function computes the point on the surface closest to the input 00233 //- location -- i.e., closest_location. 00234 //- The first Facet FACE in the list 00235 //- is queried. 00236 //- 00237 //- If the input pointer values of unit_normal, curvature1 and 00238 //- curvature2 00239 //- are non-NULL, the normal and principal curvatures, too, are 00240 //- returned. These are computed at closest_location, not at the 00241 //- input location. 00242 //- 00243 //- NOTE: 00244 //- It is assumed that if the calling code needs the normal or the 00245 //- principal curvatures, it will *allocate* space for the CubitVectors 00246 //- before sending in the pointers. 00247 00248 virtual CubitStatus principal_curvatures( 00249 CubitVector const& location, 00250 double& curvature_1, 00251 double& curvature_2, 00252 CubitVector* closest_location = NULL ); 00253 //R CubitStatus 00254 //R- CUBIT_SUCCESS/FAILURE 00255 //I location 00256 //I- The point at which the curvatures are being requested -- it is also 00257 //I- the point to which the closest point on the surface is returned. 00258 //I- curvatures. 00259 //O closest_location 00260 //O- The point on the surface, closest to the input location (this 00261 //O- might not be on the surface). This is input as a reference 00262 //O- so that the function can modify its contents. 00263 //O curvature_1/2 00264 //O- Returned principal curvature magnitudes. 00265 //- This functions computes the point on the surface that is closest 00266 //- to the input location and then calculates the magnitudes of the 00267 //- principal curvatures at this (possibly, new) point on the surface. 00268 00269 00270 00271 virtual CubitStatus evaluate( double u, double v, 00272 CubitVector *position, 00273 CubitVector *normal, 00274 CubitVector *curvature1, 00275 CubitVector *curvature2 ); 00276 00277 00278 00279 virtual CubitVector position_from_u_v (double u, double v); 00280 //R CubitVector 00281 //R- Returned position vector. 00282 //I u, v 00283 //I- Input point in {u.v} space 00284 //- This function returns the coordinates in world space of a point 00285 //- in the parameter space of this Surface object. 00286 00287 virtual CubitStatus u_v_from_position (CubitVector const& location, 00288 double& u, 00289 double& v, 00290 CubitVector* 00291 closest_location = NULL ); 00292 //R CubitStatus 00293 //R- CUBIT_SUCCESS/FAILURE 00294 //I location 00295 //I- The input point in global space 00296 //O closest_point 00297 //O- The point on the Surface closest to the input location 00298 //O u, v 00299 //O- The returned u, v coordinate values (in local parametric space) 00300 //O- of the closest_point 00301 //I refvolume_ptr 00302 //- This function returns the {u, v} coordinates of the point 00303 //- on the Surface closest to the input point (specified in global 00304 //- space). The closest_location is also returned. 00305 00306 virtual CubitBoolean is_periodic(); 00307 //R CubitBoolean 00308 //R- CUBIT_TRUE/CUBIT_FALSE 00309 //- This function determines whether the underlying geometry of the 00310 //- FacetSurface is periodic or not. Returns CUBIT_TRUE if it is and 00311 //- CUBIT_FALSE if it is not. 00312 //- MJP NOTE: 00313 //- The first Facet FACE in the list is queried. It is assumed 00314 //- that all the FACEs have the same underlying surface. 00315 00316 virtual CubitBoolean is_periodic_in_U( double& period ); 00317 //R CubitBoolean 00318 //R- CUBIT_TRUE/CUBIT_FALSE 00319 //O period 00320 //O- The value of the period in the U direction. 00321 //- Determines whether the Facet surface object associated 00322 //- with one of the FACEs of this FacetSurface object is 00323 //- periodic in the U direction or not. If it is, it 00324 //- returns CUBIT_TRUE and the value of the period. Otherwise, 00325 //- it returns CUBIT_FALSE and a value of 0.0 or the period. 00326 //- MJP NOTE: 00327 //- The first Facet FACE in the list is queried. It is assumed 00328 //- that all the FACEs have the same underlying surface. 00329 00330 virtual CubitBoolean is_periodic_in_V( double& period ); 00331 //R CubitBoolean 00332 //R- CUBIT_TRUE/CUBIT_FALSE 00333 //O period 00334 //O- The value of the period in the V direction. 00335 //- Determines whether the Facet surface object associated 00336 //- with one of the FACEs of this FacetSurface object is 00337 //- periodic in the V direction or not. If it is, it 00338 //- returns CUBIT_TRUE and the value of the period. Otherwise, 00339 //- it returns CUBIT_FALSE and a value of 0.0 or the period. 00340 //- MJP NOTE: 00341 //- The first Facet FACE in the list is queried. It is assumed 00342 //- that all the FACEs have the same underlying surface. 00343 00344 virtual CubitBoolean is_singular_in_U( double u_param ); 00345 virtual CubitBoolean is_singular_in_V( double v_param ); 00346 //R CubitBoolean 00347 //R- CUBIT_TRUE/CUBIT_FALSE 00348 //I double u/v parameter value. 00349 //- Determines if the surface is singular in a given direction 00350 //- at a given parameter value. 00351 00352 virtual CubitBoolean is_closed_in_U(); 00353 virtual CubitBoolean is_closed_in_V(); 00354 //R CubitBoolean 00355 //R- CUBIT_TRUE/CUBIT_FALSE 00356 //- Determines if the surface is closed, smoothly or not in the 00357 //- given parameter direction. 00358 //- A periodic surface is always closed but a closed surface is 00359 //- is not always periodic. 00360 00361 virtual CubitStatus uv_derivitives( double u_param, 00362 double v_param, 00363 CubitVector &du, 00364 CubitVector &dv ); 00365 //R CubitStatus 00366 //R- CUBIT_SUCCESS/CUBIT_FAILURE 00367 //O- du, dv 00368 //- Determines the u and v derivitives from the given parameter 00369 //- values. 00370 00371 virtual CubitBoolean is_parametric(); 00372 //R CubitBoolean 00373 //R- CUBIT_TRUE/CUBIT_FALSE 00374 //- This method returns CUBIT_TRUE if a parametric representation 00375 //- is available for the surface 00376 00377 virtual CubitBoolean get_param_range_U( double& lower_bound, 00378 double& upper_bound ); 00379 //R CubitBoolean 00380 //R- CUBIT_TRUE/CUBIT_FALSE 00381 //O lower_bound 00382 //O- The lower bound of the parametric range in the U direction. 00383 //O- This is set to 0.0 if the surface is not parametric. 00384 //O upper_bound 00385 //O- The upper bound of the parametric range in the U direction. 00386 //O- This is set to 0.0 if the surface is not parametric. 00387 //- Returns the lower and upper parametric bounds of the 00388 //- surface in U, if it is parametric. Otherwise, it returns 00389 //- CUBIT_FALSE and zeroes for the upper and lower parametric 00390 //- bounds. 00391 //- MJP NOTE: 00392 //- The first Facet FACE in the list is queried. It is assumed 00393 //- that all the FACEs have the same underlying surface. 00394 00395 virtual CubitBoolean get_param_range_V( double& lower_bound, 00396 double& upper_bound ); 00397 //R CubitBoolean 00398 //R- CUBIT_TRUE/CUBIT_FALSE 00399 //O lower_bound 00400 //O- The lower bound of the parametric range in the V direction. 00401 //O- This is set to 0.0 if the surface is not parametric. 00402 //O upper_bound 00403 //O- The upper bound of the parametric range in the V direction. 00404 //O- This is set to 0.0 if the surface is not parametric. 00405 //- Returns the lower and upper parametric bounds of the 00406 //- surface in V, if it is parametric. Otherwise, it returns 00407 //- CUBIT_FALSE and zeroes for the upper and lower parametric 00408 //- bounds. 00409 //- MJP NOTE: 00410 //- The first Facet FACE in the list is queried. It is assumed 00411 //- that all the FACEs have the same underlying surface. 00412 00413 virtual CubitBoolean is_position_on( CubitVector &test_position ); 00414 //R CubitBoolean 00415 //R- CUBIT_TRUE/CUBIT_FALSE 00416 //I CubitVector 00417 //I- position, point where we want to test, whether or not it 00418 //- is on the surface. 00419 00420 virtual CubitPointContainment point_containment( const CubitVector &point ); 00421 virtual CubitPointContainment point_containment( double u, double v ); 00422 // virtual CubitPointContainment point_containment( const CubitVector &point, 00423 // double u, double v ); 00424 //R CubitPointContainment - is the point outside, inside or on the boundary? 00425 //R- CUBIT_PNT_OUTSIDE, CUBIT_PNT_INSIDE, CUBIT_PNT_BOUNDARY, 00426 // CUBIT_PNT_UNKNOWN 00427 //I CubitVector 00428 //I- position to check, known to be on the Surface 00429 //I double 00430 //I- u coordinate, if known (significantly faster, if this is known - however 00431 // if not known let the function figure it out) 00432 //I double 00433 //I- v coordinate, if known (significantly faster, if this is known - however 00434 // if not known let the function figure it out) 00435 // NOTE: POINT MUST LIE ON THE SURFACE FOR THIS FUNCTION TO WORK PROPERLY. 00436 00437 GeometryType geometry_type(); 00438 //R GeometryType (enum) 00439 //R- The enumerated type of the geometric representation 00440 00441 virtual double measure(); 00442 //R double 00443 //R- The numeric value of the measure (its units depend on the dimension 00444 //R- of the RefEntity being "measured") 00445 //- A generic geometric extent function. 00446 //- Returns volume for Lump, area for Surface, length for Curve and 00447 //- 1.0 for Point 00448 00449 00450 virtual CubitStatus get_projected_distance_on_surface( CubitVector *pos1, 00451 CubitVector *pos2, 00452 double &distance ); 00453 00454 void update_measurement(); 00455 //Make sure we don't retain an out-dated measurement. 00456 00457 virtual CubitSense get_geometry_sense(); 00458 //- Return the relative surface sense. (see below) 00459 00460 virtual void reverse_sense(); 00461 //- Switch the sense of this Surface wrt the RefFace that owns it: 00462 //- For Facet, this means switch the sense of the RefFace that 00463 //- owns this Surface with respect to the positive sense of the 00464 //- first FACE in FACEPtrList_. 00465 00466 CubitStatus save_attribs( FILE* file_ptr ); 00467 // Write FactAttribs out to file 00468 00469 CubitStatus restore_attribs( FILE* file_ptr, unsigned int endian ); 00470 // Read FactAttribs from file 00471 00472 void get_bodies ( DLIList<FacetBody *>& bodies ); 00473 void get_lumps ( DLIList<FacetLump *>& lumps ); 00474 void get_shells ( DLIList<FacetShell *>& shells ); 00475 void get_loops ( DLIList<FacetLoop *>& loops ); 00476 void get_coedges ( DLIList<FacetCoEdge *>& coedges ); 00477 void get_curves ( DLIList<FacetCurve *>& curves ); 00478 00479 void get_parents_virt( DLIList<TopologyBridge*>& parents ); 00480 void get_children_virt( DLIList<TopologyBridge*>& children ); 00481 00482 CubitStatus get_my_facets(DLIList<CubitFacet*>& facet_list, 00483 DLIList<CubitPoint*>& point_list); 00484 //- Gets the list of facets describing this surface. 00485 void tris(DLIList<CubitFacet*> &facet_list); 00486 void get_my_points(DLIList<CubitPoint*>& point_list); 00487 //- Gets the list of points describing this surface. 00488 void get_my_facetedges(DLIList<CubitFacetEdge*>& edge_list); 00489 //- Gets the list of points describing this surface. 00490 FacetEvalTool *get_eval_tool() 00491 { return facetEvalTool; } 00492 const FacetEvalTool *get_eval_tool() const 00493 { return facetEvalTool; } 00494 //- return the facet evaluation tool for this surface 00495 00496 CubitSense get_shell_sense( ShellSM *facet_shell ) const; 00497 // return the sense with respect to the given shell 00498 00499 void get_shell_sense( CubitSense &sense0 ); 00500 // return senses 00501 00502 void set_shell_sense( FacetShell *facet_shell, 00503 CubitSense thesense ); 00504 // set the sense of the surface with respect to the shell 00505 00506 CubitStatus copy_facets(DLIList<CubitFacet*>©_facet_list, 00507 DLIList<CubitPoint*>©_point_list, 00508 std::map<CubitPoint*, CubitPoint*>&old_to_new_cubit_pts); 00509 // create a copy of the points and facets 00510 00511 int interp_order(); 00512 double min_dot(); 00513 00514 CubitBoolean is_flat(); 00515 CubitBoolean is_spherical(); 00516 CubitBoolean is_conical(); 00517 00518 virtual CubitStatus get_nurb_params( bool &rational, 00519 int °ree_u, 00520 int °ree_v, 00521 int &num_cntrl_pts_u, 00522 int &num_cntrl_pts_v, 00523 DLIList<CubitVector> &cntrl_pts, 00524 DLIList<double> &weights, 00525 DLIList<double> &u_knots, 00526 DLIList<double> &v_knots ) const; 00527 //- Only valid for nurbs surfaces 00528 //O rational 00529 //O- True if the nurb is rational 00530 //O degree_u 00531 //O- The degree of the nurb in the u direction 00532 //O degree_v 00533 //O- The degree of the nurb in the v direction 00534 //O num_cntrl_pts_u 00535 //O- Number of control points in the u direction 00536 //O num_cntrl_pts_v 00537 //O- Number of control points in the v direction 00538 //O cntrl_pts 00539 //O- The control points stored as 00540 //O- cntrl_pts[0 ] = pt[u=0][v=0] 00541 //O- cntrl_pts[1 ] = pt[u=1][v=0] 00542 //O- ... 00543 //O- cntrl_pts[num_cntrl_pts_u-1] = pt[u=?][v=0] 00544 //O- cntrl_pts[num_cntrl_pts_u ] = pt[u=0][v=1] 00545 //O- ... 00546 //O weights 00547 //O- If rational, weights for each control point, stored in the same 00548 //O- order as the control points. No weights are returned if 00549 //O- rational == false 00550 //O u_knots 00551 //O- knot vector in the u direction 00552 //O v_knots 00553 //O- knot vector in the v direction 00554 00555 virtual CubitStatus get_sphere_params( CubitVector ¢er, 00556 double &radius ) const; 00557 //- Only valid for spherical surfaces 00558 //O center 00559 //O- The center of the sphere 00560 //O radius 00561 //O- The radius of the sphere 00562 00563 virtual CubitStatus get_cone_params( CubitVector ¢er, 00564 CubitVector &normal, 00565 CubitVector &major_axis, 00566 double &radius_ratio, 00567 double &sine_angle, 00568 double &cos_angle ) const; 00569 //- Only valid for conical surfaces. Cylinders are a special case of conicals. 00570 //O center 00571 //O- 00572 //O normal 00573 //O- 00574 //O major_axis 00575 //O- 00576 //O radius_ratio 00577 //O- 00578 //O sine_angle 00579 //O- 00580 //O cos_angle 00581 //O- 00582 00583 virtual CubitStatus get_torus_params( CubitVector ¢er, 00584 CubitVector &normal, 00585 double &major_radius, 00586 double &minor_radius ) const; 00587 //- Only valid for torus surfaces. 00588 //O center 00589 //O- 00590 //O normal 00591 //O- 00592 //O major_radius 00593 //O- 00594 //O minor_radius 00595 //O- 00596 00597 const CubitEvaluatorData *evaluator_data(); 00598 void add_transformation( CubitTransformMatrix &tfmat ); 00599 00600 }; 00601 00602 00603 // ********** BEGIN INLINE FUNCTIONS ********** 00604 // ********** END INLINE FUNCTIONS ********** 00605 00606 // ********** BEGIN FRIEND FUNCTIONS ********** 00607 // ********** END FRIEND FUNCTIONS ********** 00608 00609 // ********** BEGIN EXTERN FUNCTIONS ********** 00610 // ********** END EXTERN FUNCTIONS ********** 00611 00612 #endif 00613