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);
}
|