diff options
Diffstat (limited to 'graphics/sketch/geometry.h')
-rw-r--r-- | graphics/sketch/geometry.h | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/graphics/sketch/geometry.h b/graphics/sketch/geometry.h new file mode 100644 index 0000000000..c7863fd836 --- /dev/null +++ b/graphics/sketch/geometry.h @@ -0,0 +1,359 @@ +/* geometry.h + Copyright (C) 2005,2006,2007 Eugene K. Ressler, Jr. + +This file is part of Sketch, a small, simple system for making +3d drawings with LaTeX and the PSTricks or TikZ package. + +Sketch is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +Sketch is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Sketch; see the file COPYING.txt. If not, see +http://www.gnu.org/copyleft */ + +#ifndef __GEOMETRY_H +#define __GEOMETRY_H + +// ---- memory ----------------------------------------------------------------- + +#include <float.h> // floating point definitions +#include "dynarray.h" // dynamic arrays + +// bit N +#define bit(N) (1u << (N)) + +// size of a static or auto declared array +#define ARRAY_SIZE(A) (sizeof (A) / sizeof (A)[0]) + +// checking memory allocators +void *safe_malloc (unsigned size); +void *safe_realloc (void *p, unsigned size); +char *safe_strdup (char *str); +void safe_free (void *p); +#ifdef _DEBUG +#define malloc(N) __call_safe_malloc_instead() +#define realloc(P,N) __call_safe_alloc_instead() +#define strdup(S) __call_safe_alloc_instead() +#define free(P) __call_safe_free_instead() +#endif + +// ---- numerics --------------------------------------------------------------- + +// float declarations to ease compilation +// with either single or double precision +typedef unsigned int SIZE, INDEX; +typedef double FLOAT; + +#define FLOAT_SCAN_FMT "%lf" +#define FLOAT_EPS (8*DBL_EPSILON) +#define FLOAT_MIN FLT_MIN +#define FLOAT_MAX FLT_MAX + +#ifdef _MSC_VER +// kill loss of precision warnings for case where FLOAT is float +#pragma warning(disable:4244 4305) +#endif + +#define PI ((FLOAT)3.1415926535897932384626433832795028841971693993751) + +// Max and min operators +FLOAT max_float (FLOAT x, FLOAT y); +FLOAT min_float (FLOAT x, FLOAT y); + +// ---- points ----------------------------------------------------------------- + +// indices +#define X 0 +#define Y 1 +#define Z 2 +#define W 3 + +// points +typedef FLOAT POINT_2D[2], POINT_3D[3]; +void copy_pt_2d (POINT_2D r, POINT_2D s); +void copy_pt_3d (POINT_3D r, POINT_3D s); +void find_pt_3d_from_2d (POINT_3D r, POINT_2D pt); + +// ---- polylines -------------------------------------------------------------- + +// polylines are just dynamic arrays of points + +typedef struct polyline_2d_t +{ + DYNAMIC_2D_ARRAY_FIELDS (POINT_2D, v, n_vertices); + struct polyline_2d_t *next; +} +POLYLINE_2D; + +DECLARE_DYNAMIC_2D_ARRAY_PROTOS (POLYLINE_2D, POINT_2D, FLOAT, polyline_2d, + v, n_vertices) + typedef struct polyline_3d_t + { + DYNAMIC_2D_ARRAY_FIELDS (POINT_3D, v, n_vertices); + struct polyline_3d_t *next; + } +POLYLINE_3D; + +DECLARE_DYNAMIC_2D_ARRAY_PROTOS (POLYLINE_3D, POINT_3D, FLOAT, polyline_3d, + v, n_vertices) +// ---- polygons --------------------------------------------------------------- +// polygons are just a dynamic arrays of points; chains represent complex polygons + typedef struct polygon_2d_t + { + DYNAMIC_2D_ARRAY_FIELDS (POINT_2D, v, n_sides); + struct polygon_2d_t *next; + } +POLYGON_2D; + +DECLARE_DYNAMIC_2D_ARRAY_PROTOS (POLYGON_2D, POINT_2D, FLOAT, polygon_2d, v, + n_sides) + typedef struct polygon_3d_t + { + DYNAMIC_2D_ARRAY_FIELDS (POINT_3D, v, n_sides); + struct polygon_3d_t *next; + } +POLYGON_3D; + +DECLARE_DYNAMIC_2D_ARRAY_PROTOS (POLYGON_3D, POINT_3D, FLOAT, polygon_3d, v, + n_sides) +// ---- vectors ---------------------------------------------------------------- + typedef FLOAT *VECTOR; + +// vectors of dynamic length + void init_vec (VECTOR * v); + void clear_vec (VECTOR * v); + void setup_vec (VECTOR * v, SIZE n); + void init_and_setup_vec (VECTOR * v, SIZE n); + void zero_vec (VECTOR r, SIZE n); + void copy_vec (VECTOR r, VECTOR v, SIZE n); + +// vectors of useful static length. + typedef FLOAT VECTOR_2D[2], VECTOR_3D[3], VECTOR_4D[4]; + + FLOAT length_vec_2d (VECTOR_2D v); + FLOAT length_vec_3d (VECTOR_3D v); + FLOAT dist_2d (POINT_2D p1, POINT_2D p2); + FLOAT dist_3d (POINT_3D p1, POINT_3D p2); + FLOAT length_vec_2d_sqr (VECTOR_2D v); + FLOAT length_vec_3d_sqr (VECTOR_3D v); + FLOAT dist_2d_sqr (POINT_2D p1, POINT_2D p2); + FLOAT dist_3d_sqr (POINT_3D p1, POINT_3D p2); + void zero_vec_2d (VECTOR_2D v); + void zero_vec_3d (VECTOR_3D v); + void negate_vec_2d (VECTOR_2D r, VECTOR_2D v); + void negate_vec_3d (VECTOR_3D r, VECTOR_3D v); + void copy_vec_2d (VECTOR_2D r, VECTOR_2D s); + void copy_vec_3d (VECTOR_3D r, VECTOR_3D s); + void scale_vec_2d (VECTOR_2D r, VECTOR_2D v, FLOAT s); + void scale_vec_3d (VECTOR_3D r, VECTOR_3D v, FLOAT s); + int find_unit_vec_2d (VECTOR_2D r, VECTOR_2D v); + int find_unit_vec_3d (VECTOR_3D r, VECTOR_3D v); + void add_vecs_2d (VECTOR_2D r, VECTOR_2D a, VECTOR_2D b); + void add_vecs_3d (VECTOR_3D r, VECTOR_3D a, VECTOR_3D b); + void sub_vecs_2d (VECTOR_2D r, VECTOR_2D a, VECTOR_2D b); + void sub_vecs_3d (VECTOR_3D r, VECTOR_3D a, VECTOR_3D b); + void add_vec_to_pt_2d (POINT_2D r, POINT_2D pt, VECTOR_2D v); + void add_vec_to_pt_3d (POINT_3D r, POINT_3D pt, VECTOR_3D v); + void add_scaled_vec_to_pt_2d (POINT_2D r, POINT_2D pt, VECTOR_2D v, + FLOAT s); + void add_scaled_vec_to_pt_3d (POINT_3D r, POINT_3D pt, VECTOR_3D v, + FLOAT s); + void sub_pts_2d (VECTOR_2D r, POINT_2D a, POINT_2D b); + void sub_pts_3d (VECTOR_3D r, POINT_3D a, POINT_3D b); + void fold_min_pt_2d (POINT_2D min, POINT_2D new_pt); + void fold_min_pt_3d (POINT_3D min, POINT_3D new_pt); + void fold_max_pt_2d (POINT_2D max, POINT_2D new_pt); + void fold_max_pt_3d (POINT_3D max, POINT_3D new_pt); + + FLOAT dot_2d (VECTOR_2D a, VECTOR_2D b); + FLOAT dot_3d (VECTOR_3D a, VECTOR_3D b); + void cross (VECTOR_3D r, VECTOR_3D a, VECTOR_3D b); + +// linear interpolation operators + void lerp_2d (POINT_2D r, FLOAT t, POINT_2D p1, POINT_2D p2); + void lerp_3d (POINT_3D r, FLOAT t, POINT_3D p1, POINT_3D p2); + +// find parameters of intersection point of two line segments + int line_intersect_2d (POINT_2D a, POINT_2D b, POINT_2D c, POINT_2D d, + FLOAT eps, FLOAT * t_ab, FLOAT * t_cd); + +// ---- planes ----------------------------------------------------------------- + typedef struct plane_t + { + VECTOR_3D n; + POINT_3D p; + FLOAT c; + } +PLANE; + +// return description of the plane of a polygon using Newell's method + void find_polygon_plane (PLANE * plane, POLYGON_3D * polygon); + +#define S_IN (1) +#define S_ON (2) +#define S_OUT (4) +#define S_IN_ON (S_ON | 8) +#define S_OUT_ON (S_ON | 16) +#define S_SPLIT (32) + +// #define PLANE_HALF_THICKNESS (10.0 * FLOAT_EPS) +#define PLANE_HALF_THICKNESS (.001/2) + +// given a plane of thickness 2 * half_thickness, return: +// S_IN or S_OUT if the point is resp. inside or outside the thickness of the plane +// S_IN_ON or S_OUT_ON if the point is within half_thickness of the plane on the resp. side +// S_ON if the point is precisely on the plane; no IN or OUT determination can be made + int pt_side_of_plane (PLANE * plane, POINT_3D p); + +// given a polygon and a plane, return: +// S_IN if all the verices are IN or ON the thickened plane +// S_OUT if all the verices are OUTside or ON the thickened plane +// S_ON if all vertice are ON the thickened plane +// S_SPLIT otherwise + int polygon_side_of_plane (POLYGON_3D * polygon, PLANE * plane); + +// given a polyline and a plane, return: +// S_IN if all segments of the line are fully INside the thickened plane +// S_OUT if all segments of the line are fully OUTside the thickened plane +// S_ON if all vertice are ON the thickened plane +// S_SPLIT otherwise + int polyline_side_of_plane (POLYLINE_3D * polyline, PLANE * plane); + +// ---- boxes ------------------------------------------------------------------ + + typedef struct box_2d_t + { + POINT_2D min, max; + } +BOX_2D; + + typedef struct box_3d_t + { + POINT_3D min, max; + } +BOX_3D; + + void init_box_2d (BOX_2D * b); + void init_box_3d (BOX_3D * b); + void fold_min_max_pt_2d (BOX_2D * b, POINT_2D p); + void fold_min_max_pt_3d (BOX_3D * b, POINT_3D p); + void fold_min_max_polygon_2d (BOX_2D * b, POLYGON_2D * polygon); + void fold_min_max_polygon_3d (BOX_3D * b, POLYGON_3D * polygon); + void fold_min_max_polyline_2d (BOX_2D * b, POLYLINE_2D * polyline); + void fold_min_max_polyline_3d (BOX_3D * b, POLYLINE_3D * polyline); + void copy_box_2d (BOX_2D * r, BOX_2D * s); + void copy_box_3d (BOX_3D * r, BOX_3D * s); + int boxes_2d_intersect_p (BOX_2D * a, BOX_2D * b); + int boxes_3d_intersect_p (BOX_2D * a, BOX_2D * b); + +// ---- transformations -------------------------------------------------------- + +// homogeneous transform stored in column major order + typedef FLOAT TRANSFORM[16]; + +// for initializations of identity transforms +#define IDENT_TRANSFORM \ +{ 1.0, 0.0, 0.0, 0.0, \ + 0.0, 1.0, 0.0, 0.0, \ + 0.0, 0.0, 1.0, 0.0, \ + 0.0, 0.0, 0.0, 1.0 } + +// ---- global contstants ------------------------------------------------------ + + extern TRANSFORM identity; + extern POINT_2D origin_2d; + extern POINT_3D origin_3d; + extern VECTOR_2D I_2d; + extern VECTOR_2D J_2d; + extern VECTOR_3D I_3d; + extern VECTOR_3D J_3d; + extern VECTOR_3D K_3d; + +// row-column tranform indexing matches OpenGL convention: column major +#define IT(I,J) (4 * ((J) - 1) + ((I) - 1)) + +// copy source to result transform + void copy_transform (TRANSFORM r, TRANSFORM s); + +// set the result transform to the identity + void set_ident (TRANSFORM r); + +// create a rotation transform thru angle theta about axis u (must be unit vec) + void set_angle_axis_rot (TRANSFORM r, FLOAT theta, VECTOR_3D u); + +// create a rotation transform thru angle theta +// u is optional axis which need not be a unit vector (default is [0,0,1]) +// p is optional center of rotation (default is (0,0,0)) + void set_angle_axis_rot_about_point (TRANSFORM r, FLOAT theta, + POINT_3D p, VECTOR_3D u); + +// create a scale transform + void set_scale (TRANSFORM r, FLOAT sx, FLOAT sy, FLOAT sz); + +// create a translation transform + void set_translation (TRANSFORM r, FLOAT dx, FLOAT dy, FLOAT dz); + +// create a true perspective projection (depth = p for all projected points) + void set_perspective_projection (TRANSFORM r, FLOAT p); + +// create a perspective transformation (depth is a pseudodepth) + void set_perspective_transform (TRANSFORM r, FLOAT p); + +// create a true parallel projection (depth = 0 for all projected points) + void set_parallel_projection (TRANSFORM r); + +// create an OpenGL-like view transformation matrix + void set_view_transform (TRANSFORM r, POINT_3D eye, VECTOR_3D vd, + VECTOR_3D up); + void set_view_transform_with_look_at (TRANSFORM r, POINT_3D eye, + POINT_3D look_at, VECTOR_3D up); + +// invert a given transform m; return its determinant; we give up if the +// determinant is too small + void invert (TRANSFORM r, FLOAT * det_rtn, TRANSFORM m, FLOAT min_det); + +// compose two transforms, but result cannot be the same as either operand + void compose_unsafe (TRANSFORM r, TRANSFORM a, TRANSFORM b); + +// same as above, but safe to use either operand to hold result. + void compose (TRANSFORM r, TRANSFORM a, TRANSFORM b); + + void transform_pt_3d (POINT_3D r, TRANSFORM m, POINT_3D p); + void transform_vec_3d (VECTOR_3D r, TRANSFORM m, VECTOR_3D p); + +// ---- quaternions ------------------------------------------------------------ + + typedef FLOAT QUATERNION[4]; + +// for initializations of identity quaternions +#define IDENT_QUAT { 0.0, 0.0, 0.0, 1.0 } + + void set_ident_quat (QUATERNION q); + void set_angle_axis_quat (QUATERNION q, FLOAT theta, VECTOR_3D axis); + void find_rot_from_quat (TRANSFORM r, QUATERNION q); + void find_quat_from_rot (QUATERNION q, TRANSFORM r); + void mult_quat (QUATERNION r, QUATERNION a, QUATERNION b); + +// clear any storage for vertices in a polygon; after this, +// its state is the same as after init_polygon_2d() + void clear_polygon_2d (POLYGON_2D * poly); + +// compute minkowski difference B - A with distinguished point p + void make_cso_polygon_2d (POLYGON_2D * r, POLYGON_2D * a, POINT_2D p, + POLYGON_2D * b); + +// checks to see if p is left of or on all the edges of polygon a. + int point_inside_convex_polygon_2d_p (POINT_2D p, POLYGON_2D * a); + +// checks to see if p is no more than eps right of all the edges of polygon a. + int point_near_convex_polygon_2d_p (POINT_2D p, POLYGON_2D * a, + FLOAT eps); + +#endif |