File: rgndrop.c

package info (click to toggle)
saoimage 1.35.1-3
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 4,188 kB
  • ctags: 4,403
  • sloc: ansic: 52,848; makefile: 243; sh: 31
file content (203 lines) | stat: -rw-r--r-- 5,949 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#ifndef lint
static char SccsId[] = "%W%  %G%";
#endif

/* Module:	rgndrop.c (Region Drop)
 * Purpose:	Select and remove a region no longer wanted
 * Subroutine:	unsave_region()			returns: void
 * Subroutine:	region_indicated_by_pointer()	returns: struct cursorRec *
 * Copyright:	1989 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		27 June 1989
 *		{n} <who> -- <does what> -- <when>
 */

#include <stdio.h>		/* stderr, NULL, etc. */
#include <math.h>		/* declare sqrt */
#include <X11/Xlib.h>		/* X window stuff */
#include <X11/Xutil.h>		/* X window manager stuff */
#include "hfiles/constant.h"	/* define codes */
#include "hfiles/color.h"	/* cursor colors needed by Cursor.h */
#include "hfiles/cursor.h"	/* define cursor parameter structures */
#include "hfiles/define.h"	/* define SQR, SMALL_NUMBER */

extern struct cursorRec *cycle_region;

/*
 * Subroutine:	unsave_region
 * Purpose:	Remove and discard region from region list
 */
void unsave_region ( cursor, dead_meat )
     struct cursorRec *cursor;		/* i: main cursor record */
     struct cursorRec *dead_meat;	/* i: ptr to region being deleted */
{
  struct cursorRec *region;
  void free_cursor();

  if( (cursor->next_region == NULL) || (dead_meat == NULL) )
    return;
  region = cursor;
  while( region->next_region != dead_meat ) {
    region = region->next_region;
    region->index--;
  }
  region->next_region = dead_meat->next_region;
  /* if deleting region pointed at by cycle region, change cycle region */
  if( cycle_region == dead_meat )
    cycle_region = region;
  /* free deleted region and any annuli it might have */
  do {
    region = dead_meat->next_annulus;
    free_cursor (dead_meat);
    dead_meat = region;
  } while( dead_meat != NULL );
}

/*
 * Subroutine:	region_indicated_by_pointer
 * Purpose:	Identify which region if any is indicated by the pointer
 * Method:	Chooses smallest region which encloses pointer.  (Point
 *		cursors enclose one or two digit label but have 0 area).
 *		In case of equal areas (i.e. points), closer center is used.
 */
struct cursorRec *region_indicated_by_pointer ( cursor, x, y, point_only )
     struct cursorRec *cursor;
     int x, y;
     int point_only;
{
  struct cursorRec *region, *chosen;
  static int pointer_is_inside_region();
  static int closer_to_center();

  chosen = NULL;
  region = cursor->next_region;
  /* erase smallest region which encloses the mouse */
  while( region != NULL ) {
    if( !point_only || region->type == COP_Point ) {
      if( pointer_is_inside_region(x, y, region) ) {
	if( (chosen == NULL) || (region->file.area < chosen->file.area) ) {
	  chosen = region;
	} else if( (region->file.area == chosen->file.area) &&
		   closer_to_center(region, chosen, x, y) )
	  /* compare distance from center */
	  chosen = region;
      }
    }
    region = region->next_region;
  }
  return( chosen );
}

/*
 * Subroutine:	closer_to_center
 */
static int closer_to_center ( challenger, champ, x, y )
     struct cursorRec *challenger, *champ;
     int x, y;
{
  double X, Y, Xn, Yn;

  X = (double)x + 0.5 - champ->win.X;
  Y = (double)y + 0.5 - champ->win.Y;
  Xn = (double)x + 0.5 - challenger->win.X;
  Yn = (double)y + 0.5 - challenger->win.Y;
  if( (SQR(Xn) + SQR(Yn)) > (SQR(X) + SQR(Y)) )
    return( 1 );
  else
    return( 0 );
}

/*
 * Subroutine:	is_inside_region
 * Purpose:	Determine if mouse is within a region
 */
static int pointer_is_inside_region ( x, y, region )
     int x, y;
     struct cursorRec *region;
{
  double rayX, rayY, ray;
  int inside;
  static int pointer_is_inside_polygon();

  if( region->type == COP_Polygon )
    return( pointer_is_inside_polygon((double)x, (double)y,
				      region->poly, region->poly_cnt) );
  rayX = (double)x + 0.5 - region->win.X;
  rayY = (double)y + 0.5 - region->win.Y;
  inside = 0;
  switch( region->type ) {
  case COP_Circle:
    if( (SQR(rayX) + SQR(rayY)) <
        (region->win.rayX * region->win.rayY) )
      inside = 1;
    break;
  case COP_Box:
    if( region->rot.angle != 0.0 ) {
      /* rotate mouse coords into the rotated space */
      ray = (rayX * region->rot.cos) + (rayY * region->rot.sin);
      rayY = (rayY * region->rot.cos) - (rayX * region->rot.sin);
      rayX = ray;
    }
    if( (rayX < region->win.rayX) && (rayX > -region->win.rayX) &&
        (rayY < region->win.rayY) && (rayY > -region->win.rayY) )
      inside = 1;
    break;
  case COP_Point:
    /* cursor is over point index marker (one or two 6x13 characters) */
    if( (rayX >= -2) && (rayX <= 6) && (rayY <= 2) && (rayY >= (-11)) )
      inside = 1;
    break;
  case COP_Ellipse:
    rayX *= region->ctrl.axis_ratio;
    ray = sqrt(SQR(rayX) + SQR(rayY));
    if( (ray < region->win.rayY) &&
        ((ray / region->ctrl.axis_ratio) < region->win.rayX) )
      inside = 1;
    break;
  default:
    break;
  }
  return( inside );
}

/*
 * Subroutine:	pointer_is_inside_polygon
 * Purpose:	Determine if mouse is within a polygon
 */
static int pointer_is_inside_polygon ( x, y, polypt, poly_cnt )
     double x, y;
     PolyPoint *polypt;
     int poly_cnt;
{
  double yi, yj, xi, xj;
  int i, j, crossings;

  crossings = 0;
  j = poly_cnt - 1;
  for( i=0; i<poly_cnt; i++ ) {
    if( (polypt[i].winX >= x) != (polypt[j].winX > x) ) {
      yi = polypt[i].winY;
      yj = polypt[j].winY;
      if( (yi < y) || (yj < y) ) {
	if( (yi < y) && (yj < y) )
	  crossings++;
	else {
	  xi = polypt[i].winX;
	  xj = polypt[j].winX;
	  if( xj != xi ) {
	    if( ((x - xj) * (yi-yj)/(xi-xj) + yj) < y )
	      crossings++;
	  }
	}
      }
    }
  }
  if( crossings & 1 )
    return(1);
  else
    return(0);
}