AKTIVE

Artifact [6c8d6d2109]
Login

Artifact [6c8d6d2109]

Artifact 6c8d6d2109213fec98856a34a67f5b2acec0d8fc944c3517125d7f35ebdb1a5f:


/* -*- c -*-
 * - - -- --- ----- -------- -------------
 *
 * -- Geometry API -- Types and methods
 */
#ifndef AKTIVE_GEOMETRY_H
#define AKTIVE_GEOMETRY_H

/*
 * - - -- --- ----- -------- -------------
 */

#include <tclpre9compat.h>
#include <base.h>

/*
 * - - -- --- ----- -------- -------------
 */

#define TRACE_POINT(p)     TRACE (#p " @(%d,%d)",                  (p)->x, (p)->y)
#define TRACE_RECTANGLE(r) TRACE (#r " @(%d..%d,%d..%d %ux%u)",    (r)->x, (r)->x+(r)->width-1, (r)->y, (r)->y+(r)->height-1, (r)->width, (r)->height)
#define TRACE_GEOMETRY(g)  TRACE (#g " @(%d..%d,%d..%d %ux%ux%u)", (g)->x, (g)->x+(g)->width-1, (g)->y, (g)->y+(g)->height-1, (g)->width, (g)->height, (g)->depth)

#define TRACE_POINT_M(m,p)     TRACE (m " @(%d,%d)",                  (p)->x, (p)->y)
#define TRACE_RECTANGLE_M(m,r) TRACE (m " @(%d..%d,%d..%d %ux%u)",    (r)->x, (r)->x+(r)->width-1, (r)->y, (r)->y+(r)->height-1, (r)->width, (r)->height)
#define TRACE_GEOMETRY_M(m,g)  TRACE (m " @(%d..%d,%d..%d %ux%ux%u)", (g)->x, (g)->x+(g)->width-1, (g)->y, (g)->y+(g)->height-1, (g)->width, (g)->height, (g)->depth)

/*
 * - - -- --- ----- -------- -------------
 * -- Points	 :: 2D location
 * -- Rectangles :: 2D area   (location + dimensions)
 * -- Geometries :: 3D volume (dimensions)
 * -- Ranges     :: Degenerated Rectangle (Height 1) + Pixel value
 *
 * NOTE
 *
 *  - How `aktive_point`     is a proper prefix of `aktive_rectangle`, and
 *  - How `aktive_rectangle` is a proper prefix of `aktive_geometry`
 *
 *  - Looking into `block.h`, see that aktive_geometry is a proper prefix of
 *    `aktive_block too.
 */

A_STRUCTURE (aktive_point) {
    A_FIELD (int, x) ; // X coordinate, increasing to the right
    A_FIELD (int, y) ; // Y coordinate, increasing downward
} A_END (aktive_point);

A_STRUCTURE (aktive_rectangle) {
    A_FIELD (int,         x)      ; // X coordinate, increasing to the right
    A_FIELD (int,         y)      ; // Y coordinate, increasing downward
    A_FIELD (aktive_uint, width)  ; // Number of columns
    A_FIELD (aktive_uint, height) ; // Number of rows
} A_END (aktive_rectangle);

A_STRUCTURE (aktive_geometry) {
    A_FIELD (int,         x)      ; // X coordinate, increasing to the right
    A_FIELD (int,         y)      ; // Y coordinate, increasing downward
    A_FIELD (aktive_uint, width)  ; // Number of image columns
    A_FIELD (aktive_uint, height) ; // Number of image rows
    A_FIELD (aktive_uint, depth)  ; // Number of image bands
} A_END (aktive_geometry);

A_STRUCTURE (aktive_range) {
    A_FIELD (int,         xmin)   ; // X coordinate, start of range
    A_FIELD (int,         xmax)   ; // X coordinate, end of range
    A_FIELD (int,         y)      ; // Y coordinate
    A_FIELD (double,      value)  ; // Pixel value
} A_END (aktive_range);

/*
 * - - -- --- ----- -------- -------------
 */

extern Tcl_Obj* aktive_new_range_obj (aktive_range* p);

#define aktive_range_set(dst,xa,xb,yv,pval) \
    { (dst)->xmin = (xa) ; (dst)->xmax = (xb) ; (dst)->y = (yv) ; (dst)->value = (pval) ; }

extern void aktive_range_union (aktive_rectangle* dst, aktive_uint c, aktive_range* v);
extern void aktive_range_sort  (aktive_uint c, aktive_range* v);

/*
 * - - -- --- ----- -------- -------------
 */

extern Tcl_Obj* aktive_new_point_obj (aktive_point* p);

#define aktive_point_def(varname,xv,yv) \
    aktive_point varname = { .x = (xv), .y = (yv) }

#define aktive_point_def_as(varname,src) \
    aktive_point_def(varname, (src)->x, (src)->y)

/*
 * - - -- --- ----- -------- -------------
 * extern void aktive_point_set           (aktive_point* dst, int x,  int y);
 * extern void aktive_point_copy          (aktive_point* dst, aktive_point*     src);
 * extern void aktive_point_from_rect     (aktive_point* dst, aktive_rectangle* src);
 * extern void aktive_point_from_geometry (aktive_point* dst, aktive_geometry*  src);
 * extern void aktive_point_move          (aktive_point* dst, int dx, int dy);
 * extern void aktive_point_add           (aktive_point* dst, aktive_point* delta);
 * extern void aktive_point_sub           (aktive_point* dst, aktive_point* delta);
 */

#define aktive_point_set(dst,xv,yv)         { (dst)->x = (xv) ; (dst)->y = (yv); }
#define aktive_point_copy(dst,src)          aktive_point_set (dst, (src)->x, (src)->y)
#define aktive_point_from_rect(dst,src)     aktive_point_copy (dst, src)
#define aktive_point_from_geometry(dst,src) aktive_point_copy (dst, src)
#define aktive_point_move(dst,dx,dy)        { (dst)->x += (dx) ; (dst)->y += (dy) ; }
#define aktive_point_add(dst,delta)         aktive_point_move(dst, (delta)->x, (delta)->y)
#define aktive_point_sub(dst,delta)         aktive_point_move(dst, - (delta)->x, - (delta)->y)
#define aktive_point_neg(dst)               { (dst)->x = - (dst)->x ; (dst)->y = - (dst)->y ; }
#define aktive_point_conj(dst)              { (dst)->y = - (dst)->y ; }

extern void aktive_point_union    (aktive_rectangle* dst, aktive_uint c, aktive_point* v);
extern int  aktive_point_is_equal (aktive_point* a, aktive_point* b);

/*
 * - - -- --- ----- -------- -------------
 */

extern Tcl_Obj* aktive_new_rectangle_obj (aktive_rectangle* r);

#define aktive_rectangle_def(varname,xv,yv,wv,hv) \
    aktive_rectangle varname = { .x = (xv), .y = (yv), .width = (wv), .height = (hv) }

#define aktive_rectangle_def_as(varname,src) \
    aktive_rectangle_def(varname, (src)->x, (src)->y, (src)->width, (src)->height)

/*
 * - - -- --- ----- -------- -------------
 * extern void aktive_rectangle_set           (aktive_rectangle* dst, int x, int y, aktive_uint w, aktive_uint h);
 * extern void aktive_rectangle_copy          (aktive_rectangle* dst, aktive_rectangle* src);
 * extern void aktive_rectangle_set_point     (aktive_rectangle* dst, aktive_point*     src);
 * extern void aktive_rectangle_from_geometry (aktive_rectangle* dst, aktive_geometry*  src);
 * extern int  aktive_rectangle_get_x         (aktive_rectangle* src);
 * extern int  aktive_rectangle_get_xmax      (aktive_rectangle* src);
 * extern int  aktive_rectangle_get_y         (aktive_rectangle* src);
 * extern int  aktive_rectangle_get_ymax      (aktive_rectangle* src);
 */

#define aktive_rectangle_sub(dst,delta) aktive_rectangle_move(dst, - (delta)->x, - (delta)->y)

extern void aktive_rectangle_move         (aktive_rectangle* dst, int dx, int dy);
extern void aktive_rectangle_add          (aktive_rectangle* dst, aktive_point* delta);
extern void aktive_rectangle_grow         (aktive_rectangle* dst, int left, int right, int top, int bottom);

#define aktive_rectangle_set(dst, xv, yv, wv, hv) { (dst)->x = (xv) ; (dst)->y = (yv) ; (dst)->width = (wv) ; (dst)->height = (hv) ; }
#define aktive_rectangle_copy(dst, src)           aktive_rectangle_set  (dst, (src)->x, (src)->y, (src)->width, (src)->height)
#define aktive_rectangle_set_point(dst, src)      aktive_point_copy     (dst, src)
#define aktive_rectangle_from_geometry(dst, src)  aktive_rectangle_copy (dst, src)
#define aktive_rectangle_get_x(src)               ((src)->x)
#define aktive_rectangle_get_xmax(src)            ((src)->x + (src)->width - 1)
#define aktive_rectangle_get_y(src)               ((src)->y)
#define aktive_rectangle_get_ymax(src)            ((src)->y + (src)->height - 1)

#define aktive_rectangle_as_point(src)     ((aktive_point*) (src))

extern int aktive_rectangle_is_equal  (aktive_rectangle* a, aktive_rectangle* b);
extern int aktive_rectangle_is_dim_eq (aktive_rectangle* a, aktive_rectangle* b);
extern int aktive_rectangle_is_subset (aktive_rectangle* a, aktive_rectangle* b);
extern int aktive_rectangle_is_empty  (aktive_rectangle* r);
extern int aktive_rectangle_contains  (aktive_rectangle* r, aktive_point* p);

/* Both `union` and `intersection operations allow one of the input rectangles
 * to be used as `dst` without issue, due to modifying the destination only
 * after the result is fully calculated and no data from the input is required
 * anymore.
 */
extern void aktive_rectangle_union     (aktive_rectangle* dst, aktive_rectangle* a, aktive_rectangle* b);
extern void aktive_rectangle_intersect (aktive_rectangle* dst, aktive_rectangle* a, aktive_rectangle* b);

// Compute intersection of request with domain, and the zones of request outside of the domain.
// The array `v` has to have enough space for 5 results (intersection + at most 4 zones.
// The intersection is always stored in v[0].
extern void aktive_rectangle_outzones  (aktive_rectangle* domain, aktive_rectangle* request,
					aktive_uint* c, aktive_rectangle* v);

/*
 * - - -- --- ----- -------- -------------
 *
 * debug support -- -------- -------------
 *
 * - - -- --- ----- -------- -------------
 */

extern void __aktive_rectangle_dump (char* prefix, aktive_rectangle* r);

/*
 * - - -- --- ----- -------- -------------
 */

extern Tcl_Obj* aktive_new_geometry_obj (aktive_geometry* r);

#define aktive_geometry_def(varname,xv,yv,wv,hv,dv) \
    aktive_geometry varname = { .x = (xv), .y = (yv), .width = (wv), .height = (hv), .depth = (dv) }

/*
 * - - -- --- ----- -------- -------------
 * extern void        aktive_geometry_set           (aktive_geometry* dst, int x, int y, aktive_uint w, aktive_uint h, aktive_uint d);
 * extern void        aktive_geometry_copy          (aktive_geometry* dst, aktive_geometry*  src);
 * extern void        aktive_geometry_set_point     (aktive_geometry* dst, aktive_point*     src);
 * extern void        aktive_geometry_set_rectangle (aktive_geometry* dst, aktive_rectangle* src);
 * extern int         aktive_geometry_get_x         (aktive_geometry* src);
 * extern int         aktive_geometry_get_xmax      (aktive_geometry* src);
 * extern int         aktive_geometry_get_y         (aktive_geometry* src);
 * extern int         aktive_geometry_get_ymax      (aktive_geometry* src);
 * extern aktive_uint aktive_geometry_get_width     (aktive_geometry* src);
 * extern aktive_uint aktive_geometry_get_height    (aktive_geometry* src);
 * extern aktive_uint aktive_geometry_get_depth     (aktive_geometry* src);
 * extern aktive_uint aktive_geometry_get_pitch     (aktive_geometry* src);
 * extern aktive_uint aktive_geometry_get_pixels    (aktive_geometry* src);
 * extern aktive_uint aktive_geometry_get_size      (aktive_geometry* src);
 */

#define aktive_geometry_set(dst, xv, yv, wv, hv, dv) { (dst)->x = (xv) ; (dst)->y = (yv) ; (dst)->width = (wv) ; (dst)->height = (hv) ; (dst)->depth = (dv) ; }
#define aktive_geometry_copy(dst, src)               aktive_geometry_set (dst, (src)->x, (src)->y, (src)->width, (src)->height, (src)->depth)
#define aktive_geometry_set_point(dst, src)          aktive_point_copy(dst, src)
#define aktive_geometry_set_rectangle(dst, src)      aktive_rectangle_copy(dst, src)
#define aktive_geometry_get_x(src)                   ((src)->x)
#define aktive_geometry_get_xmax(src)                ((src)->x + (src)->width - 1)
#define aktive_geometry_get_y(src)                   ((src)->y)
#define aktive_geometry_get_ymax(src)                ((src)->y + (src)->height - 1)
#define aktive_geometry_get_width(src)	             ((src)->width)
#define aktive_geometry_get_height(src)	             ((src)->height)
#define aktive_geometry_get_depth(src)	             ((src)->depth)
#define aktive_geometry_get_pitch(src)	             ((src)->width * (src)->depth)
#define aktive_geometry_get_pixels(src)	             ((src)->width * (src)->height)
#define aktive_geometry_get_size(src)	             ((src)->width * (src)->height * (src)->depth)

#define aktive_geometry_get_z(src)        (0)
#define aktive_geometry_get_zmax(src)     ((src)->depth - 1)
#define aktive_geometry_as_point(src)     ((aktive_point*)     (src))
#define aktive_geometry_as_rectangle(src) ((aktive_rectangle*) (src))

/*
 * - - -- --- ----- -------- -------------
 */

#define AKTIVE_SWIVEL(s,a,b) { aktive_uint tmp = (s)->a ; (s)->a = (s)->b ; (s)->b = tmp; }

/*
 * - - -- --- ----- -------- -------------
 * Variants of points and rectangles supporting (f)ractional locations.
 *
 * -- Points	 :: 2D location
 * -- Rectangles :: 2D area   (location + dimensions)
 *
 * NOTE
 *
 *  - How `aktive_fpoint` is a proper prefix of `aktive_frectangle`
 */

A_STRUCTURE (aktive_fpoint) {
    A_FIELD (double, x) ; // X coordinate, increasing to the right
    A_FIELD (double, y) ; // Y coordinate, increasing downward
} A_END (aktive_fpoint);

A_STRUCTURE (aktive_frectangle) {
    A_FIELD (double, x)      ; // X coordinate, increasing to the right
    A_FIELD (double, y)      ; // Y coordinate, increasing downward
    A_FIELD (double, width)  ; // Number of columns
    A_FIELD (double, height) ; // Number of rows
} A_END (aktive_frectangle);

/*
 * - - -- --- ----- -------- -------------
 */

extern Tcl_Obj* aktive_new_fpoint_obj (aktive_fpoint* p);

#define aktive_fpoint_def(varname,xv,yv) \
    aktive_fpoint varname = { .x = (xv), .y = (yv) }

#define aktive_fpoint_def_as(varname,src) \
    aktive_fpoint_def(varname, (src)->x, (src)->y)

#define aktive_fpoint_set(dst,xv,yv)         { (dst)->x = (xv) ; (dst)->y = (yv); }
#define aktive_fpoint_copy(dst,src)          aktive_fpoint_set (dst, (src)->x, (src)->y)
#define aktive_fpoint_from_rect(dst,src)     aktive_fpoint_copy (dst, src)
#define aktive_fpoint_from_geometry(dst,src) aktive_fpoint_copy (dst, src)
#define aktive_fpoint_move(dst,dx,dy)        { (dst)->x += (dx) ; (dst)->y += (dy) ; }
#define aktive_fpoint_add(dst,delta)         aktive_fpoint_move(dst, (delta)->x, (delta)->y)
#define aktive_fpoint_sub(dst,delta)         aktive_fpoint_move(dst, - (delta)->x, - (delta)->y)
#define aktive_fpoint_neg(dst)               { (dst)->x = - (dst)->x ; (dst)->y = - (dst)->y ; }
#define aktive_fpoint_conj(dst)              { (dst)->y = - (dst)->y ; }

/*
 * - - -- --- ----- -------- -------------
 */

extern Tcl_Obj* aktive_new_frectangle_obj (aktive_frectangle* r);

#define aktive_frectangle_def(varname,xv,yv,wv,hv) \
    aktive_frectangle varname = { .x = (xv), .y = (yv), .width = (wv), .height = (hv) }

#define aktive_frectangle_def_as(varname,src) \
    aktive_frectangle_def(varname, (src)->x, (src)->y, (src)->width, (src)->height)

/*
 * = = == === ===== ======== ============= =====================
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
#endif /* AKTIVE_GEOMETRY_H */