/* geometry.h --
 *
 *     ********************************************************************* 
 *     * Copyright (C) 1985, 1990 Regents of the University of California. * 
 *     * Permission to use, copy, modify, and distribute this              * 
 *     * software and its documentation for any purpose and without        * 
 *     * fee is hereby granted, provided that the above copyright          * 
 *     * notice appear in all copies.  The University of California        * 
 *     * makes no representations about the suitability of this            * 
 *     * software for any purpose.  It is provided "as is" without         * 
 *     * express or implied warranty.  Export of this software outside     * 
 *     * of the United States of America may require an export license.    * 
 *     *********************************************************************
 *
 * This module contains the basic definitions for geometrical
 * elements:  points, rectangles, and transforms.
 */

/* rcsid "$Header: /ufs/repository/magic/utils/geometry.h,v 1.3 2006/07/08 19:06:57 fang Exp $" */

#ifndef _GEOMETRY
#define _GEOMETRY 1

#include "utils/geometry_types.h"	// defines Point, Rect, Transform

#define TRUE 1
#define FALSE 0

#define r_xbot r_ll.p_x
#define r_ybot r_ll.p_y
#define r_xtop r_ur.p_x
#define r_ytop r_ur.p_y

/**
 * LinkedRect, typedef'd in "utils/geometry_types.h"
 */
struct G1		/* A linked rectangle */
{
    Rect r_r;			/* A rectangle. */
    struct G1 *r_next;		/* Pointer to another linked rectangle */
};	/* LinkedRect */

/*-------------------------------------------------------------------
 *	Definitions for positions.  Positions are small integers
 *	used to select where text gets placed, relative to a point.
 *-------------------------------------------------------------------
 */

#define GEO_CENTER	0
#define GEO_NORTH	1
#define GEO_NORTHEAST	2
#define GEO_EAST	3
#define GEO_SOUTHEAST	4
#define GEO_SOUTH	5
#define GEO_SOUTHWEST	6
#define GEO_WEST	7
#define GEO_NORTHWEST	8


/* See if two points are equal */
#define GEO_SAMEPOINT(p1, p2) ((p1).p_x == (p2).p_x && (p1).p_y == (p2).p_y)

/* See if two rects are equal */
#define	GEO_SAMERECT(r1, r2) \
    (GEO_SAMEPOINT((r1).r_ll, (r2).r_ll) && GEO_SAMEPOINT((r1).r_ur, (r2).r_ur))

/*-------------------------------------------------------------------
 *	The following macros are predicates to see if two
 *	rectangles overlap or touch.  
 *-------------------------------------------------------------------
 */

/* see if the rectangles overlap (the overlap contains some area) */

#define GEO_OVERLAP(r1, r2) \
    (((r1)->r_xbot < (r2)->r_xtop) && ((r2)->r_xbot < (r1)->r_xtop) \
    && ((r1)->r_ybot < (r2)->r_ytop) && ((r2)->r_ybot < (r1)->r_ytop))

/* see if the rectangles touch (share part of a side) or overlap */

#define GEO_TOUCH(r1, r2) \
    (((r1)->r_xbot <= (r2)->r_xtop) && ((r2)->r_xbot <= (r1)->r_xtop) \
    && ((r1)->r_ybot <= (r2)->r_ytop) && ((r2)->r_ybot <= (r1)->r_ytop))

/* see if rectangle r1 completely surrounds rectangle r2.  Touching between
 * r2 and r1 IS allowed.
 */

#define GEO_SURROUND(r1,r2) \
    ( ((r2)->r_xbot >= (r1)->r_xbot) && ((r2)->r_xtop <= (r1)->r_xtop) \
    && ((r2)->r_ybot >= (r1)->r_ybot) && ((r2)->r_ytop <= (r1)->r_ytop) )

/* see if rectangle r1 completely surrounds rectangle r2 WITHOUT touching it.
 */

#define GEO_SURROUND_STRONG(r1,r2) \
    ( ((r2)->r_xbot > (r1)->r_xbot) && ((r2)->r_xtop < (r1)->r_xtop) \
    && ((r2)->r_ybot > (r1)->r_ybot) && ((r2)->r_ytop < (r1)->r_ytop) )

/* See if point p in inside of or on the border of r */
#define GEO_ENCLOSE(p, r)	\
    ( ((p)->p_x <= (r)->r_xtop) && ((p)->p_x >= (r)->r_xbot) &&  \
      ((p)->p_y <= (r)->r_ytop) && ((p)->p_y >= (r)->r_ybot) )
    
/* See if a label is in a given area */
#define GEO_LABEL_IN_AREA(lab,area) \
    (GEO_SURROUND(area, lab) || \
	(GEO_RECTNULL(area) && GEO_TOUCH(lab, area) && \
	!(GEO_SURROUND_STRONG(lab, area))))

/* See if a rectangle has no area. */

#define GEO_RECTNULL(r) \
    (((r)->r_xbot >= (r)->r_xtop) || ((r)->r_ybot >= (r)->r_ytop))

/* Expand a rectangular area by a given amount. */

#define GEO_EXPAND(src, amount, dst) \
{ \
    (dst)->r_xbot = (src)->r_xbot - amount; \
    (dst)->r_ybot = (src)->r_ybot - amount; \
    (dst)->r_xtop = (src)->r_xtop + amount; \
    (dst)->r_ytop = (src)->r_ytop + amount; \
}

/* Sizes of rectangles. */
#define GEO_WIDTH(r)    ((r)->r_xtop - (r)->r_xbot)
#define GEO_HEIGHT(r)   ((r)->r_ytop - (r)->r_ybot)


/*-------------------------------------------------------------------
 *	Declarations for exported procedures:
 *-------------------------------------------------------------------
 */

extern int GeoNameToPos();
extern char * GeoPosToName();
extern void GeoTransRect(), GeoTransTrans();
extern void GeoTransPoint(), GeoInvertTrans();
extern void GeoTranslateTrans();
extern void GeoTransTranslate();
extern int GeoInclude(), GeoTransPos(), GeoIncludeAll();
extern void GeoClip();
extern void GeoClipPoint();
extern int GeoRectPointSide();
extern int GeoRectRectSide();
extern void GeoIncludePoint();
extern void GeoDecomposeTransform();
extern void GeoCanonicalRect(register Rect *r, register Rect *rnew);
extern int GeoScale(register Transform*);
extern bool GeoDisjoint(Rect*, Rect*, bool (*)(Rect*, ClientData), ClientData);

/*
 *-------------------------------------------------------------------
 *	Declarations of exported transforms and rectangles:
 *-------------------------------------------------------------------
 */

extern Transform GeoIdentityTransform;
extern Transform GeoUpsideDownTransform;
extern Transform GeoSidewaysTransform;
extern Transform Geo90Transform;
extern Transform Geo180Transform;
extern Transform Geo270Transform;
extern Transform GeoRef45Transform;
extern Transform GeoRef135Transform;

extern Rect GeoNullRect;

extern int GeoOppositePos[];

#endif	/* _GEOMETRY */
