Starlink-AST

 view release on metacpan or  search on metacpan

ast/src/plot.c  view on Meta::CPAN


static void Apoly( AstPlot *this, float x, float y, int *status ){
/*
*  Name:
*     Apoly

*  Purpose:
*     Append a another point to a poly line.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     void Apoly( AstPlot *this, float x, float y, int *status )

*  Class Membership:
*     Plot member function.

*  Description:
*     This function appends the supplied point to the current poly line.

*  Parameters:
*     x
*        The graphics x coordinate.
*     y
*        The graphics y coordinate.
*     status
*        Pointer to the inherited status variable.

*/

/* Local Variables: */
   int ipoint;
   astDECLARE_GLOBALS      /* Pointer to thread-specific global data */

/* Check the global status. */
   if( !astOK ) return;

/* Get a pointer to the thread specific global data structure. */
   astGET_GLOBALS(this);

/* Extend the buffers, and add the supplied point to the end. */
   ipoint = Poly_n++;
   Poly_x = astGrow( Poly_x, Poly_n, sizeof(*Poly_x) );
   Poly_y = astGrow( Poly_y, Poly_n, sizeof(*Poly_y) );
   if( astOK ) {
      Poly_x[ ipoint ] = x;
      Poly_y[ ipoint ] = y;
   }

/* Update the box containing all plotted lines. */
   Box_lbnd[ 0 ] = astMIN( x, Box_lbnd[ 0 ] );
   Box_ubnd[ 0 ] = astMAX( x, Box_ubnd[ 0 ] );
   Box_lbnd[ 1 ] = astMIN( y, Box_lbnd[ 1 ] );
   Box_ubnd[ 1 ] = astMAX( y, Box_ubnd[ 1 ] );

}

static void AxPlot( AstPlot *this, int axis, const double *start, double length,
                    int ink, AstPlotCurveData *cdata, const char *method, const char *class, int *status ){
/*
*
*  Name:
*     AxPlot

*  Purpose:
*     Draw a curve with constant axis value.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     void AxPlot( AstPlot *this, int axis, const double *start, double length,
*                  int ink, AstPlotCurveData *cdata, const char *method, const char *class, int *status )

*  Class Membership:
*     Plot member function.

*  Description:
*     This function draws a section of a curve of the specified length
*     with constant value on a specified axis in the current Frame of the
*     Plot, starting at the specified position. The algorithm used can handle
*     discontinuities in the Mapping between the current Frame and graphics
*     coordinates, and information describing any breaks in the curve
*     (including the start and end of the curve) are returned in the supplied
*     AstPlotCurveData structure.

*  Parameters:
*     this
*        Pointer to the Plot.
*     axis
*        The zero-based index of an axis within the current Frame of the Plot.
*        The curve has a varying value on this axis.
*     start
*        A pointer to a an array holding the coordinates of the start of the
*        curve within the current Frame of the Plot.
*     length
*        The length of the section of the curve to be drawn, given as an
*        increment along the axis specified by parameter "axis".
*     ink
*        If zero, the curve is not actually drawn, but information about
*        the breaks is still returned. If non-zero, the curve is also drawn.
*     cdata
*        A pointer to a structure in which to return information about the
*        breaks in the curve.
*     method
*        Pointer to a string holding the name of the calling method.
*        This is only for use in constructing error messages.
*     class
*        Pointer to a string holding the name of the supplied object class.
*        This is only for use in constructing error messages.
*     status
*        Pointer to the inherited status variable.

*  Notes:
*     -  No curve is draw if the "start" array contains any bad values
*     (i.e. values equal to AST__BAD), or if the "length" value is bad,
*     or if a NULL pointer is supplied for "cdata". No errors are reported
*     in these cases.
*/

/* Local Variables: */
   astDECLARE_GLOBALS      /* Pointer to thread-specific global data */
   double d[ CRV_NPNT ];   /* Offsets to evenly spaced points along curve */
   double x[ CRV_NPNT ];   /* X coords at evenly spaced points along curve */
   double y[ CRV_NPNT ];   /* Y coords at evenly spaced points along curve */
   double tol;             /* Absolute tolerance value */
   int i;                  /* Loop count */
   int naxes;              /* No. of axes in the base Frame */
   int ok;                 /* Are all start coords good? */
   int gridid;             /* Identifier value for element being drawn */

/* Check the global error status. */
   if ( !astOK ) return;

/* Get a pointer to the thread specific global data structure. */
   astGET_GLOBALS(this);

#ifdef CRV_TRACE
   printf("AXPLOT: axis %d, start (%.*g,%.*g), length %.*g\n",
          axis, AST__DBL_DIG, start[0], AST__DBL_DIG, start[1], AST__DBL_DIG, length );
   getchar();
#endif


/* Initialise any supplied cdata structure to hold safe values. */
   if( cdata ){
      cdata->length = 0.0;
      cdata->out = 1;
      cdata->nbrk = 0;
   }

/* Get the number of axes in the current Frame. */
   naxes = astGetNout( this );

/* Check the "start" parameter for bad values. */
   ok = 1;
   for( i = 0; i < naxes; i++ ) {
      if( start[ i ] == AST__BAD ){
         ok = 0;
         break;
      }
   }

/* Check the "length" parameter for bad values. */
   if( length == AST__BAD ) ok = 0;

/* Check that the "cdata" pointer can be used. */
   if( !cdata ) ok = 0;

/* Only proceed if the parameters are OK, and there has been no error. */
   if( ok && astOK ){

/* Establish the correct graphical attributes as defined by attributes
   with the supplied Plot. */
      if( axis == 0 ) {
         gridid = AST__GRIDLINE2_ID;
      } else {
         gridid = AST__GRIDLINE1_ID;
      }
      astGrfAttrs( this, gridid, 1, GRF__LINE, method, class );

/* Ensure the globals holding the scaling from graphics coords to equally
   scaled coords are available. */
      GScales( this, NULL, NULL, method, class, status );

/* Set up the externals used to communicate with the Map1 function...
   The number of axes in the physical coordinate system (i.e. the current
   Frame). */
      Map1_ncoord = naxes;

/* See if tick marks are logarithmically or linearly spaced. */
      Map1_log = astGetLogTicks( this, axis );

/* A pointer to the Plot, the Current Frame and the Mapping. */
      Map1_plot = this;
      Map1_frame = astGetFrame( this, AST__CURRENT );
      Map1_map = astGetMapping( this, AST__BASE, AST__CURRENT );

/* Physical coords at the start of the curve (dist=0). */
      Map1_origin = start;

/* Length of the curve. */
      Map1_length = length;

/* The index of the axis which the curve follows. */
      Map1_axis = axis;

/* Decide whether to omit points not in their normal ranges. */
      Map1_norm = !IsASkyAxis( Map1_frame, 0, status ) &&
                  !IsASkyAxis( Map1_frame, 1, status );

/* Convert the tolerance from relative to absolute graphics coordinates. */
      tol = astGetTol( this )*astMAX( this->xhi - this->xlo,
                                   this->yhi - this->ylo );

/* Now set up the external variables used by the Crv and CrvLine function. */
      Crv_scerr = ( astGetLogPlot( this, 0 ) ||
                    astGetLogPlot( this, 1 ) ) ? 100.0 : 1.5;
      Crv_ux0 = AST__BAD;
      Crv_tol = tol;
      Crv_limit = 0.5*tol*tol;
      Crv_map = Map1;
      Crv_ink = ink;
      Crv_xlo = this->xlo;
      Crv_xhi = this->xhi;
      Crv_ylo = this->ylo;
      Crv_yhi = this->yhi;
      Crv_out = 1;
      Crv_xbrk = cdata->xbrk;
      Crv_ybrk = cdata->ybrk;
      Crv_vxbrk = cdata->vxbrk;
      Crv_vybrk = cdata->vybrk;
      Crv_clip = astGetClip( this ) & 1;

/* Set up a list of points spread evenly over the curve. */
      for( i = 0; i < CRV_NPNT; i++ ){
        d[ i ] = ( (double) i)/( (double) CRV_NSEG );
      }

/* Map these points into graphics coordinates. */
      Map1( CRV_NPNT, d, x, y, method, class, status GLOBALS_NAME );

/* Use Crv and Map1 to draw the curve. */
      Crv( this, d, x, y, 0, NULL, NULL, method, class, status );

/* End the current poly line. */
      Opoly( this, status );

/* Tidy up the static data used by Map1. */
      Map1( 0, NULL, NULL, NULL, method, class, status GLOBALS_NAME );

/* If no part of the curve could be drawn, set the number of breaks and the
   length of the drawn curve to zero. */
      if( Crv_out ) {
         Crv_nbrk = 0;
         Crv_len = 0.0F;

/* Otherwise, add an extra break to the returned structure at the position of
   the last point to be plotted. */
      } else {
         Crv_nbrk++;
         if( Crv_nbrk > AST__PLOT_CRV_MXBRK ){
            astError( AST__CVBRK, "%s(%s): Number of breaks in curve "
                      "exceeds %d.", status, method, class, AST__PLOT_CRV_MXBRK );
         } else {
            *(Crv_xbrk++) = (float) Crv_xl;
            *(Crv_ybrk++) = (float) Crv_yl;
            *(Crv_vxbrk++) = (float) -Crv_vxl;
            *(Crv_vybrk++) = (float) -Crv_vyl;
         }
      }

/* Store extra information about the curve in the returned structure, and
   purge any zero length sections. */
      if( cdata ){
         cdata->length = Crv_len;
         cdata->out = Crv_out;
         cdata->nbrk = Crv_nbrk;
         PurgeCdata( cdata, status );
      }

/* Annul the Frame and Mapping. */
      Map1_frame = astAnnul( Map1_frame );
      Map1_map = astAnnul( Map1_map );

/* Re-establish the original graphical attributes. */
      astGrfAttrs( this, gridid, 0, GRF__LINE, method, class );

   }

/* Return. */
   return;

}

static void BBuf( AstPlot *this, int *status ) {
/*
*++
*  Name:
c     astBBuf
f     AST_BBUF

*  Purpose:
*     Begin a new graphical buffering context.

*  Type:
*     Public function.

*  Synopsis:
c     #include "plot.h"
c     void astBBuf( AstPlot *this )
f     CALL AST_BBUF( THIS STATUS )

*  Class Membership:
*     Plot member function.

*  Description:
c     This function
f     This routine
*     starts a new graphics buffering context. A matching call to the
c     function astEBuf
f     routine AST_EBUF
*     should be used to end the context.

*  Parameters:
c     this
f     THIS = INTEGER (Given)
*        Pointer to the Plot.
f     STATUS = INTEGER (Given and Returned)
f        The global status.

*  Notes:
*     - The nature of the buffering is determined by the underlying
*     graphics system (as defined by the current grf module). Each call
c     to this function
f     to this routine
c     to this function
f     to this routine
*     simply invokes the astGBBuf function in the grf module.

ast/src/plot.c  view on Meta::CPAN

c     int astBorder( AstPlot *this )
f     RESULT = AST_BORDER( THIS, STATUS )

*  Class Membership:
*     Plot method.

*  Description:
*     This function draws a (line) border around regions of the
*     plotting area of a Plot which correspond to valid, unclipped
*     physical coordinates. For example, when plotting using an
*     all-sky map projection, this function could be used to draw the
*     boundary of the celestial sphere when it is projected on to the
*     plotting surface.
*
*     If the entire plotting area contains valid, unclipped physical
*     coordinates, then the boundary will just be a rectangular box
*     around the edges of the plotting area.
*
*     If the Plot is a Plot3D, this method is applied individually to
*     each of the three 2D Plots encapsulated within the Plot3D (each of
*     these Plots corresponds to a single 2D plane in the 3D graphics
*     system). In addition, if the entire plotting volume has valid
*     coordinates in the 3D current Frame of the Plot3D, then additional
*     lines are drawn along the edges of the 3D plotting volume so that
*     the entire plotting volume is enclosed within a cuboid grid.

*  Parameters:
c     this
f     THIS = INTEGER (Given)
*        Pointer to the Plot.
f     STATUS = INTEGER (Given and Returned)
f        The global status.

*  Returned Value:
c     astBorder()
f     AST_BORDER = LOGICAL
c        Zero is returned if the plotting space is completely filled by
f        .FALSE. is returned if the plotting space is completely filled by
*        valid, unclipped physical coordinates (so that only a
c        rectangular box was drawn around the edge). Otherwise, one is
f        rectangular box was drawn around the edge). Otherwise, .TRUE. is
*        returned.

*  Notes:
c     - A value of zero will be returned if this function is invoked
f     - A value of .FALSE. will be returned if this function is invoked
c     with the AST error status set, or if it should fail for any
f     with STATUS set to an error value, or if it should fail for any
*     reason.
*     - An error results if either the current Frame or the base Frame
*     of the Plot is not 2-dimensional or (for a Plot3D) 3-dimensional.
*     - An error also results if the transformation between the base
*     and current Frames of the Plot is not defined (i.e. the Plot's
*     TranForward attribute is zero).
*--
*/

/* Local Variables: */
   astDECLARE_GLOBALS      /* Pointer to thread-specific global data */
   AstPlot *this;          /* Plot with no more than 2 current axes */
   AstPlotCurveData cdata; /* Structure to receive break information */
   const char *class;      /* Object class */
   const char *method;     /* Current method */
   int inval;              /* Were any bad regions found? */
   int naxes;              /* No. of axes in the base Frame */

/* Check the global error status. */
   if ( !astOK ) return 0;

/* Get a pointer to the thread specific global data structure. */
   astGET_GLOBALS(this_nd);

/* Store the current method, and the class of the supplied object for use
   in error messages.*/
   method = "astBorder";
   class = astGetClass( this_nd );

/* Initialise the bounding box for primitives produced by this call. */
   if( !Boxp_freeze ) {
      Boxp_lbnd[ 0 ] = FLT_MAX;
      Boxp_lbnd[ 1 ] = FLT_MAX;
      Boxp_ubnd[ 0 ] = FLT_MIN;
      Boxp_ubnd[ 1 ] = FLT_MIN;
   }

/* Check the base Frame of the Plot is 2-D. */
   naxes = astGetNin( this_nd );
   if( naxes != 2 && astOK ){
      astError( AST__NAXIN, "%s(%s): Number of axes (%d) in the base "
                "Frame of the supplied %s is invalid - this number should "
                "be 2.", status, method, class, naxes, class );
   }

/* Get a Plot with a 2D (or 1D) current Frame. */
   this = (AstPlot *) Fset2D( (AstFrameSet *) this_nd, AST__CURRENT, status );

/* Check the current Frame of the Plot is 2-D. */
   naxes = astGetNout( this );
   if( naxes != 2 && astOK ){
      astError( AST__NAXIN, "%s(%s): Number of axes (%d) in the current "
                "Frame of the supplied %s is invalid - this number should "
                "be 2.", status, method, class, naxes, class );
   }

/* Indicate that the GRF module should re-calculate it's cached values
   (in case the state of the graphics system has changed since the last
   thing was drawn). */
   RESET_GRF;

/* Establish the correct graphical attributes as defined by attributes
   with the supplied Plot. */
   astGrfAttrs( this, AST__BORDER_ID, 1, GRF__LINE, method, class );

/* We first draw the intersections of the regions containing valid
   physical coordinates with the edges of the plotting area. First do
   the bottom edge. */
   LinePlot( this, this->xlo, this->ylo, this->xhi, this->ylo,
             1, &cdata, method, class, status );

/* Now do the right-hand edge. */
   LinePlot( this, this->xhi, this->ylo, this->xhi, this->yhi,
             1, &cdata, method, class, status );

/* Now do the top edge. */
   LinePlot( this, this->xhi, this->yhi, this->xlo, this->yhi,
             1, &cdata, method, class, status );

/* Now do the left-hand edge. */
   LinePlot( this, this->xlo, this->yhi, this->xlo, this->ylo,
             1, &cdata, method, class, status );

/* Now draw a curve following the boundary through the interior of the
   plotting area. If the current Frame in the Plot is a Region, we use a
   shorter method if possible. If this is not possible, we use a longer
   method. */
   inval = Boundary( this, method, class, status );

/* Ensure all lines are flushed to the graphics system. */
   Fpoly( this, method, class, status );

/* Re-establish the original graphical attributes. */
   astGrfAttrs( this, AST__BORDER_ID, 0, GRF__LINE, method, class );

/* Annul the 2d plot. */
   this = astAnnul( this );

/* Return. */
   return inval;

}

static void BoundingBox( AstPlot *this, float lbnd[2], float ubnd[2], int *status ){
/*
*++
*  Name:
c     astBoundingBox
f     AST_BOUNDINGBOX

*  Purpose:
*     Return a bounding box for previously drawn graphics.

*  Type:
*     Public virtual function.

*  Synopsis:
c     #include "plot.h"
c     void astBoundingBox( AstPlot *this, float lbnd[2], float ubnd[2] )
f     CALL AST_BOUNDINGBOX( THIS, LBND, UBND, STATUS )

*  Class Membership:
*     Plot method.

*  Description:
c     This function returns the bounds of a box which just encompasess the
f     This routine returns the bounds of a box which just encompasess the
*     graphics produced by the previous call to any of the Plot methods
*     which produce graphical output. If no such previous call has yet
*     been made, or if the call failed for any reason, then the bounding box
c     returned by this function is undefined.
f     returned by this routine is undefined.

*  Parameters:
c     this
f     THIS = INTEGER (Given)
*        Pointer to the Plot.
c     lbnd
f     LBND( 2 ) = REAL (Returned)
*        A two element array in which is returned the lower limits of the
*        bounding box on each of the two axes of the graphics coordinate
*        system (the base Frame of the Plot).

ast/src/plot.c  view on Meta::CPAN


*  Purpose:
*     Return the length of a string excluding any trailing white space.

*  Type:
*     Private function.

*  Synopsis:
*     int ChrLen( const char *string, int *status )

*  Class Membership:
*     Plot

*  Description:
*     This function returns the length of a string excluding any trailing
*     white space.

*  Parameters:
*     string
*        Pointer to the string.
*     status
*        Pointer to the inherited status variable.

*  Returned Value:
*     The length of a string excluding any trailing white space.

*  Notes:
*     -  A value of zero is returned if a NULL pointer is supplied, or if an
*     error has already occurred.

*/

/* Local Variables: */
   const char *c;      /* Pointer to the next character to check */
   int ret;            /* The returned string length */

/* Check the global status. */
   if( !astOK ) return 0;

/* Initialise the returned string length. */
   ret = 0;

/* Check a string has been supplied. */
   if( string ){

/* Check each character in turn, starting with the last one. */
      ret = strlen( string );
      c = string + ret - 1;
      while( ret ){
         if( !isspace( (int) *c ) ) break;
         c--;
         ret--;
      }
   }

/* Return the answer. */
   return ret;

}

static AstPlotCurveData **CleanCdata( AstPlotCurveData **cdata, int *status ){
/*
*  Name:
*     CleanCdata

*  Purpose:
*     Release the structures holding curve break information.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     AstPlotCurveData **CleanCdata( AstPlotCurveData **cdata, int *status )

*  Class Membership:
*     Plot member function.

*  Description:
*     This function releases the memory used to hold the curve break
*     information returned by function DrawGrid, and returns a NULL pointer.

*  Parameters:
*     cdata
*        Pointer to the information to be freed.
*     status
*        Pointer to the inherited status variable.

*  Returned Value:
*     A NULL pointer.

*  Notes:
*     -  This function attempts to execute even if an error has already
*     occurred.

*/

/* Return if a NULL pointer has been supplied. */
   if( !cdata ) return NULL;

/* Release each of the two structures in turn (if they exist). */
   (void) astFree( (void *) cdata[ 0 ] );
   (void) astFree( (void *) cdata[ 1 ] );

/* Release the memory used to hold the two AstPlotCurveData pointers. */
   (void) astFree( (void *) cdata );

/* Return. */
   return NULL;

}

static TickInfo **CleanGrid( TickInfo **grid, int *status ){
/*
*  Name:
*     CleanGrid

*  Purpose:
*     Release the structures holding grid information.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     TickInfo **CleanGrid( TickInfo **grid )

*  Class Membership:
*     Plot member function.

*  Description:
*     This function releases the memory used to hold the grid information
*     returned by function GridLines, and returns a NULL pointer.

*  Parameters:
*     grid
*        Pointer to the information to be freed.

*  Returned Value:
*     A NULL pointer.

*  Notes:
*     -  This function attempts to execute even if an error has already
*     occurred.

*/

/* Local Variables: */
   TickInfo *info;             /* Pointer to TickInfo structure being freed */
   int i;                      /* Axis index */
   int j;                      /* Tick mark index */

/* Return if a NULL pointer has been supplied. */
   if( !grid ) return NULL;

/* Release each of the TickInfo structures in turn (if they exist). */
   for( i = 0; i < 2; i++ ){
      if( ( info = grid[ i ] ) ){

/* Release the memory holding major tick mark values. */
         (void) astFree( (void *) info->ticks );

/* Release the memory holding minor tick mark values. */
         (void) astFree( (void *) info->minticks );

/* Release the memory holding curve section starting positions. */

ast/src/plot.c  view on Meta::CPAN

c     contains any coordinates with the value AST__BAD.
f     - No curve is drawn if either of the START or FINISH arrays
f     contains any coordinates with the value AST__BAD.
*     - An error results if the base Frame of the Plot is not 2-dimensional.
*     - An error also results if the transformation between the
*     current and base Frames of the Plot is not defined (i.e. the
*     Plot's TranInverse attribute is zero).
*--
*/
/* Local Variables: */
   astDECLARE_GLOBALS      /* Pointer to thread-specific global data */
   const char *class;      /* Object class */
   const char *method;     /* Current method */
   int naxes;              /* No. of axes in the base Frame */

/* Check the global error status. */
   if ( !astOK ) return;

/* Get a pointer to the thread specific global data structure. */
   astGET_GLOBALS(this);

/* Store the current method, and the class of the supplied object for use
   in error messages.*/
   method = "astCurve";
   class = astGetClass( this );

/* Check the base Frame of the Plot is 2-D. */
   naxes = astGetNin( this );
   if( naxes != 2 && astOK ){
      astError( AST__NAXIN, "%s(%s): Number of axes (%d) in the base "
                "Frame of the supplied %s is invalid - this number should "
                "be 2.", status, method, class, naxes, class );
   }

/* Initialise the bounding box for primitives produced by this call. */
   if( !Boxp_freeze ) {
      Boxp_lbnd[ 0 ] = FLT_MAX;
      Boxp_lbnd[ 1 ] = FLT_MAX;
      Boxp_ubnd[ 0 ] = FLT_MIN;
      Boxp_ubnd[ 1 ] = FLT_MIN;
   }

/* Indicate that the GRF module should re-calculate it's cached values
   (in case the state of the graphics system has changed since the last
   thing was drawn). */
   RESET_GRF;

/* Draw the curve. The break information is stored in an external structure
   where it can be accessed by public methods which return information
   about the most recently drawn curve. */
   CurvePlot( this, start, finish, 1, &Curve_data, method, class, status );

/* Ensure all lines are flushed to the graphics system. */
   Fpoly( this, method, class, status );

/* Return. */
   return;
}

static void CurvePlot( AstPlot *this, const double *start, const double *finish,
                     int ink, AstPlotCurveData *cdata, const char *method,
                     const char *class, int *status ){
/*
*
*  Name:
*     CurvePlot

*  Purpose:
*     Draw a geodesic curve.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     void CurvePlot( AstPlot *this, const double *start, const double *finish,
*                   int ink, AstPlotCurveData *cdata, const char *method,
*                   const char *class, int *status )

*  Class Membership:
*     Plot member function.

*  Description:
*     This function draws a geodesic curve between the supplied starting and
*     finishing positions. The algorithm used can handle discontinuities in the
*     Mapping between the current Frame and graphics coordinates, and
*     information describing any breaks in the curve (including the start and
*     end of the curve) are returned in the supplied AstPlotCurveData structure.

*  Parameters:
*     this
*        Pointer to the Plot.
*     start
*        A pointer to a an array holding the coordinates of the start of the
*        curve within the current Frame of the Plot.
*     finish
*        A pointer to a an array holding the coordinates of the finish of the
*        curve within the current Frame of the Plot.
*     ink
*        If zero, the curve is not actually drawn, but information about
*        the breaks is still returned. If non-zero, the curve is also drawn.
*     cdata
*        A pointer to a structure in which to return information about the
*        breaks in the curve.
*     method
*        Pointer to a string holding the name of the calling method.
*        This is only for use in constructing error messages.
*     class
*        Pointer to a string holding the name of the supplied object class.
*        This is only for use in constructing error messages.
*     status
*        Pointer to the inherited status variable.

*  Notes:
*     -  No curve is draw if the "start" or "finish" arrays contains any bad
*     values, or if a NULL pointer is supplied for "cdata". No errors are
*     reported in these cases.
*/

/* Local Variables: */
   astDECLARE_GLOBALS      /* Pointer to thread-specific global data */
   double d[ CRV_NPNT ];   /* Offsets to evenly spaced points along curve */
   double x[ CRV_NPNT ];   /* X coords at evenly spaced points along curve */
   double y[ CRV_NPNT ];   /* Y coords at evenly spaced points along curve */
   double tol;             /* Absolute tolerance value */
   int i;                  /* Loop count */
   int naxes;              /* No. of axes in the base Frame */
   int ok;                 /* Are all start coords good? */

/* Check the global error status. */
   if ( !astOK ) return;

/* Get a pointer to the thread specific global data structure. */
   astGET_GLOBALS(this);

/* Get the number of axes in the current Frame. */
   naxes = astGetNout( this );

/* Check the "start" and "finish" parameter for bad values. */
   ok = 1;
   for( i = 0; i < naxes; i++ ) {
      if( start[ i ] == AST__BAD || finish[ i ] == AST__BAD ){
         ok = 0;
         break;
      }
   }

/* Check that the "cdata" pointer can be used. */
   if( !cdata ) ok = 0;

/* Only proceed if the parameters are OK, and there has been no error. */
   if( ok && astOK ){

/* Establish the correct graphical attributes as defined by attributes
   with the supplied Plot. */
      astGrfAttrs( this, AST__CURVE_ID, 1, GRF__LINE, method, class );

/* Ensure the globals holding the scaling from graphics coords to equally
   scaled coords are available. */
      GScales( this, NULL, NULL, method, class, status );

/* Set up the externals used to communicate with the Map3 function...
   The number of axes in the physical coordinate system (i.e. the current
   Frame). */
      Map3_ncoord = naxes;

/* A pointer to the Plot, the Curretn Frame, and and Mapping. */
      Map3_plot = this;
      Map3_frame = astGetFrame( this, AST__CURRENT );
      Map3_map = astGetMapping( this, AST__BASE, AST__CURRENT );

/* The physical coordinates at the start of the curve. */
      Map3_origin = start;

/* The physical coordinates at the end of the curve. */
      Map3_end = finish;

/* The scale factor to convert "dist" values into physical offset values. */
      Map3_scale = astDistance( Map3_frame, start, finish );

/* Convert the tolerance from relative to absolute graphics coordinates. */
      tol = astGetTol( this )*astMAX( this->xhi - this->xlo,
                                      this->yhi - this->ylo );

/* Now set up the external variables used by the Crv and CrvLine function. */
      Crv_scerr = ( astGetLogPlot( this, 0 ) ||
                    astGetLogPlot( this, 1 ) ) ? 100.0 : 1.5;
      Crv_ux0 = AST__BAD;
      Crv_tol = tol;
      Crv_limit = 0.5*tol*tol;
      Crv_map = Map3;
      Crv_ink = ink;
      Crv_xlo = this->xlo;
      Crv_xhi = this->xhi;
      Crv_ylo = this->ylo;
      Crv_yhi = this->yhi;
      Crv_out = 1;
      Crv_xbrk = cdata->xbrk;
      Crv_ybrk = cdata->ybrk;
      Crv_vxbrk = cdata->vxbrk;
      Crv_vybrk = cdata->vybrk;
      Crv_clip = astGetClip( this ) & 1;

/* Set up a list of points spread evenly over the curve. */
      for( i = 0; i < CRV_NPNT; i++ ){
        d[ i ] = ( (double) i)/( (double) CRV_NSEG );
      }

/* Map these points into graphics coordinates. */
      Map3( CRV_NPNT, d, x, y, method, class, status GLOBALS_NAME );

/* Use Crv and Map3 to draw the curve. */
      Crv( this, d, x, y, 0, NULL, NULL, method, class, status );

/* End the current poly line. */
      Opoly( this, status );

/* Tidy up the static data used by Map3. */
      Map3( 0, NULL, NULL, NULL, method, class, status GLOBALS_NAME );

/* If no part of the curve could be drawn, set the number of breaks and the
   length of the drawn curve to zero. */
      if( Crv_out ) {
         Crv_nbrk = 0;
         Crv_len = 0.0F;

/* Otherwise, add an extra break to the returned structure at the position of
   the last point to be plotted. */
      } else {
         Crv_nbrk++;
         if( Crv_nbrk > AST__PLOT_CRV_MXBRK ){
            astError( AST__CVBRK, "%s(%s): Number of breaks in curve "
                      "exceeds %d.", status, method, class, AST__PLOT_CRV_MXBRK );
         } else {
            *(Crv_xbrk++) = (float) Crv_xl;
            *(Crv_ybrk++) = (float) Crv_yl;
            *(Crv_vxbrk++) = (float) -Crv_vxl;
            *(Crv_vybrk++) = (float) -Crv_vyl;
         }
      }

/* Store extra information about the curve in the returned structure, and
   purge any zero length sections. */
      if( cdata ){
         cdata->length = Crv_len;
         cdata->out = Crv_out;
         cdata->nbrk = Crv_nbrk;
         PurgeCdata( cdata, status );
      }

/* Annul the Frame and Mapping. */
      Map3_frame = astAnnul( Map3_frame );
      Map3_map = astAnnul( Map3_map );

/* Re-establish the original graphical attributes. */
      astGrfAttrs( this, AST__CURVE_ID, 0, GRF__LINE, method, class );

   }

/* Return. */
   return;

}


static AstPointSet *DefGap( AstPlot *this, double *gaps, int *ngood,
                            double *frac, int *inval, const char *method,
                            const char *class, int *status ){
/*
*  Name:
*     DefGap

*  Purpose:
*     Find default gap sizes for the tick marks on the axes of a 2-D
*     physical coordinate system.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     AstPointSet *DefGap( AstPlot *this, double *gaps, int *ngood,
*                          double *frac, int *inval, const char *method,
*                          const char *class, int *status  )

*  Class Membership:
*     Plot method.

*  Description:
*     This function returns default gap sizes for each axis in a 2-D Frame.
*     The values are found by first obtaining a grid of points spread over
*     the region containing good physical coordinates. The physical
*     coordinate values (non-normalized) for each axis are sorted into
*     increasing order.
*
*     For linearly spaced tick marks, a set of quantile axis values is then
*     found, and the median of the gaps between these quantiles is returned
*     as the default gap for the axis.
*
*     For logarithmically spaced tick marks, the returned gap size is the
*     ratio between adjacent tick mark values, chosen to give an optimal
*     number of ticks between the maximum and minimum axis values found in
*     the grid.

*  Parameters:
*     this
*        Pointer to a Plot.
*     gaps

ast/src/plot.c  view on Meta::CPAN


static void DrawAxis( AstPlot *this, TickInfo **grid, double *labelat,
                      double *gap, const char *method, const char *class, int *status ){
/*
*
*  Name:
*     DrawAxis

*  Purpose:
*     Draw a curve joining the major tick marks.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     void DrawAxis( AstPlot *this, TickInfo **grid, double *labelat,
*                    double *gap, const char *method, const char *class, int *status )

*  Class Membership:
*     Plot member function.

*  Description:
*     This function draws a curve through interior tick marks on both axes.
*     The curve is drawn even if it has already been drawn as part of a
*     grid of curves, because it may have been assigned different graphics
*     attributes to the grid curves.

*  Parameters:
*     this
*        A pointer to the Plot.
*     grid
*        A pointer to an array of two TickInfo pointers (one for each axis),
*        each pointing to a TickInfo structure holding information about
*        tick marks on the axis. See function GridLines.
*     labelat
*        A pointer to a 2 element array giving the constant axis values at
*        which tick marks are put. Element 0 should give the axis 1 value at
*        which tick marks for axis 0 are placed. Element 1 should give the
*        axis 0 value at which tick marks for axis 1 are placed.
*     gap
*        Pointer to array of two values holding the gap between major
*        tick marks on the two axes.
*     method
*        Pointer to a string holding the name of the calling method.
*        This is only for use in constructing error messages.
*     class
*        Pointer to a string holding the name of the supplied object class.
*        This is only for use in constructing error messages.
*     status
*        Pointer to the inherited status variable.

*  Notes:
*     -  This function assumes the current Frame of the Plot is 2
*     dimensional, and it should not be called if this is not the case.

*/

/* Local Variables: */
   AstFrame *frm;         /* Pointer to current Frame */
   AstPlotCurveData cdata;/* Somewhere to put the unneeded curve information */
   TickInfo *info;        /* Pointer to the TickInfo for the current axis */
   double *value;         /* Current tick value */
   double bot;            /* Lowest axis value to be displayed */
   double diff;           /* Difference between adjacent tick marks */
   double udiff;          /* Used section length */
   double start[ 2 ];     /* The start of the curve in physical coordinates */
   double tmp;            /* Temporary storage */
   double top;            /* Highest axis value to be displayed */
   int axis;              /* Current axis index */
   int axisid;            /* ID value for current axis plotting attributes */
   int logticks;          /* Are major ticks spaced logarithmically? */
   int tick;              /* Current tick index */

/* Check the global status. */
   if( !astOK ) return;

/* Not the id value for the first axis. */
   axisid = AST__AXIS1_ID;

/* Get a pointer to the current Frame. */
   frm = astGetFrame( this, AST__CURRENT );

/* Consider drawing a curve parallel to each axis in turn. */
   for( axis = 0; axis < 2; axis++ ){

/* Establish the correct graphical attributes for this axis as defined by
   attributes with the supplied Plot. */
      astGrfAttrs( this, axisid, 1, GRF__LINE, method, class );

/* Check the axis is required. */
      if( astGetDrawAxes( this, axis ) ){

/* If the tick marks have been placed round the edges of the plotting
   area, we do not need to draw the curves. */
         if( labelat[ axis ] != AST__BAD ){

/* Get the max and min values allowed on this axis. */
            bot = astGetBottom( frm, axis );
            top = astGetTop( frm, axis );
            if( bot > top ) {
               tmp = top;
               top = bot;
               bot = tmp;
            }

/* Get a pointer to the structure containing information describing the
   positions of the major tick marks along the current axis. */
            info = grid[ axis ];

/* Get a pointer to the axis value at the first major tick mark. */
            value = info->ticks;

/* See if the major tick marks are logarithmically spaced on this axis. */
            logticks = astGetLogTicks( this, axis );

/* Initialise the difference between major tick marks. */
            diff = logticks ? 0.0 : gap[ axis ];

/* Loop round all ticks. */
            for( tick = 0; tick < info->nmajor; tick++, value++ ){

/* Update the difference between major tick marks if we are producing
   logarithmically spaced ticks (in which "gap" is a ratio, not a
   difference). */
               if( logticks ) diff = (*value)*( gap[ axis ] - 1.0 );

/* Note the starting point for this section. */
               start[ axis ] = *value;
               start[ 1 - axis ] = labelat[ axis ];

/* If this is the first tick, draw an axis section going "backwards" in
   case the first tick isn't at the lower visible bound. Limit the length
   of this backwards section so that it does not extend beyond the minimum
   axis value. */
               if( tick == 0 ) {
                  udiff = *value - bot;
                  if( udiff > diff ) udiff = diff;
                  if( udiff > 0.0 ) {
                     AxPlot( this, axis, start, -udiff, 1, &cdata, method,
                             class, status );
                  }
               }

/* Limit the length of the section so that it does not extend beyond the
   maximum axis value. */
               udiff = ( *value + diff > top ) ? top - *value : diff;

/* Do not draw zero length sections. */
               if( udiff > 0.0 ) {

/* Draw a curve parallel to the current axis, starting at the tick mark,
   with length equal to the gap between tick marks. Do not draw sections
   of the curve which are outside the primary domains of the physical axes. */
                  AxPlot( this, axis, start, udiff, 1, &cdata, method,
                          class, status );
               }

            }

/* Once the last section has been drawn, draw another axis section in case the
   last tick isn't at the upper visible bound. Limit the length of this
   section so that it does not extend beyond the maximum axis value. */
            udiff = top - start[ axis ];
            if( udiff > diff ) udiff = diff;
            if( udiff > 0.0 ) {
               AxPlot( this, axis, start, udiff, 1, &cdata, method,
                       class, status );
            }
         }
      }

/* Re-establish the original graphical attributes. */
      astGrfAttrs( this, axisid, 0, GRF__LINE, method, class );

/* Set up the id value for the next axis. */
      axisid = AST__AXIS2_ID;

   }

/* Free the pointer to the current Frame. */
   frm = astAnnul( frm );

}


static AstPlotCurveData **DrawGrid( AstPlot *this, TickInfo **grid, int drawgrid,
                             const char *method, const char *class, int *status ){
/*
*  Name:
*     DrawGrid

*  Purpose:
*     Draw a grid of lines at the major tick mark positions on both axes.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     AstPlotCurveData **DrawGrid( AstPlot *this, TickInfo **grid, int drawgrid,
*                           const char *method, const char *class )

*  Class Membership:
*     Plot method.

*  Description:
*     This function draw a grid of curves at the major tick mark
*     positions on both axes, and returns information describing the
*     breaks in the curves. If short tick marks are required rather
*     than long curves (as specified by the Grid attribute of the supplied
*     Plot), then the curves are not drawn but the break information is
*     still returned.

*  Parameters:
*     this
*        Pointer to a Plot.
*     grid
*        A pointer to an array of two pointers (one for each axis), each
*        pointing to a TickInfo structure. These describe the positions
*        of the tick marks and should have been produced by function
*        GridLines.
*     drawgrid
*        If non-zero, draw a grid of curves marking the major axis
*        values. Otherwise, tick marks will be drawn at these values later.
*     method
*        Pointer to a string holding the name of the calling method.
*        This is only for use in constructing error messages.
*     class
*        Pointer to a string holding the name of the supplied object class.
*        This is only for use in constructing error messages.

*  Returned Value:
*     A pointer to an array of two AstPlotCurveData pointers (one for each axis),
*     each pointing to an array of AstPlotCurveData structures (one for each tick
*     value).

*  Notes:
*     -  This function assumes that the physical coordinate system is 2
*     dimensional, and it should not be used if this is not the case.
*     -  If an error has already occurred, or if this function should fail
*     for any reason, then a NULL pointer is returned.

*/

/* Local Variables: */
   AstPlotCurveData **cdata;/* The returned pointer */
   AstPlotCurveData *cdt;   /* Pointer to break info. for current tick mark */
   AstPlotCurveData tcdt;   /* Pointer to break info. for current curve section */
   TickInfo *info;          /* Tick mark information for a single axis */
   double start[ 2 ];       /* Strting position for current curve section */
   double total_length;     /* Total curve length for all axis ticks */
   int i;                   /* Axis index */
   int j;                   /* Tick mark index */
   int k;                   /* Curve section index */

/* Check the global status. */
   if( !astOK ) return NULL;

/* Allocate memory to hold two pointers, each pointing to an array of
   AstPlotCurveData structure. */
   cdata = (AstPlotCurveData **) astMalloc( 2*sizeof( AstPlotCurveData *) );

/* If succesful, initialise the pointers. */
   if( astOK ){
      cdata[ 0 ] = NULL;
      cdata[ 1 ] = NULL;

/* Draw the curves marking the major tick values on each axis. If no grid is
   required, we still do this in order to get information about the breaks
   in the curves which will be used later to decide where to put the labels,
   but we use "invisible ink". */
      for( i = 0; i < 2; i++ ){

/* Get a pointer to the TickInfo structure for this axis holding information
   about where to put tick marks on this axis. */
         info = grid[ i ];

/* Allocate memory to hold information describing the breaks in each tick
   mark curve. This takes the form of an array of AstPlotCurveData structures,
   one for each tick mark. */
         cdata[ i ] = (AstPlotCurveData *) astMalloc( sizeof(AstPlotCurveData)*
                                               (size_t) info->nmajor );

/* Check the pointer can be used. */
         if( astOK ){

/* Initialise a pointer to the first AstPlotCurveData structure for this axis. */
            cdt = cdata[ i ];
            total_length = 0.0;

/* Do each tick mark. */
            for( j = 0; j < info->nmajor; j++ ){

/* Store the starting point of the first section of the curve. */
               start[ i ] = (info->ticks)[ j ];
               start[ 1 - i ] = (info->start)[ 0 ];

/* Draw the first section of the curve parallel to the other axis, starting
   at the values in "start", and extending for a length given in the TickInfo
   structure. We use invisible ink if short tick marks are required instead
   of a grid of curves. */
               AxPlot( this, 1 - i, start, (info->length)[ 0 ],
                       drawgrid, cdt, method, class, status );

/* Now draw any other sections in the curve. */
               for( k = 1; k < info->nsect; k++ ){

/* Modify the starting value on the other axis. The starting value on
   the current axis remains set to the tick mark value. */
                  start[ 1 - i ] = (info->start)[ k ];

/* Draw the curve, the information describing the breaks goes into
   temporary storage in the local structure "tcdt". */
                  AxPlot( this, 1 - i, start, (info->length)[ k ],
                          drawgrid, &tcdt, method, class, status );

/* Concatenate the break information for this section with the break
   information describing the previous sections. */
                  AddCdt( cdt, &tcdt, method, class, status );

               }

/* Increment the total length of curves drawn for all ticks on this axis. */
               total_length += cdt->length;

/* Point to the AstPlotCurveData structure for the next tick mark. */
               cdt++;

            }

/* Report an error if the total length of all curves on this axis is zero.
   This can be caused for instance by bugs in the algorithm for finding
   major tick values (which may cause AST__BAD tick mark values). */
            if( total_length == 0.0 && astOK ) {
               astError( AST__INTER, "%s(%s): No grid curves can be drawn for "
                         "axis %d.", status, method, class, i + 1 );
            }

         }

      }

   }

/* If an error has occurred, clean up the returned structures. */
   if( !astOK ) cdata = CleanCdata( cdata, status );

/* Return. */
   return cdata;

}

static int DrawRegion( AstPlot *this, AstFrame *frm, const char *method,
                       const char *class, int *status ){
/*
*
*  Name:
*     DrawRegion

*  Purpose:
*     Draw the outline of a Region.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     int DrawRegion( AstPlot *this, AstFrame *frm, const char *method,
*                     const char *class, int *status )

*  Class Membership:
*     Plot member function.

*  Description:
*     If the current Frame in the supplied Plot is a Region, this function
*     draws a curve marking the outline of the Region. It returns without
*     action otherwise.

*  Parameters:
*     this
*        Pointer to the Plot.
*     frm
*        Pointer to the current Frame in the Plot (possibly a Region).
*     method
*        Pointer to a string holding the name of the calling method.
*        This is only for use in constructing error messages.
*     class
*        Pointer to a string holding the name of the supplied object class.
*        This is only for use in constructing error messages.
*     status
*        Pointer to the inherited status variable.

*  Returned Value:
*     Non-zero if and only if a Region outline was drawn.

*/

/* Local Variables: */
   AstMapping *map;        /* Mapping with Region masking included */
   AstPlotCurveData cdata; /* Stores information about curve breaks */
   AstRegion **comps;      /* List of component Regions */
   astDECLARE_GLOBALS      /* Pointer to thread-specific global data */
   double d[ CRV_NPNT ];   /* Offsets to evenly spaced points along curve */
   double tol;             /* Absolute tolerance value */
   double x[ CRV_NPNT ];   /* X coords at evenly spaced points along curve */
   double y[ CRV_NPNT ];   /* Y coords at evenly spaced points along curve */
   int i;                  /* Loop count */
   int icomp;              /* Index of component Region */
   int ncomp;              /* Number of component Regions */
   int result;             /* The returned value */

/* Initialise */
   result = 0;

/* Check the global error status. */
   if ( !astOK ) return result;

/* Get a pointer to the thread specific global data structure. */
   astGET_GLOBALS(this);

/* Check the current Frame is a Region, and is of a class that implements
   the astRegTrace method. */
   if( astIsARegion( frm ) &&
       astRegTrace( (AstRegion *) frm, 0, NULL, NULL ) ){

/* Set up the externals used to communicate with the Map5 function...
   The number of axes in the physical coordinate system (i.e. the
   Region). */
      Map5_ncoord =  astGetNaxes( frm );

/* A pointer to the Plot. */
      Map5_plot = this;

/* Also store a pointer to the Mapping, ensuring that the Mapping does
   not contain any masking effects from the Region. */
      map = astGetMapping( this, AST__BASE, AST__CURRENT );
      Map5_map = astRemoveRegions( map );
      map = astAnnul( map );

/* Convert the tolerance from relative to absolute graphics coordinates.
   Make the tolerance smaller by a factor of 10 because Regions
   (specifically Polygonsd) can have very crinkly edges. */
      tol = 0.1* astGetTol( this )*astMAX( this->xhi - this->xlo,
                                           this->yhi - this->ylo );

/* Ensure the globals holding the scaling from graphics coords to equally
   scaled coords are available. */
      GScales( this, NULL, NULL, method, class, status );

/* Now set up the external variables used by the Crv and CrvLine function. */
      Crv_scerr = ( astGetLogPlot( this, 0 ) ||
                    astGetLogPlot( this, 1 ) ) ? 100.0 : 1.5;
      Crv_ux0 = AST__BAD;
      Crv_tol = 2*tol;
      Crv_limit = 0.5*tol*tol;
      Crv_map = Map5;
      Crv_ink = 1;
      Crv_xlo = this->xlo;
      Crv_xhi = this->xhi;
      Crv_ylo = this->ylo;
      Crv_yhi = this->yhi;
      Crv_out = 1;
      Crv_xbrk = cdata.xbrk;
      Crv_ybrk = cdata.ybrk;
      Crv_vxbrk = cdata.vxbrk;
      Crv_vybrk = cdata.vybrk;
      Crv_clip = astGetClip( this ) & 1;

/* Attempt to split the Region into a set of disjoint component Regions. */
      comps = astRegSplit( (AstRegion *) frm, &ncomp );

/* Draw each one. */
      for( icomp = 0; icomp < ncomp; icomp++ ) {

/* A pointer to the Region. */
         Map5_region = comps[ icomp ];

/* Set up a list of points spread evenly over the curve. */
         for( i = 0; i < CRV_NPNT; i++ ){
           d[ i ] = ( (double) i)/( (double) CRV_NSEG );
         }

/* Map these points into graphics coordinates. */
         Map5( CRV_NPNT, d, x, y, method, class, status GLOBALS_NAME );

/* Use Crv and Map5 to draw the curve. */
         Crv( this, d, x, y, 0, NULL, NULL, method, class, status );

/* End the current poly line. */
         Opoly( this, status );

/* Tidy up the static data used by Map5. */
         Map5( 0, NULL, NULL, NULL, method, class, status GLOBALS_NAME );

/* Annul the component Region pointer. */
         comps[ icomp ] = astAnnul( Map5_region );
      }

/* Free the memory holding the list of component Region pointers. */
      comps = astFree( comps );

/* Annul the Mapping. */
      Map5_map = astAnnul( Map5_map );

/* Indicate the outline was drawn. */
      result = 1;
   }

/* Return. */
   return result;
}

static void DrawText( AstPlot *this, int ink, int esc, const char *text,
                      float x, float y, const char *just, float upx,
                      float upy, float *xbn, float *ybn, float *drop,
                      const char *method, const char *class, int *status ){
/*
*  Name:
*     DrawText

*  Purpose:
*     Draw a character string, potentially including superscripts and
*     subscripts.

*  Synopsis:
*     #include "plot.h"

ast/src/plot.c  view on Meta::CPAN


/* Return. */
   return;

}

static void EBuf( AstPlot *this, int *status ) {
/*
*++
*  Name:
c     astEBuf
f     AST_EBUF

*  Purpose:
*     End the current graphical buffering context.

*  Type:
*     Public function.

*  Synopsis:
c     #include "plot.h"
c     void astEBuf( AstPlot *this )
f     CALL AST_EBUF( THIS STATUS )

*  Class Membership:
*     Plot member function.

*  Description:
c     This function
f     This routine
*     ends the current graphics buffering context. It should match a
*     corresponding call to the
c     astBBuf function.
f     AST_EBUF routine.

*  Parameters:
c     this
f     THIS = INTEGER (Given)
*        Pointer to the Plot.
f     STATUS = INTEGER (Given and Returned)
f        The global status.

*  Notes:
*     - The nature of the buffering is determined by the underlying
*     graphics system (as defined by the current grf module). Each call
c     to this function
f     to this routine
*     simply invokes the astGEBuf function in the grf module.

*--
*/

/* Check the global error status. */
   if ( !astOK ) return;

/* Invoke the active GRF EBuf function. */
   GEBuf( this, "astEBuf", astGetClass( this ), status );
}

static int EdgeLabels( AstPlot *this, int ink, TickInfo **grid,
                       AstPlotCurveData **cdata, int force, const char *method,
                       const char *class, int *status ){
/*
*
*  Name:
*     EdgeLabels

*  Purpose:
*     Attempts to display labels for the major tick values around the edges
*     of the plotting area.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     int EdgeLabels( AstPlot *this, int ink, TickInfo **grid,
*                     AstPlotCurveData **cdata, int force, const char *method,
*                     const char *class, int *status )

*  Class Membership:
*     Plot member function.

*  Description:
*     This function determines how many major tick value labels could be
*     placed on the specified edges of the plotting area, and then if
*     requested, and if sufficient such labels are found (more than 3 on
*     each axis), they are drawn. To place a label on an edge, the curve
*     defining the major tick value must cross the edge at a reasonably
*     angle (at least 3 degrees). Labels are not drawn which would overlap
*     other, previously drawn, labels. A flag is returned indicating if
*     edge labels were (or could be) drawn.

*  Parameters:
*     this
*        A pointer to the Plot.
*     ink
*        If zero, then no labels are drawn, but the decision whether or
*        not to draw them is still made and indicated in the returned function
*        value.
*     grid
*        A pointer to an array of two TickInfo pointers (one for each axis),
*        each pointing to a TickInfo structure holding information about
*        tick marks on the axis. See function GridLines.
*     cdata
*        A pointer to an array of two AstPlotCurveData pointers (one for each axis),
*        each pointing to an array of AstPlotCurveData structure (one for each
*        major tick value on the axis), holding information about breaks
*        in the curves drawn to mark the major tick values. See function
*        DrawGrid.
*     force
*        If non-zero, then an attempt is made to draw edge labels even if
*        it looks like insufficient edge labels can be produced.
*     method
*        Pointer to a string holding the name of the calling method.
*        This is only for use in constructing error messages.
*     class
*        Pointer to a string holding the name of the supplied object class.
*        This is only for use in constructing error messages.
*     status
*        Pointer to the inherited status variable.

*  Returned Value:
*     If edge labels were drawn, 1 is returned. Otherwise 0 is returned.

*  Notes:
*     -  Zero is returned if an error has already occurred.
*/


/* Local Variables: */
   AstFrame *frame;       /* Pointer to current Frame */
   AstPlotCurveData *cdt; /* Pointer to the AstPlotCurveData for the next tick */
   LabelList *labellist;  /* Pointer to a ingle list of labels to be plotted */
   LabelList *ll;         /* Pointer to next label to be plotted */
   LabelList *llist[2];   /* Pointers to both lists of labels to be plotted */
   TickInfo *info;        /* Pointer to the TickInfo for the current axis */
   const char *just[ 2 ]; /* Justification string */
   const char *text;      /* Pointer to label text */
   double edgeval;        /* Axis value at the labelled edge */
   double mindim;         /* Minimum dimension of the plotting area */
   double tol;            /* Max. distance between a break and the edge */
   double txtgap;         /* Absolute gap between labels and edges */
   float *box;            /* Pointer to array of label bounding boxes */
   float *vxbrk;          /* X component of unit vector at current break */
   float *vybrk;          /* Y component of unit vector at current break */
   float *xbrk;           /* X coord. of current break */
   float *ybrk;           /* Y coord. of current break */
   float xref;            /* X coordinate at label's reference position */
   float yref;            /* Y coordinate at label's reference position */
   int axis;              /* Current axis index */
   int brk;               /* Current break index */
   int edge;              /* The edge to be labelled */
   int edgeax;            /* Index of axis parallel to the labelled edge */
   int edgelabs;          /* Can edge labels be produced? */
   int esc;               /* INterpret escape sequences? */
   int gelid;             /* ID for next graphical element to be drawn */
   int ii;                /* Index into existing labels */
   int maxlab;            /* Number of distinct edge labels */
   int medge[2];          /* No. of distinct edge labels for each axis */
   int naxlab;            /* Number of edge labels */
   int near;              /* Draw a label on the near edge? */
   int nedge[2];          /* No. of edge labels for each axis */
   int ok;                /* Can the current tick mark be labelled on the edge? */
   int labfound;          /* Label value has already been used? */

ast/src/plot.c  view on Meta::CPAN

            yref = (float)( edgeval + txtgap );
         } else {
            edgeval = this->ylo;
            yref = (float)( edgeval - txtgap );
         }

         edgeax = 0;

/* Do the same if the labels are to go on the right-hand edge. */
      } else if( edge == 2 ){

         if( !upright ) {
            just[ axis ] = "BC";
         } else if( txtgap > 0.0 ){
            just[ axis ] = "CL";
         } else if( txtgap < 0.0 ){
            just[ axis ] = "CR";
         } else {
            just[ axis ] = "CC";
         }

         if( !this->xrev ){
            edgeval = this->xhi;
            xref = (float)( edgeval + txtgap );
         } else {
            edgeval = this->xlo;
            xref = (float)( edgeval - txtgap );
         }

         edgeax = 1;

/* Do the same if the labels are to go on the bottom edge. */
      } else {
         if( txtgap > 0.0 ){
            just[ axis ] = "TC";
         } else if( txtgap < 0.0 ){
            just[ axis ] = "BC";
         } else {
            just[ axis ] = "CC";
         }

         if( !this->yrev ){
            edgeval = this->ylo;
            yref = (float)( edgeval - txtgap );
         } else {
            edgeval = this->yhi;
            yref = (float)( edgeval + txtgap );
         }

         edgeax = 0;

      }

/* Get a pointer to the structure containing information describing the
   positions of the major tick marks along this axis. */
      info = grid[ axis ];

/* Get a pointer to the structure containing information describing the
   breaks in the curve which is parallel to the other axis and passes
   through the first major tick mark. */
      cdt = cdata[ axis ];

/* Initialise the pointer to the list of text strings to be drawn. */
      labellist = NULL;

/* Initialise the number of labels which can be placed on the near edge of
   the plotting zone (some of which may be the same). */
      naxlab = 0;

/* Initialise the number of distinct labelled tick mark values. */
      maxlab = 0;

/* Loop round each of the major tick marks on the current axis. */
      for( tick = 0; cdt && info && tick < info->nmajor; tick++ ){

/* Store pointers to the values giving the position and unit direction
   vector of the curve at the first break. */
         xbrk = cdt->xbrk;
         ybrk = cdt->ybrk;
         vxbrk = cdt->vxbrk;
         vybrk = cdt->vybrk;

/* Loop round each of the breaks in the curve which passes through the
   current major tick mark, and is parallel to the other axis. */
         ok = 0;
         for( brk = 0; brk < cdt->nbrk; brk++ ){

/* A label can be produced on the near edge of the plotting zone if the
   current break occurs on, or close to, the edge, and the curve is not
   nearly parallel to the axis (limit is 5 degs). */
            near = ( ( edgeax == 0 &&
                       fabs( (double) *ybrk - edgeval ) < tol &&
                       fabs( (double) *vybrk ) > 0.09 ) ||
                     ( edgeax == 1 &&
                       fabs( (double) *xbrk - edgeval ) < tol &&
                       fabs( (double) *vxbrk ) > 0.09 ) );

/* Get the label text. */
            if( info->labels ) {
               text = (info->labels)[ tick ];
            } else {
               text = NULL;
            }

/* If a label can be produced, record the information needed to draw the
   label. */
            if( near && text ){

               labellist = (LabelList *) astGrow( (void *) labellist, naxlab + 1, sizeof(LabelList) );
               if ( !astOK ) break;

               if( edgeax == 0 ){
                  (labellist + naxlab)->index = (double) *xbrk;
                  (labellist + naxlab)->x = (double) *xbrk;
                  (labellist + naxlab)->y = (double) yref;
               } else {
                  (labellist + naxlab)->index = (double) *ybrk;
                  (labellist + naxlab)->x = (double) xref;
                  (labellist + naxlab)->y = (double) *ybrk;
               }

ast/src/plot.c  view on Meta::CPAN

                "Grf function id %d not yet supported.", status, method, class,
                ifun );
   }
}

static void Grid( AstPlot *this_nd, int *status ){
/*
*++
*  Name:
c     astGrid
f     AST_GRID

*  Purpose:
*     Draw a set of labelled coordinate axes.

*  Type:
*     Public virtual function.

*  Synopsis:
c     #include "plot.h"
c     void astGrid( AstPlot *this )
f     CALL AST_GRID( THIS, STATUS )

*  Class Membership:
*     Plot method.

*  Description:
c     This function draws a complete annotated set of
f     This routine draws a complete annotated set of
*     coordinate axes for a Plot with (optionally) a coordinate grid
*     superimposed. Details of the axes and grid can be controlled by
*     setting values for the various attributes defined by the Plot
*     class (q.v.).

*  Parameters:
c     this
f     THIS = INTEGER (Given)
*        Pointer to the Plot.
f     STATUS = INTEGER (Given and Returned)
f        The global status.

*  Notes:
*     - If the supplied Plot is a Plot3D, the axes will be annotated
*     using three 2-dimensional Plots, one for each 2D plane in the 3D
*     current coordinate system. The plots will be "pasted" onto 3 faces
*     of the cuboid graphics volume specified when the Plot3D was
*     constructed. The faces to be used can be controlled by the "RootCorner"
*     attribute.
*     - An error results if either the current Frame or the base Frame
*     of the Plot is not 2-dimensional or (for a Plot3D) 3-dimensional.
*     - An error also results if the transformation between the base
*     and current Frames of the Plot is not defined in either
*     direction (i.e. the Plot's TranForward or TranInverse attribute
*     is zero).
*--
*/

/* Local Variables: */
   astDECLARE_GLOBALS      /* Pointer to thread-specific global data */
   AstPlot *this;          /* Plot with 2d current Frame */
   AstPlotCurveData **cdata;/* Pointer to info. about breaks in curves */
   TickInfo **grid;        /* Pointer to info. about tick marks */
   const char *class;      /* Object class */
   const char *method;     /* Current method */
   double cen[ 2 ];        /* Position of first tick mark */
   double gap[ 2 ];        /* Gap between tick marks */
   double labelat[ 2 ];    /* Axis values at which tick marks are put */
   int axis;               /* Physical axis index */
   int border;             /* Draw a border? */
   int clip;               /* Original Clip attribute value */
   int dounits[2];         /* Include Units in each axis label? */
   int drawgrid;           /* Is a grid of lines to be drawn? */
   int clredge;            /* Clear the Edge attributes before returning? */
   int edgeticks;          /* Draw labels round edges of plotting area? */
   int escs;               /* Original astEscapes value */
   int ink;                /* Draw the grid with visible ink? */
   int inval;              /* Were areas of invalid coordinates found? */
   int labelling;          /* Value of Labelling attribute */
   int loglabelset[2];     /* Were the LogLabel attributes set initially? */
   int logticksset[2];     /* Were the LogTicks attributes set initially? */
   int naxes;              /* No. of axes in the base or current Frame */
   int oldedge0;           /* Default value for Edge(1) */
   int oldedge1;           /* Default value for Edge(2) */
   int useint;             /* Do interior labels give us an advantage? */

/* Check the global error status. */
   if ( !astOK ) return;

/* Get a pointer to the thread specific global data structure. */
   astGET_GLOBALS(this_nd);

/* Store the current method and class for inclusion in error messages
   generated by lower level functions. */
   method = "astGrid";
   class = astClass( this_nd );

/* Check the base Frame of the Plot is 2-D. */
   naxes = astGetNin( this_nd );
   if( naxes != 2 && astOK ){
      astError( AST__NAXIN, "%s(%s): Number of axes (%d) in the base "
                "Frame of the supplied %s is invalid - this number should "
                "be 2.", status, method, class, naxes, class );
   }

/* Ensure AST functions included graphical escape sequences in any
   returned text strings. */
   escs = astEscapes( 1 );

/* Note if attributes which have complex dynamic defaults are set
   initially. */
   logticksset[0] = astTestLogTicks( this_nd, 0 );
   logticksset[1] = astTestLogTicks( this_nd, 1 );
   loglabelset[0] = astTestLogLabel( this_nd, 0 );
   loglabelset[1] = astTestLogLabel( this_nd, 1 );

/* Indicate that the GRF module should re-calculate it's cached values
   (in case the state of the graphics system has changed since the last
   thing was drawn). */
   RESET_GRF;

/* Get a Plot with a 2D (or 1D) current Frame. */
   this = (AstPlot *) Fset2D( (AstFrameSet *) this_nd, AST__CURRENT, status );

/* Check the current Frame of the Plot is 2-D. */
   naxes = astGetNout( this );
   if( naxes != 2 && astOK ){
      astError( AST__NAXIN, "%s(%s): Number of axes (%d) in the current "
                "Frame of the supplied %s is invalid - this number should "
                "be 2.", status, method, class, naxes, class );
   }

/* Ensure that all lines are clipped at the plot boundary.*/
   if( astTestClip( this ) ) {
      clip = astGetClip( this );
      astSetClip( this, 1 );
   } else {
      clip = -1;
   }

/* If the protected attribute "Ink" is set to zero, then the plot
   is drawn in "invisble ink" (i.e. all the calculations needed to
   produce the grid are performed, but nothing is actually drawn). */
   ink = astGetInk( this );

/* Initialise the bounds of the box containing all plotted lines and
   numerical labels. */
   Box_lbnd[ 0 ] = FLT_MAX;
   Box_lbnd[ 1 ] = FLT_MAX;
   Box_ubnd[ 0 ] = FLT_MIN;
   Box_ubnd[ 1 ] = FLT_MIN;

/* Obtain the requested centre attribute values for both physical axes. */
   for( axis = 0; axis < 2; axis++ ){
      cen[ axis ] = astGetCentre( this, axis );
   }

/* Determine where to put the major axis values. */
   grid = GridLines( this, cen, gap, &inval, method, class, status );

/* If the user has set an explicit value for Grid, use it. */
   if( astTestGrid( this ) ){
      drawgrid = astGetGrid( this );

/* If not, the default for Grid is based on whether or not there are any
   invalid regions. */
   } else if( inval ){
      drawgrid = 1;

   } else {
      drawgrid = 0;
   }

/* Draw the curves marking the major tick values on each axis. Information
   is returned describing the positions of the breaks in these curves. */
   cdata = DrawGrid( this, grid, ( ink && drawgrid ), method, class, status );

/* See if labels and tick marks will be drawn round the edges of the
   plotting area, rather than within it (no labels are actually drawn
   yet). Interior labels can always be produced, in which case edgeticks
   is set explicitly to zero to indicate that ticks will be internal.
   Exterior labelling may or may not be possible. If it is requested,
   check to see if it is possible. */
   clredge = 0;
   labelling = astGetLabelling( this );
   if( labelling ){
      edgeticks = 0;
   } else {
      edgeticks = EdgeLabels( this, 0, grid, cdata, 0, method, class, status );

/* If the external labelling was requested, but could not be produced... */
      if( !edgeticks ) {

/* and if the Edge attributes have not been set... */
         if( !astTestEdge( this, 0 ) && !astTestEdge( this, 1 ) ) {

/* Try flipping the default Edge values, to see if this allows us to
   honour the requested Labelling scheme. */
            oldedge0 = astGetEdge( this, 0 );
            oldedge1 = astGetEdge( this, 1 );
            astSetEdge( this, 0, oldedge1 );
            astSetEdge( this, 1, oldedge0 );

/* See if exterior labels could be drawn with these new edges. */
            edgeticks = EdgeLabels( this, 0, grid, cdata, 0, method, class, status );

/* If this would allow us to use the requested labelling scheme, retain
   the new Edge values, setting a flag to indicate that they will need to be
   cleared before returning. Otherwise, clear them. */
            if( edgeticks ) {
               clredge = 1;

            } else {
               astClearEdge( this, 0 );
               astClearEdge( this, 1 );
            }
         }
      }
   }

/* If edge ticks can still not be produced, but the ForceExterior attribute
   has a non-zero value, attempt to create exterior labels even though it
   looks like there may be insufficient of them to justify their use. */
   if( !edgeticks && astGetForceExterior( this ) ) {
      edgeticks = EdgeLabels( this, 0, grid, cdata, 1, method, class, status );
   }

/* We may also need to swap edge values when using interior labelling in
   order to ensure that the text labels are placed on appropriate edges of
   the plotting box. */
   if( !edgeticks && !astTestEdge( this, 0 ) && !astTestEdge( this, 1 ) ) {
      if( swapEdges( this, grid, cdata, status ) ) {
         oldedge0 = astGetEdge( this, 0 );
         oldedge1 = astGetEdge( this, 1 );
         astSetEdge( this, 0, oldedge1 );
         astSetEdge( this, 1, oldedge0 );
         clredge = 1;
      }
   }

/* If edge ticks are being used, store bad values for the labelat values to
   indicate that labels are not being drawn within the interior of the
   plotting area. */
   if( edgeticks ){
      labelat[ 0 ] = AST__BAD;
      labelat[ 1 ] = AST__BAD;

/* Otherwise, see where interior labels and tick marks should go (the axis
   values are put in "labelat"). */
   } else {
      useint = Labelat( this, grid, cdata, labelat, method, class, status );

/* If interior labelling does not allow us to draw any more ticks, revert
   to edge labelling if that is what the user requested. */
      if( !useint && !labelling ) {
         labelat[ 0 ] = AST__BAD;
         labelat[ 1 ] = AST__BAD;
         edgeticks = EdgeLabels( this, 0, grid, cdata, 1, method, class, status );
      }
   }

/* See if a border is required. By default, a border is drawn only when
   using exterior labelling. */
   if( astTestBorder( this ) ) {
      border = astGetBorder( this );
   } else {
      border = edgeticks;
   }

/* See if the Units string is to be inluded in the label. */
   dounits[ 0 ] =  astGetLabelUnits( this, 0 );
   dounits[ 1 ] =  astGetLabelUnits( this, 1 );

/* The rest is not done if no output is required. */
   if( ink ) {

/* Draw tick marks (major and minor). */
      DrawTicks( this, grid, drawgrid, labelat, gap, method, class, status );

/* If required, ensure that curves through the tick marks have been drawn */
      DrawAxis( this, grid, labelat, gap, method, class, status );

/* If required, draw a curve around the edge of the area containing valid
   physical coordinates. */
      if( border ) (void) astBorder( this );

/* Draw the numerical labels at the major tick values. */
      Labels( this, grid, cdata, gap, labelat, method, class, status );

/* Draw the textual labels for each axis and a title. */
      TextLabels( this, edgeticks, dounits, method, class, status );
   }

/* Ensure all lines are flushed to the graphics system. */
   Fpoly( this, method, class, status );

/* Store the actual values used for all attributes which have dynamic
   defaults. Check the global status to ensure the pointer "grid" can be
   used without the possibility of a segmentation violation. */
   for( axis = 0; axis < 2 && astOK ; axis++ ) {
      SetUsedLogTicks( this_nd, axis, astGetLogTicks( this, axis ), status );
      SetUsedLogLabel( this_nd, axis, astGetLogLabel( this, axis ), status );

      if( astGetLogTicks( this, axis ) ) {
         SetUsedLogGap( this_nd, axis, gap[ axis ], status );
      } else {
         SetUsedGap( this_nd, axis, gap[ axis ], status );
      }
      SetUsedCentre( this_nd, axis, cen[ axis ], status );
      SetUsedEdge( this_nd, axis, astGetEdge( this, axis ), status );
      SetUsedLabelAt( this_nd, axis, labelat[ axis ], status );
      SetUsedLabelUnits( this_nd, axis, dounits[ axis ], status );

/* If explicit minor tick values were supplied using astSetTickValues,
   then set MinTick to the average number of minor tick divisions per major
   tick division. */
      if( grid[ axis ]->minticks ) {
         SetUsedMinTick( this_nd, axis,
                         ( grid[ axis ]->nminor + grid[ axis ]->nmajor )/
                         ( grid[ axis ]->nmajor - 1 ), status );
      } else {
         SetUsedMinTick( this_nd, axis, grid[ axis ]->nminor, status );
      }

      if( astTestTextLab( this, axis ) ) {
         SetUsedTextLab( this_nd, axis, astGetTextLab( this, axis ), status );
      } else {
         SetUsedTextLab( this_nd, axis, edgeticks, status );
      }

      if( astTestMajTickLen( this, axis ) ) {
         SetUsedMajTickLen( this_nd, axis, astGetMajTickLen( this, axis ), status );
      } else {
         SetUsedMajTickLen( this_nd, axis, drawgrid ? 0.0 :
                                           astGetMajTickLen( this, axis ), status );
      }

   }

   SetUsedGrid( this_nd, drawgrid, status );
   SetUsedLabelling( this_nd, edgeticks ? 0 : 1, status );
   SetUsedBorder( this_nd, border, status );

/* Free the memory used to hold information about the curves. */
   cdata = CleanCdata( cdata, status );

/* Free the memory used to hold information about the tick marks. */
   grid = CleanGrid( grid, status );

/* If required clear attributes. */
   if( clredge ) {
      astClearEdge( this, 0 );
      astClearEdge( this, 1 );
   }

   if( !logticksset[ 0 ] ) astClearLogTicks( this, 0 );
   if( !logticksset[ 1 ] ) astClearLogTicks( this, 1 );
   if( !loglabelset[ 0 ] ) astClearLogLabel( this, 0 );
   if( !loglabelset[ 1 ] ) astClearLogLabel( this, 1 );

/* Restore the original value of the Clip attribute. */
   if( clip != -1 ) astSetClip( this, clip );

/* Free the 2D Plot. */
   this = astAnnul( this );

/* Restore the original value of the flag which says whether graphical
   escape sequences should be incldued in any returned text strings. */
   astEscapes( escs );

/* Copy the total bounding box to the box which is returned by
   astBoundingBox. */
   if( !Boxp_freeze ){
      Boxp_lbnd[ 0 ] = Box_lbnd[ 0 ];
      Boxp_lbnd[ 1 ] = Box_lbnd[ 1 ];
      Boxp_ubnd[ 0 ] = Box_ubnd[ 0 ];
      Boxp_ubnd[ 1 ] = Box_ubnd[ 1 ];
   }

/* Return. */
   return;

}

static void GridLine( AstPlot *this, int axis, const double start[],
                      double length, int *status ){
/*
*++
*  Name:
c     astGridLine
f     AST_GRIDLINE

*  Purpose:
*     Draw a grid line (or axis) for a Plot.

*  Type:
*     Public virtual function.

*  Synopsis:
c     #include "plot.h"
c     void astGridLine( AstPlot *this, int axis, const double start[],
c                       double length )
f     CALL AST_GRIDLINE( THIS, AXIS, START, LENGTH, STATUS )

*  Class Membership:

ast/src/plot.c  view on Meta::CPAN

/* Otherwise, we work out the coords of the left end of the baseline from
   the values returned by DrawText above. Call DrawText now if it was not
   called above. */
      } else {
         if( ! called ) {
            DrawText( this, 0, esc, text, *x, *y, "BL", upx, upy, xbn, ybn,
                      &drop, method, class, status );
         }

/* Find the height and width of the bounding box. */
         dx = xbn[ 0 ] - xbn[ 3 ];
         dy = ybn[ 0 ] - ybn[ 3 ];
         width = sqrt( dx*dx + dy*dy );

         dx = xbn[ 0 ] - xbn[ 1 ];
         dy = ybn[ 0 ] - ybn[ 1 ];
         height = sqrt( dx*dx + dy*dy );

/* For "C" and "R" horizontal justification we first need to move the
   returned reference point left by 0.5 or 1.0 times the width of the whole
   string respectively. */
         if( result[ 1 ] == 'C' ) {
            f = 0.5;

         } else if( result[ 1 ] == 'R' ) {
            f = 1.0;

         } else {
            f = 0.0;
         }

         f *= width;

         *x0 = *x - f*rxu;
         *y0 = *y - f*ryu;

/* Unless the vertical justification is "B", we also need to move the
   concatenation point vertically to put it on the baseline. */
         if( result[ 0 ] == 'T' ) {
            f = height - drop;

         } else if( result[ 0 ] == 'C' ) {
            f = 0.5*height - drop;

         } else if( result[ 0 ] == 'M' ) {
            f = -drop;

         } else {
            f = 0.0;
         }

         *x0 -= f*uxu;
         *y0 -= f*uyu;
      }
   }

/* Return the result. */
   return result;
}

static int Labelat( AstPlot *this, TickInfo **grid, AstPlotCurveData **cdata,
                    double *labelat, const char *method, const char *class,
                    int *status ){
/*
*
*  Name:
*     Labelat

*  Purpose:
*     Determine the other axis value at which to place interior labels
*     and tick marks.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     int Labelat( AstPlot *this, TickInfo **grid, AstPlotCurveData **cdata,
*                  double *labelat, const char *method, const char *class )

*  Class Membership:
*     Plot member function.

*  Description:
*     If tick marks and labels are to be placed within the plotting area,
*     the tick values stored in "grid" determine their position on one
*     axis, and their position on the other axis is determined by this
*     function. If a value has been set for the "LabelAt" attribute, then
*     it is used, otherwise the "other axis" value on the longest curve
*     parallel to the "other axis" is used (although the curve "other axis
*     = zero" is used if it passes through the plotting area and is not too
*     short). The effective length assigned to each curve is reduced in
*     proportion to the number of tick marks which are close to the edge
*     of the plotting area.
*
*     A flag is returned indicating if the two axes appear to be
*     independent, in which case there is nothing to be gained by using
*     interior labelling.

*  Parameters:
*     this
*        A pointer to the Plot.
*     grid
*        A pointer to an array of two TickInfo pointers (one for each axis),
*        each pointing to a TickInfo structure holding information about
*        tick values on the axis. See function GridLines.
*     cdata
*        A pointer to an array of two AstPlotCurveData pointers (one for each axis),
*        each pointing to an array of AstPlotCurveData structure (one for each
*        major tick value on the axis), holding information about breaks
*        in the curves drawn to mark the major tick values. See function
*        DrawGrid.
*     labelat
*        A pointer to a 2 element array in which to store the constant axis
*        values at which tick marks are put. Element 0 is returned holding
*        the axis 1 value at which tick marks for axis 0 are placed. Element
*        1 is returned holding the axis 0 value at which tick marks for axis
*        1 are placed.
*     flags
*        A pointer to a 2 element array. Each element is a flag which is
*        returned non-zero if the corresponding axis
*     method
*        Pointer to a string holding the name of the calling method.
*        This is only for use in constructing error messages.
*     class
*        Pointer to a string holding the name of the supplied object class.
*        This is only for use in constructing error messages.

*  Returned Value:
*     Zero if and only if the lines of constant axis value are all the
*     same length for all tick marks on either axis. If this is so, using
*     interior labelling will not enable any more major ticks to be
*     drawn, and so there is no reason to switch to interior labelling (unless
*     the user has specifically requested interior labelling).

*  Notes:
*     -  This function assumes the current Frame of the Plot is 2
*     dimensional, and it should not be called if this is not the case.
*/

/* Local Variables: */
   AstMapping *mapping;   /* Mapping from graphics to physical coords */
   AstPointSet *pset2;    /* Pointset for graphical tick positions */
   AstPointSet *pset[ 2 ];/* Pointsets for physical tick positions */
   AstPlotCurveData *cdt; /* Pointer to the AstPlotCurveData for the next tick */
   TickInfo *info;        /* Pointer to the TickInfo for the current axis */
   double **ptr2;         /* Pointers to graphics pointset data */
   double *ptr1[ 2 ];     /* Pointers to physical pointset data */
   double *tvals[ 2 ];    /* Pointers to arrays of other axis values */
   double *value;         /* Current tick value */
   double efflen;         /* Effective length of current curve */
   double lim;            /* Largest insignificant axis value */
   double margin;         /* Width of margin around plotting area */
   double maxlen;         /* Effective length of longest curve */
   double minlen;         /* Effective length of shortest (non-zero) curve */
   double x;              /* Tick X value */
   double xhi;            /* Upper limit on acceptable X range */
   double xlo;            /* Lower limit on acceptable X range */
   double y;              /* Tick Y value */
   double yhi;            /* Upper limit on acceptable Y range */
   double ylo;            /* Lower limit on acceptable Y range */
   double zerolen;        /* Effective length of curve for other axis = 0.0 */
   int axis;              /* Current axis index */
   int i;                 /* Tick index for this axis */
   int nin;               /* No. of counted ticks */
   int result;            /* Does interior labelling allow more ticks to be drawn? */
   int tick;              /* Tick index */

/* Check the global status. */
   if( !astOK ) return 0;

/* Initialise */
   result = 1;

/* Create two PointSets to hold a set of tick mark positions along each
   axis. The values on "axis" will be taken from the info structure. For
   each axis create an array to hold values for the "other" axis. */
   for( axis = 0; axis < 2; axis++ ){
      info = grid[ axis ];
      pset[ axis ] = astPointSet( info->nmajor, 2, "", status );
      tvals[ axis ] = (double *) astMalloc( sizeof(double)*(size_t)(info->nmajor) );
   }

/* Get the mapping from Base (graphics) frame the Current (physical) */
   mapping = astGetMapping( this, AST__BASE, AST__CURRENT );

/* Get the bounds of the area in which tick marks must occur to be
   counted. This is the total plotting area minus a 5% margin at each
   edge. */
   margin = 0.05*( this->xhi - this->xlo );
   xlo = this->xlo + margin;
   xhi = this->xhi - margin;

   margin = 0.05*( this->yhi - this->ylo );
   ylo = this->ylo + margin;
   yhi = this->yhi - margin;

/* Do each axis. */
   for( axis = 0; axis < 2 && astOK; axis++ ){

/* Find the longest and shortest curves parallel to the axis being labelled.
   Also find the length of the curve which passes through the origin of the
   other axis which is within the plotting area. We need to do this even
   if LabelAt has been set since we need to calculate the returned flag. */

/* Store pointers to the arrays holding tick mark physical coordinates,
   and set these in the PointSet. */
      ptr1[ axis ] = grid[ axis ]->ticks;
      ptr1[ 1 - axis ] = tvals[ axis ];
      astSetPoints( pset[ axis ], ptr1 );

/* Get a pointer to the structure containing information describing the
   positions of the major tick marks along the other axis. */
      info = grid[ 1 - axis ];

/* Get a pointer to the other axis value at the first other axis major tick
   mark. */
      value = info->ticks;

/* Get a limit on absolute magnitude for an axis value to be consider
   equal to zero. */
      lim = 1.0E-6*fabs( value[ 1 ] - value [ 0 ] );

/* Get a pointer to the structure containing information describing the
   breaks in the curve which passes through the first major tick mark. */
      cdt = cdata[ 1 - axis ];

/* Initialise the effective length of the longest and shortest curves, and
   the curve passing through the origin. */
      maxlen = -1.0;
      minlen = DBL_MAX;
      zerolen = 0.0;
      labelat[ axis ] = AST__BAD;

/* Loop round each of the major tick marks on the other axis. */
      for( tick = 0; tick < info->nmajor && astOK; tick++ ){

/* Fill the array of other axis values with the current other axis value. */
         for( i = 0; i < grid[ axis ]->nmajor; i++ ){
            tvals[ axis ][ i ] = *value;
         }

/* Transform the tick positions from the current frame (i.e. physical
   coordinates) to the base frame (i.e. graphics coordinates) using
   the inverse Mapping. */
         pset2 = Trans( this, NULL, mapping, pset[ axis ], 0, NULL, 0,
                        method, class, status );

/* Get pointers to the graphics coordinates. */
         ptr2 = astGetPoints( pset2 );
         if( astOK ) {

/* Count the number of graphics positions which are well within the plotting
   area. */
            nin = 0;
            for( i = 0; i < grid[ axis ]->nmajor; i++ ){
               x = ptr2[ 0 ][ i ];
               y = ptr2[ 1 ][ i ];
               if( x != AST__BAD && x > xlo && x < xhi &&
                   y != AST__BAD && y > ylo && y < yhi ) nin++;
            }

/*  Find the effective length of this curve.*/
            efflen = sqrt( (float) nin )*cdt->length;

/* If the curve through this tick mark has a greater effective length than any
   other found so far, record it. */
            if( efflen > maxlen ){
               maxlen = efflen;
               labelat[ axis ] = *value;
            }

/* If the curve through this tick mark has a smaller non-zero effective length
   than any other found so far, record it. */
            if( efflen < minlen && efflen > 0.0 ) minlen = efflen;

/* If this tick mark is at the origin, note the effective length. */
            if( fabs( *value ) <= lim ) zerolen = efflen;

/* Get a pointer to the curve through the next major tick mark. */
            cdt++;

/* Get a pointer to the axis value at the next major tick mark. */
            value++;

         }

/* Free resources. */
         pset2 = astAnnul( pset2 );
      }

/* Use the curve through the origin unless it is significantly shorter
   than the longest curve. */
      if( zerolen > 0.4*maxlen ) labelat[ axis ] = 0.0;

/* Return a flag if the lengths of the shortest and longest curves are nearly
   equal. */
      if( ( maxlen - minlen )/( maxlen + minlen ) < 1.0E-5 ) result = 0;

/* If the LabelAt attribute has been set, use it in preference to the
   value found above. */
      if( astTestLabelAt( this, axis ) ){
         labelat[ axis ] = astGetLabelAt( this, axis );
      }
   }

/* Release resources. */
   for( axis = 0; axis < 2; axis++ ){
      if( pset[ axis ] ) pset[ axis ] = astAnnul( pset[ axis ] );
      if( tvals[ axis ] ) tvals[ axis ] = (double *) astFree( (void *) tvals[ axis ] );
   }
   mapping = astAnnul( mapping );

/* Return. */
   return result;

}

static void Labels( AstPlot *this, TickInfo **grid, AstPlotCurveData **cdata,
                    double *gap, double *labelat, const char *method,
                    const char *class, int *status ){
/*
*
*  Name:
*     Labels

*  Purpose:
*     Draw numerical axis labels for a 2-D annotated coordinate grid.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     void Labels( AstPlot *this, TickInfo **grid, AstPlotCurveData **cdata,
*                  double *gap, double *labelat, const char *method,
*                  const char *class, int *status )

*  Class Membership:
*     Plot member function.

*  Description:
*     The policy for placing labels for the major tick values is broadly as
*     follows: if possible, labels for a given physical axis are placed on
*     one edge of the plotting area, at the place where the curve for a
*     major tick value crosses the edge. If very few of the curves cross
*     the edge, then the label for a curve is placed at the intersection
*     of that curve with the longest of the curves representing the major
*     tick values on the other axis.

*  Parameters:
*     this
*        A pointer to the Plot.
*     grid
*        A pointer to an array of two TickInfo pointers (one for each axis),
*        each pointing to a TickInfo structure holding information about
*        tick values on the axis. See function GridLines.
*     cdata
*        A pointer to an array of two AstPlotCurveData pointers (one for each axis),
*        each pointing to an array of AstPlotCurveData structure (one for each
*        major tick value on the axis), holding information about breaks
*        in the curves drawn to mark the major tick values. See function
*        DrawGrid.
*     gap
*        Pointer to array of two values holding the gap between major
*        tick values on the two axes.
*     labelat
*        A pointer to a 2 element array holding the constant axis
*        values at which tick marks are put. Element 0 should hold
*        the axis 1 value at which tick marks for axis 0 are placed. Element
*        1 should hold the axis 0 value at which tick marks for axis
*        1 are placed. If labels are to be placed round the edges of the
*        plotting zone instead of within the plotting zone, then values of
*        AST__BAD should be supplied.
*     method
*        Pointer to a string holding the name of the calling method.
*        This is only for use in constructing error messages.
*     class
*        Pointer to a string holding the name of the supplied object class.
*        This is only for use in constructing error messages.
*     status
*        Pointer to the inherited status variable.

*  Notes:
*     -  This function assumes the current Frame of the Plot is 2
*     dimensional, and it should not be called if this is not the case.
*/

/* Local Variables: */
   AstFrame *frame;       /* Pointer to current Frame */
   AstMapping *mapping;   /* Pointer to graphics->physical Mapping */
   AstPointSet *pset1;    /* Pointer to PointSet holding physical coords. */
   AstPointSet *pset2;    /* Pointer to PointSet holding graphics coords. */
   LabelList *labellist;  /* Pointer to list of labels to be plotted */
   LabelList *ll;         /* Pointer to next label to be plotted */
   TickInfo *info;        /* Pointer to the TickInfo for the current axis */
   char just_buf[3];      /* Buffer to hold a justification string */
   const char *just;      /* Justification string */
   const char *text;      /* Pointer to label text */
   double *used;          /* Pointer to list of used label values */
   double *value;         /* Current tick value */
   double diff;           /* Difference between adjacent major tick marks */
   double dx;             /* Text base-line X component */
   double dy;             /* Text base-line Y component */
   double gx;             /* Reference position graphics X coord. */
   double gy;             /* Reference position graphics Y coord. */
   double mindim;         /* Shortest dimension of plotting area */
   double offx;           /* X component of offset vector */
   double offy;           /* Y component of offset vector */
   double rlen;           /* Length of perpendicular vector */
   double rx;             /* X comp of vector perpendicular to (dx,dy) */
   double ry;             /* Y comp of vector perpendicular to (dx,dy) */
   double sin45;          /* Sine of 45 degrees */
   double txtgap;         /* Absolute gap between labels and edges */
   double upx;            /* Text up-vector X component */
   double upy;            /* Text up-vector Y component */
   double val[ 2 ];       /* Physical coordinates */
   float *box;            /* Pointer to array of label bounding boxes */
   float alpha;           /* Factor to convert graphics X to equal scaled X */
   float beta;            /* Factor to convert graphics Y to equal scaled Y */
   int axis;              /* Current axis index */
   int esc;               /* Interpret escape sequences? */
   int flag;              /* Flag indicating which way the base-vector points */
   int iused;             /* Index into list of used axis values */
   int logticks;          /* ARe major ticks spaced logarithmically? */
   int nlab;              /* The number of labels to be plotted */
   int nused;             /* Number of used axis values */
   int t0;                /* Index of central tick */
   int tick;              /* Current tick index */
   int tinc;              /* Increment between ticks */
   int upfree;            /* Are we free to change the up-vector? */
   int gelid;             /* ID for next graphical element to be drawn */

/* Check the global status. */
   if( !astOK ) return;

/* See if escape sequences in text strings are to be interpreted */
   esc = astGetEscape( this );

/* Empty the list of bounding boxes kept by the Overlap function. */
   (void) Overlap( this, 0, 0, NULL, 0.0, 0.0, NULL, 0.0, 0.0, NULL,
                   method, class, status );

/* If required, draw the labels around the edges of the plotting area. */
   if( labelat[ 0 ] == AST__BAD || labelat[ 1 ] == AST__BAD ){
      (void) EdgeLabels( this, 1, grid, cdata, 1, method, class, status );

/* Otherwise, draw labels within the interior of the plotting area. */
   } else {

/* Find the scale factors for the two axes which scale graphics coordinates
   into a "standard" equal scaled coordinate system in which: 1) the axes
   have equal scale in terms of (for instance) millimetres per unit distance,
   2) X values increase from left to right, 3) Y values increase from bottom
   to top. */
      GScales( this, &alpha, &beta, method, class, status );

/* Get the minimum dimension of the plotting area in equal scaled coords. */
      mindim = astMIN( fabs( alpha*(this->xhi - this->xlo) ),
                    fabs( beta*(this->yhi - this->ylo) ) );

/* Store a value for the sine of 45 degrees. */
      sin45 = 1.0/sqrt( 2.0 );

/* Initialise the pointer to the memory holding the bounding boxes for
   all labels (used by function Overlap). */
      box = NULL;

/* Get a pointer to the current Frame in the Plot. */
      frame = astGetFrame( this, AST__CURRENT );

/* Get a pointer to the mapping form the base Frame to the current Frame in
   the Plot. */
      mapping = astGetMapping( this, AST__BASE, AST__CURRENT );

/* Initialize the id value for graphical element being drawn. */
      gelid = AST__NUMLAB1_ID;

/* Do each axis. */
      for( axis = 0; axis < 2; axis++ ){

/* See of major ticks are spaced logarithmically on this axis. */
         logticks = astGetLogTicks( this, axis );

/* Establish the correct graphical attributes as defined by attributes
   with the supplied Plot. */
         astGrfAttrs( this, gelid, 1, GRF__TEXT, method, class );

/* Get a pointer to the structure containing information describing the
   positions of the major tick marks along this axis. */
         info = grid[ axis ];

/* Only progress if there are some labels stored within the structure. */
         if( info->labels ) {

/* Initialise the pointer to the list of text strings to be drawn. */
            labellist = NULL;
            nlab = 0;

/* See if numerical labels are always to be drawn horizontal. If so, set
   a flag and initialise a vertical up-vector. */
            if( astGetLabelUp( this, axis ) ){
               upfree = 0;
               upx = 0.0;
               upy = 1.0;

ast/src/plot.c  view on Meta::CPAN

                              (labellist + nlab)->just = (char *) astStore( NULL, (void *) just, strlen(just) + 1 );
                              (labellist + nlab)->upx = upx;
                              (labellist + nlab)->upy = upy;
                              (labellist + nlab)->val = val[ axis ];
                              nlab++;
                           } else {
                              break;
                           }
                        }
                     }
                  }
               }
            }

/* If any labels were stored, draw the text strings, and then release the
   memory used to hold the text, etc. */
            if( nlab > 0 ) {
               PlotLabels( this, esc, frame, axis, labellist, info->fmt, nlab,
                           &box, method, class, status );
               ll = labellist;
               for( tick = 0; tick < nlab; tick ++ ) {
                  ll->text = (char *) astFree( (void *) ll->text );
                  ll->just = (char *) astFree( (void *) ll->just );
                  ll++;
               }
               labellist = (LabelList *) astFree( (void *) labellist );
            }

/* Free the memory used to hold the axis values at which labels have
   been put. */
            used = (double *) astFree( (void *) used );

/* Annul the PointSets (if used). */
            if( pset1 ) pset1 = astAnnul( pset1 );
            if( pset2 ) pset2 = astAnnul( pset2 );

/* Re-establish the original graphical attributes. */
            astGrfAttrs( this, gelid, 0, GRF__TEXT, method, class );

/* Set up the id for the next graphical element to be drawn. */
            gelid = AST__NUMLAB2_ID;

         }
      }

/* Free the memory used to hold the bounding boxes. */
      box = (float *) astFree( (void *) box );

/* Annul the pointers to the Frame and the Mapping. */
      mapping = astAnnul( mapping );
      frame = astAnnul( frame );

   }

/* Return. */
   return;

}

static void LinePlot( AstPlot *this, double xa, double ya, double xb,
                      double yb, int ink, AstPlotCurveData *cdata,
                      const char *method, const char *class, int *status ){
/*
*
*  Name:
*     LinePlot

*  Purpose:
*     Draws a straight line omitting bad regions.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     void LinePlot( AstPlot *this, double xa, double ya, double xb,
*                    double yb, int ink, AstPlotCurveData *cdata,
*                    const char *method, const char *class, int *status )

*  Class Membership:
*     Plot member function.

*  Description:
*     This function draws a straight line between two positions in graphics
*     coordinates but leaves gaps in the line where it passes through
*     regions which have no corresponding physical coordinates.

*  Parameters:
*     this
*        Pointer to the Plot.
*     xa
*        The graphics X coordinate at the start of the line.
*     ya
*        The graphics Y coordinate at the start of the line.
*     xb
*        The graphics X coordinate at the end of the line.
*     yb
*        The graphics Y coordinate at the end of the line.
*     ink
*        If zero, the line is not actually drawn, but information about
*        the breaks is still returned. If non-zero, the line is also drawn.
*     cdata
*        A pointer to a structure in which to return information about the
*        breaks in the line.
*     method
*        Pointer to a string holding the name of the calling method.
*        This is only for use in constructing error messages.
*     class
*        Pointer to a string holding the name of the supplied object class.
*        This is only for use in constructing error messages.
*     status
*        Pointer to the inherited status variable.

*  Notes:
*     -  No curve is draw if any of the start or end positions are bad
*     (i.e. equal to AST__BAD), or if a NULL pointer is supplied for "cdata".
*     No errors are reported in these cases.
*/

/* Local Variables: */
   astDECLARE_GLOBALS      /* Pointer to thread-specific global data */
   double d[ CRV_NPNT ];   /* Offsets to evenly spaced points along curve */
   double x[ CRV_NPNT ];   /* X coords at evenly spaced points along curve */
   double y[ CRV_NPNT ];   /* Y coords at evenly spaced points along curve */
   double tol;             /* Absolute tolerance value */
   int i;                  /* Loop count */

/* Check the global error status. */
   if ( !astOK ) return;

/* Get a pointer to the thread specific global data structure. */
   astGET_GLOBALS(this);

/* Check the supplied values are usable. */
   if( xa == AST__BAD || ya == AST__BAD ||
       xb == AST__BAD || yb == AST__BAD ||
      !cdata ) return;

/* Convert the tolerance from relative to absolute graphics coordinates. */
   tol = astGetTol( this )*astMAX( this->xhi - this->xlo, this->yhi - this->ylo );

/* Ensure the globals holding the scaling from graphics coords to equally
   scaled coords are available. */
   GScales( this, NULL, NULL, method, class, status );

/* Set up the external variables used by the Crv and CrvLine function (see
   their prologues for details). */
   Crv_scerr = ( astGetLogPlot( this, 0 ) ||
                 astGetLogPlot( this, 1 ) ) ? 100.0 : 1.5;
   Crv_ux0 = AST__BAD;
   Crv_limit = 0.5*tol*tol;
   Crv_tol = tol;
   Crv_map = Map2;
   Crv_ink = ink;
   Crv_len = 0.0F;
   Crv_xlo = this->xlo;
   Crv_xhi = this->xhi;
   Crv_ylo = this->ylo;
   Crv_yhi = this->yhi;
   Crv_out = 1;
   Crv_xbrk = cdata->xbrk;
   Crv_ybrk = cdata->ybrk;
   Crv_vxbrk = cdata->vxbrk;
   Crv_vybrk = cdata->vybrk;
   Crv_clip = astGetClip( this ) & 1;

/* Create a set of evenly spaced values between 0.0 and 1.0. These are the
   offsets the edge of the plotting zone at which the mapping is tested. */
   for( i = 0; i < CRV_NPNT; i++ ){
     d[ i ] = ( (double) i)/( (double) CRV_NSEG );
   }

/* Now set up the externals used to communicate with the Map2 function.
   Map2 transforms a set of offsets between zero and one into a set of
   corresponding graphics coordinates, with bad values substituted for any
   offsets which correspond to points outside the domain of the mapping. */

/* The number of axes in the physical coordinate system (i.e. the current
   Frame). */
   Map2_ncoord = astGetNout( this );

/* A pointer to the mapping from graphics world cordinates to physical
   coordinates. */
   Map2_plot = this;
   Map2_map = astGetMapping( this, AST__BASE, AST__CURRENT );

/* The graphics coordinates corresponding to an offset of zero (i.e.
   the start of the line). */
   Map2_x0 = xa;
   Map2_y0 = ya;

/* The increments in X and Y between offset zero (the start of the
   line) and offset 1 (the end of the line). */
   Map2_deltax = xb - xa;
   Map2_deltay = yb - ya;

/* Get the graphics coordinates corresponding to the initial set of
   offsets. */
   Map2( CRV_NPNT, d, x, y, method, class, status GLOBALS_NAME );

/* Use Crv and Map2 to draw the intersection of the straight line with
   the region containing valid physical coordinates. */
   Crv( this, d, x, y, 0, NULL, NULL, method, class, status );

/* End the current poly line. */
   Opoly( this, status );

/* Tidy up the static data used by Map2. */
   Map2( 0, NULL, NULL, NULL, method, class, status GLOBALS_NAME );

/* If no part of the curve could be drawn, set the number of breaks and the
   length of the drawn curve to zero. */
   if( Crv_out ) {
      Crv_nbrk = 0;
      Crv_len = 0.0F;

/* Otherwise, add an extra break to the returned structure at the position of
   the last point to be plotted. */
   } else {
      Crv_nbrk++;
      if( Crv_nbrk > AST__PLOT_CRV_MXBRK ){
         astError( AST__CVBRK, "%s(%s): Number of breaks in curve "
                   "exceeds %d.", status, method, class, AST__PLOT_CRV_MXBRK );
      } else {
         *(Crv_xbrk++) = (float) Crv_xl;
         *(Crv_ybrk++) = (float) Crv_yl;
         *(Crv_vxbrk++) = (float) -Crv_vxl;
         *(Crv_vybrk++) = (float) -Crv_vyl;
      }
   }

/* Store extra information about the curve in the returned structure, and
   purge any zero length sections. */
   if( cdata ){
      cdata->length = Crv_len;
      cdata->out = Crv_out;
      cdata->nbrk = Crv_nbrk;
      PurgeCdata( cdata, status );
   }

/* Annul the Mapping. */
   Map2_map = astAnnul( Map2_map );

/* Return. */
   return;

}

static double **MakeGrid( AstPlot *this, AstFrame *frm, AstMapping *map,
                          int disk, int dim, double xlo, double xhi,
                          double ylo, double yhi, int nphy, AstPointSet **pset1,
                          AstPointSet **pset2, int norm, const char *method,
                          const char *class, int *status ){
/*
*  Name:
*     MakeGrid

*  Purpose:
*     Create a square grid of graphics coordinates and the corresponding
*     physical coordinates.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     double **MakeGrid( AstPlot *this, AstFrame *frm, AstMapping *map,
*                        int disk, int dim, double xlo, double xhi, double ylo,
*                        double yhi, int nphy, AstPointSet **pset1,
*                        AstPointSet **pset2, int norm, const char *method,
*                        const char *class, int *status ){

*  Class Membership:
*     Plot member function.

*  Description:
*     This function creates two PointSets, one holding a square grid of
*     graphics coordinates covering the supplied area, and the other
*     holding the corresponding physical coordinates. The points are
*     stored row by row in the returned PointSets, i.e. if the cell size
*     for the grid is (dx,dy), the first point is (xmin,ymin), followed
*     by (xmin+dx,ymin), (xmin+2*dx,ymin), up to (xmin+(dim-1)*dx,ymin),
*     followed by the next row (xmin,ymin+dy), (xmin+dx,ymin+dy), etc.

*  Parameters:
*     this
*        The Plot.
*     frm
*        A pointer to the Current Frame in the Plot. If this is supplied
*        NULL, then a pointer is found within this function if required (i.e.
*        if "norm" is non-zero).
*     map
*        The Mapping from graphics to physical coordinates, extracted from
*        the Plot.
*     disk
*        If non-zero, the corners of the grid are omitted form the
*        returned PointSets, resulting in a grid that is more disk like than
*        rectangular.

ast/src/plot.c  view on Meta::CPAN


*  Parameters:
*     this
*        Pointer to the Plot.
*     rise
*        Pointer to a location at which to return thhe height of the baseline
*        above the normal baseline, expressed as a percentage of the normal
*        character height.
*     method
*        Pointer to a string holding the name of the calling method.
*        This is only for use in constructing error messages.
*     class
*        Pointer to a string holding the name of the supplied object class.
*        This is only for use in constructing error messages.
*     status
*        Pointer to the inherited status variable.

*  Returned Value:
*     Returns zero if the stack is empty, and 1 otherwise.

*/

/* Local Variables: */
   AstGat *gat;
   int result;

/* Initialise */
   result = 0;

/* Check inherited status */
   if( !astOK ) return result;

/* Check there is at least one AstGat structure on the stack. */
   if( this->ngat ) {

/* Decrement the number of entries in the stack, and get a pointer to the
   AstGat structure. Nullify the pointer on the stack. */
      gat = (this->gat)[ --(this->ngat) ];
      (this->gat)[ this->ngat ] = NULL;

/* Restore the values in the AstGat structure */
      *rise = gat->rise;
      GAttr( this, GRF__SIZE, gat->size, NULL, GRF__TEXT, method, class, status );
      GAttr( this, GRF__WIDTH, gat->width, NULL, GRF__TEXT, method, class, status );
      GAttr( this, GRF__COLOUR, gat->col, NULL, GRF__TEXT, method, class, status );
      GAttr( this, GRF__FONT, gat->font, NULL, GRF__TEXT, method, class, status );
      GAttr( this, GRF__STYLE, gat->style, NULL, GRF__TEXT, method, class, status );

/* Free the AstGat structure. */
      gat = astFree( gat );

/* Indicate success.*/
      result = 1;
   }

/* Return the result. */
   return result;

}

static void PurgeCdata( AstPlotCurveData *cdata, int *status ){
/*
*
*  Name:
*     AstPlotCurveData

*  Purpose:
*     Remove any zero length sections from the description of a curve.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     void PurgeCdata( AstPlotCurveData *cdata )

*  Class Membership:
*     Plot member function.

*  Description:
*     This function removes any zero length sections from the supplied
*     AstPlotCurveData struture, which describes a multi-section curve.

*  Parameters:
*     cdata
*        A pointer to the structure containing information about the
*        breaks in a curve.

*/

/* Local Variables: */
   int brk;                       /*Break index */
   int i;                       /*Break index */

/* Check the global error status. */
   if ( !astOK || !cdata ) return;

/* Loop round all breaks. */
   brk = 0;
   while( brk < cdata->nbrk ) {

/* If this break and the next one are co-incident, remove both breaks. */
      if( cdata->xbrk[ brk ] == cdata->xbrk[ brk + 1 ] &&
          cdata->ybrk[ brk ] == cdata->ybrk[ brk + 1 ] ) {

/* Shuffle down the higher elements of all the arrays in the curve data. */
         for( i = brk + 2; i < cdata->nbrk; i++ ){
            cdata->xbrk[ i - 2 ] = cdata->xbrk[ i ];
            cdata->ybrk[ i - 2 ] = cdata->ybrk[ i ];
            cdata->vxbrk[ i - 2 ] = cdata->vxbrk[ i ];
            cdata->vybrk[ i - 2 ] = cdata->vybrk[ i ];
         }

/*  Decrement the number of breaks in the curve data. */
         cdata->nbrk -= 2;

/* If the section is not zero length, move on to the next pair of breaks. */
      } else {
         brk += 2;
      }
   }
}

static void PushGat( AstPlot *this, float rise, const char *method,
                     const char *class, int *status ) {
/*
*  Name:
*     PushGat

*  Purpose:
*     Push current graphical attributes for text onto a stack.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     void PushGat( AstPlot *this, float rise, const char *method,
*                   const char *class, int *status )

*  Class Membership:
*     Plot member function.

*  Description:
*     This function stores the current graphical attributes for text
*     on a stack.

*  Parameters:
*     this
*        Pointer to the Plot.
*     rise
*        The height of the baseline above the normal baseline, expressed
*        as a percentage of the normal character height.
*     method
*        Pointer to a string holding the name of the calling method.
*        This is only for use in constructing error messages.
*     class
*        Pointer to a string holding the name of the supplied object class.
*        This is only for use in constructing error messages.
*     status
*        Pointer to the inherited status variable.

*/

/* Local Variables: */
   AstGat *new_gat;

/* Check inherited status */
   if( !astOK ) return;

/* Allocate memory for a new AstGat structure to store the graphical
   attributes. */
   new_gat = astMalloc( sizeof( AstGat ) );
   if( astOK ) {

ast/src/plot.c  view on Meta::CPAN


/* Local Variables: */
   astDECLARE_GLOBALS
   const char *a;
   char *b;
   int nc;
   int ncc;
   int type;
   int value;
   const char *result;

/* Initialise */
   result= text;

/* Get a pointer to the thread specific global data structure. */
   astGET_GLOBALS(NULL);

/* Check inherited status and supplied pointer. Also return if the
   string contains no escape sequences or if stripping of escapes has
   been supressed. */
   if( !astOK || astEscapes( -1 ) || !text || !HasEscapes( text, status ) ) return result;

/* Initialise a pointer to the next character to be read from the
   supplied string. */
   a = text;

/* Initialise a pointer to the next character to be written to the
   returned string. */
   b = stripescapes_buff;

/* Note the available space left in the buffer. */
   ncc = AST__PLOT_STRIPESCAPES_BUFF_LEN;

/* Loop until all the string has been read, or the buffer is full. */
   while( *a && ncc > 0 ){

/* If the remaining string starts with an escape sequence, increment the
   read point by the length of the escape sequence, but leave the write
   pointer where it is. */
      if( astFindEscape( a, &type, &value, &nc ) ) {
         a += nc;

/* If the remaining string does not start with an escape sequence, copy
   the following text from the read position to the write position. */
      } else {
         if( nc > ncc ) nc = ncc;
         memcpy( b, a, sizeof( char )*nc );
         a += nc;
         b += nc;
         ncc -= nc;
      }
   }

/* Terminate the returned string. */
   *b = 0;

/* Return the result.*/
   return stripescapes_buff;
}

static int swapEdges( AstPlot *this, TickInfo **grid, AstPlotCurveData **cdata, int *status ) {
/*
*  Name:
*     swapEdges

*  Purpose:
*     Determine if edges for text labels should be swapped.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     int swapEdges( AstPlot *this, TickInfo **grid, AstPlotCurveData **cdata, int *status )

*  Class Membership:
*     Plot member function.

*  Description:
*     This function returns a boolean result (0 or 1) to indicate whether
*     or not it is necessary to swap the Edges(0) and Edges(1) attributes
*     in order to place textual labels on appropriate edges. This should
*     only be used if the attributes have not explicitly been set, and if
*     interior labelling is being used. The sides are determines by
*     looking at the bounding box of tick marks on axis 0, in graphics
*     coordinates. The returned value causes the label for axis 0 to be
*     placed on the edge parallel to the longest side of this bounding box.
*     The label for axis 1 is placed parallel to the shortest side of this
*     bounding box.

*  Parameters:
*     this
*        A pointer to the Plot.
*     grid
*        A pointer to an array of two TickInfo pointers (one for each axis),
*        each pointing to a TickInfo structure holding information about
*        tick marks on the axis. See function GridLines.
*     cdata
*        A pointer to an array of two AstPlotCurveData pointers (one for each axis),
*        each pointing to an array of AstPlotCurveData structure (one for each
*        major tick value on the axis), holding information about breaks
*        in the curves drawn to mark the major tick values. See function
*        DrawGrid.
*     status
*        Pointer to the inherited status variable.

*  Returned Value:
*     One if the edges should be swapped, otherwise zero.

*  Notes:
*     - A value of zero will be returned if this function is invoked
*     with the global status set, or if it should fail for any reason.
*/

/* Local Variables: */
   AstPlotCurveData *cdt; /* Pointer to the AstPlotCurveData for the next tick */
   TickInfo *info;        /* Pointer to the TickInfo for the current axis */
   float xmax;            /* Max graphics X value */
   float xmin;            /* Min graphics X value */
   float ymax;            /* Max graphics Y value */
   float ymin;            /* Min graphics Y value */
   int oldedge;           /* The original edge for axis 0 */
   int result;            /* Swap edges? */
   int tick;              /* Tick index */

/* Initialise. */
   result = 0;

/* Check the global error status. */
   if ( !astOK ) return result;

/* Get a pointer to the structure containing information describing the
   positions of the major tick marks along axis 0. */
   info = grid[ 0 ];

/* Get a pointer to the structure containing information describing
   the breaks in the curve which is parallel to axis 1 and passes
   through the first major tick mark on axis 0. */
   cdt = cdata[ 0 ];

/* Initialise the graphiocs X and Y bounds of the area covered by the
   axis. */
   xmax = -1.0E10;
   xmin = 1.0E10;
   ymax = -1.0E10;
   ymin = 1.0E10;

/* Loop round each of the major tick marks on axis 0. */
   for( tick = 0; cdt && info && tick < info->nmajor; tick++ ){

/* Update the max and min graphics X and Y coords covered by the axis. */
      if( cdt->nbrk > 0 ) {
         xmax = astMAX( xmax, cdt->xbrk[0] );
         xmin = astMIN( xmin, cdt->xbrk[0] );
         ymax = astMAX( ymax, cdt->ybrk[0] );
         ymin = astMIN( ymin, cdt->ybrk[0] );
      }

/* Get a pointer to the curve through the next major tick mark. */
      cdt++;

   }

/* See which edge axis 0 would normally be labelled on. */
   oldedge = astGetEdge( this, 0 );

/* If the X range is larger than the Y range, the textual label should be
   placed on the bottom edge. If required, indicate that the edges must
   be swapped to achieve this. */
   if( xmax - xmin > ymax - ymin ) {
      if( oldedge == 0 || oldedge == 2 ) result = 1;

/* If the X range is smaller  than the Y range, the textual label should be
   placed on the left edge. If required, indicate that the edges must
   be swapped to achieve this. */
   } else {
      if( oldedge == 1 || oldedge == 3 ) result = 1;
   }

   return result;
}

static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) {
/*
*  Name:
*     TestAttrib

*  Purpose:
*     Test if a specified attribute value is set for a Plot.

*  Type:
*     Private function.

*  Synopsis:
*     #include "plot.h"
*     int TestAttrib( AstObject *this, const char *attrib, int *status )

*  Class Membership:
*     Plot member function (over-rides the astTestAttrib protected



( run in 0.484 second using v1.01-cache-2.11-cpan-d8267643d1d )