blend_spl_sur
List of: Classes
Subjects: Blending, SAT Save and Restore
Contents: Kernel

Purpose: Provides common functionality and data for all blend surfaces.

Derivation: blend_spl_sur : spl_sur : subtrans_object : subtype_object : ACIS_OBJECT : -

SAT Identifier: blend_spl_sur

Filename: kern/kernel/kerngeom/splsur/blnd_spl.hxx

Description: This is an abstract class that tries to predict some of the fields that derived classes will need; for example, it contains pointers for a left surface, a left curve and a left point although in practice only one of these will be needed in a particular derived class. The reason for doing this is that the base class can (probably) completely handle the administrative functions such as operator=, save and restore, making these trivial for the derived classes.

References: KERN blend_section, blend_support, curve, var_cross_section, var_radius

by KERN blend_support

BASE SPAinterval

Data: protected BOUNDED_CURVE* _def_bcu;

Storage for the bounded curve.


protected CVEC* _def_cvec;

Storage for the CVEC.


protected blend_section* _section_data;

New blend section data.


protected double initial_fitol;

The fit tolerance that was requested when the approx sf was first made. When we extend it, we carry on to this same fitol.


protected int initial_num_u_pts;

The number of u points sampled in fitting the approx sf. When we extend it, we must continue sampling exactly the same points.


protected SPAinterval _support_u_param_range;

The u-parameters of the supports. The u-parameter should just be [0,1], but we'll make it variable, in order to keep things such as shift_u consistent.


public blend_support *left_support;

A support entity. May be a surface, a curve or a point. Have to be a pointer, to allow classes derived from blend_support to be used.


public blend_support *right_support;

A support entity. May be a surface, a curve or a point. Have to be a pointer, to allow classes derived from blend_support to be used.


public curve *def_curve;

Defining curve (reference curve). For a rolling ball blend, this is the blend spine, i.e., the path of the center of the ball. def_cvec is a cvec on the def_curve which is set by each call to evaluate, and may subsequently be used by the application.


public double left_offset;

Objects describing the radius. If the radius is constant then the value of the double is used and the var_radius pointer will be zero. Otherwise, the value of the double will be ignored. The variable radius objects are pointers, so that if the left and right radii are not different, then right_rad will point to the same object as left_rad. Also, rad equals left_rad, always, for convenience.


public double right_offset;

Objects describing the radius. If the radius is constant then the value of the double is used and the var_radius pointer will be zero. Otherwise, the value of the double will be ignored. The variable radius objects are pointers, so that if the left and right radii are not different, then right_rad will point to the same object as left_rad. Also, rad equals left_rad, always, for convenience.


public SPAinterval legal_range;

The "legal" v range is that v range over which the surface is well-behaved. This is initialized to an infinite interval, but if self-intersecting regions of surface are discovered, this range bounds the surface away from them. When infinite, this means the surface is legal in that direction as far as has been analyzed. Semi-infinite will be quite common.


public logical approximation_not_reqd;

Flag to determine whether an approximation is required.


public logical left_handed;

Flag to indicate the handedness.


public logical supports_extended;

Flag to indicate whether the supports are extended.


public var_cross_section* section;

Object describing the cross section. If this is zero then the cross section is assumed to be circular, or elliptical if the radius functions are not equal.


public var_radius *left_rad;

Objects describing the radius. If the radius is constant then the value of the double is used and the var_radius pointer will be zero. Otherwise, the value of the double will be ignored. The variable radius objects are pointers, so that if the left and right radii are not different, then right_rad will point to the same object as left_rad. Also, rad equals left_rad, always, for convenience.


public var_radius *rad;

Objects describing the radius. If the radius is constant then the value of the double is used and the var_radius pointer will be zero. Otherwise, the value of the double will be ignored. The variable radius objects are pointers, so that if the left and right radii are not different, then right_rad will point to the same object as left_rad. Also, rad equals left_rad, always, for convenience.


public var_radius *right_rad;

Objects describing the radius. If the radius is constant then the value of the double is used and the var_radius pointer will be zero. Otherwise, the value of the double will be ignored. The variable radius objects are pointers, so that if the left and right radii are not different, then right_rad will point to the same object as left_rad. Also, rad equals left_rad, always, for convenience.

Constructor: public: blend_spl_sur::blend_spl_sur (


blend_support* left_support,
// blend support






// for left side


blend_support* right_support, // blend support






// for right side


const curve& def_crv,

// defining curve


SPAinterval v_range,

// v param range


double left_offset,

// left offset


double right_offset,

// right offset


var_radius* radius1,

// left radius


var_radius* radius2

// rt rad if diff



= NULL,

// from lt


const var_cross_section* x_sect // cross section,



= NULL,

// if not






// circular


closed_forms u_closure

// u closure



= OPEN,


closed_forms v_closure

// v closure



= CLOSURE_UNSET


);


C++ initialize constructor requests memory for this object and populates it with the data supplied as arguments.


Only certain combinations of input are valid, but this is not enforced by the constructor. The reason for this is that the derived classes are anticipated and have constructors that ensure only valid combinations are passed through to this constructor. For example, the derived classes are expected to make the blend support entities (on the heap) and pass them to this constructor.


The constructor copies the reference curve (which is passed by reference), but assumes ownership of the data that is passed to it by pointer - namely the blend_supports, radius functions and cross sections.






public: blend_spl_sur::blend_spl_sur ();


C++ allocation constructor requests memory for this object but does not populate it.






public: blend_spl_sur::blend_spl_sur (


const blend_spl_sur& //blend spl sur


);


C++ copy constructor requests memory for this object and populates it with the data from the object supplied as an argument.




Destructor: public: virtual blend_spl_sur::~blend_spl_sur ();


C++ destructor, deleting a blend_spl_sur.



Methods: public: virtual int blend_spl_sur::accurate_derivs (


SPApar_box const&
// parameter box



= * (SPApar_box* ) NULL_REF


) const =0;


Returns the number of derivatives which evaluate can find accurately (and fairly directly), rather than by finite differencing, over the given portion of the surface. If there is no limit to the number of accurate derivatives, returns the value ALL_SURFACE_DERIVATIVES, which is large enough to be more than anyone could reasonably want.






public: virtual void blend_spl_sur::append_u (


spl_sur& // spline surface


);


Concatenate the contents of two surfaces into one. The surfaces are guaranteed to be the same base or derived type, and to have contiguous parameter ranges ("this" is the beginning part of the combined surface (i.e., lower parameter values), the argument gives the end part).






public: virtual void blend_spl_sur::append_v (


spl_sur& // spline surface


);


Concatenate the contents of two surfaces into one. The surfaces are guaranteed to be the same base or derived type, and to have contiguous parameter ranges ("this" is the beginning part of the combined surface (i.e., lower parameter values), the argument gives the end part).






public: virtual double blend_spl_sur::blend_angle (


SPAunit_vector& Tan,
// tangent direction


SPAvector const& R0,
// first vectors


SPAvector const& R1,
// second vectors


double& rr_sina
// sine of angle



= * (double* ) NULL_REF, // between vectors


double& rr_cosa
// cosine of angle



= * (double* ) NULL_REF // between vectors


) const = 0;


Find the angle between two vectors, in a plane determined by the tangent vector in the given CVEC.






public: virtual double


blend_spl_sur::blend_total_angle (


SPAposition& P,
// position


SPAunit_vector& Tan,
// tangent direction


SPAvector const& R0,
// first vectors


SPAvector const& R1,
// second vectors


double& rr_sina
// sine of angle



= * (double* ) NULL_REF, // between vectors


double& rr_cosa
// cosine of angle



= * (double* ) NULL_REF // between vectors


) const = 0;


Find the angle between two vectors, in a plane determined by the tangent vector in the given CVEC.






public: logical blend_spl_sur::check_cache (


double v, // v parameter


int spine_nder, // number of required




// spine derivs


int def_nder, // number of required




// spine derivs


int spring_nder, // number of required




// spring derivs


logical xcrv_norm, // whether to fill in




// xcurve normal


blend_section& section, // all output in here


int side // evaluation side


) const;


Method for handling cache data.






public: void blend_spl_sur::check_safe_range (


int which_end // which end to look at



= 0 // default both ends


);


Checks for bad singularities at the ends and sets the legal range such that it avoids them. The argument indicates which end to look at. 0 is for both ends (the default). A negative number represents the low end and a positive the high end.


It checks whether or not a safe_range has been applied to the defining curve. If so, it checks for the case in which the angle between the vectors from the spine point to the contact points is 180 degrees, i.e. the contact points and the spine point are collinear, with the spine point in the middle. The related degeneracy, where the angle is zero and the contact points coincide (tangent surfaces), is not a "bad" singularity and doesn't hurt anything.


If the safe range limits a bad singularity, then the end of the safe range are before the singularity actually happens, so it checks for "close" to a bad singularity at the end.






public: virtual void blend_spl_sur::compute_section (


double v, // v parameter


int spine_nder, // number of required




// spine derivs


int spring_nder, // number of required




// spring derivs


logical xcrv_norm, // whether to fill in




// xcurve normal


blend_section& section, // all output in here


int
// the evaluation



= 0 // location - 1 => above,




// -1 => below,




// 0 => don't care


) const = 0;


A form of evaluation specific to blend_spl_surs (certain numerical algorithms used by blending need this function). Evaluates spine, defining curve, contact points and their derivatives at the given v-parameter, according to the blend_section class declaration as above. We may specify exactly how may spine and spring curve derivatives we require. As the two are typically connected you may get more than you asked for, but you are guaranteed to get at least what you ask for. Implementations of this should also ensure it does no more than is necessary. Finally the logical flag indicates whether you require the cross curve normal filled in; again this may (will) have implications on the amount of other stuff you get back, but if passed as TRUE then this is guaranteed to be returned. Note that calling this with for example -1, -1 and TRUE is valid.






public: virtual subtrans_object*


blend_spl_sur::copy () const = 0;


Construct a duplicate in free store of this object but with zero use count.






public: virtual void blend_spl_sur::debug (


char const*, // character


logical, // integer


FILE* // file


) const;


Debug printout. The virtual function debug prints a class-specific identifying line, then calls the ordinary function debug_data to put out the details. It is done this way so that a derived class' debug_data can call its parent's version first, to put out the common data. Indeed, if the derived class has no additional data it need not define its own version of debug_data and use its parent's instead. A string argument provides the introduction to each displayed line after the first, and a logical sets "brief" output (normally removing detailed subsidiary curve and surface definitions).






public: void blend_spl_sur::debug_data (


char const*, // character


logical, // integer


FILE* // file


) const;


Debug printout. The virtual function debug prints a class-specific identifying line, then calls the ordinary function debug_data to put out the details. It is done this way so that a derived class' debug_data can call its parent's version first, to put out the common data. Indeed, if the derived class has no additional data it need not define its own version of debug_data and use its parent's instead. A string argument provides the introduction to each displayed line after the first, and a logical sets "brief" output (normally removing detailed subsidiary curve and surface definitions).






public: virtual spl_sur* blend_spl_sur::deep_copy (


pointer_map* pm // list of items within



= NULL // the entity that are




// already deep copied


) const = 0;


Creates a copy of an item that does not share any data with the original. Allocates new storage for all member data and any pointers. Returns a pointer to the copied item.


In a deep copy, all the information about the copied item is self-contained in a new memory block. By comparison, a shallow copy stores only the first instance of the item in memory, and increments the reference count for each copy.


The pointer_map keeps a list of all pointers in the original object that have already been deep copied. For example, a deep_copy of a complex model results in self contained data, but identical sub-parts within the model are allowed to share a single set of data.






public: CVEC& blend_spl_sur::def_cvec () const;


Returns the CVEC on the defining curve of the blend, which is set each time the blend surface is evaluated.






public: void blend_spl_sur::determine_singularity ();


Determine the singularity of the surface. The results are stored in the u_singularity and v_singularity flags.






public: virtual int blend_spl_sur::evaluate (


SPApar_pos const&,

// parameter


SPAposition&,

// pt on surface






// at given param


SPAvector**

// array of pts



= NULL,

// to vector






// array


int


// # derivatives



= 0,

// required (nd)


evaluate_surface_quadrant
// eval location



= evaluate_surface_unknown


) const =0;


The evaluate function calculates derivatives, of any order up to the number requested, and stores them in vectors provided by the user. It returns the number it was able to calculate; this will be equal to the number requested in all but the most exceptional circumstances. A certain number will be evaluated directly and (more or less) accurately; higher derivatives will be automatically calculated by finite differencing; the accuracy of these decreases with the order of the derivative, as the cost increases.


Any of the pointers may be NULL, in which case the corresponding derivatives will not be returned. Otherwise they must point to arrays long enough for all the derivatives of that order; i.e., 2 for the first derivatives, 3 for the second, etc.






public: virtual SPAunit_vector


blend_spl_sur::eval_outdir (


SPApar_pos const& // outward direction


) const;


Returns a direction which points outward from the surface. This should be the outward normal if the point is not singular, otherwise a fairly arbitrary outward direction.






public: logical blend_spl_sur::extend_approx_sf (


double start,

// starting spine






// parameter


double end,

// ending spine






// parameter


double requested_tol,

// requested






// tolerance


logical stop_if_illegal,

// flag for






// approximating


SPAbox const& region

// bounding box



= * (SPAbox const*) NULL_REF // surface


);


This creates the approximating surface and is capable of extending an existing surface. It extends the bs3_surface from spine parameter start to end, or makes it initially if no approximating surface is yet there. The surface is created to the requested tolerance, or better. If the requested tolerance is less than 0, a default is chosen with "sensible" tolerance.


The start may be bigger than end, and the surface is constructed in decreasing parameter order. Either start or end should match an end of the existing approximating surface (if there is one). The other parameter should clearly continue on from there. If the logical flag is set, the approximating surface is terminated if it is found to self intersect or scrunch up. It still makes what it legally could, however.


The return value is TRUE if all the requested surface was made, or FALSE if it was terminated early, or any other infelicity occurs.






public: virtual void blend_spl_sur::extend_surface (


SPAinterval new_v_range // new v range


);


Extend the blend surface in place, including all the supporting data.






public: logical blend_spl_sur::find_stationary_pt (


double start,
// start parameter





// for pt


logical search_fwd,
// forward search


logical
// flag for if start



ignore_start_root,
// point is root


double& end
// limit to search



= * (double* ) NULL_REF


);


Function to find stationary points. Only does anything if one of both blend_supports is on curve. Searches from the given start parameter for stationary points in the given direction as far as the defining curve allows. If it finds one, it adds that information to the legal range. The first logical flag is for searching up the range. The second logical flag is for whether the start point is to be counted if it turns out to be a root. Optionally, a limit to the search may be given, otherwise a default behavior of searching the rest of the curve will be used.


Returns TRUE if a stationary point is found. The legal_range may be queried to find where it is. If nothing is found returns FALSE. Currently doesn't work correctly for variable radius blends.






public: virtual logical


blend_spl_sur::is_circular () const;


Returns TRUE if the given blend_spl_sur is circular; otherwise, it returns FALSE.






public: logical


blend_spl_sur::is_var_rad_type () const;


Returns TRUE if the blend_spl_sur is a variable radius type; otherwise, it returns FALSE.






public: logical blend_spl_sur::legal_v_param (


double v_param // given parameter


) const;


A query function to check whether a given v-parameter value is within the legal range.






public: virtual void blend_spl_sur::make_approx (


double fit,
// fit tolerance


const spline& spl
// pointer to output



= * (spline*) NULL_REF, // spline approx


logical force
// flag for forcing



= FALSE


) const;


Makes or remakes an approximation of the surface, within the given tolerance.






public: logical


blend_spl_sur::make_approximating_surface (


double requested_tol
// requested





// tolerance



= -1.0,


SPAinterval const& range
// interval



= * (SPAinterval const*) // pntr to interval



NULL_REF,


double const& start
// surface start



= *(double const*)
// pntr to const



NULL_REF,


SPAbox const& region
// bounding region



= * (SPAbox const* ) NULL_REF


);


After a blend_spl_sur has been constructed and all its data is in place, the approximating surface must be made. This function is an interface to extend_approx_sf which does the really hard work. The fit tolerance may be specified or not. If not specified, the default of -1.0 is used. A fit less than zero always means to have the routine choose a "sensible" value.


If range and start are unspecified, the defining curve's entire range becomes that of the surface, regardless of whether the surface is legal everywhere. If range is specified and start is not, the range becomes exactly the given range of the surface, regardless of legality or otherwise.


If the range is unspecified but the start is specified, the range becomes as much surface either side of the start as is legal. If the start lies in an illegal region of the surface, the range becomes nothing at all. For periodic defining curves, it is possible for the final surface range to cross the curve's join parameter.


If the range and start are both given, operation is performed up to the given range, starting where indicated, and watching out for illegal regions of surface. When periodic, operation never allows the bottom of the surface to go beyond the top minus the period.


A region box may be specified to indicate a particular region of interest of the spine - often defining curves may be much longer than we need. If a region is passed, construction of the approximating surface stops when the spine has wandered outside the region. If the spine starts outside the region, construction only stops when it enters the region and then leaves. The region may be omitted or left as a NULL reference to be ignored completely.


Returns TRUE if any surface at all was made, else FALSE.






public: virtual logical


blend_spl_sur::old_make_approximating_surface (


double requested_tol // desired tolerance


);


Creates a surface after a blend_spl_sur has been constructed and all its data is in place. This is the old way of creating a surface.






public: virtual void blend_spl_sur::operator*= (


SPAtransf const& // transformation


);


Transform this blend by the given transform.






public: logical blend_spl_sur::operator== (


subtype_object const& // subtype object


) const;


Tests two blends for equality. This does not guarantee that all effectively equal surfaces are determined to be equal, but does guarantee that different surfaces are correctly identified as such.






public: virtual SPApar_pos blend_spl_sur::param (


SPAposition const&,
// given point


SPApar_pos const&
// guess result



= * (SPApar_pos* ) NULL_REF


) const;


Find the parameter values of a point on the surface.






public: virtual void blend_spl_sur::point_perp (


SPAposition const&,
// given point


SPAposition&,
// resulting pt





// on the surface


SPAunit_vector&,
// surface normal


surf_princurv&,
// principal





// curvatures


SPApar_pos const&
// guess uv



= * (SPApar_pos* ) NULL_REF,


SPApar_pos&
// resulting uv



= * (SPApar_pos* ) NULL_REF,


logical f_weak
// weak flag


= FALSE


) const;


Find the point on the surface nearest to the given point, iterating from the given parameter values (if supplied). Returns the found point, the normal to the surface at that point, the principal curvatures there, and the parameter values at the found point (if requested).






public: void blend_spl_sur::restore_data ();


Restores the data from a save file. The restore operation switches on a table defined by static instances of the restore_subtype_def class. This invokes a simple friend function which constructs an object of the right derived type. Then it calls the appropriate base class member function to do the actual work.


// restoring supports

read_string // type of left support curve

left_support->restore_data // left support

read_string // type of right support curve

right_support->restore_data // restore right support data

restore_curve // restore def curve

read_real // left offset

read_real // right offset

read_enum // rad number

if (rad_num == ONE_RADIUS || rad_num == TWO_RADII) {

restore_radius // restore left radius

if ( rad_num == TWO_RADII )// if two radii

restore_radius // restore right radius

else // else


restore_cross_section // restore cross section


if ( restore_version_number < APPROX_SUMMARY_VERSION )

read_interval // u range

read_interval // support u param range

read_interval // v range

read_int // closed in u

read_int // closed in v

else // else

read_interval // support u param range

if ( restore_version_number >= 201 )

read_interval // legal interval

read_int // approximation required

read_real // initial fit tolerance

read_real // fit tolerance data not needed

read_int // left handed if false

if ( restore_version_number >= APPROX_SUMMARY_VERSION )

restore_common_data();

}






public: virtual void


blend_spl_sur::save_data () const;


Saves the information associated with this blend_spl_sur to a SAT file.






public: blend_section&


blend_spl_sur::section_data () const;


Method for handling section data.






public: void blend_spl_sur::set_fitol (


double tol // double tolerance


);


Set the approximating fit tolerance.






public: void blend_spl_sur::set_initial_fitol (


double fitol // fit tolerance


);


Set the initial fit tolerance.






public: void blend_spl_sur::set_initial_num_u (


int num_u // u value


);


Set the initial u value.






public: void blend_spl_sur::set_left_bs2_curve (


bs2_curve // bs2 curve


);


Set the bs2_curves into the support data.






public: void blend_spl_sur::set_right_bs2_curve (


bs2_curve // bs2 curve


);


Set the bs2_curves into the support data.






public: void blend_spl_sur::set_sur (


bs3_surface approx // approx. bs3 surface


);


Set the approximating surface tolerance.






public: void blend_spl_sur::set_u_closure (


closed_forms cl // closure


);


Set closure properties. This is a protected member of spl_sur.






public: void blend_spl_sur::set_u_range (


double start, // start


double end // end


);


Set the u-parameter range. Don't allow start > end. If so, makes an empty interval.






public: void blend_spl_sur::set_v_closure (


closed_forms cl // closure


);


Set closure properties. This is a protected member of spl_sur.






public: void blend_spl_sur::set_v_range (


double start, // start


double end // end


);


Set the v-parameter range. Don't allow start > end. If so, makes an empty interval.






public: virtual void blend_spl_sur::shift_u (


double // double


);


Parameter shift: adjust the spline surface to have a parameter range increased by the argument value (which may be negative). This is only used to move portions of a periodic surface by integral multiples of the period.






public: virtual void blend_spl_sur::shift_v (


double // double


);


Parameter shift: adjust the spline surface to have a parameter range increased by the argument value (which may be negative). This is only used to move portions of a periodic surface by integral multiples of the period.






public: virtual void blend_spl_sur::split_u (


double, // double


spl_sur* [ 2 ] // second spline surface


);


Divide a surface into two pieces at the u-parameter value. If the split is at the end of the parameter range, the spl_sur is just returned as the appropriate half (in increasing parameter order), and the other is NULL. Otherwise a new spl_sur is used for one part, and the old one is modified for the other.






public: virtual void blend_spl_sur::split_v (


double, // double


spl_sur* [ 2 ] // second spline surface


);


Divide a surface into two pieces at the v-parameter value. If the split is at the end of the parameter range, the spl_sur is just returned as the appropriate half (in increasing parameter order), and the other is NULL. Otherwise a new spl_sur is used for one part, and the old one is modified for the other.






public: CVEC& blend_spl_sur::support_cvec (


int i // left support if 0,




// otherwise right


) const;


Returns the CVEC on the left or right blend support, if that support is or contains a curve. This CVEC is set each time the blend surface is evaluated.






public: SVEC& blend_spl_sur::support_svec (


int i // left support if 0,




// otherwise right


) const;


Returns the SVEC on the left or right support, if that support is, or contains a surface. This SVEC is set each time the blend surface is evaluated.






public: virtual char const*


blend_spl_sur::type_name () const =0;


Returns the string "blend_spl_sur".






public: void blend_spl_sur::update_legal_range (


double v_param, // range value


logical is_upper_bound // true if upper bound


);


Update the legal_range of the blend surface, given the parameter at which the surface must stop, and whether the bound is an upper bound or not. Does the correct thing for periodic def_curves.






public: curve* blend_spl_sur::u_param_line (


double v, // constant u parameter


spline const& owner // surface where curve is


) const;


Constructs an isoparameter line on the surface. A u parameter line runs in the direction of increasing u parameter, at constant v. A v parameter line runs in the direction of increasing v, at constant u. The parameterization in the non-constant direction matches that of the surface, and has the range obtained by use of param_range_u() or param_range_v() appropriately.






public: curve* blend_spl_sur::v_param_line (


double u, // constant u parameter


spline const& owner // surface where curve is


) const;


For v_param_line, we can make a blend_int_cur rather than a par_int_cur, but otherwise do the same as the base class. A blend_int_cur is the same as a par_int_cur, but more wary about zero length derivatives at the end of the curve.






public: virtual logical


blend_spl_sur::zero_end_radius (


logical at_start, // at start point if true


double tol // tolerance



= SPAresabs


) const;


Returns TRUE if the blend radius at the start or end point of the blend_spl_sur is zero (i.e., less than SPAresabs).






public: virtual logical


blend_spl_sur::zero_end_rad_slope (


logical at_start, // at start point if true


double tol // tolerance



= SPAresabs


) const;


Returns TRUE if the blend radius slope at the start or end point of the blend_spl_sur is zero (i.e., less than SPAresabs).

Internal Use: deep_copy_elements_blend, full_size




Related Fncs: restore_blend_spl_sur
PDF/KERN/28CLB.PDF
HTM/DATA/KERN/KERN/28CLB/0002.HTM