////////////////////////////////////////
// Start of File: CO1_GTS.HPP
////////////////////////////////////////

#ifndef CO1_GTS_HPP
#define CO1_GTS_HPP

//===================================================================
//
// COPYRIGHT NOTICE:  This code is protected by Copyright!
//
// Copyright (c) 1994, 1995, 1996, 1997 by DPC Technology.
// All rights reserved.
//
// See files "cf_copyr.txt" and "cf_licen.txt" for details of
// copyright and license specifications, and contact information.
//
//===================================================================

// Master Header File Listing:
// Usage:   #include    <cf_api/co1_gts.hpp>
            // The "Chart/Engine-Axis Grid/Tick Series" base-class
            // object -- and several context-specific derivations.

//-----------------------------------------------------
// Specify the Chart Framework objects this file needs.
//-----------------------------------------------------
class       cf_String;
#include    <cf_api/c0_dystr.hpp>

class       bf_Display;
#include    <cf_api/b0_dspla.hpp>

class       cf_DyArr;   // We'll use dynamic arrays of (void) ptrs
#include    <cf_api/c0_dyarr.hpp>  // to 3D-Text-Marker objects

class       cf_AutoScaleFontSpec;
#include    <cf_api/c0_tatb.hpp>

class       cf_Kernel;
class       cf_Virt3DObj;
#include    <cf_api/c1_vobj.hpp>

class       cf_3DTextMarker;
#include    <cf_api/co1_tmar.hpp>

class       cf_ChartModel;
class       cf_ChartEngine;
#include    <cf_api/c1_engin.hpp>


//===================================================
// OK -- Here's what we're gonna do in this file:
//===================================================
class   cf_3DGridTickSeries;
        // This cf_3D_GTS_BASE-derived class acts as a
        // base class (to the classes immediately below...)
        // that specifies basic data handling and behavior
        // for 2D/3D Grid/Tick Mark Series that automatically update
        // a "parent" engine based on the current chart/data state.

class   cf_3DGTS_AutoMarkBackFaceX;
class   cf_3DGTS_AutoMarkBottomFaceX;
class   cf_3DGTS_AutoMarkLeftFaceY;
class   cf_3DGTS_AutoMarkBackFaceY;
class   cf_3DGTS_AutoMarkLeftFaceZ;
class   cf_3DGTS_AutoMarkBottomFaceZ;
class   cf_3DGTS_AutoMarkPolarFloor;
        // These derived classes will control axis-specific
        // behavior for Grid/Tick Marks along the X/Y/Z Axes...


//=================================================================
// Declare a Chart Framework "Grid/Tick Mark Series" BASE class.
//
// Class cf_3DGridTickSeries abstracts a set of graphable
// cf_3DTextMarkers into a set of 2D/3D "cf_3DGridTickSeries"
//=================================================================
class CF_EXPORT   cf_3DGridTickSeries : public cf_Virt3DObj
{

public:

    cf_3DGridTickSeries( cf_ChartEngine *p_cf_engINowBelongTo );
                // Std c-tor implies we BELONG to a particular
                // engine, whose chart data model we will use...

    virtual     ~cf_3DGridTickSeries();
                // Derived d-tors is critical -- engine d-tor
                // will call BASE object virtual d-tor method!...


    void        applyDataUpdate( cf_ChartModel *p_cf_cmodlDataSource );
                //-----------------------------------------------
                // Performs "auto-update" behavior based on the
                // state of the BOOL "update method" vars, which
                // are set by the programmer/user's calls to the
                // use<whatever>() methods immediately below...
                // This method is typically NOT called explicitly
                // by the user, but instead by the engine the
                // user has set up. Then when the engine updates
                // this grid/tick/series, the update behavoir
                // will be controlled by the methods immediately
                // below!...
                //-----------------------------------------------

    void        applyGeomXform( cf_Kernel  *p_cf_kUseThisKernel );
    void        applyProjXform( cf_Kernel   *p_cf_kUseThisKernel );

    void        applyScaleOp(   double dXScaleFactor,
                                double dYScaleFactor,
                                double dZScaleFactor );

    void        applyTranslateOp(   double  dXTrans,
                                    double  dYTrans,
                                    double  dZTrans );
                // It's important to derive our OWN geometry
                // transform methods from the "base" object's
                // virtual implementations.

    void        colorBack( const bf_Color &cr_bf_clrNewVal );
                // Synchronizes the Text Background Color(s)

    BOOL        colorUsingDispBack();
    void        colorUsingDispBack( BOOL bNewState );
                // For future use -- no "real" effects yet...


    BOOL        dispForceMaxTickText();
    void        dispForceMaxTickText( BOOL bNewState );

    BOOL        dispForceMinTickText();
    void        dispForceMinTickText( BOOL bNewState );
                // We can choose to disregard tick freqs and
                // force the display of max/min ticks:

    BOOL        dispWithHiddenTicks();
    void        dispWithHiddenTicks( BOOL bNewState );
                // This will generate ticks, so the user can show
                // text markers, grids, etc, but will set the "tick"
                // part of the grid/tick/text marker OFF.

    BOOL        dispWithInvertedTicks();
    void        dispWithInvertedTicks( BOOL bNewState );
                // This will generate ticks in the OPPOSITE direction
                // (i.e. towards the INSIDE of the chart-data-area).

    void        draw2D( bf_Display *p_bf_dspOutputDisplay );
    void        draw3D( bf_Display *p_bf_dspOutputDisplay );
                // Important to derive our OWN draw method from
                // the "base" object's virtual implementation.


                //----------------------------------------------------
                // These freq<whatever>() methods here immediately
                // below are the programmer/user's "bread and butter"
                // for setting up grid/tick frequencies.
                // (Also pay close attention to the "update<whatever>
                // from data model" methods below...)
                //----------------------------------------------------
    void        freqTicksFromDomainFactor
                    (   cf_ChartModel   *p_cf_cmodlDataSource,
                        int             iDivideDomainItemsBy = 10 );
    void        freqTicksFromRangeFactor
                    (   cf_ChartModel   *p_cf_cmodlDataSource,
                        int             iDivideDataRangeBy = 10 );
    void        freqTicksFromRangeSumFactor
                    (   cf_ChartModel   *p_cf_cmodlDataSource,
                        int             iDivideRangeSumsBy = 10 );
                // These yield "preferred" tick mark frequencies
                // based on division factors applied to the current
                // model's domain item count, range or range sum values.
                // Normally, users can rely on the DEFAULT settings,
                // and do NOT need to use these methods -- the
                // default Factor is 10 (ten), which usually
                // produces very good results...

    void        freqTicksToDomainItems( int iEveryHowManyItems );
    int         freqTicksToDomainItems();

    void        freqTicksToRangeValues( double dIntervalOverData );
    double      freqTicksToRangeValues();
                // These methods let users over-ride "preferred"
                // grid/tick generation from domain/range factors,
                // by explicitly setting grid/tick frequencies
                // with respect to domain items or data ranges.

    void        freqGridsToTicks( int   iEveryHowManyTicks );
    int         freqGridsToTicks();

    void        freqTextsToTicks( int   iEveryHowManyTicks );
    int         freqTextsToTicks();
                // Ticks are the primary item, and grids and text
                // labels can be placed on integer intervals over
                // the existing tick marke.  Note that ticks can
                // also be set to be "hidden" with the method
                // dispWithHiddenTicks(), and thus yield any
                // desired combination of grid/tick/text markers.

    void        freqMajorToMinorTicks( int   iEveryHowManyTicks );
    int         freqMajorToMinorTicks();
                // Useful to make repeating sets of major/minor tick-patterns


    BOOL        isActive();
    BOOL        isActive( BOOL bNewState );
                // Get/set "on/off" methods let users (re)set
                // this grid/tick/series to ignore (or pay
                // attention to) update requests...

    cf_3DTextMarker*
                markerLabel();
                // returns the address of the extra 3D text/marker
                // used as a label for this grid/tick/axis/series.

    BOOL        markerLabelDispHead();
    void        markerLabelDispHead( BOOL bNewState );
    BOOL        markerLabelDispTail();
    void        markerLabelDispTail( BOOL bNewState );
    BOOL        markerLabelDispText();
    void        markerLabelDispText( BOOL bNewState );
                // Get/set display attributes for the axis label marker.

    char*       markerLabelIs();
    void        markerLabelNew( const char *p_csStringForNewLabel );
    void        markerLabelNew( double  dValueForNewLabel );
    BOOL        markerLabelSet();
    void        markerLabelUsing( cf_String *p_cf_strSomeoneElsesLabel );
                // These just pass the corresponding "text-marker"
                // call through to the axis label "text-marker" object.

    BOOL        markerLabelPositHead(   double  dPctWidthFromCtr,
                                        double  dPctHeightFromCtr,
                                        double  dPctDepthFromCtr );

    BOOL        markerLabelPositTail(   double  dPctWidthFromCtr,
                                        double  dPctHeightFromCtr,
                                        double  dPctDepthFromCtr );

    BOOL        markerLabelPositText(   double  dPctWidthFromCtr,
                                        double  dPctHeightFromCtr,
                                        double  dPctDepthFromCtr );
                // Allows the user to over-ride the default positioning
                // of the Axis Label, and specify a new position as an
                // X/Y projection away from the projected CENTER of the
                // chart.  Positive OR negative percentages are allowed.


    int         numMarks();


    void        on();
    void        off();


    void        preferTickSizeRatio( double dPreferredPercentVal );
                // C-tor inits generated tick-marks to be APPROX 5.0%
                // of grid line-length (where grids span a chart x, y,
                // or z dimension).  Use this method to change this
                // sizing parameter (e.g. use 10.0 to reset to 10
                // percent.) for any new grid/tick-marks in the series.


    void        reset();


    BOOL        useDataGroupsListIs();
    BOOL        useDataRangeIs();
    BOOL        useDataRangeSumsIs();
    BOOL        useDomainItemsIs();
    BOOL        useRangeValuesIs();
    BOOL        useRangeValSumsIs();
                // Note that the C-tor inits these member BOOL vars:
                // bUseDataRange, bUseDataRamngeSums, bUseDomainItems,
                // bUseRangeValuus, and bUseRangeValSums to FALSE!
                //
                // So these methods all return FALSE until the update
                // method vars are set via the methods below.
                //
                // This means NO UPDATE BEHAVIOR WILL OCCUR until the
                // programmer explicitly sets the update behavior!

    void        useNoUpdateSource();
                // Turns off ALL Update Behaviors!  So all useData*(),
                // useDomain*() or useRange*() methods above will
                // now return FALSE, and no updates will occur.

    void        useDataGroupsList( BOOL bNewState );
                // Sets update behavior to operate from the list of data-groups

    void        useDataRange( BOOL bNewState );
    void        useDataRangeSums( BOOL bNewState );
                // Sets update behavior to operate from data/ranges.
                // This also sets ALL domain update behavior OFF!
                // useDataRange() and useDataRangeSums() are mutually
                // exclusive.  useRangeVals() [below] is additive to
                // useDataRange() -- IF useDataRange() has been set
                // TRUE.  useRangeValSums() [below] is additive to
                // useDataRangeSums() -- IF useDataRangeSums() has
                // been set TRUE.  I.e. data-range and range-value
                // update behaviors are not mutually exclusive --
                // they are additive update behaviors.

    void        useDomainItems( BOOL bNewState );
                // Sets update behavior to look at domain items.
                // This also sets ALL range update behaviors OFF!

    void        useRangeValues( BOOL bNewState );
    void        useRangeValSums( BOOL bNewState );
                // Sets update behavior to operate from user values
                // inserted into the data range (if the values are
                // within the current data range).  This also sets
                // ALL domain update behavior OFF!  useRangeValues()
                // and useRangeValSums() are mutually exclusive.
                // As per above, data-range and range-value update
                // behaviors are not mutually exclusive -- they are
                // additive update behaviors.
                //----------------------------------------------------
                // So -- the methods immediately above are the
                // programmer/user's "bread and butter" for setting
                // up grid/tick/series "update from a data model"
                // behavior.  The other most important methods are
                // the "freq<whatever>()" methods above...
                //----------------------------------------------------

protected:

    //----------------------------------------------------------
    // This protected member methods lays the semantic framework
    // for creating any derived Axis Series' new grid/tick
    // marker for itself from the 3 cf_3DPoint params. They
    // also return a pointer to the newly activated marker,
    // so that the callee can continue with any neccessary ops
    // to modify the newly created marker...
    //----------------------------------------------------------
    cf_3DTextMarker*
            addAxisMarker(  cf_3DPoint  *p_cf_3dpTailPoint,
                            cf_3DPoint  *p_cf_3dpHeadPoint,
                            cf_3DPoint  *p_cf_3dpTextPoint );

    //----------------------------------------------------------
    // These virtual member methods lay the semantic framework
    // for creating a new grid/tick marker for an Axis Series
    // from a double value that will be interpreted according
    // to a derived Axis Serie's context. They return a pointer
    // to the newly activated marker.
    //----------------------------------------------------------
    virtual
        cf_3DTextMarker*
                markAxisAt( double      dAtUserVal,
                            cf_TickSize enumTickSize
                                        = CF_TICK_MAJOR );
                // Our most important virtual base method -- the
                // "heart" of the grid/tick/series derivation tree!

        cf_3DTextMarker*
                markAxisAt( double      dAtUserVal,
                            double      dValueForLabel,
                            cf_TickSize enumTickSize
                                        = CF_TICK_MAJOR );

        cf_3DTextMarker*
                markAxisAt( double      dAtUserVal,
                            const char  *a_cStringForLabel,
                            cf_TickSize enumTickSize
                                        = CF_TICK_MAJOR );

    //-------------------------------------------------------------
    // These protected "update from data model" methods are
    // typically invoked by the public ApplyDataUpdate()
    // method above, according to the state of the "update
    // behavior member vars" the programmer/user has set
    // up via the public methods above...
    //-------------------------------------------------------------
    void    updateDataRange(    double  dWithinRangeMin,
                                double  dWithinRangeMax );

    void    updateFromDataGroupsList( cf_ChartModel *p_cf_cmodlDataSource );

    void    updateFromDomainItems( cf_ChartModel *p_cf_cmodlDataSource );

    void    updateFromRangeValues( cf_ChartModel *p_cf_cmodlDataSource );
    void    updateFromRangeValSums( cf_ChartModel *p_cf_cmodlDataSource );

    void    updateOverDataRange( cf_ChartModel *p_cf_cmodlDataSource );
    void    updateOverDataRangeSums( cf_ChartModel *p_cf_cmodlDataSource );
            // These two BOTH call the updateRange( min, max )
            // method (above) after they set up their range limits.


    //--------------------------------------------------------
    // Protected members that manage the array(s) of
    // 3D Text Markers that compose this Grid/Tick Series:
    //--------------------------------------------------------
    cf_ChartEngine  *p_cf_engParentEngine_;
                    // Within the run-time context of a parent chart/engine.

    cf_ChartAxis    enumCurrAxisType_;

    double  dEngDataXMax, dEngDataXMin;
    double  dEngDataYMax, dEngDataYMin;
    double  dEngDataZMax, dEngDataZMin;
            // ...with these data ranges...

    double  dEngVirtXMax, dEngVirtXMin;
    double  dEngVirtYMax, dEngVirtYMin;
    double  dEngVirtZMax, dEngVirtZMin;
            // ...and these virtual ranges...

    void    gatherEngineDataVirtRanges();
            // ...gathered by this protected member method...

    double  dEngDataXDim, dEngDataYDim, dEngDataZDim;
    double  dEngVirtXDim, dEngVirtYDim, dEngVirtZDim;
            // ...which yields these dimensions to generate
            // cf_3DTextMarker objects (according to a given
            // chart engine's current dimensions)...

    cf_DyArr    da_p_cf_3dtmMarkerArray;
    int         iNumMarkAllocs;
                // ...This cf_3DGridTickSeries will coordinate the
                // creation, destruction, manipulation, and display
                // of a set of cf_3DTextMarkers along an given axis...

    cf_3DTextMarker *p_cf_3dtmAxisLabel_;
                    // Along with a "label" marker.

    BOOL    bIsActive;
            // I.e. the user may turn this series OFF (or ON)...

    //-------------------------------------------------------
    // We have to maintain a "geometry state" for our
    // collection of "Text Marker" Objects:
    //-------------------------------------------------------
    double  dTransX, dTransY, dTransZ;
    double  dScaleFacX, dScaleFacY, dScaleFacZ;
            // We'll need to keep track of how much this object
            // has been translated, or scaled, so we can "backtrack"
            // or reverse any operations on its components.

    double  dVirtXMax, dVirtXMin;
    double  dVirtYMax, dVirtYMin;
    double  dVirtZMax, dVirtZMin;
            // Used in geometric calcs for XYZ scaling & xlation.

    //---------------------------------------------------------
    // The individual markers in this series will all
    // share some properties, such as a single set of
    // "display attributes, (for rendering) and a single
    // (auto-scale) font spec for their labels...
    //---------------------------------------------------------
    double      dTickSizeRatio; // C-tor inits = 0.05;
                // Grids lines span a chart dimension.  This ratio
                // specifies how big the tick-marks will be in
                // comparison to this dimension.

    //-------------------------------------------------------
    // Vars to control update behavior for this axis series:
    //-------------------------------------------------------
    BOOL    bUseDataGroupsList;     // C-tor inits to FALSE;
    BOOL    bUseDataRange;          // C-tor inits to FALSE;
    BOOL    bUseDataRangeSums;      // C-tor inits to FALSE;
    BOOL    bUseDomainItems;        // C-tor inits to FALSE;
    BOOL    bUseRangeValues;        // C-tor inits to FALSE;
    BOOL    bUseRangeValSums;       // C-tor inits to FALSE;

    BOOL    bUsePrefModelDomainFactor;  // C-tor inits to TRUE;
    BOOL    bUsePrefModelRangeFactor;   // C-tor inits to TRUE;

    int     iPrefModelDomainFactor;     // C-tor inits to 10 (ten).
    int     iPrefModelRangeFactor;      // C-tor inits to 10 (ten).

    int     iFreqTicksToDomainItems;    // C-tor inits to 1 (one).
    double  dFreqTicksToRangeValues;    // C-tor inits to 1 (one).

    int         iFreqGridsToTicks;      // C-tor inits to 0 (zero).
    int         iFreqTextsToTicks;      // C-tor inits to 1 (one).

    int         iFreqMajorToMinor_;     // C-tor init to 0 (zero).
    cf_TickSize enumCurrTickSize_;      // C-tor inits to CF_TICK_MAJOR,
                                        // Alternates based on Major/Minor-Freq

    BOOL    bDispForceMaxTickText;      // C-tor inits to FALSE.
    BOOL    bDispForceMinTickText;      // C-tor inits to FALSE.

    BOOL    bDispWithHiddenTicks;       // C-tor inits to FALSE;
    BOOL    bDispWithInvertedTicks_;    // C-tor inits to FALSE;

    cf_3DTextMarker *p_cf_3dtmMaxTick;  // C-tor inits these to NULL,
    cf_3DTextMarker *p_cf_3dtmMinTick;  // and added marks update them.

};  // End of cf_3DGridTickSeries declaration.


//=================================================================
// Declare a specialized derivation of the Chart
// Framework "Grid/Tick Mark Series"BASE class with
// special behaviors for a SPECIFIC engine axis
//=================================================================

//----------------------------------------------------------
// Special behaviors (e.g. "updates") for the UPPER X-Axis
//----------------------------------------------------------
class CF_EXPORT   cf_3DGTS_AutoMarkBackFaceX : 
        public 
        cf_3DGridTickSeries
{

public:

    cf_3DGTS_AutoMarkBackFaceX( cf_ChartEngine *p_cf_engINowBelongTo );

    virtual ~cf_3DGTS_AutoMarkBackFaceX();

    virtual
    cf_3DTextMarker*    markAxisAt( double      dAtUserVal,
                                    cf_TickSize enumTickSize
                                                = CF_TICK_MAJOR );
                        // Derived RE-implementation acts according
                        // to instantiated context...

};  // end of class cf_3DGTS_AutoMarkBackFaceX declaration


//----------------------------------------------------------
// Special behaviors (e.g. "updates") for the LOWER X-Axis
//----------------------------------------------------------
class CF_EXPORT   cf_3DGTS_AutoMarkBottomFaceX :
        public
        cf_3DGridTickSeries
{

public:

    cf_3DGTS_AutoMarkBottomFaceX( cf_ChartEngine *p_cf_engINowBelongTo );

    virtual ~cf_3DGTS_AutoMarkBottomFaceX();

    virtual
    cf_3DTextMarker*    markAxisAt( double      dAtUserVal,
                                    cf_TickSize enumTickSize
                                                = CF_TICK_MAJOR );
                        // Derived RE-implementation acts according
                        // to instantiated context...

};  // end of class cf_3DGTS_AutoMarkBottomFaceX declaration


//----------------------------------------------------------
// Special behaviors (e.g. "updates") for the LEFT Y-Axis
//----------------------------------------------------------
class CF_EXPORT   cf_3DGTS_AutoMarkLeftFaceY :
        public
        cf_3DGridTickSeries
{

public:

    cf_3DGTS_AutoMarkLeftFaceY( cf_ChartEngine *p_cf_engINowBelongTo );

    virtual ~cf_3DGTS_AutoMarkLeftFaceY();

    virtual
    cf_3DTextMarker*    markAxisAt( double      dAtUserVal,
                                    cf_TickSize enumTickSize
                                                = CF_TICK_MAJOR );
                        // Derived RE-implementation acts according
                        // to instantiated context...

};  // end of class cf_3DGTS_AutoMarkLeftFaceY declaration


//----------------------------------------------------------
// Special behaviors (e.g. "updates") for the RIGHT Y-Axis
//----------------------------------------------------------
class CF_EXPORT   cf_3DGTS_AutoMarkBackFaceY : 
        public 
        cf_3DGridTickSeries
{

public:

    cf_3DGTS_AutoMarkBackFaceY( cf_ChartEngine *p_cf_engINowBelongTo );

    virtual ~cf_3DGTS_AutoMarkBackFaceY();

    virtual
    cf_3DTextMarker*    markAxisAt( double      dAtUserVal,
                                    cf_TickSize enumTickSize
                                                = CF_TICK_MAJOR );
                        // Derived RE-implementation acts according
                        // to instantiated context...

};  // end of class cf_3DGTS_AutoMarkBackFaceY declaration


//----------------------------------------------------------
// Special behaviors (e.g. "updates") for the LEFT Z-Axis
//----------------------------------------------------------
class CF_EXPORT   cf_3DGTS_AutoMarkLeftFaceZ : 
        public 
        cf_3DGridTickSeries
{

public:

    cf_3DGTS_AutoMarkLeftFaceZ( cf_ChartEngine *p_cf_engINowBelongTo );

    virtual ~cf_3DGTS_AutoMarkLeftFaceZ();

    virtual
    cf_3DTextMarker*    markAxisAt( double      dAtUserVal,
                                    cf_TickSize enumTickSize
                                                = CF_TICK_MAJOR );
                        // Derived RE-implementation acts according
                        // to instantiated context...

};  // end of class cf_3DGTS_AutoMarkLeftFaceZ declaration



//----------------------------------------------------------
// Special behaviors (e.g. "updates") for the RIGHT Z-Axis
//----------------------------------------------------------
class CF_EXPORT   cf_3DGTS_AutoMarkBottomFaceZ :
        public
        cf_3DGridTickSeries
{

public:

    cf_3DGTS_AutoMarkBottomFaceZ( cf_ChartEngine *p_cf_engINowBelongTo );

    virtual ~cf_3DGTS_AutoMarkBottomFaceZ();

    virtual
    cf_3DTextMarker*    markAxisAt( double      dAtUserVal,
                                    cf_TickSize enumTickSize
                                                = CF_TICK_MAJOR );
                        // Derived RE-implementation acts according
                        // to instantiated context...

};  // end of class cf_3DGTS_AutoMarkBottomFaceZ declaration



//----------------------------------------------------------
// Special behaviors (e.g. "updates") for POLAR marks
// -- around a polar origin, e.g. for Pie Chart "Tick Marks"
//----------------------------------------------------------
class CF_EXPORT   cf_3DGTS_AutoMarkPolarFloor : 
        public
        cf_3DGridTickSeries
{

public:

    cf_3DGTS_AutoMarkPolarFloor( cf_ChartEngine *p_cf_engINowBelongTo );

    virtual ~cf_3DGTS_AutoMarkPolarFloor();

    virtual
    cf_3DTextMarker*    markAxisAt( double      dAtUserVal,
                                    cf_TickSize enumTickSize
                                                = CF_TICK_MAJOR );
                        // Derived RE-implementation acts according
                        // to instantiated context...
                        // Note that in this implementation, param
                        // dAtUserVal is a RADIAN value.

};  // end of class cf_3DGTS_AutoMarkPolarFloor declaration

//---------------------------------------------------------------
// End of "Auto-Updating-Axis" Grid/Tick Mark Series Derivations.
//---------------------------------------------------------------

#endif

////////////////////////////////////////
// END of File: CO1_GTS.HPP
////////////////////////////////////////

