home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Photo CD Demo 1
/
Demo.bin
/
gems
/
gemsiii
/
con2d.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-03-16
|
9KB
|
410 lines
#include <stdio.h>
#define OFFS 4 /* first & last segment min size */
#define SMAX 20 /* object min half size */
#define DIRECT 0
#define INVERSE 1
#define LEFT 0x00
#define RIGHT 0x01
#define BOTTOM 0x02
#define TOP 0x03
#define EQSIGN(x1, x2, x3, x4) ( ( x2 - x1 ) * ( x3 - x4 ) > 0 )
#define CODE(x, y, w, h, px, py, c) { \
c = 0x00; \
if ( px < x ) c = 0x01; \
else if ( px >= x + w ) c = 0x02; \
if ( py < y ) c |= 0x04; \
else if ( py >= y + h ) c |= 0x08; \
}
typedef struct {
int direction;
int x, y;
} Pad;
typedef struct {
int x, y, w, h;
} Obj;
/*****************************************************************************
Computes & corrects the connection path from an object Out pad to an object In
pad.
Entry:
startObj - the object to start the connection from
endObj - the object to which the connection ends
outPad - the Out pad to be connected
inPad - the In pad to be connected
Exit:
nump - the number of connection points
pts - the connection point list
*****************************************************************************/
ComputeCon ( startObj, endObj, outPad, inPad, nump, pts )
Obj *startObj;
Obj *endObj;
Pad *outPad;
Pad *inPad;
int nump;
int pts[][2];
{
nump = Connect(outPad->x, outPad->y, outPad->direction,
inPad->x, inPad->y, inPad->direction, pts);
Correct(startObj->x, startObj->y, startObj->w, startObj->h, nump, pts);
Correct(endObj->x, endObj->y, endObj->w, endObj->h, nump, pts);
}
/*****************************************************************************
Computes the connection path from an object Out pad to an object In pad using
the orthogonal path algorithm.
Entry:
xo - Out pad x coordinate
yo - Out pad y coordinate
diro - Out pad direction
xi - In pad x coordinate
yi - In pad y coordinate
diri - In pad direction
Exit:
p - the connection point list
Return:
the number of connection points
*****************************************************************************/
int Connect ( xo, yo, diro, xi, yi, diri, p )
int xo, yo, diro;
int xi, yi, diri;
int p[][2];
{
static int directs[4][4] = {
{ TOP, BOTTOM, LEFT, RIGHT },
{ BOTTOM, TOP, RIGHT, LEFT },
{ RIGHT, LEFT, TOP, BOTTOM },
{ LEFT, RIGHT, BOTTOM, TOP }
};
int i, np, txi, tyi;
Transform(DIRECT, diro, xo, yo, xi, yi, &txi, &tyi);
switch ( directs[diro][diri] ) { /* In pad direction */
case LEFT:
if ( tyi > 0 ) { /* T */
if ( txi > 0 ) { /* 34 */
Shape3P(txi, tyi, p);
np = 3;
}
else { /* 12 */
Shape5PB(txi, tyi, -1, p);
np = 5;
}
}
else { /* B */
Shape5PB(txi, tyi, -1, p);
np = 5;
}
break;
case RIGHT:
if ( tyi > 0 ) { /* T */
if ( txi > 0 ) { /* 34 */
Shape5PB(txi, tyi, 1, p);
np = 5;
}
else { /* 12 */
Shape3P(txi, tyi, p);
np = 3;
}
}
else { /* B */
Shape5PB(txi, tyi, 1, p);
np = 5;
}
break;
case BOTTOM:
if ( tyi > 0 ) { /* T */
Shape4PD(txi, tyi, p);
np = 4;
}
else { /* B */
Shape6P(txi, tyi, -1, p);
np = 6;
}
break;
case TOP:
if ( txi < - SMAX || txi > SMAX ) { /* 14 */
Shape4PU(txi, tyi, p);
np = 4;
}
else { /* 23 */
Shape6R(txi, tyi, 1, p);
np = 6;
}
break;
}
for ( i = 0 ; i < np ; i++ )
Transform(INVERSE, diro, xo, yo, p[i][0], p[i][1], &p[i][0], &p[i][1]);
return (np);
}
/*****************************************************************************
Translates & rotates a point according to the Out pad direction.
Entry:
mode - transformation mode (DIRECT or INVERSE)
dout - Out pad direction
xout - Out pad x coordinate
yout - Out pad y coordinate
x, y - point to be transformed
Exit:
tx, ty - transformed point
*****************************************************************************/
Transform ( mode, dout, xout, yout, x, y, tx, ty )
int mode;
int dout, xout, yout;
int x, y;
int *tx, *ty;
{
int ox, oy;
ox = x;
oy = y;
switch ( mode ) {
case DIRECT:
switch ( dout ) {
case LEFT:
*tx = oy - yout;
*ty = xout - ox;
break;
case RIGHT:
*tx = yout - oy;
*ty = ox - xout;
break;
case BOTTOM:
*tx = xout - ox;
*ty = yout - oy;
break;
case TOP:
*tx = ox - xout;
*ty = oy - yout;
break;
}
break;
case INVERSE:
switch ( dout ) {
case LEFT:
*tx = xout - oy;
*ty = yout + ox;
break;
case RIGHT:
*tx = xout + oy;
*ty = yout - ox;
break;
case BOTTOM:
*tx = xout - ox;
*ty = yout - oy;
break;
case TOP:
*tx = xout + ox;
*ty = yout + oy;
break;
}
break;
}
}
/*****************************************************************************
Corrects the connection path moving the overcrossing segments out of the
crossed object.
Entry:
x, y - object lower left corner
w, h - object width & height
np - number of connection point
p - original path points list
Exit:
p - eventually corrected path points list
*****************************************************************************/
Correct ( x, y, w, h, np, p )
int x, y, w, h;
int np;
int p[][2];
{
int i, j, c, op[2], od[2];
op[0] = x;
op[1] = y;
od[0] = w;
od[1] = h;
for ( j = 1, i = 2 ; i < np - 1 ; i++, j++ ) {
if ( Overcross(x, y, w, h, p[j][0], p[j][1], p[i][0], p[i][1]) ) {
c = ( p[j][0] == p[i][0] ) ? 0 : 1;
if ( EQSIGN(p[j-1][c], p[j][c], p[i][c], p[i+1][c]) ) {
if ( p[j][c] < p[j-1][c] )
p[j][c] = p[i][c] = op[c] - OFFS + 2;
else p[j][c] = p[i][c] = op[c] + od[c] - 1 + OFFS - 2;
}
else {
if ( p[i][c] < p[i+1][c] )
p[j][c] = p[i][c] = op[c] - OFFS + 2;
else p[j][c] = p[i][c] = op[c] + od[c] - 1 + OFFS - 2;
}
}
}
}
/*****************************************************************************
Inplementation of line-rectangle intersection test as the first test in
Cohen-Sutherland clipping algorithm.
Entry:
x, y - rectangle lower left corner
w, h - rectangle width & height
x1, y1 - line start point
x2, y2 - line end point
Return:
TRUE if the line overcrosses the rectangle, FALSE otherwise
*****************************************************************************/
int Overcross ( x, y, w, h, x1, y1, x2, y2 )
int x, y, w, h;
int x1, y1, x2, y2;
{
int c1, c2;
CODE(x, y, w, h, x1, y1, c1);
CODE(x, y, w, h, x2, y2, c2);
return(! ( c1 & c2));
}
/*****************************************************************************
Shape functions.
Entry:
xi, yi - In pad coordinate
[sign] - sign flag
Exit:
xy - the computed path points list
*****************************************************************************/
Shape3P ( xi, yi, xy )
int xi, yi;
int xy[][2];
{
xy[0][0] = 0;
xy[0][1] = 0;
xy[1][0] = 0;
xy[1][1] = yi;
xy[2][0] = xi;
xy[2][1] = yi;
}
Shape4PD ( xi, yi, xy )
int xi, yi;
int xy[][2];
{
xy[0][0] = 0;
xy[0][1] = 0;
xy[1][0] = 0;
xy[1][1] = OFFS;
xy[2][0] = xi;
xy[2][1] = xy[1][1];
xy[3][0] = xi;
xy[3][1] = yi;
}
Shape4PU ( xi, yi, xy )
int xi, yi;
int xy[][2];
{
xy[0][0] = 0;
xy[0][1] = 0;
xy[1][0] = 0;
xy[1][1] = ( ( yi <= 0 ) ? 0 : yi ) + OFFS;
xy[2][0] = xi;
xy[2][1] = xy[1][1];
xy[3][0] = xi;
xy[3][1] = yi;
}
Shape5PB ( xi, yi, sign, xy )
int xi, yi;
int sign;
int xy[][2];
{
xy[0][0] = 0;
xy[0][1] = 0;
xy[1][0] = 0;
xy[1][1] = OFFS;
if ( sign * xi < - SMAX ) xy[2][0] = xi + sign * OFFS;
else xy[2][0] = ( ( sign * xi < 0 ) ? 0 : xi ) + sign * OFFS;
xy[2][1] = xy[1][1];
xy[3][0] = xy[2][0];
xy[3][1] = yi;
xy[4][0] = xi;
xy[4][1] = yi;
}
Shape5PT ( xi, yi, sign, xy )
int xi, yi;
int sign;
int xy[][2];
{
xy[0][0] = 0;
xy[0][1] = 0;
xy[1][0] = 0;
xy[1][1] = OFFS;
xy[2][0] = xi + sign * OFFS;
xy[2][1] = xy[1][1];
xy[3][0] = xy[2][0];
xy[3][1] = yi;
xy[4][0] = xi;
xy[4][1] = yi;
}
Shape6P ( xi, yi, sign, xy )
int xi, yi;
int sign;
int xy[][2];
{
int xm;
xm = xi / 2;
xy[0][0] = 0;
xy[0][1] = 0;
xy[1][0] = 0;
xy[1][1] = OFFS;
if ( yi < 0 ) {
if ( xi > 0 ) xy[2][0] = ( xm > SMAX ) ? xm : SMAX;
else xy[2][0] = ( xm > SMAX ) ? xm : - SMAX;
}
else {
if ( xi > 0 ) xy[2][0] = ( xm > SMAX ) ? xm : - SMAX;
else xy[2][0] = ( xm > SMAX ) ? xm : SMAX;
}
xy[2][1] = xy[1][1];
xy[3][0] = xy[2][0];
xy[3][1] = yi + sign * OFFS;
xy[4][0] = xi;
xy[4][1] = xy[3][1];
xy[5][0] = xi;
xy[5][1] = yi;
}