Logo Search packages:      
Sourcecode: saoimage version File versions

csrshape.c

#ifndef lint
static char SccsId[] = "%W%  %G%";
#endif

/* Module:  csrshape.c (Cursor Shape)
 * Purpose: Make basic software cursors
 * Subroutine:    make_cursor()                 returns: void
 * Subroutine:    change_circle_granularity()   returns: void
 * Copyright:     1989, 1991, 1996 Smithsonian Astrophysical Observatory
 *          You may do anything you like with this file except remove
 *          this copyright.  The Smithsonian Astrophysical Observatory
 *          makes no representations about the suitability of this
 *          software for any purpose.  It is provided "as is" without
 *          express or implied warranty.
 * Modified:      {0} Michael VanHilst    initial version            9 May 1989
 *          {1} MVH added arrow cursor                   1 Jan 1991
 *          {2} Doug Mink added pie cursor                    10 Oct 1996
 *          {3} Doug Mink added WCS sizing                    25 Oct 1996
 *          {n} <who> -- <does what> -- <when>
 */

#include <stdio.h>            /*  stderr, NULL, etc.  */
#include <X11/Xlib.h>         /*  X window stuff  */
#include <X11/Xutil.h>        /*  X window manager stuff  */
#include <math.h>       /*  sin, cos, etc */
#include "hfiles/constant.h"  /*  Define codes  */
#include "hfiles/coord.h"
#include "hfiles/color.h"     /*  Cursor colors needed by Cursor.h  */
#include "hfiles/cursor.h"    /*  Cursor structure */
#include "hfiles/wcs.h"       /*  World coordinate system structure */

#include "defs/circle.def"    /*  Define Unit_circles  */

#ifdef ANSIC
/*  Exported declarations must be centralized before ANSI C can be used  */

void        make_cursor(      struct cursorRec *cursor);
static int  make_arrow( double xtip, double ytip, double xray,
                        double rotsin, double rotcos, XPoint *points);
static int  make_boxcur(      double xcen, double ycen,
                        double xray, double yray,
                        double rotsin, double rotcos, XPoint *points);
static int  make_circur(      double xcen, double ycen, double radius,
                        XPoint *points )
static int  make_sqrcur(      double xcen, double ycen, double radius,
                        XPoint *points )
static int  make_diacur(      double xcen, double ycen, double radius,
                        XPoint *points )
static int  make_crosscur(    double xcen, double ycen, double radius,
                        XPoint *points )
static int  make_excur( double xcen, double ycen, double radius,
                        XPoint *points )
static int  make_ellipse(     double xcen, double ycen,
                        double xradius, double yradius,
                        double rotsin, double rotcos, XPoint *points);
static int  make_piecur(      double xcen, double ycen, double radius,
                        XPoint *points )

#else

  static int make_arrow(), make_boxcur(), make_circur();
  static int make_ellipse(), make_piecur();

#endif


/*  Declare and initialize drawing tools  */
double *UnitPieX = Circle12X;
double *UnitPieY = Circle12Y;
double *UnitCircleX = Circle48X;
double *UnitCircleY = Circle48Y;
double *UnitEllipseX = Circle64X;
double *UnitEllipseY = Circle64Y;
int CircleCnt = 48;
int PieCnt = 36;
int EllipseCnt = 64;
int SquareCnt = 5;
int CrossCnt = 7;

/*  Specify size and shape of arrow head (in pixels, regardless of zoom)  */
int ArrowHeadLength = 8;
int ArrowHeadWidth = 5;


/*  Subroutine    make_cursor
 *  Purpose:      Remake the current cursor polygon list
 */
#ifdef ANSIC
void
make_cursor ( struct cursorRec *cursor )
#else
void
make_cursor ( cursor )
     struct cursorRec *cursor;
#endif
{

  switch( cursor->type ) {
  case COP_Circle:
    cursor->point_cnt = make_circur (cursor->win.X, cursor->win.Y,
                             cursor->win.rayX, cursor->points);
    break;
  case COP_PieSlice:
    cursor->point_cnt = make_piecur (cursor->win.X, cursor->win.Y,
                             cursor->win.rayX, cursor->points);
    break;
  case COP_Ellipse:
    cursor->point_cnt = make_ellipse(cursor->win.X, cursor->win.Y,
                             cursor->win.rayX, cursor->win.rayY,
                             cursor->rot.sin, cursor->rot.cos,
                             cursor->points);
    break;
  case COP_Box:
    cursor->point_cnt = make_boxcur(cursor->win.X, cursor->win.Y,
                            cursor->win.rayX, cursor->win.rayY,
                            cursor->rot.sin, cursor->rot.cos,
                            cursor->points);
    break;
  case COP_Arrow:
    cursor->point_cnt = make_arrow(cursor->win.X, cursor->win.Y,
                           cursor->win.rayX, cursor->rot.sin,
                           cursor->rot.cos, cursor->points);
    break;
  case COP_Point:
    cursor->point_cnt = 0;
    break;
  case COP_Square:
    cursor->point_cnt = make_sqrcur (cursor->win.X, cursor->win.Y,
                             cursor->win.rayX, cursor->points);
    break;
  case COP_Diamond:
    cursor->point_cnt = make_diacur (cursor->win.X, cursor->win.Y,
                             cursor->win.rayX, cursor->points);
    break;
  case COP_Cross:
    cursor->point_cnt = make_crosscur (cursor->win.X, cursor->win.Y,
                               cursor->win.rayX, cursor->points);
    break;
  case COP_Ex:
    cursor->point_cnt = make_excur (cursor->win.X, cursor->win.Y,
                            cursor->win.rayX, cursor->points);
    break;
  case COP_Polygon:
  default:
    break;
  }
}


/*  Subroutine:   make_arrow
 *  Purpose:      Given tip and tail, make line including arrow head
 *  Returns:      Number of points needed to draw arrow
 */
#ifdef ANSIC
static int
make_arrow ( double xtip, double ytip, double xray,
                    double rotsin, double rotcos, XPoint *points )
#else
static int
make_arrow ( xtip, ytip, xray, rotsin, rotcos, points )
     double xtip, ytip;       /*  Coords of tip  */
     double xray;       /*  Length of shaft  */
     double rotsin, rotcos;   /*  Trig values for angle  */
     XPoint *points;
#endif
{
  double head_xcos, head_ycos, head_xsin, head_ysin;

  /*  Compute offset_from_tip partials to draw arrow head  */
  head_xcos = ArrowHeadWidth * rotcos;
  head_ycos = ArrowHeadLength * rotcos;
  head_xsin = ArrowHeadWidth * rotsin;
  head_ysin = ArrowHeadLength * rotsin;
  /*  Line drawn as 3 segments, all starting at tip  */
  /*  Statements with like factors grouped to help compiler optimization */
  points[5].x = xtip - (xray * rotsin);
  points[5].y = ytip + (xray * rotcos);
  points[1].x = xtip + (head_xcos - head_ysin);
  points[1].y = ytip + (head_xsin + head_ycos);
  points[3].x = xtip - (head_xcos + head_ysin);
  points[3].y = ytip - (head_xsin - head_ycos);
  points[0].x = xtip;
  points[0].y = ytip;
  points[2].x = xtip;
  points[2].y = ytip;
  points[4].x = xtip;
  points[4].y = ytip;
  return( -3 );
}


/*  Subroutine:   make_boxcur
 *  Purpose:      Set the corner coordinates for the rotating box cursor
 *  Returns:      Number of points needed to draw box
 */
#ifdef ANSIC
static int
make_boxcur ( double xcen, double ycen, double xray, double yray,
                   double rotsin, double rotcos, XPoint *points )
#else
static int
make_boxcur ( xcen, ycen, xray, yray, rotsin, rotcos, points )
     double xcen, ycen;
     double xray, yray;
     double rotsin, rotcos;
     XPoint *points;
#endif
{
  double x1, y1, x2, y2;

  /*  Calculate offset of two corners on the right  */
  x1 = (xray * rotcos) - (yray * rotsin);
  y1 = (xray * rotsin) + (yray * rotcos);
  x2 = (xray * rotcos) + (yray * rotsin);
  y2 = (xray * rotsin) - (yray * rotcos);
  /*  Define box corners  */
  points[0].x = xcen + x1;
  points[0].y = ycen + y1;
  points[1].x = xcen + x2;
  points[1].y = ycen + y2;
  points[2].x = xcen - x1;
  points[2].y = ycen - y1;
  points[3].x = xcen - x2;
  points[3].y = ycen - y2;
  points[4].x = xcen + x1;
  points[4].y = ycen + y1;
  return( 5 );
}


/*  Subroutine:   make_circur
 *  Purpose:      Create a new circle cursor with given center and radius
 *  Returns:      Number of points needed to draw circle
 */
#ifdef ANSIC
static int
make_circur ( double xcen, double ycen, double radius, XPoint *points )
#else
static int
make_circur ( xcen, ycen, radius, points )
     double xcen, ycen, radius;
     XPoint *points;
#endif
{
  int loop;
  register int i, xoff, yoff;
  register int a1, a2, a3, b1, b2, b3, b4;

  /*  Set up array indexes for 8 fold symetry  */
  /*  8 indexes radiating both ways from each of the four axes  */
  a1 = CircleCnt / 4;         /*  (1 * cnt) / 4  */
  a2 = a1 + a1;               /*  (2 * cnt) / 4  */
  a3 = a2 + a1;               /*  (3 * cnt) / 4  */
  b1 = a1 - 1;
  b2 = a2 - 1;
  b3 = a3 - 1;
  b4 = a3 + a1 - 1;           /*  (4 * cnt) / 4 - 1  */

  /*  Calculate points on circumference for 1/8th of circle  */
  /*  Apply to each of 8 pairs  */
  loop = CircleCnt / 8;
  for( i=0; i <= loop; i++ ) {
    xoff = UnitCircleX[i] * radius;
    yoff = UnitCircleY[i] * radius;
    points[i].x = xcen + xoff;
    points[i].y = ycen + yoff;
    points[a1+i].x = xcen + yoff;
    points[a1+i].y = ycen - xoff;
    points[a2+i].x = xcen - xoff;
    points[a2+i].y = ycen - yoff;
    points[a3+i].x = xcen - yoff;
    points[a3+i].y = ycen + xoff;
    points[b1-i].x = xcen + yoff;
    points[b1-i].y = ycen + xoff;
    points[b2-i].x = xcen + xoff;
    points[b2-i].y = ycen - yoff;
    points[b3-i].x = xcen - yoff;
    points[b3-i].y = ycen - xoff;
    points[b4-i].x = xcen - xoff;
    points[b4-i].y = ycen + yoff;
  }

  /*  Close the circle (end point same as starting point)  */
  points[CircleCnt].x = points[0].x;
  points[CircleCnt].y = points[0].y;
  return( CircleCnt + 1 );
}


/*  Subroutine:   make_sqrcur
 *  Purpose:      Create a new square cursor with given center and half-width
 *  Returns:      Number of points needed to draw square
 */
#ifdef ANSIC
static int
make_sqrcur ( double xcen, double ycen, double radius, XPoint *points )
#else
static int
make_sqrcur ( xcen, ycen, radius, points )
     double xcen, ycen, radius;
     XPoint *points;
#endif
{
  int loop;
  register int xoff, yoff;

  xoff = radius;
  yoff = radius;
  points[0].x = xcen + xoff;
  points[0].y = ycen + yoff;
  points[1].x = xcen + xoff;
  points[1].y = ycen - yoff;
  points[2].x = xcen - xoff;
  points[2].y = ycen - yoff;
  points[3].x = xcen - xoff;
  points[3].y = ycen + yoff;

  /*  Close the square (end point same as starting point)  */
  points[4].x = xcen + xoff;
  points[4].y = ycen + yoff;

  return (5);
}


/*  Subroutine:   make_diacur
 *  Purpose:      Create a new diamond cursor with given center and half-width
 *  Returns:      Number of points needed to draw diamond
 */
#ifdef ANSIC
static int
make_diacur ( double xcen, double ycen, double radius, XPoint *points )
#else
static int
make_diacur ( xcen, ycen, radius, points )
     double xcen, ycen, radius;
     XPoint *points;
#endif
{
  int loop;
  register int xoff, yoff;

  xoff = radius;
  yoff = radius;
  points[0].x = xcen;
  points[0].y = ycen + yoff;
  points[1].x = xcen + xoff;
  points[1].y = ycen;
  points[2].x = xcen;
  points[2].y = ycen - yoff;
  points[3].x = xcen - xoff;
  points[3].y = ycen;

  /*  Close the diamond (end point same as starting point)  */
  points[4].x = xcen;
  points[4].y = ycen + yoff;

  return (5);
}


/*  Subroutine:   make_crosscur
 *  Purpose:      Create a new cross cursor with given center and half-width
 *  Returns:      Number of points needed to draw cross
 */
#ifdef ANSIC
static int
make_crosscur ( double xcen, double ycen, double radius, XPoint *points )
#else
static int
make_crosscur ( xcen, ycen, radius, points )
     double xcen, ycen, radius;
     XPoint *points;
#endif
{
  int loop;
  register int xoff, yoff;

  xoff = radius;
  yoff = radius;
  points[0].x = xcen;
  points[0].y = ycen + yoff;
  points[1].x = xcen;
  points[1].y = ycen;
  points[2].x = xcen + xoff;
  points[2].y = ycen;
  points[3].x = xcen;
  points[3].y = ycen;
  points[4].x = xcen;
  points[4].y = ycen - yoff;
  points[5].x = xcen;
  points[5].y = ycen;
  points[6].x = xcen - xoff;
  points[6].y = ycen;

  return (7);
}


/*  Subroutine:   make_excur
 *  Purpose:      Create a new X cursor with given center and half-width
 *  Returns:      Number of points needed to draw X
 */
#ifdef ANSIC
static int
make_excur ( double xcen, double ycen, double radius, XPoint *points )
#else
static int
make_excur ( xcen, ycen, radius, points )
     double xcen, ycen, radius;
     XPoint *points;
#endif
{
  int loop;
  register int xoff, yoff;

  xoff = radius;
  yoff = radius;
  points[0].x = xcen + xoff;
  points[0].y = ycen + yoff;
  points[1].x = xcen;
  points[1].y = ycen;
  points[2].x = xcen + xoff;
  points[2].y = ycen - yoff;
  points[3].x = xcen;
  points[3].y = ycen;
  points[4].x = xcen - xoff;
  points[4].y = ycen - yoff;
  points[5].x = xcen;
  points[5].y = ycen;
  points[6].x = xcen - xoff;
  points[6].y = ycen + yoff;

  return (7);
}


/*  Subroutine:   make_piecur
 *  Purpose:      Create a new pie cursor with given center and radius
 *  Returns:      Number of points needed to draw circle
 */
#ifdef ANSIC
static int make_piecur ( double xcen, double ycen, double radius,
                   XPoint *points )
#else
static int make_piecur ( xcen, ycen, radius, points )
     double xcen, ycen, radius;
     XPoint *points;
#endif
{
  int loop;
  register int i, j, xoff, yoff, xoff1, yoff1, nskip;
  register int a0, a1, a2, a3, b1, b2, b3, b4;

  /* Draw 12 radial lines (every 30 degrees) */
  nskip = 3;
  loop = PieCnt;
  j = 0;
  for ( i = 0; i < loop; i = i + nskip ) {
    xoff = UnitPieX[j] * radius;
    yoff = UnitPieY[j] * radius;
    xoff1 = UnitPieX[j] * radius * 0.5;
    yoff1 = UnitPieY[j] * radius * 0.5;
    points[i].x = xcen + xoff;
    points[i].y = ycen + yoff;
    points[i+1].x = xcen + xoff1;
    points[i+1].y = ycen + yoff1;
    points[i+2].x = xcen + xoff;
    points[i+2].y = ycen + yoff;
    j++;
    }
  points[PieCnt].x = points[0].x;
  points[PieCnt].y = points[0].y;

  return( PieCnt+1 );
}


/*  Subroutine:   make_ellipse
 *  Purpose:      Create an ellipticle cursor with given center and radii
 *  Returns:      Number of points needed to draw ellipse
 */
#ifdef ANSIC
static int make_ellipse ( double xcen, double ycen,
                    double xradius, double yradius,
                    double rotsin, double rotcos, XPoint *points )
#else
static int make_ellipse ( xcen, ycen, xradius, yradius,
                    rotsin, rotcos, points )
     double xcen, ycen;
     double xradius, yradius;
     double rotsin, rotcos;
     XPoint *points;
#endif
{
  int loop;
  float xoff, yoff;
  register int i;
  register int x1, x2, y1, y2;
  register int a2, b1, b3;

  /*  Set up array indexes for 8 fold symetry  */
  /*  4 indexes radiating both ways from each of the two axis rays  */
  a2 = EllipseCnt / 2;
  b1 = a2 - 1;
  b3 = EllipseCnt - 1;
  /*  Recalculate points on circumference  */
  /*  Apply to each of 4 pairs  */
  loop = EllipseCnt / 4; 
  for( i=0; i < loop; i++ ) {
    /*  Calculate ray lengths for orthogonal case  */
    xoff = UnitEllipseX[i] * xradius;
    yoff = UnitEllipseY[i] * yradius;
    /*  Calculate offset of two points on the right (rotate)  */
    x2 = (xoff * rotcos) + (yoff * rotsin);
    y2 = (xoff * rotsin) - (yoff * rotcos);
    x1 = (xoff * rotcos) - (yoff * rotsin);
    y1 = (xoff * rotsin) + (yoff * rotcos);
    points[i].x = xcen + x1;
    points[i].y = ycen + y1;
    points[a2+i].x = xcen - x1;
    points[a2+i].y = ycen - y1;
    points[b1-i].x = xcen + x2;
    points[b1-i].y = ycen + y2;
    points[b3-i].x = xcen - x2;
    points[b3-i].y = ycen - y2;
  }
  /*  Close the circle (end point same as starting point)  */
  points[EllipseCnt].x = points[0].x;
  points[EllipseCnt].y = points[0].y;
  return( EllipseCnt + 1 );
}


#ifdef NOTNEEDED /* %% not yet needed */
/*  Subroutine:   change_circle_granularity
 *  Purpose:      Change number of points used to draw circles and ellipses
 */
void change_circle_granularity ( cursor, size, type )
     struct cursorRec *cursor;
     int size;                /* i: exact size (48, 64, or 80 */
     int type;                /* i: code either COP_Circle or COP_Ellipse */
{
  double *X, *Y;
  switch( size ) {
  case 48:
    X = Circle48X;
    Y = Circle48Y;
    break;
  case 64:
    X = Circle64X;
    Y = Circle64Y;
    break;
  case 80:
    X = Circle80X;
    Y = Circle80Y;
    break;
  default:
    (void)fprintf(stderr, "WARNING: Circle choices are 48, 64, or 80!\n");
    return;
  }
  if( type == COP_Circle ) {
    UnitCircleX = X;
    UnitCircleY = Y;
    CircleCnt = size;
  } else if( type = COP_Ellipse ) {
    UnitEllipseX = X;
    UnitEllipseY = Y;
    EllipseCnt = size;
  } else
    return;
  if( cursor->type == type ) {
    make_cursor (cursor);
  }
}
#endif

Generated by  Doxygen 1.6.0   Back to index