Posted to tcl by hypnotoad at Tue Oct 09 23:50:43 GMT 2018view raw
- /*
- ** This file is generated by the /Users/seandeelywoods/build/odie/odielib/make.tcl script
- ** any changes will be overwritten the next time it is run
- */
-
- /* This file was generated by practcl */
-
- #include <tcl.h>
- #include <tclOO.h>
- #include "odielibc.h"
- #include <assert.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include "inline_list.h"
- #include <limits.h>
- #include <float.h>
- #include <strings.h>
- /* BEGIN generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/hash/hash.tcl generate-cfile-header */
- /****** This file is copied from SQLite and modified *******
- **
- ** 2001 September 22
- **
- ** The author disclaims copyright to this source code. In place of
- ** a legal notice, here is a blessing:
- **
- ** May you do good and not evil.
- ** May you find forgiveness for yourself and forgive others.
- ** May you share freely, never taking more than you give.
- **
- *************************************************************************
- ** This is the implementation of generic hash-tables
- ** used in SQLite.
- **
- */
- #define uptr unsigned int
- #define Addr(X) ((uptr)X)
- #define readiMalloc malloc
- #define readiFree free
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/hash/hash.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/btree/btree.tcl generate-cfile-header */
- static void TreeClearNode(TreeElem *p, void (*xFree)(void*));
- static TreeElem *TreeFindNthElem(Tree *tree, int n);
- static void TreeBalance(TreeElem **ppElem);
- static void *TreeInsertElement(Tree *pTree, void *key, void *data);
- static TreeElem *TreeDeleteNthElem(TreeElem **ppTop, int N);
- static TreeElem *TreeDeleteElem(Tree *tree, const void *key);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/btree/btree.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/odiemath/odiemath.tcl generate-cfile-header */
- double OdieGrain=2.5;
- double OdieTolerance=0.001;
- static inline int Odie_GetMatrixElementFromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,double *R,int idx);
- static inline unsigned int hashInt(int x);
- static inline long intCoord(double x);
- static inline unsigned int hashPoint(VECTORXY p);
- static inline unsigned int hashVectorXY(VECTORXY p);
- static inline unsigned int hashVectorXYZ(VECTORXYZ p);
- static inline double roundCoord(double x);
- static inline int hashCoord(double x, double y);
- static inline int hashCoord3d(double x, double y,double z);
- static inline int floatCompare(double x0, double x1);
- static inline void GridCoord(double *x, double *y);
- static int TclCmd_odiemath_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_dist3d(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_grid_hex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_grid_round(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_grid_square(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_list_round(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_list_to_int(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_matrix_rotate_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_matrix_rotate_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_perpendicular(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_normal_2d(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_parallel_segment(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_vector_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_vector_rotate_and_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_vector_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_vector_translate_and_zoom(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_grid(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odiemath_tolerance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/odiemath/odiemath.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/module.ini generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/aabb.tcl generate-cfile-header */
- static inline void VectorXYZ_AABB_Normalize(AABBXYZ R);
- static void VectorXYZ_AABB_Copy(AABBXYZ dest,AABBXYZ src);
- static inline int VectorXYZ_AABB_Within(VectorXYZ POINT,AABBXYZ R);
- static inline int VectorXYZ_BBOX_Overlap_TwoVectors(VectorXYZ A1,VectorXYZ A2,VectorXYZ B1,VectorXYZ B2);
- static inline int AABB_AABB_Intersect(AABBXYZ A,AABBXYZ B);
- static inline void VectorXYZ_AABB_Measure(VectorXYZ POINT,AABBXYZ R);
- static inline void AABB_AABB_Combine(AABBXYZ B,AABBXYZ A);
- static inline void VectorXYZ_AABB_Reset(AABBXYZ R);
- static int TclCmd_odie_aabb_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_aabb_overlap_two_vectors(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_aabb_measure(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_aabb_faces(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_aabb_from_vectorxyz(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_aabb_from_line(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_aabb_from_center_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_aabb_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_aabb_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/aabb.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/affine2d.tcl generate-cfile-header */
- static int TclCmd_affine2d_apply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_affine2d_combine(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_affine2d_rotation_from_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_affine2d_rotation_from_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/affine2d.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/affine3d.tcl generate-cfile-header */
- static inline int affine_Compare(AFFINE A,AFFINE B);
- static inline void affine_rotate_spin(AFFINE RESULT,SCALER psi);
- static void Odie_Affine_From_Normal(AFFINE RESULT,VectorXYZ NORMAL);
- static int TclCmd_affine4x4_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_affine4x4_identity(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_affine4x4_translation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_affine4x4_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_affine4x4_rotate_nutation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_affine4x4_rotate_precession(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_affine4x4_rotate_spin(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_affine4x4_from_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_affine4x4_multiply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_affine4x4_multiply_inplace(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_affine4x4_inverse(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_affine4x4_from_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/affine3d.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/bbox.tcl generate-cfile-header */
- static inline void VectorXY_BBOX_Copy(BBOXXY dest,BBOXXY src);
- static inline void VectorXY_BBOX_Reset(BBOXXY R);
- static inline int VectorXY_IsBetween_BBOX(VectorXY POINT,VectorXY A,VectorXY B);
- static inline int VectorXY_Within_BBOX(VectorXY POINT,BBOXXY bbox);
- static inline int XY_Within_BBOX(double x, double y,BBOXXY bbox);
- static inline void VectorXY_BBOX_Measure(VectorXY POINT,BBOXXY bbox);
- static inline int BBOX_BBOX_Intersect(BBOXXY A,BBOXXY B);
- static int TclCmd_odie_bbox_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_bbox_measure(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_bbox_elements(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_bbox_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_bbox_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/bbox.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/quaternion.tcl generate-cfile-header */
- static inline void Quaternion_From_Normal(QUATERNION RESULT,VectorXYZ from,VectorXYZ to);
- static int TclCmd_quaternion_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_quaternion_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_quaternion_multiply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_quaternion_divide(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_quaternion_square_root(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_quaternion_square(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_quaternion_from_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_rotate_by_quaternion(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_quaternion_to_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_quaternion_from_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/quaternion.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector.tcl generate-cfile-header */
- static double Vector_Tolerance=0.01;
- static double Vector_Tolerance_Sq=0.0001;
- static Odie_MatrixObj *Odie_Matrix_To_Fit(Odie_MatrixObj *A,Odie_MatrixObj *B);
- static inline double Vector_GridScaler(double x,double grid,double grain);
- static int TclCmd_odie_tolerance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_vector_to_list(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_vector_index(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_vector_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_vector_is_null(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_vector_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_vector_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_vector_reciprocal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_vector_dot_product(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_vector_to_matrix(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_vector_to_fuzzy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_vector_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_vector_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_vector_length_squared(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_grid(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_odie_gridvar(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector2d.tcl generate-cfile-header */
- /*
- ** Routines in this file are designed to work with double numbers
- ** directly. Useful for screen operations where X Y lists are used
- */
- static inline int Vector2d_PointIsOnSegment(double x,double y,double x1,double y1,double x2,double y2);
- static int TclCmd_vector2d_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_affine_apply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_dotproduct(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_crossproduct(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_rightof(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_rotate_and_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_translate_and_zoom(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_point_on_segment(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_line_circle_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_line_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_line_overlap(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector2d_colinear(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector2d.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector3d.tcl generate-cfile-header */
- static int TclCmd_vector3d_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector3d_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector3d_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector3d_orthagonal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector3d_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vector3d_distanceSq(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector3d.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorn.tcl generate-cfile-header */
- static int TclCmd_vectorN_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorN_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorN_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorN_scalevar(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorn.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorxy.tcl generate-cfile-header */
- static inline void VectorXY_GridAlign(VECTORXYZ A,double grid);
- static inline void VectorXY_Midpoint(VECTORXY C,VECTORXY A,VECTORXY B);
- static int TclCmd_vectorxy_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_add_stream(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_toint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_crossproduct(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_normalize(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_dotproduct(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_rightof(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_rotate_and_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_translate_and_zoom(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxy_flatten(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorxy.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorxyz.tcl generate-cfile-header */
- static inline void VectorXYZ_Scale(VECTOR A,SCALER S);
- static inline void VectorXYZ_Zero(VECTORXYZ A);
- static inline void VectorXYZ_GridAlign(VECTORXYZ A,double grid);
- static inline void VectorXYZ_Copy(VECTORXYZ B,VECTORXYZ A);
- static inline int VectorXYZ_SamePoint(VECTORXYZ A,VECTORXYZ B);
- static inline int VectorXYZ_IsZero(VECTORXYZ A);
- static inline void VectorXYZ_Cross_Product(VectorXYZ C,VectorXYZ A,VectorXYZ B);
- static inline void VectorXYZ_Add(VECTORXYZ C,VECTORXYZ A,VECTORXYZ B);
- static inline void VectorXYZ_Subtract(VECTORXYZ C,VECTORXYZ A,VECTORXYZ B);
- static inline int VectorXYZ_IsOrthagonal(VECTORXYZ A,VECTORXYZ B);
- static inline void VectorXYZ_Midpoint(VECTORXYZ C,VECTORXYZ A,VECTORXYZ B);
- static inline double VectorXYZ_Distance(VECTORXYZ A,VECTORXYZ B);
- static inline double VectorXYZ_DistanceSq(VECTORXYZ A,VECTORXYZ B);
- static inline double VectorXYZ_Dot_Product(VectorXYZ A,VectorXYZ B);
- static inline void VectorXYZ_MatrixMultiply(VECTORXYZ R,VECTORXYZ A,AFFINE M);
- static inline double VectorXYZ_MagnitudeSq(VECTOR A);
- static inline double VectorXYZ_Magnitude(VECTOR A);
- static inline double VectorXYZ_MagnitudeInvSqr(VECTOR A);
- static inline int VectorXYZ_Normalize(VectorXYZ A);
- static inline int VectorXYZ_PointIsOnSegment(VectorXYZ POINT,VectorXYZ A,VectorXYZ B);
- static inline int VectorXYZ_AxisOfNormal(VectorXYZ NORMAL);
- static inline int VectorXYZ_NormalStrictAxisAligned(VectorXYZ NORMAL);
- static inline int VectorXYZ_AxisAligned(VectorXYZ A,VectorXYZ B,VectorXYZ C);
- static inline int VectorXYZ_BendDirection(VectorXYZ A,VectorXYZ B,VectorXYZ C);
- static inline double VectorXYZ_Angle_Three_Point(VectorXYZ A,VectorXYZ B,VectorXYZ C,VectorXYZ normal);
- static inline int VectorXYZ_IsColinear(VectorXYZ A,VectorXYZ B,VectorXYZ C);
- static inline int VectorXYZ_IsCoplaner(VectorXYZ x1,VectorXYZ x2,VectorXYZ x3,VectorXYZ x4);
- static inline int VectorXYZ_LineLineCoincident(
- VectorXYZ A1, VectorXYZ A2, VectorXYZ B1, VectorXYZ B2,
- VectorXYZ ICEPT1, VectorXYZ ICEPT2
- );
- static inline int VectorXYZ_LineLineIntersect(
- VectorXYZ p1, VectorXYZ p2, VectorXYZ p3, VectorXYZ p4,
- VectorXYZ pA, VectorXYZ pB, double *mua, double *mub
- );
- static double VectorXYZ_ClosestPointOnSegment (
- VectorXYZ A, VectorXYZ B, /* End points of the line segment */
- VectorXYZ X, /* The point outside the line */
- VectorXYZ R /* Write closest point on line segment here */
- );
- static int VectorXYX_solve3by3(double *m);
- static double VectorXYZ_TriangleLineIntersect(
- VectorXYZ A, VectorXYZ B, VectorXYZ C, /* The triangle we are trying to intersect */
- VectorXYZ pStart, /* Start of the line segment */
- VectorXYZ pEnd, /* End of the line segment */
- VectorXYZ pIntersect /* Point of intersection written here if not NULL */
- );
- static inline void VectorXYZ_Normal_of_Three_Points(VectorXYZ normal,VectorXYZ A,VectorXYZ B,VectorXYZ C);
- static int TclCmd_vectorxyz_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_zero(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_polygon_normal_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_toint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_add_inplace(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_orthagonal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_cross_product(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_dot_product(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_transform(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_distanceSq(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_length_inv_sqr(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_normalize(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_point_on_segment(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_point_on_segment_x(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_axis_of_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_bend_direction(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_angle_three_points(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_colinear(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_coplaner(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_linelinecoincident_int(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_linelinecoincident(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_linelineintersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_linelineintersect_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_sizeof(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_closest_point_on_segment(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_point_in_triangle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_triangle_line_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_line_sphere_intersect_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_line_sphere_intersect_area(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_line_sphere_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_polygon_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_polygon_center(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_vectorxyz_flatten(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorxyz.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/cmatrixforms.tcl generate-cfile-header */
- const MatrixForm MatrixForms[] = {
- { MATFORM_null, "null", 0 , 0, "A matrix of arbitrary size", NULL },
- { MATFORM_aabb_xyz, "aabb_xyz", 6, 1, "An axis aligned bounding box in 3 dimensions", NULL },
- { MATFORM_affine, "affine", 4, 4, "A 4x4 affine matrix", Matrix_To_affine },
- { MATFORM_bbox_xy, "bbox_xy", 4, 1, "A 2 dimensional vector: X Y", Matrix_To_cartesian },
- { MATFORM_cylindrical, "cylindrical", 3, 1, "A 3 dimensional vector: RADIUS THETA Z", Matrix_To_cylindrical },
- { MATFORM_euler, "euler", 3, 1, "A 3 dimensional rotation: X Y Z", NULL },
- { MATFORM_heading, "heading", 3, 1, "A 3 dimensional rotation: yaw pitch roll", NULL },
- { MATFORM_mat2, "mat2", 2, 2, "A 2x2 matrix", NULL },
- { MATFORM_mat3, "mat3", 3, 3, "A 3x3 matrix", NULL },
- { MATFORM_mat4, "mat4", 4, 4, "A 4x4 matrix", NULL },
- { MATFORM_polar, "polar", 2, 1, "A 2 dimensional vector: RADIUS THETA", Matrix_To_cylindrical },
- { MATFORM_quaternion, "quaternion", 4, 1, "A quaternion: W X Y Z", Matrix_To_quaternion },
- { MATFORM_scaler, "scaler", 1, 1, "A scaler (1x1)", NULL },
- { MATFORM_spherical, "spherical", 3, 1, "A 3 dimensional vector: RADIUS THETA PHI", Matrix_To_spherical },
- { MATFORM_unknown, "unknown", 0 , 0, "A matrix of arbitrary size (but less than 4x4)", NULL },
- { MATFORM_vector_xy, "vector_xy", 2, 1, "A 2 dimensional vector: X Y", Matrix_To_cartesian },
- { MATFORM_vector_xyz, "vector_xyz", 3, 1, "A 3 dimensional vector: X Y Z", Matrix_To_cartesian },
- { MATFORM_vector_xyzw, "vector_xyzw", 4, 1, "A 4 dimensional vector: X Y Z W", Matrix_To_cartesian }
- };
- /* Module wide constants */
- const Tcl_ObjType *NumArrayType;
- const Tcl_ObjType *odieMatrixType;
- static int TclCmd_matrix_to_aabb_xyz(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_affine(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_bbox_xy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_cylindrical(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_heading(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_mat2(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_mat3(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_mat4(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_null(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_polar(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_quaternion(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_scaler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_spherical(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_unknown(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_vector_xy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_vector_xyz(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_matrix_to_vector_xyzw(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/cmatrixforms.tcl generate-cfile-header */
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/module.ini generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/fuzzy/fuzzy.tcl generate-cfile-header */
- #ifdef _MSC_VER
- # define Odie_IsInfinite(d) (!(_finite((d))))
- # define Odie_IsNaN(d) (_isnan((d)))
- #else
- # define Odie_IsInfinite(d) ((d) > DBL_MAX || (d) < -DBL_MAX)
- # ifdef NO_ISNAN
- # define Odie_IsNaN(d) ((d) != (d))
- # else
- # define Odie_IsNaN(d) (isnan(d))
- # endif
- #endif
-
- static int TclCmd_tcl_mathfunc_to_fuzzy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_tcl_mathfunc_fuzzy_abs(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_tcl_mathfunc_fuzzy_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_tcl_mathfunc_fuzzy_is_zero(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_tcl_mathfunc_fuzzy_gt_zero(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_tcl_mathfunc_fuzzy_epsilon(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/fuzzy/fuzzy.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/module.ini generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/triangulate.tcl generate-cfile-header */
- #ifndef IRM_EPSILON
- #define IRM_EPSILON FLT_EPSILON
- #endif
-
- #ifndef M_PI
- # define M_PI 3.1415926535898
- #endif
-
- static int TclCmd_triag_test_rightof(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_triag_test_dotprod(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_triag_test_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_triag_test_ideal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/triangulate.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygon.tcl generate-cfile-header */
- static inline int Odie_IsColinear(double x1,double y1,double x2,double y2,double x3,double y3);
- static inline double dist(double x0, double y0, double x1, double y1);
- static inline int withinPolygon(Odie_Polygon *p, double x, double y);
- static int TclCmd_polygon_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_simplify(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_area(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_bbox(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_info(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_center(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_canvascoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_coords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_xycoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_edges(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_bend(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_is_convex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_segments(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_rectangle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_vector_place(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_hexagon(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_poly_place(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_drawobj_orientation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_corners(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_hexgrid_location(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_hexgrid_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygon_squaregrid_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygon.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygonxyz.tcl generate-cfile-header */
- static inline int Odie_FaceXYZ_Compare(Odie_FaceXYZ *A,Odie_FaceXYZ *B);
- static inline int Odie_FaceXYZ_Coplaner(Odie_FaceXYZ *A,Odie_FaceXYZ *B);
- static inline int PolygonUV_Within(Odie_FaceXYZ *p, double x, double y);
- static inline int Odie_FaceXYZ_Within(Odie_FaceXYZ *p, VectorXYZ POINT);
- static int Odie_FaceXYZ_IntersectTest(Odie_FaceXYZ *p1,Odie_FaceXYZ *p2);
- static double Odie_FaceXYZ_AreaOfIntersection(Odie_FaceXYZ *p1,Odie_FaceXYZ *p2,double *xin,double *yin);
- static int TclCmd_polygonxyz_info(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_createxy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_simplify(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_id(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_area(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_bbox(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_bend(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_center(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_is_2d(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_is_convex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_nVertex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_radius(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_rotation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_rotation_inv(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_axis_of_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_canvascoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_coords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_intcoordsxy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_intcoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_edges(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_triangles(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_uvcoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_xycoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_coplaner(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_flipped(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_side(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_intersect_test(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_intersect_test_uv(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_intersect_uv(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_points_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_polygonxyz_within_set(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygonxyz.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/segset.tcl generate-cfile-header */
- static void SegmentSet_Delete(ClientData clientData);
- static int SegmentSet_Clone(
- Tcl_Interp* interp, /* Tcl interpreter for error reporting */
- ClientData metadata, /* Metadata to be cloned */
- ClientData* newMetaData /* Where to put the cloned metadata */
- );
- static int SegmentSet_Cleanup_Coincident(SegmentSet *pSet,Segment *pAB);
- static int Segment_OnList(Segment *pSeg, Link *pList);
- static Segment *SegmentSet_FindById(SegmentSet *p, int id);
- static void Segment_Imprint(Segment *pSrc,Segment *pDest);
- static void Segment_SetToFrom(SegmentSet *pSet, Segment *p, VECTORXYZ from, VECTORXYZ to);
- static inline Segment *Segment_Create(SegmentSet *pSet,int newid);
- static inline void SegmentSetRemove(SegmentSet *pSet, Segment *p);
- static inline void SegRelink(SegmentSet *pSet, Segment *p);
- static inline void SegmentSetClear(SegmentSet *pSet);
- static inline void SegmentSetStep(SegmentSet *pSet);
- static int SegmentSet_AddVertex(SegmentSet *pSet,VectorXYZ A);
- static int SegmentSet_Interference_Check(SegmentSet *pSet,VectorXYZ A,VectorXYZ B);
- static int SegmentSet_Edge_Connection(SegmentSet *pSet,VectorXYZ A,int comptid,VectorXYZ RESULT);
- static int SegmentSet_Convex_Connection(SegmentSet *pSet,Segment *pAB,int back,VectorXYZ RESULT);
- static int SegmentSetNextBend(
- SegmentSet *pSet,
- Segment *pAB,
- int backwards,
- Segment **ppSeg, /* OUT: First segment clockwise from xR,yR->xV,yV */
- int *pfBack, /* OUT: True if output segment goes backwards */
- int *pfBend, /* OUT: Bend direction */
- double *pfAngle
- );
- static int SegmentSet_SelfCheck(Tcl_Interp *interp, SegmentSet *p);
- static Link *SegmentSet_Segments_AtVertex(SegmentSet *p, VectorXYZ point,int *nSeg);
- static int SegmentSetNext(
- SegmentSet *pSet,
- Segment *pAB,
- int backwards,
- Segment **ppSeg, /* OUT: First segment clockwise from xR,yR->xV,yV */
- int *pfBack, /* OUT: True if output segment goes backwards */
- int *pfBend, /* OUT: Bend direction */
- double *pfAngle
- );
- static void SegmentSet_ClearFaceEdgeCache(SegmentSet *pSet);
- static void FaceBoundary_Mark_Degenerate(FaceBoundary *pFace,int code);
- static int SegmentSet_BuildFaceEdgeCache_ExpandRight(SegmentSet *pSet,int faceid,int stage);
- static void SegmentSet_BuildFaceEdgeCache(SegmentSet *pSet);
- static int OOMethod_SegmentSet_segment_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_SegmentSet_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_modified(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_segment_count(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_bbox(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_segment_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_segment_add(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_segment_add_virtual(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_polygon_add(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_vertex_add(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_segment_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_cleanup(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_cleanup_looseend(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_edge_connection(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_check_intersecting(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_check_coincident(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_segment_linelineintersect(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_segment_coincident(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_segment_find(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_vertex_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_segment_next(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_check_oblique(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_check_looseends(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_fix_looseends(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_grid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_segment_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_segment_coords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_segment_uvcoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_selfcheck(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_uv_transform(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_polygons_xyz(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_polygons(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_polygon_faces(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SegmentSet_polygon_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int SegmentSet_OO_Init(Tcl_Interp *interp);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/segset.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/shapes.tcl generate-cfile-header */
- static int TclCmd_shapes_corners(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_shapes_drawobj_orientation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_shapes_poly_hex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_shapes_poly_place(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_shapes_polygon_to_vectors(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_shapes_rectangle_as_polygon(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_shapes_rectangle_as_vectors(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_shapes_vector_place(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_shapes_hexagon(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_shapes_canvas(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/shapes.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/plotter.tcl generate-cfile-header */
- static void Plotter_Delete(ClientData clientData);
- static int Plotter_Clone(
- Tcl_Interp* interp, /* Tcl interpreter for error reporting */
- ClientData metadata, /* Metadata to be cloned */
- ClientData* newMetaData /* Where to put the cloned metadata */
- );
- static inline double Plotter_xCanvasToActual(Plotter *p,double cx);
- static inline double Plotter_yCanvasToActual(Plotter *p,double cy);
- static inline double Plotter_xActualToCanvas(Plotter *p,double ax);
- static inline double Plotter_yActualToCanvas(Plotter *p,double ay);
- static int OOMethod_Plotter_actualcoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Plotter_canvascoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Plotter_centerset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Plotter_xoffset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Plotter_yoffset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Plotter_zoom(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Plotter_constructor(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int Plotter_OO_Init(Tcl_Interp *interp);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/plotter.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/slicer.tcl generate-cfile-header */
- static void Slicer_Delete(ClientData clientData);
- static int Slicer_Clone(
- Tcl_Interp* interp, /* Tcl interpreter for error reporting */
- ClientData metadata, /* Metadata to be cloned */
- ClientData* newMetaData /* Where to put the cloned metadata */
- );
- static double Slicer_xCanvasToActual(Slicer *p,struct OneSlice *pS, double cx);
- static double Slicer_yCanvasToActual(Slicer *p,struct OneSlice *pS, double cy);
- static double Slicer_xActualToCanvas(Slicer *p,struct OneSlice *pS, double ax);
- static double Slicer_yActualToCanvas(Slicer *p,struct OneSlice *pS, double ay);
- static double Slicer_deckHeight(struct OneSlice *p, double rX);
- static struct OneSlice *Slicer_deckAt(Slicer *p, double rX, double rZ);
- static struct OneSlice *Slicer_deckAbove(Slicer *p, struct OneSlice *pRef);
- static struct OneSlice *Slicer_deckBelow(Slicer *p, struct OneSlice *pRef);
- static void Slicer_computeTopAndBottom(Slicer *p);
- static int Slicer_getDeck(
- Tcl_Interp *interp, /* Put error messages here */
- Slicer *p, /* The slicer */
- double rX, /* X coord used to find deck if pObj is a Z coord */
- Tcl_Obj *pObj, /* Either a deck name or a Z coordinate */
- struct OneSlice **ppS /* Write the slice pointer here */
- );
- static int Slicer_getDeckId(
- Tcl_Interp *interp, /* Put error messages here */
- Slicer *p, /* The slicer */
- Tcl_Obj *pObj, /* Either a deck name or a Z coordinate */
- struct OneSlice **ppS /* Write the slice pointer here */
- );
- static inline struct OneSlice *Slicer_getDeck_FromInt(
- Slicer *p,
- int did
- );
- static int slicer_drawline_do(
- Tcl_Interp *interp,
- Slicer *p,
- int coord_count,
- int *deckCoord,double *xCoord,double *yCoord,
- struct OneSlice **apDeck,
- Tcl_Obj *canvas,
- const char *zKTag,
- const char *zXTag,
- const char *zBTag
- );
- static inline double Slicer_Location_zabs(Slicer *p,struct OneSlice *pS,double x0,double dheight);
- static inline double Location_zdeck(Slicer *p,struct OneSlice *pS,double x0,double dheight);
- static int OOMethod_Slicer_drawline(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_above(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_below(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_deckid_to_name(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_deckname_to_id(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_bbox_to_location(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_bbox_to_midpoint(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_xyz_to_location(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_location_to_xyz(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_location_z(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_distance(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_actualcoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_canvascoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_deck_at_xyz(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_deckid_at_xyx(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_makedlist(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_find(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_finddid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_flatheight(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_headroom(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_ceiling(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_height(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_deckheight(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_profile(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_xoffset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_zoom(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_upper_height(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Slicer_Slicer_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int Slicer_OO_Init(Tcl_Interp *interp);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/slicer.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/wallset.tcl generate-cfile-header */
- static void Wallset_Delete(ClientData clientData);
- static int Wallset_Clone(
- Tcl_Interp* interp, /* Tcl interpreter for error reporting */
- ClientData metadata, /* Metadata to be cloned */
- ClientData* newMetaData /* Where to put the cloned metadata */
- );
- static int OOMethod_Wallset_atvertex(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_boundary(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_closure(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_closure_polygon(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_closure_check(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_comptlist(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_corners(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_firstboundary(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_foreach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_rawinfo(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_insert(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_primary(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_intersect(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_left(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_looseends(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_nearest(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_nextcwwall(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_right(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_selfcheck(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_zoom(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_Wallset_constructor(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int Wallset_OO_Init(Tcl_Interp *interp);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/wallset.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/faceset.tcl generate-cfile-header */
- static PolygonHullVertex *PolygonHullVertex_ById(PolygonHull *pHull, int id);
- static PolygonHullVertex *PolygonHullVertex_ByCoords(PolygonHull *pHull, VectorXYZ A);
- static PolygonHullVertex *PolygonHullVertex_Create(
- PolygonHull *pHull,
- int id,
- VectorXYZ point
- );
- static void PolygonHullVertex_Remove(PolygonHullVertex *pVertex);
- static const char *PolygonHullFace_VertexInject(PolygonHullFace *pFace,PolygonHullVertex *pThisVertex);
- static PolygonHullFace *PolygonHullFace_Create(
- PolygonHull *pHull,
- int id
- );
- static PolygonHullFace *PolygonHull_mergeFaceList(PolygonHullFace *a, PolygonHullFace *b);
- static PolygonHullFace *PolygonHull_sortFaceList(PolygonHullFace *pList);
- static PolygonHullFace *PolygonHullFace_ById(PolygonHull *pHull, int id);
- static int PolygonHull_findFace(
- Tcl_Interp *interp, /* Leave any error message here */
- PolygonHull *pHull,
- Tcl_Obj *pObj, /* The PolygonHullFace ID */
- PolygonHullFace **ppHullFace /* Write PolygonHullFace pointer here */
- );
- static void PolygonHullFace_Remove(PolygonHullFace *pFace);
- static void PolygonHullFace_SerializeEdges(PolygonHullFace *p);
- static void PolygonHullFace_Compute(PolygonHullFace *pFace);
- static double PolygonHull_sqrDistPointToEdge(
- VectorXYZ A, VectorXYZ B, /* End points of the line segment */
- VectorXYZ X /* The point to measure distance to */
- );
- static double PolygonHull_intersectLineSegFace(
- PolygonHullFace *pFace, /* The triangle we are trying to intersect */
- VectorXYZ pStart, /* Start of the line segment */
- VectorXYZ pEnd, /* End of the line segment */
- VectorXYZ pIntersect /* Point of intersection written here if not NULL */
- );
- static PolygonHullFace *PolygonHullFace_findHits(PolygonHull *pHull, VectorXYZ A, VectorXYZ B);
- static double PolygonHull_closestPointOnFace(PolygonHullFace *p, VectorXYZ X, VectorXYZ R);
- static PolygonHullFace *PolygonHullFace_findClosest(PolygonHull *pHull,VectorXYZ X, VectorXYZ R, double *pDist);
- static PolygonHullVolume *PolygonHullVolume_ById(PolygonHull *pHull, int id);
- static PolygonHullVolume *PolygonHullVolume_Create(
- PolygonHull *pHull,
- int id
- );
- static void PolygonHullVolume_Unlink(PolygonHullVolume *pVolume);
- static void PolygonHull_clearSurfaces(PolygonHull *pHull);
- static void PolygonHull_Reset(PolygonHull *pHull);
- static void PolygonHull_Delete(ClientData clientData);
- static int PolygonHull_Clone(
- Tcl_Interp* interp, /* Tcl interpreter for error reporting */
- ClientData metadata, /* Metadata to be cloned */
- ClientData* newMetaData /* Where to put the cloned metadata */
- );
- static int OOMethod_PolygonHull_vertex_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_vertex_coords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_vertex_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_vertex_idlist(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_vertex_inject(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_vertex_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_vertex_at(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_exists(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_active(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_center(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_polygon(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_vertices(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_intersect(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_nearest(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_radius(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_normal(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_side(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_volume(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_faces_at(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_face_within(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_volume_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_volume_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_volume_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_volume_faces(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_volume_group(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_volume_center(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_PolygonHull_PolygonHull_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int PolygonHull_OO_Init(Tcl_Interp *interp);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/faceset.tcl generate-cfile-header */
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/module.ini generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/listcmd/listcmd.tcl generate-cfile-header */
- static int TclCmd_get(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_list_to_int(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_ladd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_ldelete(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/listcmd/listcmd.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/logicset/logicset.tcl generate-cfile-header */
- #define UCHAR(c) ((unsigned char) (c))
- #define TclFormatInt(buf, n) sprintf((buf), "%ld", (long)(n))
-
- #define MEM_DEBUG 0
-
- /*
- * Macros used to cast between pointers and integers (e.g. when storing an int
- * in ClientData), on 64-bit architectures they avoid gcc warning about "cast
- * to/from pointer from/to integer of different size".
- */
-
- #if !defined(INT2PTR) && !defined(PTR2INT)
- # if defined(HAVE_INTPTR_T) || defined(intptr_t)
- # define INT2PTR(p) ((void *)(intptr_t)(p))
- # define PTR2INT(p) ((int)(intptr_t)(p))
- # else
- # define INT2PTR(p) ((void *)(p))
- # define PTR2INT(p) ((int)(p))
- # endif
- #endif
- #if !defined(UINT2PTR) && !defined(PTR2UINT)
- # if defined(HAVE_UINTPTR_T) || defined(uintptr_t)
- # define UINT2PTR(p) ((void *)(uintptr_t)(p))
- # define PTR2UINT(p) ((unsigned int)(uintptr_t)(p))
- # else
- # define UINT2PTR(p) ((void *)(p))
- # define PTR2UINT(p) ((unsigned int)(p))
- # endif
- #endif
-
- #define VERSION "1.0"
-
- /*
- ** Internal call required for munging integers
- */
- #ifndef _TCLINT
- /*
- * The structure used as the internal representation of Tcl list objects. This
- * struct is grown (reallocated and copied) as necessary to hold all the
- * list's element pointers. The struct might contain more slots than currently
- * used to hold all element pointers. This is done to make append operations
- * faster.
- *
- * We only need this when compiling as a seperate library from tcl
- */
-
- typedef struct List {
- int refCount;
- int maxElemCount; /* Total number of element array slots. */
- int elemCount; /* Current number of list elements. */
- int canonicalFlag; /* Set if the string representation was
- * derived from the list representation. May
- * be ignored if there is no string rep at
- * all.*/
- Tcl_Obj *elements; /* First list element; the struct is grown to
- * accomodate all elements. */
- } List;
- #endif
- /*
- * During execution of the "lsort" command, structures of the following type
- * are used to arrange the objects being sorted into a collection of linked
- * lists.
- */
-
- typedef struct SortElement {
- union {
- char *strValuePtr;
- long intValue;
- double doubleValue;
- Tcl_Obj *objValuePtr;
- } index;
- Tcl_Obj *objPtr; /* Object being sorted, or its index. */
- struct SortElement *nextPtr;/* Next element in the list, or NULL for end
- * of list. */
- } SortElement;
-
-
- typedef struct SortInfo {
- int isIncreasing; /* Nonzero means sort in increasing order. */
- int sortMode; /* The sort mode. One of SORTMODE_* values * defined below. */
- Tcl_Obj *compareCmdPtr; /* The Tcl comparison command when sortMode is
- * SORTMODE_COMMAND. Pre-initialized to hold
- * base of command. */
- int *indexv; /* If the -index option was specified, this
- * holds the indexes contained in the list
- *
- * supplied as an argument to that option.
- * NULL if no indexes supplied, and points to
- * singleIndex field when only one
- * supplied.
- */
- int indexc; /* Number of indexes in indexv array. */
- int singleIndex; /* Static space for common index case. */
- int unique;
- int numElements;
- Tcl_Interp *interp; /* The interpreter in which the sort is being
- * done.
- */
- int resultCode; /* Completion code for the lsort command. If
- * an error occurs during the sort this is
- * changed from TCL_OK to TCL_ERROR. */
- } SortInfo;
-
- /*
- * These function pointer types are used with the "lsearch" and "lsort"
- * commands to facilitate the "-nocase" option.
- */
-
- typedef int (*SortStrCmpFn_t) (const char *, const char *);
- typedef int (*SortMemCmpFn_t) (const void *, const void *, size_t);
-
- /*
- * The "lsort" command needs to pass certain information down to the function
- * that compares two list elements, and the comparison function needs to pass
- * success or failure information back up to the top-level "lsort" command.
- * The following structure is used to pass this information.
- */
-
-
- /*
- * The "sortMode" field of the SortInfo structure can take on any of the
- * following values.
- */
-
- #define SORTMODE_ASCII 0
- #define SORTMODE_INTEGER 1
- #define SORTMODE_REAL 2
- #define SORTMODE_COMMAND 3
- #define SORTMODE_DICTIONARY 4
- #define SORTMODE_ASCII_NC 8
-
- /*
- * Magic values for the index field of the SortInfo structure. Note that the
- * index "end-1" will be translated to SORTIDX_END-1, etc.
- */
-
- #define SORTIDX_NONE -1 /* Not indexed; use whole value. */
- #define SORTIDX_END -2 /* Indexed from end. */
-
- /*
- * Forward declarations for procedures defined in this file:
- */
-
- static int DictionaryCompare(char *left, char *right);
- static SortElement * MergeLists(SortElement *leftPtr, SortElement *rightPtr,
- SortInfo *infoPtr);
- static int SortCompare(SortElement *firstPtr, SortElement *second,
- SortInfo *infoPtr);
- static Tcl_Obj *Odie_MergeList_ToObj(SortElement *elementPtr);
- static int TclCmd_logicset_union(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_logicset_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_logicset_contains(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_logicset_empty(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_logicset_expr_and(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_logicset_expr_or(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_logicset_product_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_logicset_product_union(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_logicset_product_xor(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_logicset_product_missing(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_logicset_remove(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/logicset/logicset.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/literal/literal.tcl generate-cfile-header */
- /*
- ** constant.c
- ** Series of routines to minimize memory usage through the use
- ** of shared strings
- */
-
- static Tcl_HashTable OdieLiteralStringTable;
- static Tcl_Obj *OdieStatic[14];
- static unsigned int nOdieObjString = 0;
- static unsigned int nOdieHashTable = 0;
- static unsigned int nOdieHashTableCreated = 0;
- static unsigned int nOdieHashTableDeleted = 0;
- static unsigned int nOdieDictSpecCount = 0;
- static unsigned int nOdieDictSpecCreated = 0;
- static unsigned int nOdieDictSpecDeleted = 0;
- static unsigned int nOdieDictSpecShared = 0;
- static unsigned int nOdieDictSpecNull = 0;
- static unsigned int nOdieDictSpecRecycled = 0;
- static unsigned int nOdieDictSpecModified = 0;
- static unsigned int nOdieDictSpecAccessed = 0;
-
- static int OdieTrace=0;
-
- typedef struct constObj {
- char *string;
- Tcl_Obj *tclobj;
- } constObj;
- static Tcl_Obj *Odie_constant(const char *zName,int create);
- static void Odie_constant_inject(Tcl_Obj *value);
- static int TclCmd_literal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_literal_dump(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_literal_stats(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_constant_string(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/literal/literal.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/module.ini generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/param.tcl generate-cfile-header */
- Tcl_Interp *local_interp = NULL;
- Simulator *CurrentSim = NULL;
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/param.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/location.tcl generate-cfile-header */
- static int TclCmd_location_grid_square(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_location_gridhash_square(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_location_location_gridhash(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_location_grid_hex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_location_gridhash_hex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_location_gridhash_adjacent(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_location_object(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_location_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- static int TclCmd_location_match(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/location.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simulator.tcl generate-cfile-header */
- static int OOMethod_Simulator_C_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int Simulator_OO_Init(Tcl_Interp *interp);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simulator.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/entity.tcl generate-cfile-header */
- #define CSTRUCT_agent 1
- #define CSTRUCT_compartment 2
- #define CSTRUCT_crew 3
- #define CSTRUCT_entity 4
- #define CSTRUCT_objective 5
- #define CSTRUCT_portal 6
- #define CSTRUCT_routecompartment 7
- #define CSTRUCT_routeportal 8
- #define CSTRUCT_simlink 9
- #define CSTRUCT_simnode 10
- #define CSTRUCT_simulator 11
- #define CSTRUCT_Count 11
- #define CSTRUCT_ENTITY_AliasCount 19
-
- #define ENTITY_ACTIVE_NULL 0 /* Not Checked */
- #define ENTITY_ACTIVE_SHOW 1 /* Mark Checked */
- #define ENTITY_ACTIVE_HIDE 2 /* Marked Hidden */
- #define ENTITY_CLASS_AGENT a /* Agent */
- #define ENTITY_CLASS_COMPARTMENT c /* Compartment */
- #define ENTITY_CLASS_EQUIPMENT e /* Equipment */
- #define ENTITY_CLASS_LINK l /* Conduit, Cable or Link */
- #define ENTITY_CLASS_MATERIAL m /* Material */
- #define ENTITY_CLASS_PORTAL p /* Portal */
- #define ENTITY_CLASS_ROLLUP r /* Deactivation Rollup */
- #define ENTITY_CLASS_HUMAN v /* Human */
- #define ENTITY_CLASS_WALL w /* Wall Type */
- #define ENTITY_CLASS_TREE x /* Type Tree Branch */
- #define ENTITY_CLASS_GENERIC y /* Generic Type */
- #define CSTRUCT_ENTITY_ACTIVE 0
- #define CSTRUCT_ENTITY_CHANGED 1
- #define CSTRUCT_ENTITY_CLASS 2
- #define CSTRUCT_ENTITY_DRAWN 3
- #define CSTRUCT_ENTITY_GROUPID 4
- #define CSTRUCT_ENTITY_HIDDEN 5
- #define CSTRUCT_ENTITY_HIGHLIGHT 6
- #define CSTRUCT_ENTITY_IS_TYPE 7
- #define CSTRUCT_ENTITY_MOVED 8
- #define CSTRUCT_ENTITY_NCHILD 9
- #define CSTRUCT_ENTITY_ONCOUNT 10
- #define CSTRUCT_ENTITY_OPEN 11
- #define CSTRUCT_ENTITY_PARENT 12
- #define CSTRUCT_ENTITY_REDRAW 13
- #define CSTRUCT_ENTITY_REPAINT 14
- #define CSTRUCT_ENTITY_SYNTHETIC 15
- #define CSTRUCT_ENTITY_TRACE 16
- #define CSTRUCT_ENTITY_VISIBLE 17
- #define CSTRUCT_ENTITY_Count 18
- static int OOMethod_OOEntity_C_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_attach_to(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_compartment(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_comptid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_count(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_deckid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_drawn_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_exists(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_for(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_foreach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_groupid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_groups_recalculate(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_hidden_inherit(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_location(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_midpoint(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_nodeget(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_nodeput(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_nodewith(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_normalize(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_orientation(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_redraw(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_setting(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_spec_get(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_spec_put(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_spec_replace(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_struct_get(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_struct_put(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_type(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_typeid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_visible(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_visible_filter(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_visible_hidden_subtract(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_visible_inherit(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_visible_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_visible_tree(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_OOEntity_witheach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOEntity_OO_Init(Tcl_Interp *interp);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/entity.tcl generate-cfile-header */
- /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simtype.tcl generate-cfile-header */
- static int OOMethod_SimType_C_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_children(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_count(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_exists(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_for(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_foreach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_groupid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_nodeget(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_nodeput(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_nodewith(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_normalize(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_parent(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_setting(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_spec_get(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_spec_put(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_spec_replace(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_struct_get(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_struct_put(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_type(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_typeid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_visible_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int OOMethod_SimType_witheach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
- static int SimType_OO_Init(Tcl_Interp *interp);
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simtype.tcl generate-cfile-header */
- /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/module.ini generate-cfile-header */
- /* END generate-cfile-header */
- /* BEGIN generate-cfile-constant */
- const static Tcl_ObjectMetadataType LinkDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "Link",
- NULL,
- NULL
- };
- #define GETLINK(OBJCONTEXT) (Link *) Tcl_ObjectGetMetadata(OBJCONTEXT,&LinkDataType)
- const static Tcl_ObjectMetadataType HashDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "Hash",
- NULL,
- NULL
- };
- #define GETHASH(OBJCONTEXT) (Hash *) Tcl_ObjectGetMetadata(OBJCONTEXT,&HashDataType)
- const static Tcl_ObjectMetadataType HashElemDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "HashElem",
- NULL,
- NULL
- };
- #define GETHASHELEM(OBJCONTEXT) (HashElem *) Tcl_ObjectGetMetadata(OBJCONTEXT,&HashElemDataType)
- const static Tcl_ObjectMetadataType Odie_MatrixObjDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "Odie_MatrixObj",
- NULL,
- NULL
- };
- #define GETODIE_MATRIXOBJ(OBJCONTEXT) (Odie_MatrixObj *) Tcl_ObjectGetMetadata(OBJCONTEXT,&Odie_MatrixObjDataType)
- const static Tcl_ObjectMetadataType MatrixFormDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "MatrixForm",
- NULL,
- NULL
- };
- #define GETMATRIXFORM(OBJCONTEXT) (MatrixForm *) Tcl_ObjectGetMetadata(OBJCONTEXT,&MatrixFormDataType)
- const Tcl_ObjType matrix_tclobjtype = {
- .name="matrix",
- .freeIntRepProc = &MatrixObj_freeIntRepProc,
- .dupIntRepProc = &MatrixObj_dupIntRepProc,
- .updateStringProc = &MatrixObj_updateStringProc,
- .setFromAnyProc = &MatrixObj_setFromAnyProc
- };
- const static Tcl_ObjectMetadataType TriagPointDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "TriagPoint",
- NULL,
- NULL
- };
- #define GETTRIAGPOINT(OBJCONTEXT) (TriagPoint *) Tcl_ObjectGetMetadata(OBJCONTEXT,&TriagPointDataType)
- const static Tcl_ObjectMetadataType TriagSegmentDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "TriagSegment",
- NULL,
- NULL
- };
- #define GETTRIAGSEGMENT(OBJCONTEXT) (TriagSegment *) Tcl_ObjectGetMetadata(OBJCONTEXT,&TriagSegmentDataType)
- const static Tcl_ObjectMetadataType TriagSegSetDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "TriagSegSet",
- NULL,
- NULL
- };
- #define GETTRIAGSEGSET(OBJCONTEXT) (TriagSegSet *) Tcl_ObjectGetMetadata(OBJCONTEXT,&TriagSegSetDataType)
- const static Tcl_ObjectMetadataType Odie_PolygonDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "Odie_Polygon",
- NULL,
- NULL
- };
- #define GETODIE_POLYGON(OBJCONTEXT) (Odie_Polygon *) Tcl_ObjectGetMetadata(OBJCONTEXT,&Odie_PolygonDataType)
- const Tcl_ObjType polygon_tclobjtype = {
- .name="polygon",
- .freeIntRepProc = &PolygonObj_freeIntRepProc,
- .dupIntRepProc = &PolygonObj_dupIntRepProc,
- .updateStringProc = &PolygonObj_updateStringRepProc,
- .setFromAnyProc = &PolygonObj_setFromAnyProc
- };
- const static Tcl_ObjectMetadataType Odie_FaceXYZDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "Odie_FaceXYZ",
- NULL,
- NULL
- };
- #define GETODIE_FACEXYZ(OBJCONTEXT) (Odie_FaceXYZ *) Tcl_ObjectGetMetadata(OBJCONTEXT,&Odie_FaceXYZDataType)
- const Tcl_ObjType odie_polygon_tclobjtype = {
- .name="odie_polygon",
- .freeIntRepProc = &Odie_FaceXYZ_freeIntRepProc,
- .dupIntRepProc = &Odie_FaceXYZ_dupIntRepProc,
- .updateStringProc = &Odie_FaceXYZ_updateStringProc,
- .setFromAnyProc = &Odie_FaceXYZ_setFromAnyProc
- };
- const static Tcl_ObjectMetadataType FaceBoundaryDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "FaceBoundary",
- NULL,
- NULL
- };
- #define GETFACEBOUNDARY(OBJCONTEXT) (FaceBoundary *) Tcl_ObjectGetMetadata(OBJCONTEXT,&FaceBoundaryDataType)
- const static Tcl_ObjectMetadataType SegmentDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "Segment",
- NULL,
- NULL
- };
- #define GETSEGMENT(OBJCONTEXT) (Segment *) Tcl_ObjectGetMetadata(OBJCONTEXT,&SegmentDataType)
- const static Tcl_ObjectMetadataType SegmentSetDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "SegmentSet",
- SegmentSet_Delete,
- SegmentSet_Clone
- };
- #define GETSEGMENTSET(OBJCONTEXT) (SegmentSet *) Tcl_ObjectGetMetadata(OBJCONTEXT,&SegmentSetDataType)
- const static Tcl_MethodType OOMethodType_SegmentSet_segment_info = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "segment_info",
- .callProc = OOMethod_SegmentSet_segment_info,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_SegmentSet_Init = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "SegmentSet_Init",
- .callProc = OOMethod_SegmentSet_SegmentSet_Init,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_modified = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "modified",
- .callProc = OOMethod_SegmentSet_modified,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_segment_count = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "segment_count",
- .callProc = OOMethod_SegmentSet_segment_count,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_bbox = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "bbox",
- .callProc = OOMethod_SegmentSet_bbox,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_segment_reset = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "segment_reset",
- .callProc = OOMethod_SegmentSet_segment_reset,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_segment_add = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "segment_add",
- .callProc = OOMethod_SegmentSet_segment_add,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_segment_add_virtual = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "segment_add_virtual",
- .callProc = OOMethod_SegmentSet_segment_add_virtual,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_polygon_add = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "polygon_add",
- .callProc = OOMethod_SegmentSet_polygon_add,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_vertex_add = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "vertex_add",
- .callProc = OOMethod_SegmentSet_vertex_add,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_segment_delete = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "segment_delete",
- .callProc = OOMethod_SegmentSet_segment_delete,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_delete = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "delete",
- .callProc = OOMethod_SegmentSet_delete,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_cleanup = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "cleanup",
- .callProc = OOMethod_SegmentSet_cleanup,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_cleanup_looseend = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "cleanup_looseend",
- .callProc = OOMethod_SegmentSet_cleanup_looseend,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_edge_connection = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "edge_connection",
- .callProc = OOMethod_SegmentSet_edge_connection,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_check_intersecting = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "check_intersecting",
- .callProc = OOMethod_SegmentSet_check_intersecting,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_check_coincident = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "check_coincident",
- .callProc = OOMethod_SegmentSet_check_coincident,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_segment_linelineintersect = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "segment_linelineintersect",
- .callProc = OOMethod_SegmentSet_segment_linelineintersect,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_segment_coincident = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "segment_coincident",
- .callProc = OOMethod_SegmentSet_segment_coincident,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_segment_find = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "segment_find",
- .callProc = OOMethod_SegmentSet_segment_find,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_vertex_delete = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "vertex_delete",
- .callProc = OOMethod_SegmentSet_vertex_delete,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_segment_next = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "segment_next",
- .callProc = OOMethod_SegmentSet_segment_next,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_check_oblique = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "check_oblique",
- .callProc = OOMethod_SegmentSet_check_oblique,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_check_looseends = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "check_looseends",
- .callProc = OOMethod_SegmentSet_check_looseends,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_fix_looseends = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "fix_looseends",
- .callProc = OOMethod_SegmentSet_fix_looseends,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_grid = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "grid",
- .callProc = OOMethod_SegmentSet_grid,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_segment_list = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "segment_list",
- .callProc = OOMethod_SegmentSet_segment_list,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_segment_coords = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "segment_coords",
- .callProc = OOMethod_SegmentSet_segment_coords,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_segment_uvcoords = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "segment_uvcoords",
- .callProc = OOMethod_SegmentSet_segment_uvcoords,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_selfcheck = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "selfcheck",
- .callProc = OOMethod_SegmentSet_selfcheck,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_uv_transform = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "uv_transform",
- .callProc = OOMethod_SegmentSet_uv_transform,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_polygons_xyz = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "polygons_xyz",
- .callProc = OOMethod_SegmentSet_polygons_xyz,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_polygons = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "polygons",
- .callProc = OOMethod_SegmentSet_polygons,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_polygon_faces = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "polygon_faces",
- .callProc = OOMethod_SegmentSet_polygon_faces,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SegmentSet_polygon_info = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "polygon_info",
- .callProc = OOMethod_SegmentSet_polygon_info,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_ObjectMetadataType PlotterDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "Plotter",
- Plotter_Delete,
- Plotter_Clone
- };
- #define GETPLOTTER(OBJCONTEXT) (Plotter *) Tcl_ObjectGetMetadata(OBJCONTEXT,&PlotterDataType)
- const static Tcl_MethodType OOMethodType_Plotter_actualcoords = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "actualcoords",
- .callProc = OOMethod_Plotter_actualcoords,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Plotter_canvascoords = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "canvascoords",
- .callProc = OOMethod_Plotter_canvascoords,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Plotter_centerset = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "centerset",
- .callProc = OOMethod_Plotter_centerset,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Plotter_xoffset = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "xoffset",
- .callProc = OOMethod_Plotter_xoffset,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Plotter_yoffset = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "yoffset",
- .callProc = OOMethod_Plotter_yoffset,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Plotter_zoom = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "zoom",
- .callProc = OOMethod_Plotter_zoom,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Plotter_constructor = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "constructor",
- .callProc = OOMethod_Plotter_constructor,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_ObjectMetadataType OneSliceDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "OneSlice",
- NULL,
- NULL
- };
- #define GETONESLICE(OBJCONTEXT) (OneSlice *) Tcl_ObjectGetMetadata(OBJCONTEXT,&OneSliceDataType)
- const static Tcl_ObjectMetadataType SlicerDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "Slicer",
- Slicer_Delete,
- Slicer_Clone
- };
- #define GETSLICER(OBJCONTEXT) (Slicer *) Tcl_ObjectGetMetadata(OBJCONTEXT,&SlicerDataType)
- const static Tcl_MethodType OOMethodType_Slicer_drawline = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "drawline",
- .callProc = OOMethod_Slicer_drawline,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_above = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "above",
- .callProc = OOMethod_Slicer_above,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_below = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "below",
- .callProc = OOMethod_Slicer_below,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_deckid_to_name = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "deckid_to_name",
- .callProc = OOMethod_Slicer_deckid_to_name,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_deckname_to_id = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "deckname_to_id",
- .callProc = OOMethod_Slicer_deckname_to_id,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_bbox_to_location = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "bbox_to_location",
- .callProc = OOMethod_Slicer_bbox_to_location,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_bbox_to_midpoint = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "bbox_to_midpoint",
- .callProc = OOMethod_Slicer_bbox_to_midpoint,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_xyz_to_location = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "xyz_to_location",
- .callProc = OOMethod_Slicer_xyz_to_location,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_location_to_xyz = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "location_to_xyz",
- .callProc = OOMethod_Slicer_location_to_xyz,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_location_z = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "location_z",
- .callProc = OOMethod_Slicer_location_z,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_distance = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "distance",
- .callProc = OOMethod_Slicer_distance,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_actualcoords = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "actualcoords",
- .callProc = OOMethod_Slicer_actualcoords,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_canvascoords = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "canvascoords",
- .callProc = OOMethod_Slicer_canvascoords,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_create = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "create",
- .callProc = OOMethod_Slicer_create,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_deck_at_xyz = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "deck_at_xyz",
- .callProc = OOMethod_Slicer_deck_at_xyz,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_deckid_at_xyx = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "deckid_at_xyx",
- .callProc = OOMethod_Slicer_deckid_at_xyx,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_delete = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "delete",
- .callProc = OOMethod_Slicer_delete,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_makedlist = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "makedlist",
- .callProc = OOMethod_Slicer_makedlist,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_find = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "find",
- .callProc = OOMethod_Slicer_find,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_finddid = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "finddid",
- .callProc = OOMethod_Slicer_finddid,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_flatheight = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "flatheight",
- .callProc = OOMethod_Slicer_flatheight,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_headroom = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "headroom",
- .callProc = OOMethod_Slicer_headroom,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_ceiling = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "ceiling",
- .callProc = OOMethod_Slicer_ceiling,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_height = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "height",
- .callProc = OOMethod_Slicer_height,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_deckheight = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "deckheight",
- .callProc = OOMethod_Slicer_deckheight,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_info = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "info",
- .callProc = OOMethod_Slicer_info,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_list = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "list",
- .callProc = OOMethod_Slicer_list,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_profile = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "profile",
- .callProc = OOMethod_Slicer_profile,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_xoffset = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "xoffset",
- .callProc = OOMethod_Slicer_xoffset,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_zoom = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "zoom",
- .callProc = OOMethod_Slicer_zoom,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_upper_height = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "upper_height",
- .callProc = OOMethod_Slicer_upper_height,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Slicer_Slicer_Init = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "Slicer_Init",
- .callProc = OOMethod_Slicer_Slicer_Init,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_ObjectMetadataType BoundaryDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "Boundary",
- NULL,
- NULL
- };
- #define GETBOUNDARY(OBJCONTEXT) (Boundary *) Tcl_ObjectGetMetadata(OBJCONTEXT,&BoundaryDataType)
- const static Tcl_ObjectMetadataType ComptBoxDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "ComptBox",
- NULL,
- NULL
- };
- #define GETCOMPTBOX(OBJCONTEXT) (ComptBox *) Tcl_ObjectGetMetadata(OBJCONTEXT,&ComptBoxDataType)
- const static Tcl_ObjectMetadataType WallsetDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "Wallset",
- Wallset_Delete,
- Wallset_Clone
- };
- #define GETWALLSET(OBJCONTEXT) (Wallset *) Tcl_ObjectGetMetadata(OBJCONTEXT,&WallsetDataType)
- const static Tcl_MethodType OOMethodType_Wallset_atvertex = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "atvertex",
- .callProc = OOMethod_Wallset_atvertex,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_boundary = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "boundary",
- .callProc = OOMethod_Wallset_boundary,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_closure = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "closure",
- .callProc = OOMethod_Wallset_closure,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_closure_polygon = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "closure_polygon",
- .callProc = OOMethod_Wallset_closure_polygon,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_closure_check = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "closure_check",
- .callProc = OOMethod_Wallset_closure_check,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_comptlist = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "comptlist",
- .callProc = OOMethod_Wallset_comptlist,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_corners = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "corners",
- .callProc = OOMethod_Wallset_corners,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_delete = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "delete",
- .callProc = OOMethod_Wallset_delete,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_firstboundary = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "firstboundary",
- .callProc = OOMethod_Wallset_firstboundary,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_foreach = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "foreach",
- .callProc = OOMethod_Wallset_foreach,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_info = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "info",
- .callProc = OOMethod_Wallset_info,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_rawinfo = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "rawinfo",
- .callProc = OOMethod_Wallset_rawinfo,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_insert = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "insert",
- .callProc = OOMethod_Wallset_insert,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_primary = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "primary",
- .callProc = OOMethod_Wallset_primary,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_intersect = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "intersect",
- .callProc = OOMethod_Wallset_intersect,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_left = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "left",
- .callProc = OOMethod_Wallset_left,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_list = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "list",
- .callProc = OOMethod_Wallset_list,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_looseends = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "looseends",
- .callProc = OOMethod_Wallset_looseends,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_nearest = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "nearest",
- .callProc = OOMethod_Wallset_nearest,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_nextcwwall = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "nextcwwall",
- .callProc = OOMethod_Wallset_nextcwwall,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_right = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "right",
- .callProc = OOMethod_Wallset_right,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_selfcheck = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "selfcheck",
- .callProc = OOMethod_Wallset_selfcheck,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_zoom = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "zoom",
- .callProc = OOMethod_Wallset_zoom,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_Wallset_constructor = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "constructor",
- .callProc = OOMethod_Wallset_constructor,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_ObjectMetadataType PolygonHullVertexDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "PolygonHullVertex",
- NULL,
- NULL
- };
- #define GETPOLYGONHULLVERTEX(OBJCONTEXT) (PolygonHullVertex *) Tcl_ObjectGetMetadata(OBJCONTEXT,&PolygonHullVertexDataType)
- const static Tcl_ObjectMetadataType PolygonHullFaceDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "PolygonHullFace",
- NULL,
- NULL
- };
- #define GETPOLYGONHULLFACE(OBJCONTEXT) (PolygonHullFace *) Tcl_ObjectGetMetadata(OBJCONTEXT,&PolygonHullFaceDataType)
- const static Tcl_ObjectMetadataType PolygonHullVolumeDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "PolygonHullVolume",
- NULL,
- NULL
- };
- #define GETPOLYGONHULLVOLUME(OBJCONTEXT) (PolygonHullVolume *) Tcl_ObjectGetMetadata(OBJCONTEXT,&PolygonHullVolumeDataType)
- const static Tcl_ObjectMetadataType PolygonHullDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "PolygonHull",
- PolygonHull_Delete,
- PolygonHull_Clone
- };
- #define GETPOLYGONHULL(OBJCONTEXT) (PolygonHull *) Tcl_ObjectGetMetadata(OBJCONTEXT,&PolygonHullDataType)
- const static Tcl_MethodType OOMethodType_PolygonHull_vertex_create = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "vertex_create",
- .callProc = OOMethod_PolygonHull_vertex_create,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_vertex_coords = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "vertex_coords",
- .callProc = OOMethod_PolygonHull_vertex_coords,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_vertex_delete = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "vertex_delete",
- .callProc = OOMethod_PolygonHull_vertex_delete,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_vertex_idlist = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "vertex_idlist",
- .callProc = OOMethod_PolygonHull_vertex_idlist,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_vertex_inject = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "vertex_inject",
- .callProc = OOMethod_PolygonHull_vertex_inject,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_vertex_list = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "vertex_list",
- .callProc = OOMethod_PolygonHull_vertex_list,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_vertex_at = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "vertex_at",
- .callProc = OOMethod_PolygonHull_vertex_at,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_info = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_info",
- .callProc = OOMethod_PolygonHull_face_info,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_exists = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_exists",
- .callProc = OOMethod_PolygonHull_face_exists,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_active = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_active",
- .callProc = OOMethod_PolygonHull_face_active,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_center = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_center",
- .callProc = OOMethod_PolygonHull_face_center,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_polygon = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_polygon",
- .callProc = OOMethod_PolygonHull_face_polygon,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_vertices = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_vertices",
- .callProc = OOMethod_PolygonHull_face_vertices,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_create = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_create",
- .callProc = OOMethod_PolygonHull_face_create,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_delete = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_delete",
- .callProc = OOMethod_PolygonHull_face_delete,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_intersect = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_intersect",
- .callProc = OOMethod_PolygonHull_face_intersect,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_list = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_list",
- .callProc = OOMethod_PolygonHull_face_list,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_nearest = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_nearest",
- .callProc = OOMethod_PolygonHull_face_nearest,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_radius = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_radius",
- .callProc = OOMethod_PolygonHull_face_radius,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_normal = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_normal",
- .callProc = OOMethod_PolygonHull_face_normal,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_side = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_side",
- .callProc = OOMethod_PolygonHull_face_side,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_volume = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_volume",
- .callProc = OOMethod_PolygonHull_face_volume,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_faces_at = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "faces_at",
- .callProc = OOMethod_PolygonHull_faces_at,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_face_within = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "face_within",
- .callProc = OOMethod_PolygonHull_face_within,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_volume_create = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "volume_create",
- .callProc = OOMethod_PolygonHull_volume_create,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_volume_delete = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "volume_delete",
- .callProc = OOMethod_PolygonHull_volume_delete,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_volume_list = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "volume_list",
- .callProc = OOMethod_PolygonHull_volume_list,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_volume_faces = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "volume_faces",
- .callProc = OOMethod_PolygonHull_volume_faces,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_volume_group = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "volume_group",
- .callProc = OOMethod_PolygonHull_volume_group,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_volume_center = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "volume_center",
- .callProc = OOMethod_PolygonHull_volume_center,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_reset = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "reset",
- .callProc = OOMethod_PolygonHull_reset,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_PolygonHull_PolygonHull_Init = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "PolygonHull_Init",
- .callProc = OOMethod_PolygonHull_PolygonHull_Init,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_ObjectMetadataType Odie_ObjDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "Odie_Obj",
- NULL,
- NULL
- };
- #define GETODIE_OBJ(OBJCONTEXT) (Odie_Obj *) Tcl_ObjectGetMetadata(OBJCONTEXT,&Odie_ObjDataType)
- const static Tcl_ObjectMetadataType entityObjDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "entityObj",
- NULL,
- NULL
- };
- #define GETENTITYOBJ(OBJCONTEXT) (entityObj *) Tcl_ObjectGetMetadata(OBJCONTEXT,&entityObjDataType)
- const static Tcl_ObjectMetadataType OdieParamNameMapDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "OdieParamNameMap",
- NULL,
- NULL
- };
- #define GETODIEPARAMNAMEMAP(OBJCONTEXT) (OdieParamNameMap *) Tcl_ObjectGetMetadata(OBJCONTEXT,&OdieParamNameMapDataType)
- const static Tcl_ObjectMetadataType Irm_LocationDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "Irm_Location",
- NULL,
- NULL
- };
- #define GETIRM_LOCATION(OBJCONTEXT) (Irm_Location *) Tcl_ObjectGetMetadata(OBJCONTEXT,&Irm_LocationDataType)
- const static Tcl_ObjectMetadataType SimulatorDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "Simulator",
- NULL,
- NULL
- };
- #define GETSIMULATOR(OBJCONTEXT) (Simulator *) Tcl_ObjectGetMetadata(OBJCONTEXT,&SimulatorDataType)
- const static Tcl_MethodType OOMethodType_Simulator_C_Init = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "C_Init",
- .callProc = OOMethod_Simulator_C_Init,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_ObjectMetadataType EntityDataType = {
- TCL_OO_METADATA_VERSION_CURRENT,
- "Entity",
- NULL,
- NULL
- };
- #define GETENTITY(OBJCONTEXT) (Entity *) Tcl_ObjectGetMetadata(OBJCONTEXT,&EntityDataType)
- const static Tcl_MethodType OOMethodType_OOEntity_C_Init = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "C_Init",
- .callProc = OOMethod_OOEntity_C_Init,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_create = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "create",
- .callProc = OOMethod_OOEntity_create,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_attach_to = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "attach_to",
- .callProc = OOMethod_OOEntity_attach_to,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_compartment = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "compartment",
- .callProc = OOMethod_OOEntity_compartment,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_comptid = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "comptid",
- .callProc = OOMethod_OOEntity_comptid,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_count = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "count",
- .callProc = OOMethod_OOEntity_count,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_deckid = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "deckid",
- .callProc = OOMethod_OOEntity_deckid,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_delete = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "delete",
- .callProc = OOMethod_OOEntity_delete,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_drawn_reset = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "drawn_reset",
- .callProc = OOMethod_OOEntity_drawn_reset,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_exists = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "exists",
- .callProc = OOMethod_OOEntity_exists,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_for = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "for",
- .callProc = OOMethod_OOEntity_for,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_foreach = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "foreach",
- .callProc = OOMethod_OOEntity_foreach,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_groupid = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "groupid",
- .callProc = OOMethod_OOEntity_groupid,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_groups_recalculate = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "groups_recalculate",
- .callProc = OOMethod_OOEntity_groups_recalculate,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_hidden_inherit = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "hidden_inherit",
- .callProc = OOMethod_OOEntity_hidden_inherit,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_list = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "list",
- .callProc = OOMethod_OOEntity_list,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_location = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "location",
- .callProc = OOMethod_OOEntity_location,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_midpoint = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "midpoint",
- .callProc = OOMethod_OOEntity_midpoint,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_nodeget = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "nodeget",
- .callProc = OOMethod_OOEntity_nodeget,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_nodeput = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "nodeput",
- .callProc = OOMethod_OOEntity_nodeput,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_nodewith = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "nodewith",
- .callProc = OOMethod_OOEntity_nodewith,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_normalize = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "normalize",
- .callProc = OOMethod_OOEntity_normalize,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_orientation = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "orientation",
- .callProc = OOMethod_OOEntity_orientation,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_redraw = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "redraw",
- .callProc = OOMethod_OOEntity_redraw,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_reset = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "reset",
- .callProc = OOMethod_OOEntity_reset,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_setting = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "setting",
- .callProc = OOMethod_OOEntity_setting,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_spec_get = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "spec_get",
- .callProc = OOMethod_OOEntity_spec_get,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_spec_put = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "spec_put",
- .callProc = OOMethod_OOEntity_spec_put,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_spec_replace = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "spec_replace",
- .callProc = OOMethod_OOEntity_spec_replace,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_struct_get = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "struct_get",
- .callProc = OOMethod_OOEntity_struct_get,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_struct_put = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "struct_put",
- .callProc = OOMethod_OOEntity_struct_put,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_type = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "type",
- .callProc = OOMethod_OOEntity_type,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_typeid = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "typeid",
- .callProc = OOMethod_OOEntity_typeid,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_visible = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "visible",
- .callProc = OOMethod_OOEntity_visible,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_visible_filter = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "visible_filter",
- .callProc = OOMethod_OOEntity_visible_filter,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_visible_hidden_subtract = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "visible_hidden_subtract",
- .callProc = OOMethod_OOEntity_visible_hidden_subtract,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_visible_inherit = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "visible_inherit",
- .callProc = OOMethod_OOEntity_visible_inherit,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_visible_reset = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "visible_reset",
- .callProc = OOMethod_OOEntity_visible_reset,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_visible_tree = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "visible_tree",
- .callProc = OOMethod_OOEntity_visible_tree,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_OOEntity_witheach = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "witheach",
- .callProc = OOMethod_OOEntity_witheach,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_C_Init = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "C_Init",
- .callProc = OOMethod_SimType_C_Init,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_children = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "children",
- .callProc = OOMethod_SimType_children,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_count = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "count",
- .callProc = OOMethod_SimType_count,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_create = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "create",
- .callProc = OOMethod_SimType_create,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_delete = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "delete",
- .callProc = OOMethod_SimType_delete,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_exists = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "exists",
- .callProc = OOMethod_SimType_exists,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_for = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "for",
- .callProc = OOMethod_SimType_for,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_foreach = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "foreach",
- .callProc = OOMethod_SimType_foreach,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_groupid = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "groupid",
- .callProc = OOMethod_SimType_groupid,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_list = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "list",
- .callProc = OOMethod_SimType_list,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_nodeget = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "nodeget",
- .callProc = OOMethod_SimType_nodeget,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_nodeput = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "nodeput",
- .callProc = OOMethod_SimType_nodeput,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_nodewith = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "nodewith",
- .callProc = OOMethod_SimType_nodewith,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_normalize = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "normalize",
- .callProc = OOMethod_SimType_normalize,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_parent = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "parent",
- .callProc = OOMethod_SimType_parent,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_setting = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "setting",
- .callProc = OOMethod_SimType_setting,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_spec_get = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "spec_get",
- .callProc = OOMethod_SimType_spec_get,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_spec_put = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "spec_put",
- .callProc = OOMethod_SimType_spec_put,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_spec_replace = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "spec_replace",
- .callProc = OOMethod_SimType_spec_replace,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_struct_get = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "struct_get",
- .callProc = OOMethod_SimType_struct_get,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_struct_put = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "struct_put",
- .callProc = OOMethod_SimType_struct_put,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_type = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "type",
- .callProc = OOMethod_SimType_type,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_typeid = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "typeid",
- .callProc = OOMethod_SimType_typeid,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_visible_reset = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "visible_reset",
- .callProc = OOMethod_SimType_visible_reset,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- const static Tcl_MethodType OOMethodType_SimType_witheach = {
- .version = TCL_OO_METADATA_VERSION_CURRENT,
- .name = "witheach",
- .callProc = OOMethod_SimType_witheach,
- .deleteProc = NULL,
- .cloneProc = NULL
- };
- /* END generate-cfile-constant */
- /* BEGIN generate-cfile-functions */
- /* *Odie_Alloc */
- void *Odie_Alloc(unsigned int size){
- /*
- ** Provide wrappers around malloc and free
- */
- void *p;
- p=(void *)ckalloc(size);
- memset(p,0,size);
- return p;
- }
- /*
- ** Hash and comparison functions when the mode is READI_HASH_INT
- */
- static int intHash(const void *pKey, int nKey){
- return nKey ^ (nKey<<8) ^ (nKey>>8);
- }
- static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- return n2 - n1;
- }
-
- /*
- ** Hash and comparison functions when the mode is READI_HASH_POINTER
- */
- static int ptrHash(const void *pKey, int nKey){
- uptr x = Addr(pKey);
- return x ^ (x<<8) ^ (x>>8);
- }
- static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( pKey1==pKey2 ) return 0;
- if( pKey1<pKey2 ) return -1;
- return 1;
- }
-
- /*
- ** Hash and comparison functions when the mode is READI_HASH_BINARY
- */
- static int binHash(const void *pKey, int nKey){
- int h = 0;
- const char *z = (const char *)pKey;
- while( nKey-- > 0 ){
- h = (h<<3) ^ h ^ *(z++);
- }
- return h & 0x7fffffff;
- }
- static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( n1!=n2 ) return n2-n1;
- return memcmp(pKey1,pKey2,n1);
- }
-
- /*
- ** Return a pointer to the appropriate hash function given the key class.
- **
- ** The C syntax in this function definition may be unfamilar to some
- ** programmers, so we provide the following additional explanation:
- **
- ** The name of the function is "hashFunction". The function takes a
- ** single parameter "keyClass". The return value of hashFunction()
- ** is a pointer to another function. Specifically, the return value
- ** of hashFunction() is a pointer to a function that takes two parameters
- ** with types "const void*" and "int" and returns an "int".
- */
- static int (*hashFunction(int keyClass))(const void*,int){
- switch( keyClass ){
- case READI_HASH_INT: return &intHash;
- case READI_HASH_POINTER: return &ptrHash;
- case READI_HASH_BINARY: return &binHash;;
- default: break;
- }
- return 0;
- }
-
- /*
- ** Return a pointer to the appropriate hash function given the key class.
- **
- ** For help in interpreted the obscure C code in the function definition,
- ** see the header comment on the previous function.
- */
- static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
- switch( keyClass ){
- case READI_HASH_INT: return &intCompare;
- case READI_HASH_POINTER: return &ptrCompare;
- case READI_HASH_BINARY: return &binCompare;
- default: break;
- }
- return 0;
- }
-
-
- /* Resize the hash table so that it cantains "new_size" buckets.
- ** "new_size" must be a power of 2. The hash table might fail
- ** to resize if Odie_Alloc() fails.
- */
- static void rehash(Hash *pH, int new_size){
- struct _ht *new_ht; /* The new hash table */
- HashElem *elem, *next_elem; /* For looping over existing elements */
- HashElem *x; /* Element being copied to new hash table */
- int (*xHash)(const void*,int); /* The hash function */
-
- assert( (new_size & (new_size-1))==0 );
- new_ht = (struct _ht *)Odie_Alloc( new_size*sizeof(struct _ht) );
- if( new_ht==0 ) return;
- memset(new_ht, 0, new_size*sizeof(struct _ht));
- if( pH->ht ) Odie_Free((char *)pH->ht);
- pH->ht = new_ht;
- pH->htsize = new_size;
- xHash = hashFunction(pH->keyClass);
- for(elem=pH->first, pH->first=0; elem; elem = next_elem){
- int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
- next_elem = elem->next;
- x = new_ht[h].chain;
- if( x ){
- elem->next = x;
- elem->prev = x->prev;
- if( x->prev ) x->prev->next = elem;
- else pH->first = elem;
- x->prev = elem;
- }else{
- elem->next = pH->first;
- if( pH->first ) pH->first->prev = elem;
- elem->prev = 0;
- pH->first = elem;
- }
- new_ht[h].chain = elem;
- new_ht[h].count++;
- }
- }
-
- /* This function (for internal use only) locates an element in an
- ** hash table that matches the given key. The hash for this key has
- ** already been computed and is passed as the 4th parameter.
- */
- static HashElem *findElementGivenHash(
- const Hash *pH, /* The pH to be searched */
- const void *pKey, /* The key we are searching for */
- int nKey,
- int h /* The hash for this key. */
- ){
- HashElem *elem; /* Used to loop thru the element list */
- int count; /* Number of elements left to test */
- int (*xCompare)(const void*,int,const void*,int); /* comparison function */
-
- if( pH->ht ){
- elem = pH->ht[h].chain;
- count = pH->ht[h].count;
- xCompare = compareFunction(pH->keyClass);
- while( count-- && elem ){
- if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
- return elem;
- }
- elem = elem->next;
- }
- }
- return 0;
- }
-
- /* Remove a single entry from the hash table given a pointer to that
- ** element and a hash on the element's key.
- */
- static void removeElementGivenHash(
- Hash *pH, /* The pH containing "elem" */
- HashElem* elem, /* The element to be removed from the pH */
- int h /* Hash value for the element */
- ){
- if( elem->prev ){
- elem->prev->next = elem->next;
- }else{
- pH->first = elem->next;
- }
- if( elem->next ){
- elem->next->prev = elem->prev;
- }
- if( pH->ht[h].chain==elem ){
- pH->ht[h].chain = elem->next;
- }
- pH->ht[h].count--;
- if( pH->ht[h].count<=0 ){
- pH->ht[h].chain = 0;
- }
- if( pH->copyKey && elem->pKey ){
- Odie_Free((char *)elem->pKey);
- }
- Odie_Free((char *) elem );
- pH->count--;
- }
- /* readiHashNoCase */
- int readiHashNoCase(const void *pKey, int nKey){
- const char *z = (const char *)pKey;
- int h = 0;
- if( nKey<=0 ) nKey = strlen(z);
- while( nKey > 0 ){
- h = (h<<3) ^ h ^ tolower(*z++);
- nKey--;
- }
- return h & 0x7fffffff;
- }
- /* readiHashInit */
- void readiHashInit(Hash *new, int keyClass, int copyKey){
-
- assert( new!=0 );
- assert( keyClass>=READI_HASH_INT && keyClass<=READI_HASH_BINARY );
- new->keyClass = keyClass;
- new->copyKey = copyKey && keyClass==READI_HASH_BINARY;
- new->first = 0;
- new->count = 0;
- new->htsize = 0;
- new->ht = 0;
- }
- /* readiHashClear */
- void readiHashClear(Hash *pH){
- HashElem *elem; /* For looping over all elements of the table */
-
- assert( pH!=0 );
- elem = pH->first;
- pH->first = 0;
- if( pH->ht ) Odie_Free((char *)pH->ht);
- pH->ht = 0;
- pH->htsize = 0;
- while( elem ){
- HashElem *next_elem = elem->next;
- if( pH->copyKey && elem->pKey ){
- Odie_Free((char *)elem->pKey);
- }
- Odie_Free((char *)elem);
- elem = next_elem;
- }
- pH->count = 0;
- }
- /* *readiHashFind */
- void *readiHashFind(const Hash *pH, const void *pKey, int nKey){
- int h; /* A hash on key */
- HashElem *elem; /* The element that matches key */
- int (*xHash)(const void*,int); /* The hash function */
-
- if( pH==0 || pH->ht==0 ) return 0;
- xHash = hashFunction(pH->keyClass);
- assert( xHash!=0 );
- h = (*xHash)(pKey,nKey);
- assert( (pH->htsize & (pH->htsize-1))==0 );
- elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
- return elem ? elem->data : 0;
- }
- /* *readiHashInsert */
- void *readiHashInsert(Hash *pH, const void *pKey, int nKey, void *data){
- int hraw; /* Raw hash value of the key */
- int h; /* the hash of the key modulo hash table size */
- HashElem *elem; /* Used to loop thru the element list */
- HashElem *new_elem; /* New element added to the pH */
- int (*xHash)(const void*,int); /* The hash function */
-
- assert( pH!=0 );
- xHash = hashFunction(pH->keyClass);
- assert( xHash!=0 );
- hraw = (*xHash)(pKey, nKey);
- assert( (pH->htsize & (pH->htsize-1))==0 );
- h = hraw & (pH->htsize-1);
- elem = findElementGivenHash(pH,pKey,nKey,h);
- if( elem ){
- void *old_data = elem->data;
- if( data==0 ){
- removeElementGivenHash(pH,elem,h);
- }else{
- elem->data = data;
- }
- return old_data;
- }
- if( data==0 ) return 0;
- new_elem = (HashElem*)Odie_Alloc( sizeof(HashElem) );
- if( new_elem==0 ) return data;
-
- if( pH->copyKey && pKey!=0 ){
- new_elem->pKey = Odie_Alloc( nKey );
- if( new_elem->pKey==0 ){
- Odie_Free((char *)new_elem);
- return data;
- }
- memcpy((void*)new_elem->pKey, pKey, nKey);
- }else{
- new_elem->pKey = (void*)pKey;
- }
- new_elem->nKey = nKey;
- pH->count++;
- if( pH->htsize==0 ) rehash(pH,8);
- if( pH->htsize==0 ){
- pH->count = 0;
- Odie_Free((char *)new_elem);
- return data;
- }
- if( pH->count > pH->htsize ){
- rehash(pH,pH->htsize*2);
- }
- assert( (pH->htsize & (pH->htsize-1))==0 );
- h = hraw & (pH->htsize-1);
- elem = pH->ht[h].chain;
- if( elem ){
- new_elem->next = elem;
- new_elem->prev = elem->prev;
- if( elem->prev ){ elem->prev->next = new_elem; }
- else { pH->first = new_elem; }
- elem->prev = new_elem;
- }else{
- new_elem->next = pH->first;
- new_elem->prev = 0;
- if( pH->first ){ pH->first->prev = new_elem; }
- pH->first = new_elem;
- }
- pH->ht[h].count++;
- pH->ht[h].chain = new_elem;
- new_elem->data = data;
- return 0;
- }
- /* int */
- void TreeInit(Tree *tree, int (*xCompare)(const void*, const void*),void *(*xCopy)(const void*),void (*xFree)(void*)){
- /* Turn bulk memory into a Tree structure
- Tree *tree, Tree object to initialize
- int (*xCompare)(const void*, const void*), Comparison function
- void *(*xCopy)(const void*), Key copy function or NULL
- void (*xFree)(void*) Key delete function or NULL
- */
- tree->xCompare = xCompare;
- tree->xCopy = xCopy;
- tree->xFree = xFree;
- tree->top = 0;
- }
- /* TreeCount */
- int TreeCount(Tree *pTree){
- /* Return the number of elements in the tree. */
- if( pTree && pTree->top ){
- return pTree->top->weight;
- }else{
- return 0;
- }
- }
- /* void */
- static void TreeClearNode(TreeElem *p, void (*xFree)(void*)){
- /* Delete a single node of the binary tree and all of its children */
- if( p==0 ) return;
- if( p->left ) TreeClearNode(p->left, xFree);
- if( p->right ) TreeClearNode(p->right, xFree);
- if( xFree ){
- xFree(p->key);
- }
- Tcl_Free((char *)p);
- }
- /* TreeClear */
- void TreeClear(Tree *tree){
- /* Remove all nodes from a tree */
- if( tree->top ){
- TreeClearNode(tree->top, tree->xFree);
- }
- tree->top = 0;
- }
- /* *TreeFind */
- void *TreeFind(Tree *tree, const void *key){
- /* Find the element of the tree (if any) whose key matches "key".
- ** Return a pointer to the data for that element. If no match
- ** is found, return NULL.
- */
- TreeElem *p;
-
- p = tree->top;
- while( p ){
- int c = tree->xCompare(p->key, key);
- if( c==0 ){
- return p->data;
- }else if( c<0 ){
- p = p->right;
- }else{
- p = p->left;
- }
- }
- return 0;
- }
- /* TreeRank */
- int TreeRank(Tree *tree, const void *key){
- /* If the node with key "key" is the left-most element of the tree,
- ** return 0. If it is the second to the left, return 1. And so
- ** forth.
- **
- ** If there is no node in the tree with the key "key", then return
- ** the number that would have been returned if such a node were
- ** inserted.
- */
- TreeElem *p;
- int rank = 0;
-
- p = tree->top;
- while( p ){
- int c = tree->xCompare(p->key, key);
- if( c==0 ){
- rank += p->left ? p->left->weight: 0;
- break;
- }else if( c<0 ){
- rank += (p->left ? p->left->weight: 0) + 1;
- p = p->right;
- }else{
- p = p->left;
- }
- }
- return rank;
- }
- /* *TreeFindNthElem */
- static TreeElem *TreeFindNthElem(Tree *tree, int n){
- /* Return a pointer to the N-th element of a tree. (The left-most
- ** element is number 0, the next is number 1 and so forth.)
- */
- TreeElem *p;
-
- p = tree->top;
- while( p ){
- int c = p->left ? p->left->weight : 0;
- if( n==c ){
- return p;
- }else if( n>c ){
- n -= c+1;
- p = p->right;
- }else{
- p = p->left;
- }
- }
- return 0;
- }
- /* *TreeData */
- void *TreeData(Tree *tree, int n){
- /* Return the data associated with the N-th element of the tree. Return
- ** NULL if there is no N-th element.
- */
- TreeElem *p = TreeFindNthElem(tree,n);
- return p ? p->data : 0;
- }
- /* *TreeKey */
- const void *TreeKey(Tree *tree, int n){
- /* Return the key associated with the N-th element of the tree. Return
- ** NULL if there is no N-th element.
- */
- TreeElem *p = TreeFindNthElem(tree,n);
- if( p ){
- return p->key;
- }else{
- return 0;
- }
- }
- /* TreeBalance */
- static void TreeBalance(TreeElem **ppElem){
- /*
- ** Definitions:
- ** WEIGHT
- ** The weight of a node is the total number of children for the node
- ** plus 1. Leaf nodes have a weight of 1. The root node has a weight
- ** which equals the number of nodes in the tree.
- **
- ** BALANCE
- ** A node is balanced if the weight of the one child is not more than
- ** twice the weight of the other child.
- */
-
- /* The following routine rebalances the tree rooted at *ppElem after
- ** the insertion or deletion of a single ancestor.
- */
- TreeElem *n; /* Pointer to self */
- int l,r; /* Weight of left and right daughters */
- int a,b; /* Weights of various nodes */
-
- if( ppElem==0 || (n=*ppElem)==0 ) return;
- l = n->left ? n->left->weight: 0;
- r = n->right ? n->right->weight: 0;
- if( l>r*2 ){ /* Too heavy on the left side */
- TreeElem *nl; /* Pointer to left daughter */
- TreeElem *nr; /* Pointer to right daughter */
- int ll, lr; /* Weight of left daughter's left and right daughter */
- nl = n->left;
- ll = nl->left ? nl->left->weight: 0;
- lr = nl->right ? nl->right->weight: 0;
- if( ll>lr || nl->right==0 ){
- /*
- ** Convert from: n to: nl
- ** / \ / ** nl c a n
- ** / \ / ** a b b c
- */
- n->left = nl->right;
- nl->right = n;
- n->weight = a = r + lr + 1;
- nl->weight = a + ll + 1;
- *ppElem = nl;
- }else{
- /*
- ** Convert from: n to: nr
- ** / \ / ** nl d nl n
- ** / \ / \ / ** a nr a b c d
- ** / ** b c
- */
- int lrl, lrr; /* Weight of Great-granddaughter nodes */
- nr = nl->right;
- lrl = nr->left ? nr->left->weight: 0;
- lrr = nr->right ? nr->right->weight: 0;
- nl->right = nr->left;
- nr->left = nl;
- n->left = nr->right;
- nr->right = n;
- n->weight = a = lrr + r + 1;
- nl->weight = b = ll + lrl + 1;
- nr->weight = a + b + 1;
- *ppElem = nr;
- }
- }else if( r>l*2 ){/* Too deep on the right side */
- TreeElem *nl; /* Pointer to left daughter */
- TreeElem *nr; /* Pointer to right daughter */
- int rl, rr; /* Weight of right daughter's left and right daughter */
- nr = n->right;
- rl = nr->left ? nr->left->weight: 0;
- rr = nr->right ? nr->right->weight: 0;
- if( rr>rl || nr->left==0 ){
- /*
- ** Convert from: n to: nr
- ** / \ / ** a nr n c
- ** / \ / ** b c a b
- */
- n->right = nr->left;
- nr->left = n;
- n->weight = a = l + rl + 1;
- nr->weight = a + rr + 1;
- *ppElem = nr;
- }else{
- /*
- ** Convert from: n to: nl
- ** / \ / ** a nr n nr
- ** / \ / \ / ** nl d a b c d
- ** / ** b c
- */
- int rll,rlr; /* Weights of great-granddaughter nodes */
- nl = nr->left;
- rll = nl->left ? nl->left->weight: 0;
- rlr = nl->right ? nl->right->weight: 0;
- nr->left = nl->right;
- nl->right = nr;
- n->right = nl->left;
- nl->left = n;
- n->weight = a = l + rll + 1;
- nr->weight = b = rr + rlr + 1;
- nl->weight = a + b + 1;
- *ppElem = nl;
- }
- }else{ /* Node is already balanced. Just recompute its weight. */
- n->weight = l + r + 1;
- }
- }
- /* *TreeInsertElement */
- static void *TreeInsertElement(Tree *pTree, void *key, void *data){
- /*
- Tree *pTree, The root of the tree
- void *key, Insert data at this key
- void *data Data to be inserted
- */
- /* This routine either changes the data on an existing node in the tree,
- ** or inserts a new node. "key" identifies the node. If the data on
- ** an existing node is changed, then the function returns the old data.
- ** If a new node is created, NULL is returned.
- */
- TreeElem *n;
- void *old = 0;
- TreeElem **h[100]; /* Sufficient for a tree with up to 4.0E+17 nodes */
- int level = 0;
-
-
- h[0] = &pTree->top;
- level = 1;
- n = pTree->top;
- while( n ){
- int c;
- c = pTree->xCompare(key, n->key);
- if( c<0 ){
- h[level++] = &(n->left);
- n = n->left;
- }else if( c>0 ){
- h[level++] = &(n->right);
- n = n->right;
- }else{
- old = n->data;
- n->data = data; /* Replace data in an existing node */
- break;
- }
- }
- if( n==0 ){ /* Insert a leaf node */
- level--;
- n = *h[level] = (TreeElem *)Tcl_Alloc( sizeof(TreeElem) );
- if( n==0 ){
- return data;
- }
- n->data = data;
- if( pTree->xCopy ){
- n->key = pTree->xCopy(key);
- }else{
- n->key = key;
- }
- n->left = n->right = 0;
- while( level>=0 ) TreeBalance(h[level--]);
- }
- return old;
- }
- /* *TreeDeleteNthElem */
- static TreeElem *TreeDeleteNthElem(TreeElem **ppTop, int N){
- /* Unlink the N-th node of the tree and return a pointer to that
- ** node. (The left-most node is 0, the next node to the right is
- ** 1 and so forth.)
- */
- TreeElem *p; /* For walking the tree */
- int level = 0; /* Depth of the blancing stack */
- TreeElem **h[100]; /* Balance stack. 100 is sufficient for balancing
- ** a tree with up to 4.0E+17 nodes */
-
- h[0] = ppTop;
- level = 1;
- p = *ppTop;
- while( p ){
- int w;
- w = (p->left ? p->left->weight: 0);
- if( N>w ){
- h[level++] = &(p->right);
- p = p->right;
- N -= w+1;
- }else if( N<w ){
- h[level++] = &(p->left);
- p = p->left;
- }else{
- break;
- }
- }
- if( p ){
- level--;
- if( p->left==0 ){
- *h[level] = p->right;
- level--;
- }else if( p->right==0 ){
- *h[level] = p->left;
- level--;
- }else{
- TreeElem *x;
- x = TreeDeleteNthElem(&(p->right),0);
- x->right = p->right;
- x->left = p->left;
- *h[level] = x;
- }
- while( level>=0 ) TreeBalance(h[level--]);
- }
- return p;
- }
- /* *TreeDeleteElem */
- static TreeElem *TreeDeleteElem(Tree *tree, const void *key){
- /* Unlink the node of the tree corresponding to key and return a pointer
- ** to that node.
- */
- TreeElem *p; /* For walking the tree */
- int level = 0; /* Depth of the blancing stack */
- TreeElem **h[100]; /* Balance stack. 100 is sufficient for balancing
- ** a tree with up to 4.0E+17 nodes */
-
- h[0] = &tree->top;
- level = 1;
- p = tree->top;
- while( p ){
- int w;
- w = tree->xCompare(p->key, key);
- if( w<0 ){
- h[level++] = &(p->right);
- p = p->right;
- }else if( w>0 ){
- h[level++] = &(p->left);
- p = p->left;
- }else{
- break;
- }
- }
- if( p ){
- level--;
- if( p->left==0 ){
- *h[level] = p->right;
- level--;
- }else if( p->right==0 ){
- *h[level] = p->left;
- level--;
- }else{
- TreeElem *x;
- x = TreeDeleteNthElem(&(p->right),0);
- x->right = p->right;
- x->left = p->left;
- *h[level] = x;
- }
- while( level>=0 ) TreeBalance(h[level--]);
- }
- return p;
- }
- /* *TreeInsert */
- void *TreeInsert(Tree *tree, void *key, void *data){
- /* Insert new data into a node of the tree. The node is identified
- ** by "key".
- **
- ** If the new data is NULL, then node is deleted.
- **
- ** If the node aready exists, the new data overwrites the old and
- ** the old data is returned. If the node doesn't already exist, then
- ** a new node is created and the function returns NULL.
- */
-
- void *old;
- if( data==0 ){
- TreeElem *elem = TreeDeleteElem(tree, key);
- if( elem ){
- if( tree->xFree ){
- tree->xFree(elem->key);
- }
- old = elem->data;
- Tcl_Free((char *)elem);
- }else{
- old = 0;
- }
- }else{
- old = TreeInsertElement(tree,key,data);
- }
- return old;
- }
- /* *TreeChangeNth */
- void *TreeChangeNth(Tree *tree, int n, void *data){
- /* Change the data on the n-th node of the tree. The old data
- ** is returned.
- **
- ** If data==NULL, then the n-th node of the tree is deleted. (The
- ** data associated with that node is still returned.)
- **
- ** If the value N is out-of-bounds, then no new node is created.
- ** Instead, the "data" parameter is returned.
- */
- void *old;
- if( data==0 ){
- TreeElem *elem = TreeDeleteNthElem(&tree->top,n);
- if( elem ){
- if( tree->xFree ){
- tree->xFree(elem->key);
- }
- old = elem->data;
- Tcl_Free((char *)elem);
- }else{
- old = 0;
- }
- }else{
- TreeElem *elem = TreeFindNthElem(tree,n);
- if( elem ){
- old = elem->data;
- elem->data = data;
- }else{
- old = data;
- }
- }
- return old;
- }
- /* Odie_GetMatrixElementFromObj */
- static inline int Odie_GetMatrixElementFromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,double *R,int idx){
- double temp;
- if( Tcl_GetDoubleFromObj(interp, objPtr, &temp) ) return TCL_ERROR;
- R[idx]=temp;
- return TCL_OK;
- }
- /* hashInt */
- static inline unsigned int hashInt(int x){
- /*
- ** Compute a hash on an integer.
- */
- return (x & 0x7fffffff) % SZ_HASH;
- }
- /* intCoord */
- static inline long intCoord(double x){
- /*
- ** Round a coordinate to its nearest grain boundary
- */
- long idxX = x/OdieGrain + (x>0.0 ? 0.5 : -0.5);
- return idxX*OdieGrain;
- }
- /* hashPoint */
- static inline unsigned int hashPoint(VECTORXY p){
- /*
- ** Compute a hash on a point.
- */
- long x=intCoord(p[X_IDX])*ODIE_X_HASH;
- long y=intCoord(p[Y_IDX])*ODIE_Y_HASH;
- return hashInt(x ^ y);
- }
- /* hashVectorXY */
- static inline unsigned int hashVectorXY(VECTORXY p){
- long x=intCoord(p[X_IDX])*ODIE_X_HASH;
- long y=intCoord(p[Y_IDX])*ODIE_Y_HASH;
- return hashInt(x ^ y);
- }
- /* hashVectorXYZ */
- static inline unsigned int hashVectorXYZ(VECTORXYZ p){
- long x=intCoord(p[X_IDX])*ODIE_X_HASH;
- long y=intCoord(p[Y_IDX])*ODIE_Y_HASH;
- long z=intCoord(p[Z_IDX])*ODIE_Z_HASH;
- if(z!=0) {
- return hashInt(x ^ y ^ z);
- } else {
- return hashInt(x ^ y);
- }
- }
- /* roundCoord */
- static inline double roundCoord(double x){
- return intCoord(x);
- }
- /* hashCoord */
- static inline int hashCoord(double x, double y){
- /*
- ** Compute a hash on a pair of floating point number.
- */
- long idxX = intCoord(x)*ODIE_X_HASH;
- long idxY = intCoord(y)*ODIE_Y_HASH;
- return hashInt(idxX ^ idxY);
- }
- /* hashCoord3d */
- static inline int hashCoord3d(double x, double y,double z){
- /*
- ** Compute a hash on a pair of floating point number.
- */
- long idxX = intCoord(x)*ODIE_X_HASH;
- long idxY = intCoord(y)*ODIE_Y_HASH;
- long idxZ = intCoord(z)*ODIE_Z_HASH;
- if(idxZ!=0) {
- return hashInt(idxX ^ idxY ^ idxZ);
- } else {
- return hashInt(idxX ^ idxY);
- }
- }
- /* floatCompare */
- static inline int floatCompare(double x0, double x1){
- /*
- ** Compare to floating point values and return negative, zero, or
- ** positive if the first value is less than, equal to, or greater
- ** than the second.
- */
- double diff = x1 - x0;
- if( diff>-OdieGrain && diff<OdieGrain ){
- diff = 0.0;
- }
- return (int)diff;
- }
- /* GridCoord */
- static inline void GridCoord(double *x, double *y){
- /*
- ** Round a set of coordinates by OdieGrain
- */
- *x=round(*x/OdieGrain)*OdieGrain;
- *y=round(*y/OdieGrain)*OdieGrain;
- }
- /* Math_Const_Init */
- int Math_Const_Init(Tcl_Interp *interp){
- Tcl_Obj *varname=Tcl_NewStringObj("math_const",-1);
- Tcl_IncrRefCount(varname);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_2_x_pi",-1),Tcl_NewDoubleObj(M_2_X_PI),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi_180",-1),Tcl_NewDoubleObj(M_PI_180),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi_360",-1),Tcl_NewDoubleObj(M_PI_360),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_e",-1),Tcl_NewDoubleObj(M_E),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_log2e",-1),Tcl_NewDoubleObj(M_LOG2E),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_log10e",-1),Tcl_NewDoubleObj(M_LOG10E),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_ln2",-1),Tcl_NewDoubleObj(M_LN2),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_ln10",-1),Tcl_NewDoubleObj(M_LN10),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi",-1),Tcl_NewDoubleObj(M_PI),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi_2",-1),Tcl_NewDoubleObj(M_PI_2),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi_4",-1),Tcl_NewDoubleObj(M_PI_4),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_1_pi",-1),Tcl_NewDoubleObj(M_1_PI),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_2_pi",-1),Tcl_NewDoubleObj(M_2_PI),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_2_sqrtpi",-1),Tcl_NewDoubleObj(M_2_SQRTPI),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_sqrt2",-1),Tcl_NewDoubleObj(M_SQRT2),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_sqrt1_2",-1),Tcl_NewDoubleObj(M_SQRT1_2),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_sqrt3",-1),Tcl_NewDoubleObj(M_SQRT3),TCL_GLOBAL_ONLY);
- Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_sqrt3_2",-1),Tcl_NewDoubleObj(M_SQRT3_2),TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(varname);
- return TCL_OK;}
- /* VectorXYZ_AABB_Normalize */
- static inline void VectorXYZ_AABB_Normalize(AABBXYZ R){
- double temp;
- if (R[X_MIN_IDX] > R[X_MAX_IDX]) {
- temp=R[X_MIN_IDX];
- R[X_MIN_IDX]=R[X_MAX_IDX];
- R[X_MAX_IDX]=temp;
- } if (R[Y_MIN_IDX] > R[Y_MAX_IDX]) {
- temp=R[Y_MIN_IDX];
- R[Y_MIN_IDX]=R[Y_MAX_IDX];
- R[Y_MAX_IDX]=temp;
- } if (R[Z_MIN_IDX] > R[Z_MAX_IDX]) {
- temp=R[Z_MIN_IDX];
- R[Z_MIN_IDX]=R[Z_MAX_IDX];
- R[Z_MAX_IDX]=temp;
- }}
- /* VectorXYZ_AABB_Copy */
- static void VectorXYZ_AABB_Copy(AABBXYZ dest,AABBXYZ src){
- dest[X_MIN_IDX]=src[X_MIN_IDX];
- dest[X_MAX_IDX]=src[X_MAX_IDX];
- dest[Y_MIN_IDX]=src[Y_MIN_IDX];
- dest[Y_MAX_IDX]=src[Y_MAX_IDX];
- dest[Z_MIN_IDX]=src[Z_MIN_IDX];
- dest[Z_MAX_IDX]=src[Z_MAX_IDX];
- }
- /* VectorXYZ_AABB_Within */
- static inline int VectorXYZ_AABB_Within(VectorXYZ POINT,AABBXYZ R){
- if (POINT[X_IDX]<R[X_MIN_IDX]) return 0;
- if (POINT[X_IDX]>R[X_MAX_IDX]) return 0;
- if (POINT[Y_IDX]<R[Y_MIN_IDX]) return 0;
- if (POINT[Y_IDX]>R[Y_MAX_IDX]) return 0;
- if (POINT[Z_IDX]<R[Z_MIN_IDX]) return 0;
- if (POINT[Z_IDX]>R[Z_MAX_IDX]) return 0;
- return 1;
- }
- /* VectorXYZ_BBOX_Overlap_TwoVectors */
- static inline int VectorXYZ_BBOX_Overlap_TwoVectors(VectorXYZ A1,VectorXYZ A2,VectorXYZ B1,VectorXYZ B2){
- if (A1[X_IDX]<B1[X_IDX] && A1[X_IDX]<B2[X_IDX]) {
- if (A2[X_IDX]<B1[X_IDX] && A2[X_IDX]<B2[X_IDX]) return 0;
- }
- if (A1[X_IDX]>B1[X_IDX] && A1[X_IDX]>B2[X_IDX]) {
- if (A2[X_IDX]>B1[X_IDX] && A2[X_IDX]>B2[X_IDX]) return 0;
- }
- if (A1[Y_IDX]<B1[Y_IDX] && A1[Y_IDX]<B2[Y_IDX]) {
- if (A2[Y_IDX]<B1[Y_IDX] && A2[Y_IDX]<B2[Y_IDX]) return 0;
- }
- if (A1[Y_IDX]>B1[Y_IDX] && A1[Y_IDX]>B2[Y_IDX]) {
- if (A2[Y_IDX]>B1[Y_IDX] && A2[Y_IDX]>B2[Y_IDX]) return 0;
- }
- if (A1[Z_IDX]<B1[Z_IDX] && A1[Z_IDX]<B2[Z_IDX]) {
- if (A2[Z_IDX]<B1[Z_IDX] && A2[Z_IDX]<B2[Z_IDX]) return 0;
- }
- if (A1[Z_IDX]>B1[Z_IDX] && A1[Z_IDX]>B2[Z_IDX]) {
- if (A2[Z_IDX]>B1[Z_IDX] && A2[Z_IDX]>B2[Z_IDX]) return 0;
- }
- return 1;
- }
- /* AABB_AABB_Intersect */
- static inline int AABB_AABB_Intersect(AABBXYZ A,AABBXYZ B){
- int a_inside_b=0;
- int b_inside_a=0;
- if (A[X_MIN_IDX]>=B[X_MIN_IDX] && A[X_MAX_IDX]<=B[X_MAX_IDX]) a_inside_b++;
- if (B[X_MIN_IDX]>=A[X_MIN_IDX] && B[X_MAX_IDX]<=A[X_MAX_IDX]) b_inside_a++;
- if (A[Y_MIN_IDX]>=B[Y_MIN_IDX] && A[Y_MAX_IDX]<=B[Y_MAX_IDX]) a_inside_b++;
- if (B[Y_MIN_IDX]>=A[Y_MIN_IDX] && B[Y_MAX_IDX]<=A[Y_MAX_IDX]) b_inside_a++;
- if (A[Z_MIN_IDX]>=B[Z_MIN_IDX] && A[Z_MAX_IDX]<=B[Z_MAX_IDX]) a_inside_b++;
- if (B[Z_MIN_IDX]>=A[Z_MIN_IDX] && B[Z_MAX_IDX]<=A[Z_MAX_IDX]) b_inside_a++;
-
- if (a_inside_b==0 && b_inside_a==0) return 0;
- if (a_inside_b==3 && b_inside_a==3) return 2;
- if (a_inside_b==3) return 3;
- if (b_inside_a==3) return 4;
- return 1;
- }
- /* VectorXYZ_AABB_Measure */
- static inline void VectorXYZ_AABB_Measure(VectorXYZ POINT,AABBXYZ R){
- if (POINT[X_IDX]<R[X_MIN_IDX]) R[X_MIN_IDX]=POINT[X_IDX];
- if (POINT[X_IDX]>R[X_MAX_IDX]) R[X_MAX_IDX]=POINT[X_IDX];
- if (POINT[Y_IDX]<R[Y_MIN_IDX]) R[Y_MIN_IDX]=POINT[Y_IDX];
- if (POINT[Y_IDX]>R[Y_MAX_IDX]) R[Y_MAX_IDX]=POINT[Y_IDX];
- if (POINT[Z_IDX]<R[Z_MIN_IDX]) R[Z_MIN_IDX]=POINT[Z_IDX];
- if (POINT[Z_IDX]>R[Z_MAX_IDX]) R[Z_MAX_IDX]=POINT[Z_IDX];
- }
- /* AABB_AABB_Combine */
- static inline void AABB_AABB_Combine(AABBXYZ B,AABBXYZ A){
- if (A[X_MIN_IDX]<B[X_MIN_IDX]) B[X_MIN_IDX]=A[X_MIN_IDX];
- if (A[X_MAX_IDX]>B[X_MAX_IDX]) B[X_MAX_IDX]=A[X_MAX_IDX];
- if (A[Y_MIN_IDX]<B[Y_MIN_IDX]) B[Y_MIN_IDX]=A[Y_MIN_IDX];
- if (A[Y_MAX_IDX]>B[Y_MAX_IDX]) B[Y_MAX_IDX]=A[Y_MAX_IDX];
- if (A[Z_MIN_IDX]<B[Z_MIN_IDX]) B[Z_MIN_IDX]=A[Z_MIN_IDX];
- if (A[Z_MAX_IDX]>B[Z_MAX_IDX]) B[Z_MAX_IDX]=A[Z_MAX_IDX];
- }
- /* VectorXYZ_AABB_Reset */
- static inline void VectorXYZ_AABB_Reset(AABBXYZ R){
- R[X_MIN_IDX]=R[Y_MIN_IDX]=R[Z_MIN_IDX]=1e99;
- R[X_MAX_IDX]=R[Y_MAX_IDX]=R[Z_MAX_IDX]=-1e99;
- }
- VectorXYZ Odie_Up_Direction = {0, 0, 1.0};
- /* *Matrix_To_affine */
- const char *Matrix_To_affine(Odie_MatrixObj *matrix,int form){
- if(matrix->form==MATFORM_affine) {
- return NULL;
- }
- if(matrix->form==MATFORM_euler) {
- VectorXYZ TEMP;
- VectorXYZ_Copy(TEMP,matrix->matrix);
- affine_Rotate_From_Euler(TEMP,matrix->matrix);
- matrix->form=MATFORM_affine;
- return NULL;
- }
- if(matrix->form==MATFORM_vector_xyz) {
- VectorXYZ TEMP;
- VectorXYZ_Copy(TEMP,matrix->matrix);
- Odie_Affine4x4_Translation(TEMP,matrix->matrix);
- matrix->form=MATFORM_affine;
- return NULL;
- }
- if(matrix->rows==4 && matrix->cols==4) {
- if(matrix->form==MATFORM_null) {
- matrix->form=MATFORM_affine;
- }
- return NULL;
- }
- if(matrix->rows==1 && matrix->cols==16) {
- if(matrix->form==MATFORM_null) {
- matrix->form=MATFORM_affine;
- }
- return NULL;
- }
- if(matrix->rows==16 && matrix->cols==1) {
- if(matrix->form==MATFORM_null) {
- matrix->form=MATFORM_affine;
- }
- return NULL;
- }
- return "Cannot convert to affine";
- }
- /* affine_Compare */
- static inline int affine_Compare(AFFINE A,AFFINE B){
- if(fabs(B[AFFINE_IDX_0_0]-A[AFFINE_IDX_0_0])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_0_1]-A[AFFINE_IDX_0_1])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_0_2]-A[AFFINE_IDX_0_2])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_0_3]-A[AFFINE_IDX_0_3])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_1_0]-A[AFFINE_IDX_1_0])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_1_1]-A[AFFINE_IDX_1_1])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_1_2]-A[AFFINE_IDX_1_2])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_1_3]-A[AFFINE_IDX_1_3])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_2_0]-A[AFFINE_IDX_2_0])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_2_1]-A[AFFINE_IDX_2_1])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_2_2]-A[AFFINE_IDX_2_2])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_2_3]-A[AFFINE_IDX_2_3])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_3_0]-A[AFFINE_IDX_3_0])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_3_1]-A[AFFINE_IDX_3_1])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_3_2]-A[AFFINE_IDX_3_2])>__FLT_EPSILON__) return 0;
- if(fabs(B[AFFINE_IDX_3_3]-A[AFFINE_IDX_3_3])>__FLT_EPSILON__) return 0;
- return 1;
- }
- /* Odie_Affine4x4_Copy */
- inline extern void Odie_Affine4x4_Copy(AFFINE RESULT,AFFINE A){
- RESULT[AFFINE_IDX_0_0]=A[AFFINE_IDX_0_0];
- RESULT[AFFINE_IDX_0_1]=A[AFFINE_IDX_0_1];
- RESULT[AFFINE_IDX_0_2]=A[AFFINE_IDX_0_2];
- RESULT[AFFINE_IDX_0_3]=A[AFFINE_IDX_0_3];
- RESULT[AFFINE_IDX_1_0]=A[AFFINE_IDX_1_0];
- RESULT[AFFINE_IDX_1_1]=A[AFFINE_IDX_1_1];
- RESULT[AFFINE_IDX_1_2]=A[AFFINE_IDX_1_2];
- RESULT[AFFINE_IDX_1_3]=A[AFFINE_IDX_1_3];
- RESULT[AFFINE_IDX_2_0]=A[AFFINE_IDX_2_0];
- RESULT[AFFINE_IDX_2_1]=A[AFFINE_IDX_2_1];
- RESULT[AFFINE_IDX_2_2]=A[AFFINE_IDX_2_2];
- RESULT[AFFINE_IDX_2_3]=A[AFFINE_IDX_2_3];
- RESULT[AFFINE_IDX_3_0]=A[AFFINE_IDX_3_0];
- RESULT[AFFINE_IDX_3_1]=A[AFFINE_IDX_3_1];
- RESULT[AFFINE_IDX_3_2]=A[AFFINE_IDX_3_2];
- RESULT[AFFINE_IDX_3_3]=A[AFFINE_IDX_3_3];
- }
- /* affine_ZeroMatrix */
- inline extern void affine_ZeroMatrix(AFFINE A){
- A[AFFINE_IDX_0_0]=0.0;
- A[AFFINE_IDX_0_1]=0.0;
- A[AFFINE_IDX_0_2]=0.0;
- A[AFFINE_IDX_0_3]=0.0;
- A[AFFINE_IDX_1_0]=0.0;
- A[AFFINE_IDX_1_1]=0.0;
- A[AFFINE_IDX_1_2]=0.0;
- A[AFFINE_IDX_1_3]=0.0;
- A[AFFINE_IDX_2_0]=0.0;
- A[AFFINE_IDX_2_1]=0.0;
- A[AFFINE_IDX_2_2]=0.0;
- A[AFFINE_IDX_2_3]=0.0;
- A[AFFINE_IDX_3_0]=0.0;
- A[AFFINE_IDX_3_1]=0.0;
- A[AFFINE_IDX_3_2]=0.0;
- A[AFFINE_IDX_3_3]=0.0;
- }
- /* Odie_Affine4x4_Identity */
- inline extern void Odie_Affine4x4_Identity(AFFINE A){
- A[AFFINE_IDX_0_0]=1.0;
- A[AFFINE_IDX_0_1]=0.0;
- A[AFFINE_IDX_0_2]=0.0;
- A[AFFINE_IDX_0_3]=0.0;
- A[AFFINE_IDX_1_0]=0.0;
- A[AFFINE_IDX_1_1]=1.0;
- A[AFFINE_IDX_1_2]=0.0;
- A[AFFINE_IDX_1_3]=0.0;
- A[AFFINE_IDX_2_0]=0.0;
- A[AFFINE_IDX_2_1]=0.0;
- A[AFFINE_IDX_2_2]=1.0;
- A[AFFINE_IDX_2_3]=0.0;
- A[AFFINE_IDX_3_0]=0.0;
- A[AFFINE_IDX_3_1]=0.0;
- A[AFFINE_IDX_3_2]=0.0;
- A[AFFINE_IDX_3_3]=1.0;
- }
- /* Odie_Affine4x4_Translation */
- void Odie_Affine4x4_Translation(AFFINE RESULT,VECTOR A){
- Odie_Affine4x4_Identity(RESULT);
- RESULT[AFFINE_IDX_0_3]=-A[X_IDX];
- RESULT[AFFINE_IDX_1_3]=-A[Y_IDX];
- RESULT[AFFINE_IDX_2_3]=-A[Z_IDX];
- }
- /* Odie_Affine4x4_Scale */
- inline extern void Odie_Affine4x4_Scale(AFFINE RESULT,VECTOR A){
- Odie_Affine4x4_Identity(RESULT);
- RESULT[AFFINE_IDX_0_0]=A[X_IDX];
- RESULT[AFFINE_IDX_1_1]=A[Y_IDX];
- RESULT[AFFINE_IDX_2_2]=A[Z_IDX];
- RESULT[AFFINE_IDX_3_3]=1.0;
- }
- /* affine_rotate_nutation */
- inline extern void affine_rotate_nutation(AFFINE RESULT,SCALER theta){
- double cos_theta,sin_theta;
- cos_theta=cos(theta);
- sin_theta=sin(theta);
-
- Odie_Affine4x4_Identity(RESULT);
- RESULT[AFFINE_IDX_1_1]=cos_theta;
- RESULT[AFFINE_IDX_1_2]=sin_theta;
- RESULT[AFFINE_IDX_2_1]=-sin_theta;
- RESULT[AFFINE_IDX_2_2]=cos_theta;
- }
- /* affine_rotate_precession */
- inline extern void affine_rotate_precession(AFFINE RESULT,SCALER phi){
- double cos_phi,sin_phi;
- cos_phi=cos(phi);
- sin_phi=sin(phi);
-
- Odie_Affine4x4_Identity(RESULT);
- RESULT[AFFINE_IDX_0_0]=cos_phi;
- RESULT[AFFINE_IDX_0_1]=sin_phi;
- RESULT[AFFINE_IDX_1_0]=-sin_phi;
- RESULT[AFFINE_IDX_1_1]=cos_phi;
- }
- /* affine_rotate_spin */
- static inline void affine_rotate_spin(AFFINE RESULT,SCALER psi){
- double cos_psi,sin_psi;
- cos_psi=cos(psi);
- sin_psi=sin(psi);
-
- Odie_Affine4x4_Identity(RESULT);
- RESULT[AFFINE_IDX_0_0]=cos_psi;
- RESULT[AFFINE_IDX_0_1]=sin_psi;
- RESULT[AFFINE_IDX_1_0]=-sin_psi;
- RESULT[AFFINE_IDX_1_1]=cos_psi;
- }
- /* affine_Rotate_From_Euler */
- void affine_Rotate_From_Euler(AFFINE RESULT,VECTOR rotate){
- double cos_theta,sin_theta;
- double cos_phi,sin_phi;
- double cos_psi,sin_psi;
- cos_theta=cos(rotate[EULER_THETA]);
- sin_theta=sin(rotate[EULER_THETA]);
- cos_phi=cos(rotate[EULER_PHI]);
- sin_phi=sin(rotate[EULER_PHI]);
- cos_psi=cos(rotate[EULER_PSI]);
- sin_psi=sin(rotate[EULER_PSI]);
- RESULT[AFFINE_IDX_0_0]=cos_psi*cos_phi-cos_theta*sin_psi*sin_psi;
- RESULT[AFFINE_IDX_0_1]=cos_psi*sin_phi+cos_theta*cos_phi*sin_psi;
- RESULT[AFFINE_IDX_0_2]=sin_theta*sin_psi;
- RESULT[AFFINE_IDX_0_3]=0.0;
- RESULT[AFFINE_IDX_1_0]=-sin_psi*cos_phi-cos_theta*sin_phi*cos_psi;
- RESULT[AFFINE_IDX_1_1]=-sin_psi*sin_phi+cos_theta*cos_phi*cos_psi;
- RESULT[AFFINE_IDX_1_2]=sin_theta*cos_psi;
- RESULT[AFFINE_IDX_1_3]=0.0;
- RESULT[AFFINE_IDX_2_0]=sin_phi*sin_theta;
- RESULT[AFFINE_IDX_2_1]=-cos_phi*sin_theta;
- RESULT[AFFINE_IDX_2_2]=cos_theta;
- RESULT[AFFINE_IDX_2_3]=0.0;
- RESULT[AFFINE_IDX_3_0]=0.0;
- RESULT[AFFINE_IDX_3_1]=0.0;
- RESULT[AFFINE_IDX_3_2]=0.0;
- RESULT[AFFINE_IDX_3_3]=1.0;
- }
- /* Odie_Affine4x4_Multiply */
- inline extern void Odie_Affine4x4_Multiply(AFFINE R,AFFINE A,AFFINE B){
- double cell_0_0;
- double cell_0_1;
- double cell_0_2;
- double cell_0_3;
- double cell_1_0;
- double cell_1_1;
- double cell_1_2;
- double cell_1_3;
- double cell_2_0;
- double cell_2_1;
- double cell_2_2;
- double cell_2_3;
- double cell_3_0;
- double cell_3_1;
- double cell_3_2;
- double cell_3_3;
- cell_0_0=A[AFFINE_IDX_0_0]*B[AFFINE_IDX_0_0]+A[AFFINE_IDX_0_1]*B[AFFINE_IDX_1_0]+A[AFFINE_IDX_0_2]*B[AFFINE_IDX_2_0]+A[AFFINE_IDX_0_3]*B[AFFINE_IDX_3_0];
- cell_0_1=A[AFFINE_IDX_0_0]*B[AFFINE_IDX_0_1]+A[AFFINE_IDX_0_1]*B[AFFINE_IDX_1_1]+A[AFFINE_IDX_0_2]*B[AFFINE_IDX_2_1]+A[AFFINE_IDX_0_3]*B[AFFINE_IDX_3_1];
- cell_0_2=A[AFFINE_IDX_0_0]*B[AFFINE_IDX_0_2]+A[AFFINE_IDX_0_1]*B[AFFINE_IDX_1_2]+A[AFFINE_IDX_0_2]*B[AFFINE_IDX_2_2]+A[AFFINE_IDX_0_3]*B[AFFINE_IDX_3_2];
- cell_0_3=A[AFFINE_IDX_0_0]*B[AFFINE_IDX_0_3]+A[AFFINE_IDX_0_1]*B[AFFINE_IDX_1_3]+A[AFFINE_IDX_0_2]*B[AFFINE_IDX_2_3]+A[AFFINE_IDX_0_3]*B[AFFINE_IDX_3_3];
- cell_1_0=A[AFFINE_IDX_1_0]*B[AFFINE_IDX_0_0]+A[AFFINE_IDX_1_1]*B[AFFINE_IDX_1_0]+A[AFFINE_IDX_1_2]*B[AFFINE_IDX_2_0]+A[AFFINE_IDX_1_3]*B[AFFINE_IDX_3_0];
- cell_1_1=A[AFFINE_IDX_1_0]*B[AFFINE_IDX_0_1]+A[AFFINE_IDX_1_1]*B[AFFINE_IDX_1_1]+A[AFFINE_IDX_1_2]*B[AFFINE_IDX_2_1]+A[AFFINE_IDX_1_3]*B[AFFINE_IDX_3_1];
- cell_1_2=A[AFFINE_IDX_1_0]*B[AFFINE_IDX_0_2]+A[AFFINE_IDX_1_1]*B[AFFINE_IDX_1_2]+A[AFFINE_IDX_1_2]*B[AFFINE_IDX_2_2]+A[AFFINE_IDX_1_3]*B[AFFINE_IDX_3_2];
- cell_1_3=A[AFFINE_IDX_1_0]*B[AFFINE_IDX_0_3]+A[AFFINE_IDX_1_1]*B[AFFINE_IDX_1_3]+A[AFFINE_IDX_1_2]*B[AFFINE_IDX_2_3]+A[AFFINE_IDX_1_3]*B[AFFINE_IDX_3_3];
- cell_2_0=A[AFFINE_IDX_2_0]*B[AFFINE_IDX_0_0]+A[AFFINE_IDX_2_1]*B[AFFINE_IDX_1_0]+A[AFFINE_IDX_2_2]*B[AFFINE_IDX_2_0]+A[AFFINE_IDX_2_3]*B[AFFINE_IDX_3_0];
- cell_2_1=A[AFFINE_IDX_2_0]*B[AFFINE_IDX_0_1]+A[AFFINE_IDX_2_1]*B[AFFINE_IDX_1_1]+A[AFFINE_IDX_2_2]*B[AFFINE_IDX_2_1]+A[AFFINE_IDX_2_3]*B[AFFINE_IDX_3_1];
- cell_2_2=A[AFFINE_IDX_2_0]*B[AFFINE_IDX_0_2]+A[AFFINE_IDX_2_1]*B[AFFINE_IDX_1_2]+A[AFFINE_IDX_2_2]*B[AFFINE_IDX_2_2]+A[AFFINE_IDX_2_3]*B[AFFINE_IDX_3_2];
- cell_2_3=A[AFFINE_IDX_2_0]*B[AFFINE_IDX_0_3]+A[AFFINE_IDX_2_1]*B[AFFINE_IDX_1_3]+A[AFFINE_IDX_2_2]*B[AFFINE_IDX_2_3]+A[AFFINE_IDX_2_3]*B[AFFINE_IDX_3_3];
- cell_3_0=A[AFFINE_IDX_3_0]*B[AFFINE_IDX_0_0]+A[AFFINE_IDX_3_1]*B[AFFINE_IDX_1_0]+A[AFFINE_IDX_3_2]*B[AFFINE_IDX_2_0]+A[AFFINE_IDX_3_3]*B[AFFINE_IDX_3_0];
- cell_3_1=A[AFFINE_IDX_3_0]*B[AFFINE_IDX_0_1]+A[AFFINE_IDX_3_1]*B[AFFINE_IDX_1_1]+A[AFFINE_IDX_3_2]*B[AFFINE_IDX_2_1]+A[AFFINE_IDX_3_3]*B[AFFINE_IDX_3_1];
- cell_3_2=A[AFFINE_IDX_3_0]*B[AFFINE_IDX_0_2]+A[AFFINE_IDX_3_1]*B[AFFINE_IDX_1_2]+A[AFFINE_IDX_3_2]*B[AFFINE_IDX_2_2]+A[AFFINE_IDX_3_3]*B[AFFINE_IDX_3_2];
- cell_3_3=A[AFFINE_IDX_3_0]*B[AFFINE_IDX_0_3]+A[AFFINE_IDX_3_1]*B[AFFINE_IDX_1_3]+A[AFFINE_IDX_3_2]*B[AFFINE_IDX_2_3]+A[AFFINE_IDX_3_3]*B[AFFINE_IDX_3_3];
- R[AFFINE_IDX_0_0]=cell_0_0;
- R[AFFINE_IDX_0_1]=cell_0_1;
- R[AFFINE_IDX_0_2]=cell_0_2;
- R[AFFINE_IDX_0_3]=cell_0_3;
- R[AFFINE_IDX_1_0]=cell_1_0;
- R[AFFINE_IDX_1_1]=cell_1_1;
- R[AFFINE_IDX_1_2]=cell_1_2;
- R[AFFINE_IDX_1_3]=cell_1_3;
- R[AFFINE_IDX_2_0]=cell_2_0;
- R[AFFINE_IDX_2_1]=cell_2_1;
- R[AFFINE_IDX_2_2]=cell_2_2;
- R[AFFINE_IDX_2_3]=cell_2_3;
- R[AFFINE_IDX_3_0]=cell_3_0;
- R[AFFINE_IDX_3_1]=cell_3_1;
- R[AFFINE_IDX_3_2]=cell_3_2;
- R[AFFINE_IDX_3_3]=cell_3_3;
- }
- /* Odie_Affine4x4_Inverse */
- int Odie_Affine4x4_Inverse(AFFINE r, AFFINE m){
- double d00, d01, d02, d03;
- double d10, d11, d12, d13;
- double d20, d21, d22, d23;
- double d30, d31, d32, d33;
- double m00, m01, m02, m03;
- double m10, m11, m12, m13;
- double m20, m21, m22, m23;
- double m30, m31, m32, m33;
- double D;
-
- m00 = m[AFFINE_IDX_0_0]; m01 = m[AFFINE_IDX_0_1]; m02 = m[AFFINE_IDX_0_2]; m03 = m[AFFINE_IDX_0_3];
- m10 = m[AFFINE_IDX_1_0]; m11 = m[AFFINE_IDX_1_1]; m12 = m[AFFINE_IDX_1_2]; m13 = m[AFFINE_IDX_1_3];
- m20 = m[AFFINE_IDX_2_0]; m21 = m[AFFINE_IDX_2_1]; m22 = m[AFFINE_IDX_2_2]; m23 = m[AFFINE_IDX_2_3];
- m30 = m[AFFINE_IDX_3_0]; m31 = m[AFFINE_IDX_3_1]; m32 = m[AFFINE_IDX_3_2]; m33 = m[AFFINE_IDX_3_3];
-
- d00 = m11*m22*m33 + m12*m23*m31 + m13*m21*m32 - m31*m22*m13 - m32*m23*m11 - m33*m21*m12;
- d01 = m10*m22*m33 + m12*m23*m30 + m13*m20*m32 - m30*m22*m13 - m32*m23*m10 - m33*m20*m12;
- d02 = m10*m21*m33 + m11*m23*m30 + m13*m20*m31 - m30*m21*m13 - m31*m23*m10 - m33*m20*m11;
- d03 = m10*m21*m32 + m11*m22*m30 + m12*m20*m31 - m30*m21*m12 - m31*m22*m10 - m32*m20*m11;
-
- d10 = m01*m22*m33 + m02*m23*m31 + m03*m21*m32 - m31*m22*m03 - m32*m23*m01 - m33*m21*m02;
- d11 = m00*m22*m33 + m02*m23*m30 + m03*m20*m32 - m30*m22*m03 - m32*m23*m00 - m33*m20*m02;
- d12 = m00*m21*m33 + m01*m23*m30 + m03*m20*m31 - m30*m21*m03 - m31*m23*m00 - m33*m20*m01;
- d13 = m00*m21*m32 + m01*m22*m30 + m02*m20*m31 - m30*m21*m02 - m31*m22*m00 - m32*m20*m01;
-
- d20 = m01*m12*m33 + m02*m13*m31 + m03*m11*m32 - m31*m12*m03 - m32*m13*m01 - m33*m11*m02;
- d21 = m00*m12*m33 + m02*m13*m30 + m03*m10*m32 - m30*m12*m03 - m32*m13*m00 - m33*m10*m02;
- d22 = m00*m11*m33 + m01*m13*m30 + m03*m10*m31 - m30*m11*m03 - m31*m13*m00 - m33*m10*m01;
- d23 = m00*m11*m32 + m01*m12*m30 + m02*m10*m31 - m30*m11*m02 - m31*m12*m00 - m32*m10*m01;
-
- d30 = m01*m12*m23 + m02*m13*m21 + m03*m11*m22 - m21*m12*m03 - m22*m13*m01 - m23*m11*m02;
- d31 = m00*m12*m23 + m02*m13*m20 + m03*m10*m22 - m20*m12*m03 - m22*m13*m00 - m23*m10*m02;
- d32 = m00*m11*m23 + m01*m13*m20 + m03*m10*m21 - m20*m11*m03 - m21*m13*m00 - m23*m10*m01;
- d33 = m00*m11*m22 + m01*m12*m20 + m02*m10*m21 - m20*m11*m02 - m21*m12*m00 - m22*m10*m01;
-
- D = m00*d00 - m01*d01 + m02*d02 - m03*d03;
-
-
- if (D == 0.0)
- {
- /* MatStack_Error("Singular matrix in MInvers."); */
- return TCL_ERROR;
- }
-
- r[AFFINE_IDX_0_0] = d00/D; r[AFFINE_IDX_0_1] = -d10/D; r[AFFINE_IDX_0_2] = d20/D; r[AFFINE_IDX_0_3] = -d30/D;
- r[AFFINE_IDX_1_0] = -d01/D; r[AFFINE_IDX_1_1] = d11/D; r[AFFINE_IDX_1_2] = -d21/D; r[AFFINE_IDX_1_3] = d31/D;
- r[AFFINE_IDX_2_0] = d02/D; r[AFFINE_IDX_2_1] = -d12/D; r[AFFINE_IDX_2_2] = d22/D; r[AFFINE_IDX_2_3] = -d32/D;
- r[AFFINE_IDX_3_0] = -d03/D; r[AFFINE_IDX_3_1] = d13/D; r[AFFINE_IDX_3_2] = -d23/D; r[AFFINE_IDX_3_3] = d33/D;
- return TCL_OK;
- }
- /* Odie_Affine_From_Normal */
- static void Odie_Affine_From_Normal(AFFINE RESULT,VectorXYZ NORMAL){
- double c,s,C;
- VectorXYZ axis;
-
- /* If UP and NORMAL are identical (or nearly identical) no rotation */
- if (VectorXYZ_IsZero(NORMAL)) {
- Odie_Affine4x4_Identity(RESULT);
- return;
- }
-
- if (VectorXYZ_SamePoint(Odie_Up_Direction,NORMAL)) {
- Odie_Affine4x4_Identity(RESULT);
- return;
- }
- VectorXYZ_Cross_Product(axis,Odie_Up_Direction,NORMAL);
- VectorXYZ_Normalize(axis);
- c=VectorXYZ_Dot_Product(Odie_Up_Direction,NORMAL);
- s=sqrt(1-c*c);
- C=1-c;
- RESULT[AFFINE_IDX_0_0]=axis[X_IDX]*axis[X_IDX]*C+c;
- RESULT[AFFINE_IDX_0_1]=axis[X_IDX]*axis[Y_IDX]*C-axis[Z_IDX]*s;
- RESULT[AFFINE_IDX_0_2]=axis[X_IDX]*axis[Z_IDX]*C+axis[Y_IDX]*s;
- RESULT[AFFINE_IDX_0_3]=0.0;
-
- RESULT[AFFINE_IDX_1_0]=axis[Y_IDX]*axis[X_IDX]*C+axis[Z_IDX]*s;
- RESULT[AFFINE_IDX_1_1]=axis[Y_IDX]*axis[Y_IDX]*C+c;
- RESULT[AFFINE_IDX_1_2]=axis[Y_IDX]*axis[Z_IDX]*C-axis[X_IDX]*s;
- RESULT[AFFINE_IDX_1_3]=0.0;
-
- RESULT[AFFINE_IDX_2_0]=axis[Z_IDX]*axis[X_IDX]*C-axis[Y_IDX]*s;
- RESULT[AFFINE_IDX_2_1]=axis[Z_IDX]*axis[Y_IDX]*C+axis[X_IDX]*s;
- RESULT[AFFINE_IDX_2_2]=axis[Z_IDX]*axis[Z_IDX]*C+c;
- RESULT[AFFINE_IDX_2_3]=0.0;
-
- RESULT[AFFINE_IDX_3_0]=0.0;
- RESULT[AFFINE_IDX_3_1]=0.0;
- RESULT[AFFINE_IDX_3_2]=0.0;
- RESULT[AFFINE_IDX_3_3]=1.0;
-
- }
- /* VectorXY_BBOX_Copy */
- static inline void VectorXY_BBOX_Copy(BBOXXY dest,BBOXXY src){ dest[BBOX_X0_IDX]=src[BBOX_X0_IDX];
- dest[BBOX_Y1_IDX]=src[BBOX_Y1_IDX];
- dest[BBOX_X1_IDX]=src[BBOX_X1_IDX];
- dest[BBOX_X1_IDX]=src[BBOX_X1_IDX];
- }
- /* VectorXY_BBOX_Reset */
- static inline void VectorXY_BBOX_Reset(BBOXXY R){
- R[BBOX_X0_IDX]=R[BBOX_Y0_IDX]=1e99;
- R[BBOX_Y1_IDX]=R[BBOX_X1_IDX]=-1e99;
- }
- /* VectorXY_IsBetween_BBOX */
- static inline int VectorXY_IsBetween_BBOX(VectorXY POINT,VectorXY A,VectorXY B){
- if (POINT[X_IDX]<A[X_IDX] && POINT[X_IDX]<B[X_IDX]) return 0;
- if (POINT[X_IDX]>A[X_IDX] && POINT[X_IDX]>B[X_IDX]) return 0;
- if (POINT[Y_IDX]<A[Y_IDX] && POINT[Y_IDX]<B[Y_IDX]) return 0;
- if (POINT[Y_IDX]>A[Y_IDX] && POINT[Y_IDX]>B[Y_IDX]) return 0;
- return 1;
- }
- /* VectorXY_Within_BBOX */
- static inline int VectorXY_Within_BBOX(VectorXY POINT,BBOXXY bbox){
- if(POINT[X_IDX]<bbox[BBOX_X0_IDX]) return 0;
- if(POINT[Y_IDX]>bbox[BBOX_Y1_IDX]) return 0;
- if(POINT[X_IDX]>bbox[BBOX_X1_IDX]) return 0;
- if(POINT[Y_IDX]<bbox[BBOX_Y0_IDX]) return 0;
- return 1;
- }
- /* XY_Within_BBOX */
- static inline int XY_Within_BBOX(double x, double y,BBOXXY bbox){
- if(x<bbox[BBOX_X0_IDX]) return 0;
- if(y>bbox[BBOX_Y1_IDX]) return 0;
- if(x>bbox[BBOX_X1_IDX]) return 0;
- if(y<bbox[BBOX_Y0_IDX]) return 0;
- return 1;
- }
- /* VectorXY_BBOX_Measure */
- static inline void VectorXY_BBOX_Measure(VectorXY POINT,BBOXXY bbox){
- if(POINT[X_IDX]<bbox[BBOX_X0_IDX]) bbox[BBOX_X0_IDX]=POINT[X_IDX];
- if(POINT[Y_IDX]>bbox[BBOX_Y1_IDX]) bbox[BBOX_Y1_IDX]=POINT[Y_IDX];
- if(POINT[X_IDX]>bbox[BBOX_X1_IDX]) bbox[BBOX_X1_IDX]=POINT[X_IDX];
- if(POINT[Y_IDX]<bbox[BBOX_Y0_IDX]) bbox[BBOX_Y0_IDX]=POINT[Y_IDX];
- }
- /* BBOX_BBOX_Intersect */
- static inline int BBOX_BBOX_Intersect(BBOXXY A,BBOXXY B){
- int a_inside_b=0;
- int b_inside_a=0;
- int i,j;
- if(A[BBOX_X0_IDX]>=B[BBOX_X0_IDX] && A[BBOX_X1_IDX]<=B[BBOX_X1_IDX]) {
- if(A[BBOX_Y1_IDX]<=B[BBOX_Y1_IDX] && A[BBOX_Y0_IDX]>=B[BBOX_Y0_IDX]) {
- a_inside_b=1;
- }
- }
- if(B[BBOX_X0_IDX]>=A[BBOX_X0_IDX] && B[BBOX_X1_IDX]<=A[BBOX_X1_IDX]) {
- if(B[BBOX_Y1_IDX]<=A[BBOX_Y1_IDX] && B[BBOX_Y0_IDX]>=A[BBOX_Y0_IDX]) {
- b_inside_a=1;
- }
- }
- if(a_inside_b && b_inside_a) {
- return 2;
- }
- if(a_inside_b) {
- return 3;
- }
- if(b_inside_a) {
- return 4;
- }
- if(XY_Within_BBOX(B[BBOX_X0_IDX],B[BBOX_Y1_IDX],A)) return 1;
- if(XY_Within_BBOX(B[BBOX_X0_IDX],B[BBOX_Y0_IDX],A)) return 1;
- if(XY_Within_BBOX(B[BBOX_X1_IDX],B[BBOX_Y1_IDX],A)) return 1;
- if(XY_Within_BBOX(B[BBOX_X1_IDX],B[BBOX_Y0_IDX],A)) return 1;
- if(XY_Within_BBOX(A[BBOX_X0_IDX],A[BBOX_Y1_IDX],B)) return 1;
- if(XY_Within_BBOX(A[BBOX_X0_IDX],A[BBOX_Y0_IDX],B)) return 1;
- if(XY_Within_BBOX(A[BBOX_X1_IDX],A[BBOX_Y1_IDX],B)) return 1;
- if(XY_Within_BBOX(A[BBOX_X1_IDX],A[BBOX_Y0_IDX],B)) return 1;
- return 0;
- }
- /* *Matrix_To_quaternion */
- const char *Matrix_To_quaternion(Odie_MatrixObj *matrix,int form){
- if(matrix->form==form) {
- return NULL;
- }
- if(Matrix_To_cartesian(matrix,MATFORM_cartesian)) {
- return "Cannot convert to spherical";
- }
- if(matrix->form==MATFORM_cartesian) {
- odiemath_cartesian_to_spherical(matrix->matrix,matrix->matrix);
- }
- matrix->form=form;
- matrix->rows=4;
- matrix->cols=1;
- return NULL;
- }
- /* *Quaternion_To_TclObj */
- Tcl_Obj *Quaternion_To_TclObj(QUATERNION R){
- Odie_MatrixObj *RESULT;
- RESULT=Odie_MatrixObj_Create(MATFORM_quaternion);
- RESULT->matrix[QW_IDX]=R[QW_IDX];
- RESULT->matrix[QX_IDX]=R[QX_IDX];
- RESULT->matrix[QY_IDX]=R[QY_IDX];
- RESULT->matrix[QZ_IDX]=R[QZ_IDX];
- return Matrix_To_TclObj(RESULT);
- }
- /* Odie_GetQuaternionFromTclObj */
- int Odie_GetQuaternionFromTclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,QUATERNION R){
- Tcl_Obj **elemPtrs;
- int cols,i;
- if(objPtr->typePtr) {
- if(objPtr->typePtr->setFromAnyProc==&MatrixObj_setFromAnyProc) {
- /*
- ** Object is a matrix
- */
- const char *err;
- Odie_MatrixObj *value=objPtr->internalRep.otherValuePtr;
- err=Matrix_To_cartesian(value,MATFORM_quaternion);
- if(err) {
- Tcl_AppendResult(interp,err,NULL);
- return TCL_ERROR;
- }
- R[QW_IDX]=value->matrix[QW_IDX];
- R[QX_IDX]=value->matrix[QX_IDX];
- R[QY_IDX]=value->matrix[QY_IDX];
- R[QZ_IDX]=value->matrix[QZ_IDX];
- return TCL_OK;
- }
- }
-
- /* Step one, Measure the matrix */
- if(Tcl_ListObjGetElements(interp, objPtr, &cols, &elemPtrs)) return TCL_ERROR;
- if(cols<4) {
- Tcl_SetObjResult(interp,Tcl_NewStringObj("Needs 3 columns",-1));
- return TCL_ERROR;
- }
- for(i=0;i<4;i++) {
- double temp;
- if(Tcl_GetDoubleFromObj(interp, elemPtrs[i], &temp)) return TCL_ERROR;
- R[i]=temp;
- }
- return TCL_OK;
- }
- /* Quaternion_Add */
- void Quaternion_Add(QUATERNION r, QUATERNION p, QUATERNION q){
- r[QW_IDX]=p[QW_IDX]+q[QW_IDX];
- r[QX_IDX]=p[QX_IDX]+q[QX_IDX];
- r[QY_IDX]=p[QY_IDX]+q[QY_IDX];
- r[QZ_IDX]=p[QZ_IDX]+q[QZ_IDX];
- }
- /* Quaternion_Subtract */
- void Quaternion_Subtract(QUATERNION r, QUATERNION p, QUATERNION q){
- r[QW_IDX]=p[QW_IDX]-q[QW_IDX];
- r[QX_IDX]=p[QX_IDX]-q[QX_IDX];
- r[QY_IDX]=p[QY_IDX]-q[QY_IDX];
- r[QZ_IDX]=p[QZ_IDX]-q[QZ_IDX];
- }
- /* Quaternion_Multiply */
- void Quaternion_Multiply(QUATERNION r, QUATERNION p, QUATERNION q){
- double t0, t1, t2;
-
- t0 = p[QW_IDX] * q[QW_IDX] - p[QX_IDX] * q[QX_IDX] - p[QY_IDX] * q[QY_IDX] - p[QZ_IDX] * q[QZ_IDX];
- t1 = p[QW_IDX] * q[QX_IDX] + p[QX_IDX] * q[QW_IDX] + p[QY_IDX] * q[QZ_IDX] - p[QZ_IDX] * q[QY_IDX];
- t2 = p[QW_IDX] * q[QY_IDX] + p[QY_IDX] * q[QW_IDX] + p[QZ_IDX] * q[QX_IDX] - p[QX_IDX] * q[QZ_IDX];
- r[QZ_IDX] = p[QW_IDX] * q[QZ_IDX] + p[QZ_IDX] * q[QW_IDX] + p[QX_IDX] * q[QY_IDX] - p[QY_IDX] * q[QX_IDX];
- r[QW_IDX] = t0;
- r[QX_IDX] = t1;
- r[QY_IDX] = t2;
- }
- /* Quaternion_Divide */
- void Quaternion_Divide(QUATERNION r, QUATERNION p, QUATERNION q){
- QUATERNION Q,t,s;
- double a;
- Q[QW_IDX]=q[QW_IDX];
- Q[QX_IDX]=-q[QX_IDX];
- Q[QY_IDX]=-q[QY_IDX];
- Q[QZ_IDX]=-q[QZ_IDX];
- Quaternion_Multiply(t,p,Q);
- Quaternion_Multiply(s,Q,Q);
- a=1.0/s[QW_IDX];
- r[QW_IDX]=t[QW_IDX]*a;
- r[QX_IDX]=t[QX_IDX]*a;
- r[QY_IDX]=t[QY_IDX]*a;
- r[QZ_IDX]=t[QY_IDX]*a;
- }
- /* Quaternion_Square_Root */
- void Quaternion_Square_Root(QUATERNION s, QUATERNION q){
- double len,m;
- double a,b;
- QUATERNION r;
-
- len=sqrt(q[QW_IDX]*q[QW_IDX]+q[QX_IDX]*q[QX_IDX]+q[QY_IDX]*q[QY_IDX]);
- if(len==0) {
- s[QW_IDX]=s[QX_IDX]=s[QY_IDX]=s[QZ_IDX]=0.0;
- return;
- }
- r[QW_IDX]=q[QW_IDX]*1.0;
- r[QX_IDX]=q[QX_IDX]*1.0;
- r[QY_IDX]=q[QY_IDX]*1.0;
- r[QZ_IDX]=0.0;
- m=1.0/sqrt(r[QW_IDX]*r[QW_IDX]+r[QX_IDX]*r[QX_IDX]);
- a=sqrt((1.0+r[QY_IDX])*0.5);
- b=sqrt((1.0-r[QY_IDX])*0.5);
- s[QW_IDX]=sqrt(len)*b*r[QW_IDX]*m;
- s[QX_IDX]=sqrt(len)*b*r[QX_IDX]*m;
- s[QY_IDX]=sqrt(len)*a;
- s[QZ_IDX]=q[QZ_IDX];
- }
- /* Quaternion_Square */
- void Quaternion_Square(QUATERNION r, QUATERNION q){
- double a;
- a=2.0*q[QW_IDX];
- r[QW_IDX]=q[QW_IDX]*q[QW_IDX]-q[QX_IDX]*q[QX_IDX]-q[QY_IDX]*q[QY_IDX]-q[QZ_IDX]*q[QZ_IDX];
- r[QX_IDX]=a*q[QX_IDX];
- r[QY_IDX]=a*q[QY_IDX];
- r[QZ_IDX]=a*q[QZ_IDX];
- }
- /* EulerRotation_To_Quaternion */
- void EulerRotation_To_Quaternion(QUATERNION q,double heading, double attitude, double bank){
- // Assuming the angles are in radians.
- double c1 = cos(heading*0.5);
- double s1 = sin(heading*0.5);
- double c2 = cos(attitude*0.5);
- double s2 = sin(attitude*0.5);
- double c3 = cos(bank*0.5);
- double s3 = sin(bank*0.5);
- double c1c2 = c1*c2;
- double s1s2 = s1*s2;
- q[QW_IDX] =c1c2*c3 - s1s2*s3;
- q[QX_IDX] =c1c2*s3 + s1s2*c3;
- q[QY_IDX] =s1*c2*c3 + c1*s2*s3;
- q[QZ_IDX] =c1*s2*c3 - s1*c2*s3;
- }
- /* VectorXYZ_Rotate_by_Quaternion */
- void VectorXYZ_Rotate_by_Quaternion(VECTORXYZ r, QUATERNION p, VECTORXYZ A){
- double w=p[QW_IDX]; // real part of quaternion
- double x=p[QX_IDX]; // imaginary i part of quaternion
- double y=p[QY_IDX]; // imaginary j part of quaternion
- double z=p[QZ_IDX]; // imaginary k part of quaternion
- double px=A[X_IDX];
- double py=A[Y_IDX];
- double pz=A[Z_IDX];
- r[X_IDX] = w*w*px + 2*y*w*pz - 2*z*w*py + x*x*px + 2*y*x*py + 2*z*x*pz - z*z*px - y*y*px;
- r[Y_IDX] = 2*x*y*px + y*y*py + 2*z*y*pz + 2*w*z*px - z*z*py + w*w*py - 2*x*w*pz - x*x*py;
- r[Z_IDX] = 2*x*z*px + 2*y*z*py + z*z*pz - 2*w*y*px - y*y*pz + 2*w*x*py - x*x*pz + w*w*pz;
- }
- /* Quaternion_To_EulerRotation */
- void Quaternion_To_EulerRotation (VECTORXYZ r, QUATERNION p){
- double sqw = p[QW_IDX]*p[QW_IDX];
- double sqx = p[QX_IDX]*p[QX_IDX];
- double sqy = p[QY_IDX]*p[QY_IDX];
- double sqz = p[QZ_IDX]*p[QZ_IDX];
- double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
- double test = p[QX_IDX]*p[QY_IDX] + p[QZ_IDX]*p[QW_IDX];
-
- if (test > 0.499*unit) { // singularity at north pole
- r[EULER_HEADING] = 2 * atan2(p[QX_IDX],p[QW_IDX]);
- r[EULER_ATTITUDE] = M_PI*0.5;
- r[EULER_BANK] = 0;
- return;
- }
- if (test < -0.499*unit) { // singularity at south pole
- r[EULER_HEADING] = -2 * atan2(p[QX_IDX],p[QW_IDX]);
- r[EULER_ATTITUDE] = M_PI*-0.5;
- r[EULER_BANK] = 0;
- return;
- }
- r[EULER_HEADING] = atan2(2*p[QY_IDX]*p[QW_IDX]-2*p[QX_IDX]*p[QZ_IDX] , sqx - sqy - sqz + sqw);
- r[EULER_ATTITUDE] = asin(2*test/unit);
- r[EULER_BANK] = atan2(2*p[QX_IDX]*p[QW_IDX]-2*p[QY_IDX]*p[QZ_IDX] , -sqx + sqy - sqz + sqw);
- }
- /* Quaternion_From_Normal */
- static inline void Quaternion_From_Normal(QUATERNION RESULT,VectorXYZ from,VectorXYZ to){
- VectorXYZ H;
- VectorXYZ_Add(H,from,to);
- /* Special case?
- if(VectorXYZ_IsZero(H)) {
- RESULT[QW_IDX]=0.0;
- RESULT[QX_IDX]=1.0;
- RESULT[QY_IDX]=0.0;
- RESULT[QZ_IDX]=0.0;
- }
- */
- VectorXYZ_Normalize(H);
- RESULT[QW_IDX]=VectorXYZ_Dot_Product(from,H);
- RESULT[QX_IDX]=from[Y_IDX]*H[Z_IDX] - from[Z_IDX]*H[Y_IDX];
- RESULT[QY_IDX]=from[Z_IDX]*H[X_IDX] - from[X_IDX]*H[Z_IDX];
- RESULT[QZ_IDX]=from[X_IDX]*H[Y_IDX] - from[Y_IDX]*H[X_IDX];
- }
- /* *Odie_Matrix_To_Fit */
- static Odie_MatrixObj *Odie_Matrix_To_Fit(Odie_MatrixObj *A,Odie_MatrixObj *B){
- Odie_MatrixObj *C;
- int size_a;
- int size_b;
- if(A->rows==B->rows && A->cols==B->cols) {
- if(A->form && A->form==B->form) {
- C=Odie_MatrixObj_Create(A->form);
- } else {
- C=Odie_MatrixObj_Create_NXN(A->rows,A->cols);
- }
- return C;
- }
- size_a=A->rows*A->cols;
- size_b=B->rows*B->cols;
- if(size_a<size_b) {
- C=Odie_MatrixObj_Create_NXN(size_b,1);
- } else {
- C=Odie_MatrixObj_Create_NXN(size_a,1);
- }
- return C;
- }
- /* Vector_GridScaler */
- static inline double Vector_GridScaler(double x,double grid,double grain){
- double q;
- q=grid*round(x/grid);
- if((x-q)>grain) {
- q+=grain;
- }
- return q;
- }
- /* Vector2d_SamePoint */
- inline extern int Vector2d_SamePoint(double x0, double y0, double x1, double y1){
- /*
- ** Return TRUE if x0,y0 is the same point as x1,y1
- */
- return floatCompare(x0,x1)==0 && floatCompare(y0,y1)==0;
- }
- /* Vector2d_IsColinear */
- inline extern int Vector2d_IsColinear(double x1,double y1,double x2,double y2,double x3,double y3){
- /* Detect of two lines are colinear */
- double c=(x3-x1)*(y2-y1)-(y3-y1)*(x2-x1);
- if(fabs(c) < __FLT_EPSILON__) return 1;
- return 0;
- }
- /* Vector2d_LineLineCoincident */
- inline extern int Vector2d_LineLineCoincident(
- double ax1, double ay1,
- double ax2, double ay2,
- double bx1, double by1,
- double bx2, double by2){
- double x,y;
- int c=0;
- /* Check if wall completely wraps other wall */
- if(Vector2d_SamePoint(ax1,ay1,bx1,by1)) {
- if(Vector2d_SamePoint(ax2,ay2,bx2,by2)) return 6;
- if(Vector2d_PointIsOnSegment(ax2,ay2,bx1,by1,bx2,by2)) return 2;
- return 0;
- }
- if(Vector2d_SamePoint(ax2,ay2,bx1,by1)) {
- if(Vector2d_SamePoint(ax1,ay1,bx2,by2)) return 6;
- if(Vector2d_PointIsOnSegment(ax1,ay1,bx1,by1,bx2,by2)) return 4;
- return 0;
- }
- if(Vector2d_SamePoint(ax1,ay1,bx2,by2)) {
- if(Vector2d_PointIsOnSegment(ax2,ay2,bx1,by1,bx2,by2)) return 2;
- return 0;
- }
- if(Vector2d_SamePoint(ax2,ay2,bx2,by2)) {
- if(Vector2d_PointIsOnSegment(ax1,ay1,bx1,by1,bx2,by2)) return 4;
- return 0;
- }
- c=ODIE_Math_LineLineIntersect(ax1,ay1,ax2,ay2,bx1,by1,bx2,by2,&x,&y);
- if(c) {
- if(Vector2d_SamePoint(ax1,ay1,x,y)) {
- return 0;
- }
- if(Vector2d_SamePoint(ax2,ay2,x,y)) {
- return 0;
- }
- }
- return c;
- }
- /* ODIE_Math_LineLineIntersect */
- int ODIE_Math_LineLineIntersect(
- double ax1, double ay1,
- double ax2, double ay2,
- double bx1, double by1,
- double bx2, double by2,
- double *x, double *y){
- /*
- ** Detect the intersection of two lines
- ** Adapted from: http://paulbourke.net/geometry/lineline2d/pdb.c
- */
- double mua,mub;
- double denom,numera,numerb;
-
-
-
- denom = (by2-by1) * (ax2-ax1) - (bx2-bx1) * (ay2-ay1);
- numera = (bx2-bx1) * (ay1-by1) - (by2-by1) * (ax1-bx1);
- numerb = (ax2-ax1) * (ay1-by1) - (ay2-ay1) * (ax1-bx1);
-
- /* Are the line parallel */
- if (ODIE_Real_Is_Zero(denom)) {
- if (ODIE_Real_Is_Zero(numera) && ODIE_Real_Is_Zero(numerb)) {
- /* Are the line coincident? */
- int within=1;
- if(ax2>ax1) {
- if(bx1>ax2 && bx2>ax2) {
- within=0;
- } else if(bx1<ax1 && bx2<ax1) {
- within=0;
- }
- } else {
- if(bx1>ax1 && bx2>ax1) {
- within=0;
- } else if(bx1<ax2 && bx2<ax2) {
- within=0;
- }
- }
- if(ay2>ay1) {
- if(by1>ay2 && by2>ay2) {
- within=0;
- } else if(by1<ay1 && by2<ay1) {
- within=0;
- }
- } else {
- if(by1>ay1 && by2>ay1) {
- within=0;
- } else if(by1<ay2 && by2<ay2) {
- within=0;
- }
- }
- if(within) {
- *x = (ax1 + ax2) / 2;
- *y = (ay1 + ay2) / 2;
- return(2);
- }
- }
- *x = 0;
- *y = 0;
- return(0);
- }
-
- /* Is the intersection along the the segments */
- mua = numera / denom;
- mub = numerb / denom;
- if (mua < 0 || mua > 1 || mub < 0 || mub > 1) {
- *x = 0;
- *y = 0;
- return(0);
- }
- *x = ax1 + mua * (ax2 - ax1);
- *y = ay1 + mua * (ay2 - ay1);
- return(1);
- }
- /* Vector2d_PointIsOnSegment */
- static inline int Vector2d_PointIsOnSegment(double x,double y,double x1,double y1,double x2,double y2){
- /* Returns:
- ** 0 - not on segment
- ** 1 - along segment
- ** 2 - endpoint of segment
- */
- /* Bounding box check */
- if(x1>x2) {
- if(x>(x1+OdieGrain)) return 0;
- if(x<(x2-OdieGrain)) return 0;
- } else {
- if(x>(x2+OdieGrain)) return 0;
- if(x<(x1-OdieGrain)) return 0;
- }
- if(y1>y2) {
- if(y>(y1+OdieGrain)) return 0;
- if(y<(y2-OdieGrain)) return 0;
- } else {
- if(y>(y2+OdieGrain)) return 0;
- if(y<(y1-OdieGrain)) return 0;
- }
- if(Vector2d_SamePoint(x,y,x1,y1)) return 2;
- if(Vector2d_SamePoint(x,y,x2,y2)) return 2;
-
- /* Detect of two lines are colinear */
- if (Vector2d_IsColinear(x,y,x1,y1,x2,y2)) {
- return 1;
- }
- return 0;
- }
- /* ODIE_Math_LineCircleIntersect */
- int ODIE_Math_LineCircleIntersect(
- double p1_x, double p1_y,
- double p2_x, double p2_y,
- double sc_x, double sc_y,
- double r,
- double *mu1, double *mu2){
- /*
- ** Detect the intersection of a line and a circle
- ** Adapted from: http://http://paulbourke.net/geometry/circlesphere/raysphere.c
- */
- double a,b,c;
- double bb4ac;
- double dp_x,dp_y;
- *mu1 = 0;
- *mu2 = 0;
-
- dp_x = p2_x - p1_x;
- dp_y = p2_y - p1_y;
- a = dp_x * dp_x + dp_y * dp_y;
- b = 2 * (dp_x * (p1_x - sc_x) + dp_y * (p1_y - sc_y));
- c = sc_x * sc_x + sc_y * sc_y;
- c += p1_x * p1_x + p1_y * p1_y;
- c -= 2 * (sc_x * p1_x + sc_y * p1_y);
- c -= r * r;
- bb4ac = b * b - 4 * a * c;
- if (ODIE_Real_Is_Zero(a) || bb4ac < 0) {
- return(0);
- }
-
- *mu1 = (-b + sqrt(bb4ac)) / (2 * a);
- *mu2 = (-b - sqrt(bb4ac)) / (2 * a);
-
- return(1);
- }
- /* Vector3d_SamePoint */
- inline extern int Vector3d_SamePoint(double x0, double y0, double z0, double x1, double y1, double z1){
- /*
- ** Return TRUE if x0,y0 is the same point as x1,y1
- */
- return floatCompare(x0,x1)==0 && floatCompare(y0,y1)==0 && floatCompare(z0,z1)==0;
- }
- /* odiemath_polar_to_vec2 */
- void odiemath_polar_to_vec2(VECTORXY A,VECTORXY R){
- /*
- ** Make a copy of the input matrix in case we are outputing back
- ** to the same pointer
- */
- double radius,theta;
- radius=A[RADIUS];
- theta=A[THETA];
- R[X_IDX]=radius*cos(theta);
- R[Y_IDX]=radius*sin(theta);
- }
- /* odiemath_vec2_to_polar */
- void odiemath_vec2_to_polar(VECTORXY A,VECTORXY R){
- double x,y;
- x=A[X_IDX];
- y=A[Y_IDX];
- R[RADIUS]=sqrt(x*x + y*y);
- R[THETA] =atan2(y,x);
- }
- /* *Matrix_To_vector_xy */
- const char *Matrix_To_vector_xy(Odie_MatrixObj *matrix,int form){
- if(matrix->form==form) {
- return NULL;
- }
- switch(matrix->form) {
- case MATFORM_vector_xy:
- return TCL_OK;
- case MATFORM_vector_xyz: {
- return NULL;
- }
- case MATFORM_cylindrical: {
- odiemath_vec2_to_polar(matrix->matrix,matrix->matrix);
- matrix->form=MATFORM_cartesian;
- return NULL;
- }
- }
- return Matrix_To_cartesian(matrix,MATFORM_vector_xy);
- }
- /* *VectorXY_To_TclObj */
- Tcl_Obj *VectorXY_To_TclObj(VectorXY R){
- Odie_MatrixObj *RESULT;
- RESULT=Odie_MatrixObj_Create(MATFORM_vector_xy);
- RESULT->matrix[X_IDX]=R[X_IDX];
- RESULT->matrix[Y_IDX]=R[Y_IDX];
- return Matrix_To_TclObj(RESULT);
- }
- /* Odie_GetVectorXYFromTclObj */
- int Odie_GetVectorXYFromTclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,VectorXY R){
- Tcl_Obj **elemPtrs;
- int cols,i;
- if(objPtr->typePtr) {
- if(objPtr->typePtr->setFromAnyProc==&MatrixObj_setFromAnyProc) {
- /*
- ** Object is a matrix
- */
- const char *err;
- Odie_MatrixObj *value=objPtr->internalRep.otherValuePtr;
- err=Matrix_To_cartesian(value,MATFORM_vector_xy);
- if(err) {
- Tcl_AppendResult(interp,err,NULL);
- return TCL_ERROR;
- }
- R[X_IDX]=value->matrix[X_IDX];
- R[Y_IDX]=value->matrix[Y_IDX];
- return TCL_OK;
- }
- }
-
- /* Step one, Measure the matrix */
- if(Tcl_ListObjGetElements(interp, objPtr, &cols, &elemPtrs)) return TCL_ERROR;
- for(i=0;i<2;i++) {
- double temp;
- if(cols<=i) {
- R[i]=0.0;
- } else {
- if(Tcl_GetDoubleFromObj(interp, elemPtrs[i], &temp)) return TCL_ERROR;
- R[i]=temp;
- }
- }
- return TCL_OK;
- }
- /* VectorXY_GridAlign */
- static inline void VectorXY_GridAlign(VECTORXYZ A,double grid){
- double x,q,grain;
- grain=grid*0.5;
- if(grid<=0) return;
- A[X_IDX]=Vector_GridScaler(A[X_IDX],grid,grain);
- A[Y_IDX]=Vector_GridScaler(A[Y_IDX],grid,grain);
- }
- /* VectorXY_SamePoint */
- inline extern int VectorXY_SamePoint(VectorXY A, VectorXY B){
- if(fabs(B[X_IDX]-A[X_IDX])>Vector_Tolerance) return 0;
- if(fabs(B[Y_IDX]-A[Y_IDX])>Vector_Tolerance) return 0;
- return 1;
- }
- /* VectorXY_SameGridPoint */
- inline extern int VectorXY_SameGridPoint(VectorXY A, VectorXY B,double grid){
- if(fabs(B[X_IDX]-A[X_IDX])>grid) return 0;
- if(fabs(B[Y_IDX]-A[Y_IDX])>grid) return 0;
- return 1;
- }
- /* VectorXY_Add */
- inline extern void VectorXY_Add(VECTORXY C,VECTORXY A,VECTORXY B){
- C[X_IDX]=B[X_IDX]+A[X_IDX];
- C[Y_IDX]=B[Y_IDX]+A[Y_IDX];
- }
- /* VectorXY_Subtract */
- inline extern void VectorXY_Subtract(VECTORXY C,VECTORXY A,VECTORXY B){
- C[X_IDX]=A[X_IDX]-B[X_IDX];
- C[Y_IDX]=A[Y_IDX]-B[Y_IDX];
- }
- /* VectorXY_Midpoint */
- static inline void VectorXY_Midpoint(VECTORXY C,VECTORXY A,VECTORXY B){
- C[X_IDX]=(B[X_IDX]-A[X_IDX])*0.5+A[X_IDX];
- C[Y_IDX]=(B[Y_IDX]-A[Y_IDX])*0.5+A[Y_IDX];
- }
- /* VectorXY_Normalize */
- inline extern void VectorXY_Normalize(VECTORXY A){
- double length=sqrt(A[X_IDX]*A[X_IDX]+A[Y_IDX]*A[Y_IDX]);
- if(length < __FLT_EPSILON__ ) {
- return;
- }
- A[X_IDX]/=length;
- A[Y_IDX]/=length;
- }
- /* VectorXY_Round */
- inline extern void VectorXY_Round(VECTORXY A){
- A[X_IDX]=round(A[X_IDX]);
- A[Y_IDX]=round(A[Y_IDX]);
- }
- /* VectorXY_Set */
- inline extern void VectorXY_Set(VECTORXY A,VECTORXY B){
- A[X_IDX]=B[X_IDX];
- A[Y_IDX]=B[Y_IDX];
- }
- /* VectorXY_crossProduct */
- inline extern double VectorXY_crossProduct(VectorXY A, VectorXY B, VectorXY P){
- double r = (A[Y_IDX]-B[Y_IDX])*(P[X_IDX]-B[X_IDX]) + (B[X_IDX]-A[X_IDX])*(P[Y_IDX]-B[Y_IDX]);
- if(fabs(r) < __FLT_EPSILON__ ) {
- return 0.0;
- }
- return r;
- }
- /* VectorXY_Dot_Product */
- inline extern double VectorXY_Dot_Product(VectorXY A, VectorXY B,VectorXY C){
- double r=(A[X_IDX]-B[X_IDX])*(C[X_IDX]-B[X_IDX])+(A[Y_IDX]-B[Y_IDX])*(C[Y_IDX]-B[Y_IDX]);
- if(fabs(r) < __FLT_EPSILON__ ) {
- return 0.0;
- }
- return r;
- }
- /* VectorXY_BendDirection */
- inline extern int VectorXY_BendDirection(VectorXY A, VectorXY B, VectorXY C){
- /*
- ** Consider traveling from VectorXY A to B to C. If you have to make
- ** a left-turn at B, then this routine returns -1. If C is on the
- ** same line as A and B then return 0. If you make a right turn
- ** at B in order to reach C then return +1.
- */
-
- /* Algorithm: Rotate AB 90 degrees counter-clockwise. Take
- ** the dot product with BP. The dot produce will be the product
- ** of two (non-negative) magnitudes and the cosine of the angle. So if
- ** the dot product is positive, the bend is to the left, or to the right if
- ** the dot product is negative.
- */
- double r = (A[Y_IDX]-B[Y_IDX])*(C[X_IDX]-B[X_IDX]) + (B[X_IDX]-A[X_IDX])*(C[Y_IDX]-B[Y_IDX]);
- if(fabs(r) < __FLT_EPSILON__ ) return 0;
- if(r>0.0) return -1;
- return 1;
- }
- /* VectorXY_strictlyRightOf */
- inline extern int VectorXY_strictlyRightOf(VectorXY A, VectorXY B, VectorXY P){
- /*
- ** This is a variation on rightOf(). Return 0 only if BP is a continuation
- ** of the line AB. If BP doubles back on AB then return -1.
- */
- int c = VectorXY_BendDirection(A,B,P);
- if( c==0 ){
- double r = (A[X_IDX]-B[X_IDX])*(P[X_IDX]-B[X_IDX]) + (A[Y_IDX]-B[Y_IDX])*(P[Y_IDX]-B[Y_IDX]);
- c = r<0.0 ? +1 : -1;
- }
- return c;
- }
- /* VectorXY_intersect */
- inline extern int VectorXY_intersect(VectorXY A, VectorXY B, VectorXY C, VectorXY D){
- /*
- ** Return TRUE if segments AB and CD intersect
- */
- return VectorXY_BendDirection(A,B,C)*VectorXY_BendDirection(A,B,D)<0 && VectorXY_BendDirection(C,D,A)*VectorXY_BendDirection(C,D,B)<0;
- }
- /* VectorXY_angleOf */
- inline extern double VectorXY_angleOf(VectorXY A, VectorXY B, VectorXY C){
- /*
- ** Compute angle ABC measured counter-clockwise from AB. Return the
- ** result.
- **
- ** This does not need to be a true angular measure as long as it is
- ** monotonically increasing.
- */
- double a1, a2, a3;
- if( VectorXY_SamePoint(A,C) ){
- return M_PI;
- }
- a1 = atan2(B[Y_IDX] - A[Y_IDX], B[X_IDX] - A[X_IDX]);
- a2 = atan2(C[Y_IDX] - B[Y_IDX], C[X_IDX] - B[X_IDX]);
- a3 = a2-a1;
- if( a3>M_PI ) a3 -= 2.0*M_PI;
- if( a3<=-M_PI ) a3 += 2.0*M_PI;
- return a3;
- }
- /* VectorXY_Angle_Three_Point */
- inline extern double VectorXY_Angle_Three_Point(VectorXY A, VectorXY B, VectorXY C){
- /*
- ** Compute angle ABC measured counter-clockwise from AB. Return the
- ** result.
- **
- ** This does not need to be a true angular measure as long as it is
- ** monotonically increasing.
- */
- double a1, a2, a3;
- if( VectorXY_SamePoint(A,C) ){
- return M_PI;
- }
- a1 = atan2(B[Y_IDX] - A[Y_IDX], B[X_IDX] - A[X_IDX]);
- a2 = atan2(C[Y_IDX] - B[Y_IDX], C[X_IDX] - B[X_IDX]);
- a3 = a2-a1;
- if( a3>M_PI ) a3 -= 2.0*M_PI;
- if( a3<=-M_PI ) a3 += 2.0*M_PI;
- return a3;
- }
- /* VectorXY_distance_squared */
- inline extern double VectorXY_distance_squared(VectorXY A, VectorXY B){
- /*
- ** Return the squared distance between two VectorXYs.
- */
- double dx = B[X_IDX] - A[X_IDX];
- double dy = B[Y_IDX] - A[Y_IDX];
- return dx*dx + dy*dy;
- }
- /* VectorXY_distance */
- inline extern double VectorXY_distance(VectorXY A, VectorXY B){
- /*
- ** Return the distance between two VectorXYs.
- */
- double dx = B[X_IDX] - A[X_IDX];
- double dy = B[Y_IDX] - A[Y_IDX];
- return sqrt(dx*dx + dy*dy);
- }
- /* odiemath_cartesian_to_spherical */
- void odiemath_cartesian_to_spherical(VECTOR A,VECTOR R){
- double S;
- /* Work with a copy in case we are writing back to the same pointer */
- double radius,theta,phi;
- radius=VectorXYZ_Magnitude(A);
- S=sqrt(A[X_IDX]*A[X_IDX]+A[Y_IDX]*A[Y_IDX]);
- if (A[X_IDX] > 0.0) {
- theta =asin(A[Y_IDX]/S);
- } else {
- theta =M_PI - asin(A[Y_IDX]/S);
- }
- phi =asin(A[Z_IDX]/R[RADIUS]);
-
- R[RADIUS]=radius;
- R[THETA]=theta;
- R[PHI]=phi;
- }
- /* odiemath_spherical_to_cartesian */
- void odiemath_spherical_to_cartesian(VECTOR A,VECTOR R){
- /*
- ** Make a copy of the input matrix in case we are outputing back
- ** to the same pointer
- */
- double radius,theta,phi;
- radius=A[RADIUS];
- theta=A[THETA];
- phi=A[PHI];
- R[X_IDX]=radius*cos(theta)*cos(phi);
- R[Y_IDX]=radius*sin(theta)*cos(phi);
- R[Z_IDX]=radius*sin(phi);
- }
- /* odiemath_cylindrical_to_cartesian */
- void odiemath_cylindrical_to_cartesian(VECTOR A,VECTOR R){
- /*
- ** Make a copy of the input matrix in case we are outputing back
- ** to the same pointer
- */
- double radius,theta,z;
- radius=A[RADIUS];
- theta=A[THETA];
- z=A[Z_IDX];
- R[X_IDX]=radius*cos(theta);
- R[Y_IDX]=radius*sin(theta);
- R[Z_IDX]=z;
- }
- /* odiemath_cartesian_to_cylindrical */
- void odiemath_cartesian_to_cylindrical(VECTOR A,VECTOR R){
- /*
- ** Make a copy of the input matrix in case we are outputing back
- ** to the same pointer
- */
- double x,y,z;
- x=A[X_IDX];
- y=A[Y_IDX];
- z=A[Z_IDX];
- R[RADIUS]=sqrt(x*x + y*y);
- R[THETA] =atan2(y,x);
- R[Z_IDX] =z;
- }
- /* *Matrix_To_cartesian */
- const char *Matrix_To_cartesian(MATOBJ *matrix,int form){
- if(matrix->form==form) {
- return NULL;
- }
- switch(matrix->form) {
- case MATFORM_vector_xy:
- case MATFORM_vector_xyz:
- case MATFORM_vector_xyzw:
- break;
- case MATFORM_spherical:
- {
- odiemath_spherical_to_cartesian(matrix->matrix,matrix->matrix);
- matrix->form=form;
- break;
- }
- case MATFORM_polar:
- case MATFORM_cylindrical: {
- odiemath_cylindrical_to_cartesian(matrix->matrix,matrix->matrix);
- matrix->form=form;
- break;
- }
- default: {
- if(matrix->rows==1) {
- int temp=matrix->cols;
- matrix->cols=matrix->rows;
- matrix->rows=temp;
- }
- if(matrix->cols != 1) {
- return "Cannot convert to cartesian";
- }
- }
- }
- switch(form) {
- case MATFORM_vector_xyz:
- matrix->form=form;
- matrix->rows=3;
- matrix->cols=1;
- return NULL;
- case MATFORM_vector_xy:
- matrix->form=form;
- matrix->rows=2;
- matrix->cols=1;
- return NULL;
- }
- return NULL;
- }
- /* *Matrix_To_cylindrical */
- const char *Matrix_To_cylindrical(MATOBJ *matrix,int form){
- if(matrix->form==form) {
- return NULL;
- }
- switch(matrix->form) {
- case MATFORM_polar:
- case MATFORM_cylindrical:
- case MATFORM_vector_xy:
- case MATFORM_vector_xyz:
- case MATFORM_vector_xyzw:
- break;
- default:
- if(Matrix_To_cartesian(matrix,MATFORM_cartesian)) {
- return "Cannot convert to polar";
- }
- }
- if(matrix->form==MATFORM_cartesian) {
- odiemath_cartesian_to_cylindrical(matrix->matrix,matrix->matrix);
- }
- switch(form) {
- case MATFORM_cylindrical:
- matrix->form=form;
- matrix->rows=3;
- matrix->cols=1;
- return NULL;
- case MATFORM_polar:
- matrix->form=form;
- matrix->rows=2;
- matrix->cols=1;
- return NULL;
- }
- return NULL;
- }
- /* *Matrix_To_spherical */
- const char *Matrix_To_spherical(MATOBJ *matrix,int form){
- if(matrix->form==form) {
- return NULL;
- }
- if(Matrix_To_cartesian(matrix,MATFORM_cartesian)) {
- return "Cannot convert to spherical";
- }
- if(matrix->form==MATFORM_cartesian) {
- odiemath_cartesian_to_spherical(matrix->matrix,matrix->matrix);
- }
- matrix->form=form;
- matrix->rows=3;
- matrix->cols=1;
- return NULL;
- }
- /* *VectorXYZ_To_TclObj */
- Tcl_Obj *VectorXYZ_To_TclObj(VectorXYZ R){
- MATOBJ *RESULT;
- RESULT=Odie_MatrixObj_Create(MATFORM_vector_xyz);
- RESULT->matrix[X_IDX]=R[X_IDX];
- RESULT->matrix[Y_IDX]=R[Y_IDX];
- RESULT->matrix[Z_IDX]=R[Z_IDX];
- return Matrix_To_TclObj(RESULT);
- }
- /* Odie_GetVectorXYZFromTclObj */
- int Odie_GetVectorXYZFromTclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,VectorXYZ R){
- Tcl_Obj **elemPtrs;
- int cols,i;
- if(objPtr->typePtr) {
- if(objPtr->typePtr->setFromAnyProc==&MatrixObj_setFromAnyProc) {
- /*
- ** Object is a matrix
- */
- const char *err;
- MATOBJ *value=objPtr->internalRep.otherValuePtr;
- err=Matrix_To_cartesian(value,MATFORM_vector_xyz);
- if(err) {
- Tcl_AppendResult(interp,err,NULL);
- return TCL_ERROR;
- }
- R[X_IDX]=value->matrix[X_IDX];
- R[Y_IDX]=value->matrix[Y_IDX];
- R[Z_IDX]=value->matrix[Z_IDX];
- return TCL_OK;
- }
- }
- /* Step one, Measure the matrix */
- if(Tcl_ListObjGetElements(interp, objPtr, &cols, &elemPtrs)) return TCL_ERROR;
- for(i=0;i<3;i++) {
- double temp;
- if(cols<=i) {
- R[i]=0.0;
- } else {
- if(Tcl_GetDoubleFromObj(interp, elemPtrs[i], &temp)) return TCL_ERROR;
- R[i]=temp;
- }
- }
- return TCL_OK;
- }
- /* VectorXYZ_Scale */
- static inline void VectorXYZ_Scale(VECTOR A,SCALER S){
- A[X_IDX]*=S;
- A[Y_IDX]*=S;
- A[Z_IDX]*=S;
- }
- /* VectorXYZ_Zero */
- static inline void VectorXYZ_Zero(VECTORXYZ A){
- A[X_IDX]=0.0;
- A[Y_IDX]=0.0;
- A[Z_IDX]=0.0;
- }
- /* VectorXYZ_GridAlign */
- static inline void VectorXYZ_GridAlign(VECTORXYZ A,double grid){
- double x,q,grain;
- grain=grid*0.5;
- if(grid<=0) return;
- A[X_IDX]=Vector_GridScaler(A[X_IDX],grid,grain);
- A[Y_IDX]=Vector_GridScaler(A[Y_IDX],grid,grain);
- A[Z_IDX]=Vector_GridScaler(A[Z_IDX],grid,grain);
- }
- /* VectorXYZ_Copy */
- static inline void VectorXYZ_Copy(VECTORXYZ B,VECTORXYZ A){
- B[X_IDX]=A[X_IDX];
- B[Y_IDX]=A[Y_IDX];
- B[Z_IDX]=A[Z_IDX];
- }
- /* VectorXYZ_SamePoint */
- static inline int VectorXYZ_SamePoint(VECTORXYZ A,VECTORXYZ B){
- if(A==B) {
- return 1;
- }
- if(fabs(B[X_IDX]-A[X_IDX])>Vector_Tolerance) return 0;
- if(fabs(B[Y_IDX]-A[Y_IDX])>Vector_Tolerance) return 0;
- if(fabs(B[Z_IDX]-A[Z_IDX])>Vector_Tolerance) return 0;
- return 1;
- }
- /* VectorXYZ_IsZero */
- static inline int VectorXYZ_IsZero(VECTORXYZ A){
- if(!A) return 1;
- if(fabs(A[X_IDX])>Vector_Tolerance) return 0;
- if(fabs(A[Y_IDX])>Vector_Tolerance) return 0;
- if(fabs(A[Z_IDX])>Vector_Tolerance) return 0;
- return 1;
- }
- /* VectorXYZ_Cross_Product */
- static inline void VectorXYZ_Cross_Product(VectorXYZ C,VectorXYZ A,VectorXYZ B){
- C[X_IDX] = A[Y_IDX] * B[Z_IDX] - A[Z_IDX] * B[Y_IDX];
- C[Y_IDX] = A[Z_IDX] * B[X_IDX] - A[X_IDX] * B[Z_IDX];
- C[Z_IDX] = A[X_IDX] * B[Y_IDX] - A[Y_IDX] * B[X_IDX];
- }
- /* VectorXYZ_Add */
- static inline void VectorXYZ_Add(VECTORXYZ C,VECTORXYZ A,VECTORXYZ B){
- C[X_IDX]=B[X_IDX]+A[X_IDX];
- C[Y_IDX]=B[Y_IDX]+A[Y_IDX];
- C[Z_IDX]=B[Z_IDX]+A[Z_IDX];
- }
- /* VectorXYZ_Subtract */
- static inline void VectorXYZ_Subtract(VECTORXYZ C,VECTORXYZ A,VECTORXYZ B){
- C[X_IDX]=A[X_IDX]-B[X_IDX];
- C[Y_IDX]=A[Y_IDX]-B[Y_IDX];
- C[Z_IDX]=A[Z_IDX]-B[Z_IDX];
- }
- /* VectorXYZ_IsOrthagonal */
- static inline int VectorXYZ_IsOrthagonal(VECTORXYZ A,VECTORXYZ B){
- int result=0;
- if((A[X_IDX]-B[X_IDX])>Vector_Tolerance) result++;
- if((A[Y_IDX]-B[Y_IDX])>Vector_Tolerance) result++;
- if((A[Z_IDX]-B[Z_IDX])>Vector_Tolerance) result++;
- return result>1 ? 0 : 1;
- }
- /* VectorXYZ_Midpoint */
- static inline void VectorXYZ_Midpoint(VECTORXYZ C,VECTORXYZ A,VECTORXYZ B){
- C[X_IDX]=(B[X_IDX]-A[X_IDX])*0.5+A[X_IDX];
- C[Y_IDX]=(B[Y_IDX]-A[Y_IDX])*0.5+A[Y_IDX];
- C[Z_IDX]=(B[Z_IDX]-A[Z_IDX])*0.5+A[Z_IDX];
- }
- /* VectorXYZ_Distance */
- static inline double VectorXYZ_Distance(VECTORXYZ A,VECTORXYZ B){
- double dx,dy,dz;
- dx=B[X_IDX]-A[X_IDX];
- dy=B[Y_IDX]-A[Y_IDX];
- dz=B[Z_IDX]-A[Z_IDX];
- return sqrt(dx*dx+dy*dy+dz*dz);
- }
- /* VectorXYZ_DistanceSq */
- static inline double VectorXYZ_DistanceSq(VECTORXYZ A,VECTORXYZ B){
- double dx,dy,dz;
- dx=A[X_IDX]-B[X_IDX];
- dy=A[Y_IDX]-B[Y_IDX];
- dz=A[Z_IDX]-B[Z_IDX];
- return (dx*dx+dy*dy+dz*dz);
- }
- /* VectorXYZ_Dot_Product */
- static inline double VectorXYZ_Dot_Product(VectorXYZ A,VectorXYZ B){
- double r;
- r=A[X_IDX] * B[X_IDX] + A[Y_IDX] * B[Y_IDX] + A[Z_IDX] * B[Z_IDX];
- if(fabs(r)<__FLT_EPSILON__) {
- return 0.0;
- }
- return r;
- }
- /* VectorXYZ_MatrixMultiply */
- static inline void VectorXYZ_MatrixMultiply(VECTORXYZ R,VECTORXYZ A,AFFINE M){
- double temp[4];
- temp[0]=A[X_IDX]*M[AFFINE_IDX_0_0] + A[Y_IDX]*M[AFFINE_IDX_1_0] + A[Z_IDX]* M[AFFINE_IDX_2_0] + M[AFFINE_IDX_3_0];
- temp[1]=A[X_IDX]*M[AFFINE_IDX_0_1] + A[Y_IDX]*M[AFFINE_IDX_1_1] + A[Z_IDX]* M[AFFINE_IDX_2_1] + M[AFFINE_IDX_3_1];
- temp[2]=A[X_IDX]*M[AFFINE_IDX_0_2] + A[Y_IDX]*M[AFFINE_IDX_1_2] + A[Z_IDX]* M[AFFINE_IDX_2_2] + M[AFFINE_IDX_3_2];
- R[0]=temp[0];
- R[1]=temp[1];
- R[2]=temp[2];
- }
- /* VectorXYZ_MagnitudeSq */
- static inline double VectorXYZ_MagnitudeSq(VECTOR A){
- double length=A[0]*A[0]+A[1]*A[1]+A[2]*A[2];
- if(length<Vector_Tolerance) {
- return 0.0;
- }
- return length;
- }
- /* VectorXYZ_Magnitude */
- static inline double VectorXYZ_Magnitude(VECTOR A){
- double length=sqrt(A[0]*A[0]+A[1]*A[1]+A[2]*A[2]);
- if(length<Vector_Tolerance) {
- return 0.0;
- }
- return length;
- }
- /* VectorXYZ_MagnitudeInvSqr */
- static inline double VectorXYZ_MagnitudeInvSqr(VECTOR A){
- double r=A[0]+A[1]+A[2];
- if(fabs(r)<Vector_Tolerance) {
- return NAN;
- }
- return (1.0/(A[0]*A[0]+A[1]*A[1]+A[2]*A[2]));
- }
- /* VectorXYZ_Normalize */
- static inline int VectorXYZ_Normalize(VectorXYZ A){
- double d;
- double r=VectorXYZ_Magnitude(A);
- if(fabs(r) < __FLT_EPSILON__) {
- A[0]=0.0;
- A[1]=0.0;
- A[3]=0.0;
- return 1;
- } else {
- d=1.0 / r;
- A[0]*=d;
- A[1]*=d;
- A[2]*=d;
- return 0;
- }
- }
- /* VectorXYZ_PointIsOnSegment */
- static inline int VectorXYZ_PointIsOnSegment(VectorXYZ POINT,VectorXYZ A,VectorXYZ B){
- VectorXYZ INTERSECT;
- double t;
- t=VectorXYZ_ClosestPointOnSegment(A,B,POINT,INTERSECT);
- if (t<0.0 && t>1.0) return 0;
- if(VectorXYZ_DistanceSq(POINT,INTERSECT)>Vector_Tolerance_Sq) return 0;
- return 1;
- }
- /* VectorXYZ_AxisOfNormal */
- static inline int VectorXYZ_AxisOfNormal(VectorXYZ NORMAL){
- if(fabs(NORMAL[Z_IDX])>fabs(NORMAL[X_IDX])) {
- if (fabs(NORMAL[Z_IDX])>fabs(NORMAL[Y_IDX])) {
- return Z_IDX;
- } else {
- return Y_IDX;
- }
- }
- if (fabs(NORMAL[X_IDX])>fabs(NORMAL[Y_IDX])) {
- return X_IDX;
- } else {
- return Y_IDX;
- }
- }
- /* VectorXYZ_NormalStrictAxisAligned */
- static inline int VectorXYZ_NormalStrictAxisAligned(VectorXYZ NORMAL){
- int i;
- for(i=2;i>=0;i--) {
- if(1.0-fabs(NORMAL[i]) < Vector_Tolerance) return i;
- }
- return -1;
- }
- /* VectorXYZ_AxisAligned */
- static inline int VectorXYZ_AxisAligned(VectorXYZ A,VectorXYZ B,VectorXYZ C){
- int i;
- for(i=2;i>=0;i--) {
- if(fabs((C[i]-B[i])+(B[i]-A[i])) < Vector_Tolerance) return i;
- }
- return -1;
- }
- /* VectorXYZ_BendDirection */
- static inline int VectorXYZ_BendDirection(VectorXYZ A,VectorXYZ B,VectorXYZ C){
- int axis;
- VectorXYZ D1,D2;
- if(VectorXYZ_SamePoint(A,C)) {
- return -1;
- }
- /* If all points are axis aligned. We can treat as a 2d problem */
- axis=VectorXYZ_AxisAligned(A,B,C);
- if(axis==Z_IDX) {
- double r = (A[Y_IDX]-B[Y_IDX])*(C[X_IDX]-B[X_IDX]) + (B[X_IDX]-A[X_IDX])*(C[Y_IDX]-B[Y_IDX]);
- if(fabs(r) < __FLT_EPSILON__) return 0;
- return r<0.0 ? +1 : (r>0.0 ? -1 : 0);
- }
- if(axis==Y_IDX) {
- double r = (A[X_IDX]-B[X_IDX])*(C[Z_IDX]-B[Z_IDX]) + (B[Z_IDX]-A[Z_IDX])*(C[X_IDX]-B[X_IDX]);
- if(fabs(r) < __FLT_EPSILON__) return 0;
- return r<0.0 ? +1 : (r>0.0 ? -1 : 0);
- }
- if(axis==X_IDX) {
- /* All points are axis aligned on Z. We can treat as a 2d problem */
- double r = (A[Z_IDX]-B[Z_IDX])*(C[Y_IDX]-B[Y_IDX]) + (B[Y_IDX]-A[Y_IDX])*(C[Z_IDX]-B[Z_IDX]);
- if(fabs(r) < __FLT_EPSILON__) return 0;
- return r<0.0 ? +1 : (r>0.0 ? -1 : 0);
- }
- VectorXYZ_Cross_Product(D1,B,A);
- VectorXYZ_Cross_Product(D2,C,B);
- if(VectorXYZ_IsZero(D1) && VectorXYZ_IsZero(D2)) {
- /* We must be colinear */
- double r=(A[X_IDX]-B[X_IDX])*(C[X_IDX]-B[X_IDX])+(A[Y_IDX]-B[Y_IDX])*(C[Y_IDX]-B[Y_IDX])+(A[Z_IDX]-B[Z_IDX])*(C[Z_IDX]-B[Z_IDX]);
- if(r<0) {
- return 0;
- }
- return -1;
- }
- /* Gauge the direction of the cross products. If all axis agree, we are pointed the right way */
- if(D1[X_IDX]>=0 && D2[X_IDX]<0) {
- return -1;
- }
- if(D1[Y_IDX]>=0 && D2[Y_IDX]<0) {
- return -1;
- }
- if(D1[Z_IDX]>=0 && D2[Z_IDX]<0) {
- return -1;
- }
- return 1;
- }
- /* VectorXYZ_Angle_Three_Point */
- static inline double VectorXYZ_Angle_Three_Point(VectorXYZ A,VectorXYZ B,VectorXYZ C,VectorXYZ normal){
- double dotprod,num;
- VectorXYZ D1,D2;
- int axis;
- if(VectorXYZ_SamePoint(A,C)) {
- return M_PI;
- }
- axis=VectorXYZ_AxisAligned(A,B,C);
- if(axis==Z_IDX) {
- /* All points are axis aligned on Z. We can treat as a 2d problem */
- return VectorXY_Angle_Three_Point(A,B,C);
- }
- VectorXYZ_Subtract(D1,B,A);
- VectorXYZ_Subtract(D2,C,B);
- num=VectorXYZ_Magnitude(D1)*VectorXYZ_Magnitude(D2);
- if(fabs(num)<Vector_Tolerance) {
- /* At least one of the vectors is zero magnetude
- ** Assume any angle is good */
- return 0.0;
- }
- dotprod=VectorXYZ_Dot_Product(D1,D2);
- return acos(dotprod/num);
- }
- /* VectorXYZ_IsColinear */
- static inline int VectorXYZ_IsColinear(VectorXYZ A,VectorXYZ B,VectorXYZ C){
- double c;
- if(VectorXYZ_SamePoint(A,C)) {
- return 1;
- }
- c=( C[Z_IDX] - A[Z_IDX] ) * ( B[Y_IDX] - A[Y_IDX] ) - ( B[Z_IDX] - A[Z_IDX] ) * ( C[Y_IDX] - A[Y_IDX] );
- if(fabs(c)>Vector_Tolerance) return 0;
- c=( B[Z_IDX] - A[Z_IDX] ) * ( C[X_IDX] - A[X_IDX] ) - ( B[X_IDX] - A[X_IDX] ) * ( C[Z_IDX] - A[Z_IDX] );
- if(fabs(c)>Vector_Tolerance) return 0;
- c=( B[X_IDX] - A[X_IDX] ) * ( C[Y_IDX] - A[Y_IDX] ) - ( B[Y_IDX] - A[Y_IDX] ) * ( C[X_IDX] - A[X_IDX] );
- if(fabs(c)>Vector_Tolerance) return 0;
- return 1;
- }
- /* VectorXYZ_IsCoplaner */
- static inline int VectorXYZ_IsCoplaner(VectorXYZ x1,VectorXYZ x2,VectorXYZ x3,VectorXYZ x4){
- double c;
- VectorXYZ d12,d14,d13,cross;
- VectorXYZ_Subtract(d12,x2,x1);
- VectorXYZ_Subtract(d14,x4,x1);
- VectorXYZ_Cross_Product(cross,d12,d14);
- VectorXYZ_Subtract(d13,x3,x1);
- c=VectorXYZ_Dot_Product(cross,d13);
- if(fabs(c)>Vector_Tolerance) return 0;
- return 1;
- }
- /* VectorXYZ_LineLineCoincident */
- static inline int VectorXYZ_LineLineCoincident(
- VectorXYZ A1, VectorXYZ A2, VectorXYZ B1, VectorXYZ B2,
- VectorXYZ ICEPT1, VectorXYZ ICEPT2
- ){
- int a,b,result=0;
- /*
- ** Optimization - two lines can't be coincident if they don't
- ** occupy the same region of space
- */
- if(!VectorXYZ_BBOX_Overlap_TwoVectors(A1,A2,B1,B2)) {
- return 0;
- }
- if(VectorXYZ_SamePoint(A1,B1)) {
- if(VectorXYZ_SamePoint(A2,B2)) {
- VectorXYZ_Copy(ICEPT1,A1);
- VectorXYZ_Copy(ICEPT2,A2);
- return 30;
- }
- }
- if(VectorXYZ_SamePoint(A2,B1)) {
- if(VectorXYZ_SamePoint(A1,B2)) {
- VectorXYZ_Copy(ICEPT1,A1);
- VectorXYZ_Copy(ICEPT2,A2);
- return 30;
- }
- }
- a=VectorXYZ_IsColinear(A1,B1,B2);
- b=VectorXYZ_IsColinear(A2,B1,B2);
- if(a==0 || b==0) {
- /* The two lines are not colinear */
- int c;
- double x,y;
- c=VectorXYZ_LineLineIntersect(A1,A2,B1,B2,ICEPT1,ICEPT2,&x,&y);
- if(c>0) {
- if(x<=0 || y<=0) return 0;
- if(x>=1 || y>=1) return 0;
- /* True if both intercepts happen on a single point */
- return 1;
- }
- }
- if(VectorXYZ_PointIsOnSegment(A1,B1,B2)) {
- result |= 2;
- }
- if(VectorXYZ_PointIsOnSegment(A2,B1,B2)) {
- result |= 4;
- }
- if(VectorXYZ_PointIsOnSegment(B1,A1,A2)) {
- result |= 8;
- }
- if(VectorXYZ_PointIsOnSegment(B2,A1,A2)) {
- result |= 16;
- }
- /* If the segments touch ends we don't count it as coincident */
- if(result==0 || result==10 || result== 18 || result == 12 || result== 20) {
- return 0;
- }
-
- if((result & 6)==6) {
- VectorXYZ_Copy(ICEPT1,A1);
- VectorXYZ_Copy(ICEPT2,A2);
- } else if((result & 24)==24) {
- /* Both B on A */
- VectorXYZ_Copy(ICEPT1,B1);
- VectorXYZ_Copy(ICEPT2,B2);
- } else {
- if(result & 2) {
- VectorXYZ_Copy(ICEPT1,A1);
- if(result&8) {
- VectorXYZ_Copy(ICEPT2,B1);
- } else if(result&16) {
- VectorXYZ_Copy(ICEPT2,B2);
- } else {
- VectorXYZ_Copy(ICEPT2,A1);
- }
- } else if(result & 4) {
- VectorXYZ_Copy(ICEPT1,A2);
- if(result&8) {
- VectorXYZ_Copy(ICEPT2,B1);
- } else if(result&16) {
- VectorXYZ_Copy(ICEPT2,B2);
- } else {
- VectorXYZ_Copy(ICEPT2,A2);
- }
- } else if(result & 8) {
- VectorXYZ_Copy(ICEPT1,B1);
- VectorXYZ_Copy(ICEPT1,B2);
- } else {
- VectorXYZ_Copy(ICEPT1,B2);
- VectorXYZ_Copy(ICEPT2,B2);
- }
- }
- return result;
- }
- /* VectorXYZ_LineLineIntersect */
- static inline int VectorXYZ_LineLineIntersect(
- VectorXYZ p1, VectorXYZ p2, VectorXYZ p3, VectorXYZ p4,
- VectorXYZ pA, VectorXYZ pB, double *mua, double *mub
- ){
- VectorXYZ p13,p43,p21;
- double d1343,d4321,d1321,d4343,d2121;
- double numer,denom;
-
- p13[X_IDX] = p1[X_IDX] - p3[X_IDX];
- p13[Y_IDX] = p1[Y_IDX] - p3[Y_IDX];
- p13[Z_IDX] = p1[Z_IDX] - p3[Z_IDX];
- p43[X_IDX] = p4[X_IDX] - p3[X_IDX];
- p43[Y_IDX] = p4[Y_IDX] - p3[Y_IDX];
- p43[Z_IDX] = p4[Z_IDX] - p3[Z_IDX];
- if (fabs(p43[X_IDX]) < Vector_Tolerance && fabs(p43[Y_IDX]) < Vector_Tolerance && fabs(p43[Z_IDX]) < Vector_Tolerance)
- return(0);
- p21[X_IDX] = p2[X_IDX] - p1[X_IDX];
- p21[Y_IDX] = p2[Y_IDX] - p1[Y_IDX];
- p21[Z_IDX] = p2[Z_IDX] - p1[Z_IDX];
- if (fabs(p21[X_IDX]) < Vector_Tolerance && fabs(p21[Y_IDX]) < Vector_Tolerance && fabs(p21[Z_IDX]) < Vector_Tolerance)
- return(0);
-
- d1343 = p13[X_IDX] * p43[X_IDX] + p13[Y_IDX] * p43[Y_IDX] + p13[Z_IDX] * p43[Z_IDX];
- d4321 = p43[X_IDX] * p21[X_IDX] + p43[Y_IDX] * p21[Y_IDX] + p43[Z_IDX] * p21[Z_IDX];
- d1321 = p13[X_IDX] * p21[X_IDX] + p13[Y_IDX] * p21[Y_IDX] + p13[Z_IDX] * p21[Z_IDX];
- d4343 = p43[X_IDX] * p43[X_IDX] + p43[Y_IDX] * p43[Y_IDX] + p43[Z_IDX] * p43[Z_IDX];
- d2121 = p21[X_IDX] * p21[X_IDX] + p21[Y_IDX] * p21[Y_IDX] + p21[Z_IDX] * p21[Z_IDX];
-
- denom = d2121 * d4343 - d4321 * d4321;
- if (fabs(denom) < __FLT_EPSILON__)
- return(0);
- numer = d1343 * d4321 - d1321 * d4343;
-
- *mua = numer / denom;
- *mub = (d1343 + d4321 * (*mua)) / d4343;
-
- pA[X_IDX] = p1[X_IDX] + *mua * p21[X_IDX];
- pA[Y_IDX] = p1[Y_IDX] + *mua * p21[Y_IDX];
- pA[Z_IDX] = p1[Z_IDX] + *mua * p21[Z_IDX];
- pB[X_IDX] = p3[X_IDX] + *mub * p43[X_IDX];
- pB[Y_IDX] = p3[Y_IDX] + *mub * p43[Y_IDX];
- pB[Z_IDX] = p3[Z_IDX] + *mub * p43[Z_IDX];
- return(1);
- }
- /* VectorXYZ_ClosestPointOnSegment */
- static double VectorXYZ_ClosestPointOnSegment (
- VectorXYZ A, VectorXYZ B, /* End points of the line segment */
- VectorXYZ X, /* The point outside the line */
- VectorXYZ R /* Write closest point on line segment here */
- ){
- VectorXYZ v1, v2;
- double t, s,mag;
-
- VectorXYZ_Subtract(v1, X, A);
- VectorXYZ_Subtract(v2, B, A);
- mag=VectorXYZ_MagnitudeSq(v2);
- if(mag<Vector_Tolerance_Sq) {
- /* A, B and X are on the same point */
- R[X_IDX] = A[X_IDX];
- R[Y_IDX] = A[Y_IDX];
- R[Z_IDX] = A[Z_IDX];
- return 0.5;
- }
- t = VectorXYZ_Dot_Product(v1, v2)/VectorXYZ_MagnitudeSq(v2);
- if( t<0.0 ){
- VectorXYZ_Copy(R,A);
- } else if( t>1.0 ){
- VectorXYZ_Copy(R,B);
- } else {
- s = 1.0 - t;
- R[X_IDX] = A[X_IDX]*s + B[X_IDX]*t;
- R[Y_IDX] = A[Y_IDX]*s + B[Y_IDX]*t;
- R[Z_IDX] = A[Z_IDX]*s + B[Z_IDX]*t;
- }
- return t;
- }
- /* VectorXYX_solve3by3 */
- static int VectorXYX_solve3by3(double *m){
- int i, j, k;
- double x, y, scale;
- /* Process three rows from top to bottom */
- for(i=0; i<3; i++){
- /* Find the pivot for the i-th row */
- x = fabs(m[i*5]);
- k = i;
- for(j=i+1; j<3; j++){
- y = fabs(m[j*4+i]);
- if( y>x ){
- x = y;
- k = j;
- }
- }
-
- /* Swap in the pivot */
- if( k>i ){
- double t;
- int n, p, q;
- p = i*5;
- q = k*4+i;
- for(n=i; n<4; n++, p++, q++){
- t = m[p];
- m[p] = m[q];
- m[q] = t;
- }
- }
-
- /* No solution if the pivot is 0.0 */
- if( m[i*5]==0.0 ) {
- return 1;
- }
-
- /* Divide the i-th row by the pivot */
- scale = m[i*5];
- for(j=i; j<4; j++){
- m[i*4+j] /= scale;
- }
-
- /* Add the i-th row to other rows to eliminate the i-th term. */
- for(j=i+1; j<3; j++){
- double scale = -m[j*4+i];
- for(k=i; k<4; k++){
- m[j*4+k] += m[i*4+k]*scale;
- }
- }
- }
-
- /* Now we have an upper triangular matrix with a diagonal of 1.
- ** Finishing the solution is easy */
- for(i=1; i>=0; i--){
- for(j=2; j>i; j--){
- m[i*4+3] -= m[j*4+3]*m[i*4+j];
- }
- }
- return 0;
- }
- /* VectorXYZ_TriangleLineIntersect */
- static double VectorXYZ_TriangleLineIntersect(
- VectorXYZ A, VectorXYZ B, VectorXYZ C, /* The triangle we are trying to intersect */
- VectorXYZ pStart, /* Start of the line segment */
- VectorXYZ pEnd, /* End of the line segment */
- VectorXYZ pIntersect /* Point of intersection written here if not NULL */
- ){
- double s, t;
- double m[12];
- m[0] = pStart[X_IDX] - pEnd[X_IDX];
- m[1] = B[X_IDX] - A[X_IDX];
- m[2] = C[X_IDX] - A[X_IDX];
- m[3] = pStart[X_IDX] - A[X_IDX];
- m[4] = pStart[Y_IDX] - pEnd[Y_IDX];
- m[5] = B[Y_IDX] - A[Y_IDX];
- m[6] = C[Y_IDX] - A[Y_IDX];
- m[7] = pStart[Y_IDX] - A[Y_IDX];
- m[8] = pStart[Z_IDX] - pEnd[Z_IDX];
- m[9] = B[Z_IDX] - A[Z_IDX];
- m[10] = C[Z_IDX] - A[Z_IDX];
- m[11] = pStart[Z_IDX] - A[Z_IDX];
- if( VectorXYX_solve3by3(m) ){
- /* The line is parallel or coplanar with the triangle */
- return -1.0;
- }
- t = m[3];
- if( t<0.0 || t>1.0 ){
- /* The point of intersection is off the ends of the line segment */
- return -1.0;
- }
- if( m[7]<0.0 || m[7]>1.0 || m[11]<0.0 || m[11]>1.0 || (m[7]+m[11])>1.0 ){
- /* The point of intersection is outside of the triangle boundary */
- return -1.0;
- }
- s = 1.0 - t;
- pIntersect[X_IDX] = pStart[X_IDX]*s + pEnd[X_IDX]*t;
- pIntersect[Y_IDX] = pStart[Y_IDX]*s + pEnd[Y_IDX]*t;
- pIntersect[Z_IDX] = pStart[Z_IDX]*s + pEnd[Z_IDX]*t;
- return t;
- }
- /* VectorXYZ_Normal_of_Three_Points */
- static inline void VectorXYZ_Normal_of_Three_Points(VectorXYZ normal,VectorXYZ A,VectorXYZ B,VectorXYZ C){
- VectorXYZ one,two;
- VectorXYZ_Subtract(one, B, A);
- VectorXYZ_Subtract(two, C, A);
- normal[X_IDX] = one[Y_IDX]*two[Z_IDX] - one[Z_IDX]*two[Y_IDX];
- normal[Y_IDX] = one[Z_IDX]*two[X_IDX] - one[X_IDX]*two[Z_IDX];
- normal[Z_IDX] = one[X_IDX]*two[Y_IDX] - one[Y_IDX]*two[X_IDX];
- }
- /* VectorXYZ_LineSphereIntersect */
- int VectorXYZ_LineSphereIntersect(
- double p1_x, double p1_y, double p1_z,
- double p2_x, double p2_y, double p2_z,
- double sc_x, double sc_y, double sc_z,
- double r,
- double *mu1, double *mu2){
- /*
- ** Detect the intersection of a line and a sphere
- ** Adapted from: http://http://paulbourke.net/geometry/circlesphere/raysphere.c
- */
- double a,b,c;
- double bb4ac;
- double dp_x,dp_y,dp_z;
- *mu1 = 0;
- *mu2 = 0;
- dp_x = p2_x - p1_x;
- dp_y = p2_y - p1_y;
- dp_z = p2_z - p1_z;
- a = dp_x * dp_x + dp_y * dp_y + dp_z * dp_z;
- b = 2 * (dp_x * (p1_x - sc_x) + dp_y * (p1_y - sc_y) + dp_z * (p1_z - sc_z));
- c = sc_x * sc_x + sc_y * sc_y + sc_z * sc_z;
- c += p1_x * p1_x + p1_y * p1_y + p1_z * p1_z;
- c -= 2 * (sc_x * p1_x + sc_y * p1_y + sc_z * p1_z);
- c -= r * r;
- bb4ac = b * b - 4 * a * c;
- if (ODIE_Real_Is_Zero(a) || bb4ac < 0) {
- return(0);
- }
-
- *mu1 = (-b + sqrt(bb4ac)) / (2 * a);
- *mu2 = (-b - sqrt(bb4ac)) / (2 * a);
- return(1);
- }
- /* *VectorXYZ_ToString */
- char *VectorXYZ_ToString(VectorXYZ VECTOR){
- char *out=Tcl_Alloc(128);
- sprintf(out,"<%g %g %g>",(float)VECTOR[X_IDX],(float)VECTOR[Y_IDX],(float)VECTOR[Z_IDX]);
- return out;
- }
- /* Vector_Set_Tolerance */
- void Vector_Set_Tolerance(double newvalue){
- Vector_Tolerance=newvalue;
- Vector_Tolerance_Sq=newvalue*newvalue;
- }
- /* *Vector_Alloc */
- double *Vector_Alloc(size_t size){
- double *ptr;
- if(size<128) {
- size=128;
- }
- ptr=(double*)ckalloc(size);
- memset(ptr,0,size);
- return ptr;
- }
- /* Odie_Matrix_AABBXYZ_From_TclObj */
- STUB_EXPORT int Odie_Matrix_AABBXYZ_From_TclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,AABBXYZ ptr){
- Odie_MatrixObj *T;
- if(Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_aabb_xyz,&T)) return TCL_ERROR;
- memcpy(ptr,T->matrix,sizeof(AABBXYZ));
- return TCL_OK;
- }
- /* *Odie_Matrix_AABBXYZ_To_TclObj */
- STUB_EXPORT Tcl_Obj *Odie_Matrix_AABBXYZ_To_TclObj(AABBXYZ ptr){
- Odie_MatrixObj *C;
- Tcl_Obj *result;
- C=Odie_MatrixObj_Create(MATFORM_aabb_xyz);
- memcpy(C->matrix,ptr,sizeof(AABBXYZ));
- result=Matrix_To_TclObj(C);
- return result;
- }
- /* Odie_Matrix_AFFINE_From_TclObj */
- STUB_EXPORT int Odie_Matrix_AFFINE_From_TclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,AFFINE ptr){
- Odie_MatrixObj *T;
- if(Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_affine,&T)) return TCL_ERROR;
- memcpy(ptr,T->matrix,sizeof(AFFINE));
- return TCL_OK;
- }
- /* *Odie_Matrix_AFFINE_To_TclObj */
- STUB_EXPORT Tcl_Obj *Odie_Matrix_AFFINE_To_TclObj(AFFINE ptr){
- Odie_MatrixObj *C;
- Tcl_Obj *result;
- C=Odie_MatrixObj_Create(MATFORM_affine);
- memcpy(C->matrix,ptr,sizeof(AFFINE));
- result=Matrix_To_TclObj(C);
- return result;
- }
- /* Odie_Matrix_BBOXXY_From_TclObj */
- STUB_EXPORT int Odie_Matrix_BBOXXY_From_TclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,BBOXXY ptr){
- Odie_MatrixObj *T;
- if(Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_bbox_xy,&T)) return TCL_ERROR;
- memcpy(ptr,T->matrix,sizeof(BBOXXY));
- return TCL_OK;
- }
- /* *Odie_Matrix_BBOXXY_To_TclObj */
- STUB_EXPORT Tcl_Obj *Odie_Matrix_BBOXXY_To_TclObj(BBOXXY ptr){
- Odie_MatrixObj *C;
- Tcl_Obj *result;
- C=Odie_MatrixObj_Create(MATFORM_bbox_xy);
- memcpy(C->matrix,ptr,sizeof(BBOXXY));
- result=Matrix_To_TclObj(C);
- return result;
- }
- /* Odie_Matrix_AFFINE3X3_From_TclObj */
- STUB_EXPORT int Odie_Matrix_AFFINE3X3_From_TclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,AFFINE3X3 ptr){
- Odie_MatrixObj *T;
- if(Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_mat3,&T)) return TCL_ERROR;
- memcpy(ptr,T->matrix,sizeof(AFFINE3X3));
- return TCL_OK;
- }
- /* *Odie_Matrix_AFFINE3X3_To_TclObj */
- STUB_EXPORT Tcl_Obj *Odie_Matrix_AFFINE3X3_To_TclObj(AFFINE3X3 ptr){
- Odie_MatrixObj *C;
- Tcl_Obj *result;
- C=Odie_MatrixObj_Create(MATFORM_mat3);
- memcpy(C->matrix,ptr,sizeof(AFFINE3X3));
- result=Matrix_To_TclObj(C);
- return result;
- }
- /* Odie_Matrix_QUATERNION_From_TclObj */
- STUB_EXPORT int Odie_Matrix_QUATERNION_From_TclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,QUATERNION ptr){
- Odie_MatrixObj *T;
- if(Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_quaternion,&T)) return TCL_ERROR;
- memcpy(ptr,T->matrix,sizeof(QUATERNION));
- return TCL_OK;
- }
- /* *Odie_Matrix_QUATERNION_To_TclObj */
- STUB_EXPORT Tcl_Obj *Odie_Matrix_QUATERNION_To_TclObj(QUATERNION ptr){
- Odie_MatrixObj *C;
- Tcl_Obj *result;
- C=Odie_MatrixObj_Create(MATFORM_quaternion);
- memcpy(C->matrix,ptr,sizeof(QUATERNION));
- result=Matrix_To_TclObj(C);
- return result;
- }
- /* Odie_Matrix_VECTORXY_From_TclObj */
- STUB_EXPORT int Odie_Matrix_VECTORXY_From_TclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,VECTORXY ptr){
- Odie_MatrixObj *T;
- if(Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_vector_xy,&T)) return TCL_ERROR;
- memcpy(ptr,T->matrix,sizeof(VECTORXY));
- return TCL_OK;
- }
- /* *Odie_Matrix_VECTORXY_To_TclObj */
- STUB_EXPORT Tcl_Obj *Odie_Matrix_VECTORXY_To_TclObj(VECTORXY ptr){
- Odie_MatrixObj *C;
- Tcl_Obj *result;
- C=Odie_MatrixObj_Create(MATFORM_vector_xy);
- memcpy(C->matrix,ptr,sizeof(VECTORXY));
- result=Matrix_To_TclObj(C);
- return result;
- }
- /* Odie_Matrix_VectorXYZ_From_TclObj */
- STUB_EXPORT int Odie_Matrix_VectorXYZ_From_TclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,VectorXYZ ptr){
- Odie_MatrixObj *T;
- if(Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_vector_xyz,&T)) return TCL_ERROR;
- memcpy(ptr,T->matrix,sizeof(VectorXYZ));
- return TCL_OK;
- }
- /* *Odie_Matrix_VectorXYZ_To_TclObj */
- STUB_EXPORT Tcl_Obj *Odie_Matrix_VectorXYZ_To_TclObj(VectorXYZ ptr){
- Odie_MatrixObj *C;
- Tcl_Obj *result;
- C=Odie_MatrixObj_Create(MATFORM_vector_xyz);
- memcpy(C->matrix,ptr,sizeof(VectorXYZ));
- result=Matrix_To_TclObj(C);
- return result;
- }
- /* Odie_GetIntFromObj */
- int Odie_GetIntFromObj(Tcl_Interp *interp,Tcl_Obj *tclObj,int *result){
- if(!Tcl_GetIntFromObj(NULL,tclObj,result)) {
- return TCL_OK;
- }
- double s;
- if(Tcl_GetDoubleFromObj(interp,tclObj,&s)) return TCL_ERROR;
- *result=(int)round(s);
- return TCL_OK;
- }
- /* Odie_GetMatrixFromTclObj */
- int Odie_GetMatrixFromTclObj(Tcl_Interp *interp,Tcl_Obj *tclObj,int form,Odie_MatrixObj **result){
- const char *(*xConvertToForm)(MATOBJ*,int)=MatrixForms[form].xConvertToForm;
- const char *error;
- *result=NULL;
- if(MatrixObj_setFromAnyProc(interp,tclObj)) {
- return TCL_ERROR;
- }
- *result=tclObj->internalRep.otherValuePtr;
- if(!xConvertToForm) {
- return TCL_OK;
- }
- error=xConvertToForm(*result,form);
- if(error) {
- Tcl_SetObjResult(interp,Tcl_NewStringObj(error,-1));
- return TCL_ERROR;
- }
- return TCL_OK;
- }
- /* *Odie_Matrix_Duplicate */
- Odie_MatrixObj *Odie_Matrix_Duplicate(Odie_MatrixObj *src){
- Odie_MatrixObj *dest;
- size_t matsize,size;
- matsize=sizeof(double)*src->rows*src->cols;
- if(matsize<128) {
- matsize=128;
- }
- size=matsize+sizeof(Odie_MatrixObj);
- dest=(Odie_MatrixObj *)Odie_Alloc(size);
- memcpy(dest,src,size);
- return dest;
- }
- /* *Odie_MatrixObj_Create_NXN */
- Odie_MatrixObj *Odie_MatrixObj_Create_NXN(int rows,int cols){
- Odie_MatrixObj *new;
- void *p;
- int size_t;
- size_t=rows*cols*sizeof(double);
- if(size_t<128) {
- size_t=128;
- }
- p=Odie_Alloc(sizeof(Odie_MatrixObj)+size_t);
- new=p;
- new->form=MATFORM_null;
- new->cols=cols;
- new->rows=rows;
- return new;
- }
- /* *Odie_MatrixObj_Create */
- Odie_MatrixObj *Odie_MatrixObj_Create(int form){
- Odie_MatrixObj *new;
- int rows,cols;
- void *p;
- int size_t;
- rows=MatrixForms[form].rows;
- cols=MatrixForms[form].cols;
- size_t=rows*cols*sizeof(double);
- if(size_t<128) {
- size_t=128;
- }
- p=Odie_Alloc(sizeof(Odie_MatrixObj)+size_t);
- new=p;
- new->form=form;
- new->cols=cols;
- new->rows=rows;
- return new;
- }
- /* Matrix_Free */
- void Matrix_Free(Odie_MatrixObj *matrix){
- if(!matrix) return;
- matrix->refCount--;
- /*
- ** Seems counter intuitive, but freeing when refCount==0 causes
- ** Tcl to Crash
- */
- if(matrix->refCount<0) {
- Odie_Free(matrix);
- }
- }
- /* *Matrix_ToAny */
- const char *Matrix_ToAny(Odie_MatrixObj *matrix,int form){
- /* Accept any input */
- matrix->form=form;
- return NULL;
- }
- /* Odie_TclObj_To_MatrixObj */
- int Odie_TclObj_To_MatrixObj(Tcl_Interp *interp,Tcl_Obj *listPtr,Odie_MatrixObj **matrix){
- Odie_MatrixObj *pNew;
- Tcl_Obj **rowPtrs;
- Tcl_Obj **elemPtrs;
- int result;
- int rows,cols;
- int idx,i,j;
- int len;
- /* Step one, Measure the matrix */
- result = Tcl_ListObjGetElements(interp, listPtr, &rows, &rowPtrs);
- if (result != TCL_OK) {
- return result;
- }
- if(rows<1) {
- Tcl_AppendResult(interp, "Could not interpret matrix", 0);
- return TCL_ERROR;
- }
- result = Tcl_ListObjGetElements(interp, rowPtrs[0], &cols, &elemPtrs);
- if (result != TCL_OK) {
- return result;
- }
- /*
- ** For NULL form, we pass the rows and cols
- ** via the data structure
- */
- pNew=Odie_MatrixObj_Create_NXN(rows,cols);
-
- idx=-1;
- for(i=0;i<rows;i++) {
- result = Tcl_ListObjGetElements(interp, rowPtrs[i], &len, &elemPtrs);
- if (result != TCL_OK) {
- return result;
- }
- if(len != cols) {
- Tcl_SetObjResult(interp,Tcl_NewStringObj("Columns are not uniform",-1));
- Matrix_Free(pNew);
- return TCL_ERROR;
- }
- for(j=0;j<len;j++) {
- double temp;
- idx++;
- result = Tcl_GetDoubleFromObj(interp, elemPtrs[j], &temp);
- if (result != TCL_OK) {
- return result;
- }
- *(pNew->matrix+idx)=(SCALER)temp;
- }
- }
- *matrix=pNew;
- return TCL_OK;
- }
- /* *Matrix_To_TclObj */
- Tcl_Obj *Matrix_To_TclObj(Odie_MatrixObj *matrix){
- Tcl_Obj *dest=Tcl_NewObj();
- dest->typePtr=&matrix_tclobjtype;
- dest->internalRep.otherValuePtr=matrix;
- matrix->refCount++;
- Tcl_InvalidateStringRep(dest);
- return dest;
- }
- /* MatrixObj_setFromAnyProc */
- int MatrixObj_setFromAnyProc(Tcl_Interp *interp,Tcl_Obj *objPtr){
- if(objPtr->typePtr) {
- if(objPtr->typePtr->setFromAnyProc==&MatrixObj_setFromAnyProc) {
- /*
- ** Object is already of the type requested
- */
- return TCL_OK;
- }
- }
- Odie_MatrixObj *matrix;
- if(Odie_TclObj_To_MatrixObj(interp,objPtr,&matrix)) {
- return TCL_ERROR;
- }
- objPtr->internalRep.otherValuePtr=matrix;
- objPtr->typePtr=&matrix_tclobjtype;
- return TCL_OK;
- }
- /* MatrixObj_updateStringProc */
- void MatrixObj_updateStringProc(Tcl_Obj *objPtr){
- float value;
- char outbuffer[128];
- Tcl_DString result;
- Odie_MatrixObj *matrix=objPtr->internalRep.otherValuePtr;
- int rows,cols;
- register int j;
- /* Step 1, dimension matrix */
- rows = matrix->rows;
- cols = matrix->cols;
- Tcl_DStringInit(&result);
- if(cols==1) {
- /*
- * Output single-row matrices (i.e. vectors)
- * as a single tcl list (rather than nest them
- * as a list within a list)
- */
- for(j=0;j<rows;j++) {
- value=(float)*(matrix->matrix+j);
- //Tcl_PrintDouble(NULL,value,outbuffer);
- sprintf(outbuffer,"%g",value);
- Tcl_DStringAppendElement(&result,outbuffer);
- }
- } else if(rows==1) {
- /*
- * Output single-row matrices (i.e. vectors)
- * as a single tcl list (rather than nest them
- * as a list within a list)
- */
- for(j=0;j<cols;j++) {
- value=(float)*(matrix->matrix+j);
- //Tcl_PrintDouble(NULL,value,outbuffer);
- sprintf(outbuffer,"%g",value);
- Tcl_DStringAppendElement(&result,outbuffer);
- }
- } else {
- register int i,idx=0;
- for(i=0;i<rows;i++) {
- Tcl_DStringStartSublist(&result);
- for(j=0;j<cols;j++) {
- idx=(i*cols)+j;
- value=(float)*(matrix->matrix+idx);
- sprintf(outbuffer,"%g",value);
- Tcl_DStringAppendElement(&result,outbuffer);
- }
- Tcl_DStringEndSublist(&result);
- }
- }
- objPtr->length=Tcl_DStringLength(&result);
- objPtr->bytes=Odie_Alloc(objPtr->length+1);
- memcpy(objPtr->bytes,Tcl_DStringValue(&result),objPtr->length);
- objPtr->bytes[objPtr->length]='\0';
- Tcl_DStringFree(&result);
- }
- /* MatrixObj_dupIntRepProc */
- void MatrixObj_dupIntRepProc(Tcl_Obj *srcPtr,Tcl_Obj *dupPtr){
- Odie_MatrixObj *srcmatrix=srcPtr->internalRep.otherValuePtr;
- Odie_MatrixObj *dupmatrix=Odie_Matrix_Duplicate(srcmatrix);
- dupPtr->typePtr=srcPtr->typePtr;
- dupPtr->internalRep.otherValuePtr=dupmatrix;
- Tcl_InvalidateStringRep(dupPtr);
- }
- /* MatrixObj_freeIntRepProc */
- void MatrixObj_freeIntRepProc(Tcl_Obj *objPtr){
- if(!objPtr->internalRep.otherValuePtr) return;
- Odie_MatrixObj *matrix=objPtr->internalRep.otherValuePtr;
- Matrix_Free(matrix);
- objPtr->typePtr=NULL;
- objPtr->internalRep.otherValuePtr=NULL;
- }
- /* MatrixObjType_Init */
- int MatrixObjType_Init(Tcl_Interp *interp){
- Tcl_RegisterObjType(&matrix_tclobjtype);
- return TCL_OK;
- }
- /* ODIE_Real_Is_Zero */
- inline extern int ODIE_Real_Is_Zero(double x){
- if(fabs(x) < __FLT_EPSILON__) {
- return 1;
- }
- return 0;
- }
- /* ODIE_Fuzzy_Compare_TclObj */
- int ODIE_Fuzzy_Compare_TclObj(Tcl_Obj *avalue,Tcl_Obj *bvalue,double epsilon){
- int result;
- char *a,*b;
- double ax,bx;
- int ai,bi;
- int atype,btype,stringcmp=0;
- ClientData internalPtrA,internalPtrB;
-
- if(Tcl_GetIntFromObj(NULL,avalue,&ai)) goto doublecmp;
- if(Tcl_GetIntFromObj(NULL,bvalue,&bi)) goto doublecmp;
- if(ai==bi) {
- return 0;
- } else {
- result=ai>bi ? 1 : -1;
- }
-
- doublecmp:
- if(Tcl_GetDoubleFromObj(NULL,avalue,&ax)) goto stringcmp;
- if(Tcl_GetDoubleFromObj(NULL,bvalue,&bx)) goto stringcmp;
- result=ODIE_Fuzzy_Compare(ax,bx,epsilon);
- return result;
-
- stringcmp:
- a=Tcl_GetString(avalue);
- b=Tcl_GetString(bvalue);
- return strcmp(a,b);
- }
- /* ODIE_FuzzyNumber */
- double ODIE_FuzzyNumber(double ax){
- char newstring[128];
- int expa;
- double siga,ipart,fpart,result;
- if (Odie_IsNaN(ax)) {
- return ax;
- }
- if(Odie_IsInfinite(ax)) {
- return ax;
- }
- if(ODIE_Real_Is_Zero(ax)) {
- return 0;
- }
- siga=frexp(ax,&expa);
- fpart=modf(ldexp(siga,10),&ipart);
- return ldexp(ipart,expa-10);
- }
- /* *ODIE_NewFuzzyObj */
- Tcl_Obj *ODIE_NewFuzzyObj(float ax){
- double bx;
- const char *use_format="%g";
- char newstring[128];
- if (Odie_IsNaN(ax)) {
- return Tcl_NewDoubleObj(ax);
- }
- if(Odie_IsInfinite(ax)) {
- return Tcl_NewDoubleObj(ax);
- }
- if(ODIE_Real_Is_Zero(ax)) {
- return ODIE_REAL_ZERO();
- }
- bx=fabs(ax);
- if(bx>1000000.0) {
- use_format="%g";
- } else if(bx>1000.0) {
- use_format="%.0f";
- } else if(bx>10.0) {
- use_format="%.1f";
- } else if (bx>1.0) {
- use_format="%.2f";
- } else if (bx>0.1) {
- use_format="%.3f";
- } else if (bx>0.01) {
- use_format="%.4f";
- } else if (bx>0.001) {
- use_format="%.5f";
- } else if (bx>0.0001) {
- use_format="%.6f";
- } else {
- use_format="%g";
- }
- sprintf(newstring,use_format,ax);
- return Tcl_NewStringObj(newstring,-1);
- }
- /* ODIE_Fuzzy_Compare */
- inline extern int ODIE_Fuzzy_Compare(double avalue,double bvalue,double epsilon){
- /* Handle the simple cases */
- int expa,expb;
- double siga,sigb;
- double c;
- siga=frexp(avalue,&expa);
- sigb=frexp(bvalue,&expb);
- if(expa==expb) {
- c=bvalue-avalue;
- if(fabs(c)<epsilon) {
- return 0;
- }
- }
- if(avalue>bvalue) return 1;
- return -1;
- }
- /* ODIE_Fuzzy_GTE */
- inline extern int ODIE_Fuzzy_GTE(double avalue,double bvalue){
- /* Handle the simple cases */
- if (avalue==bvalue) return 1;
- if (avalue<=ODIE_REAL_TOLERANCE && bvalue>ODIE_REAL_TOLERANCE) return 0;
- if (avalue>bvalue) return 1;
-
- /* Add epsilon to the send */
- avalue+=ODIE_REAL_TOLERANCE;
- if (avalue>=bvalue) return 2;
-
- /* For large quantities, loose the decimal points
- if(avalue>100.0 && bvalue>100.0) {
- avalue=ceil(avalue);
- bvalue=floor(bvalue);
- if (avalue>=bvalue) return 2;
- }
- */
- return 0;
- }
- /*
- ** This file implements code for braking up compartment floorplans
- ** into triangles.
- **
- ** A floorplan is defined by vectors (x0,y0,x1,y1) which define the
- ** parameter of each compartment. The interior of the compartment
- ** is always to the right of the vector. Thus the outer boundary
- ** of the compartment rotates clockwise when viewed from above.
- ** Compartments may contain holes which are interior voids surrounded
- ** by counter-clockwise rotating boundaries.
- */
-
-
- /*
- ** Compute a hash on a point.
- */
- static int hashTriagPoint(TriagPoint *p){
- int iTX = p->x/OdieGrain;
- int iTY = p->y/OdieGrain;
- return hashInt(iTX+iTY);
- }
-
- /*
- ** Return TRUE if A is the same point as B.
- */
- static int sameTriagPoint(TriagPoint *A, TriagPoint *B){
- return floatCompare(A->x,B->x)==0 && floatCompare(A->y,B->y)==0;
- }
-
-
- #if 0
- /*
- ** Print all vectors in the TriagSegSet. Used for debugging purposes only.
- */
- static void SegPrint(TriagSegment *p, const char *zText){
- printf("%s ", zText);
- if( p ){
- printf("%g,%g -> %g,%g\n", p->from.x, p->from.y, p->to.x, p->to.y);
- }else{
- printf(" (null)\n");
- }
- }
- static void TriagSegSetPrint(TriagSegSet *pSet){
- Link *pLink;
- printf("%d vectors:\n", pSet->nSeg);
- for(pLink=pSet->pAll; pLink; pLink=pLink->pNext){
- SegPrint(pLink->pLinkNode, " ");
- }
- }
- #endif
-
- /*
- ** Add a new segment to the set
- */
- static TriagSegment *TriagSegSetInsert(
- TriagSegSet *pSet,
- double x0,
- double y0,
- double x1,
- double y1,
- u8 isBoundary
- ){
- int h;
- if(pSet==NULL) {
- return NULL;
- }
- TriagSegment *p = (TriagSegment *)Odie_Alloc( sizeof(*p) );
- memset(p,0,sizeof(*p));
- x0=round(x0);
- y0=round(y0);
- x1=round(x1);
- y1=round(y1);
- if( p==0 ) {
- return NULL;
- }
- p->from.x = x0;
- p->from.y = y0;
- p->to.x = x1;
- p->to.y = y1;
- if( sameTriagPoint(&p->from, &p->to) ){
- Odie_Free((char *)p);
- return NULL;
- }
- p->isBoundary = isBoundary;
- p->notOblique = 0;
-
- LinkInit(p->all, p);
- LinkInit(p->tmp, p);
- LinkInit(p->orig, p);
- LinkInsert(&pSet->pAll, &p->all);
- h = hashTriagPoint(&p->from);
- LinkInsert(&pSet->aHash[h], &p->orig);
- pSet->nSeg++;
- pSet->pCurrent = p;
- return p;
- }
-
- /*
- ** Remove a segment from the segment set
- */
- static void TriagSegSetRemove(TriagSegSet *pSet, TriagSegment *p){
- LinkRemove(&p->all);
- LinkRemove(&p->orig);
- pSet->nSeg--;
- if( pSet->pCurrent==p ){
- pSet->pCurrent = pSet->pAll ? pSet->pAll->pLinkNode : 0;
- }
- }
-
- /*
- ** Call this routine to relink into a segment when the
- ** Seg.from vector changes.
- */
- static void TriagSegRelink(TriagSegSet *pSet, TriagSegment *p){
- int h;
- LinkRemove(&p->orig);
- h = hashTriagPoint(&p->from);
- LinkInsert(&pSet->aHash[h], &p->orig);
- }
-
- /*
- ** Remove all segments from a segment set
- */
- static void TriagSegSetClear(TriagSegSet *pSet){
- while( pSet->pAll ){
- TriagSegment *p;
- assert( pSet->nSeg>0 );
- p=pSet->pAll->pLinkNode;
- TriagSegSetRemove(pSet, p);
- Odie_Free((char *)p);
- }
- assert( pSet->nSeg==0 );
- }
-
- #if 0
- /*
- ** Advance the pSet->pAll pointer so that it is pointing to a different
- ** segment.
- */
- static void TriagSegSetStep(TriagSegSet *pSet){
- if( pSet->pCurrent ){
- Link *pNext = pSet->pCurrent->all.pNext;
- pSet->pCurrent = pNext ? pNext->pSeg : 0;
- }
- if( pSet->pCurrent==0 ){
- pSet->pCurrent = pSet->pAll ? pSet->pAll->pSeg : 0;
- }
- }
- #endif
-
-
- static inline double Dot_Product(TriagPoint *A, TriagPoint *B, TriagPoint *P){
- double r = (A->y-B->y)*(P->x-B->x) + (B->x-A->x)*(P->y-B->y);
- if(fabs(r) < IRM_EPSILON ) {
- return 0.0;
- }
- return r;
- }
-
- /*
- ** Consider traveling from point A to B to P. If you have to make
- ** a left-turn at B, then this routine returns -1. If P is on the
- ** same line as A and B then return 0. If you make a right turn
- ** at B in order to reach P then return +1.
- */
- static inline int rightOf(TriagPoint *A, TriagPoint *B, TriagPoint *P){
- /* Algorithm: Rotate AB 90 degrees counter-clockwise. Take
- ** the dot product with BP. The dot produce will be the product
- ** of two (non-negative) magnitudes and the cosine of the angle. So if
- ** the dot product is positive, the bend is to the left, or to the right if
- ** the dot product is negative.
- */
- double r = (A->y-B->y)*(P->x-B->x) + (B->x-A->x)*(P->y-B->y);
- if(fabs(r) < IRM_EPSILON ) {
- return 0;
- }
- if(r>0.0) {
- return -1;
- }
- return 1;
- //return r<0.0 ? +1 : (r>0.0 ? -1 : 0);
- }
-
- /*
- ** This is a variation on rightOf(). Return 0 only if BP is a continuation
- ** of the line AB. If BP doubles back on AB then return -1.
- */
- static inline int strictlyRightOf(TriagPoint *A, TriagPoint *B, TriagPoint *P){
- int c = rightOf(A,B,P);
- if( c==0 ){
- double r = (A->x-B->x)*(P->x-B->x) + (A->y-B->y)*(P->y-B->y);
- c = r<0.0 ? +1 : -1;
- }
- return c;
- }
-
- /*
- ** Return TRUE if segments AB and CD intersect
- */
- static int intersect(TriagPoint *A, TriagPoint *B, TriagPoint *C, TriagPoint *D){
- return
- rightOf(A,B,C)*rightOf(A,B,D)<0 &&
- rightOf(C,D,A)*rightOf(C,D,B)<0;
- }
-
- /*
- ** Return the squared distance between two points.
- */
- static double dist2(TriagPoint *A, TriagPoint *B){
- double dx = B->x - A->x;
- double dy = B->y - A->y;
- return dx*dx + dy*dy;
- }
-
- /*
- ** Compute angle ABC measured counter-clockwise from AB. Return the
- ** result.
- **
- ** This does not need to be a true angular measure as long as it is
- ** monotonically increasing.
- */
- static double angleOf(TriagPoint *A, TriagPoint *B, TriagPoint *C){
- double a1, a2, a3;
- if( sameTriagPoint(A,C) ){
- return M_PI;
- }
- a1 = atan2(B->y - A->y, B->x - A->x);
- a2 = atan2(C->y - B->y, C->x - B->x);
- a3 = a2-a1;
- if( a3>M_PI ) a3 -= 2.0*M_PI;
- if( a3<=-M_PI ) a3 += 2.0*M_PI;
- return a3;
- }
-
- static inline double idealAngle(TriagPoint *A, TriagPoint *B, TriagPoint *P){
- double theta = angleOf(A,B,P);
- double d = M_PI*0.25 - theta;
- if(ODIE_Real_Is_Zero(d)) {
- return 0.0;
- }
- return d;
- }
-
- /*
- ** Given line segment AB, locate segment BC and return a pointer to
- ** it. If there is not BC return NULL. If there is more than one
- ** BC return the one that minimizes the angle ABC.
- */
- static TriagSegment *TriagSegSetNext(TriagSegSet *pSet, TriagSegment *pAB){
- Link *pX;
- TriagSegment *pBest = 0;
- double angle, bestAngle;
- int cnt = 0;
- int h;
- h = hashTriagPoint(&pAB->to);
- for(pX=pSet->aHash[h]; pX; pX=pX->pNext){
- TriagSegment *pSeg = pX->pLinkNode;
- if( !sameTriagPoint(&pSeg->from, &pAB->to) ) continue;
- /* if(pAB->isBoundary > 1 && pSeg->isBoundary!=0 && pSeg->isBoundary!=pAB->isBoundary) continue; */
- if( cnt==0 ){
- pBest = pSeg;
- bestAngle = angleOf(&pAB->from, &pAB->to, &pBest->to);
- }else{
- angle = angleOf(&pAB->from, &pAB->to, &pSeg->to);
- if( angle<bestAngle ){
- bestAngle = angle;
- pBest = pSeg;
- }
- }
- cnt++;
- }
- return pBest;
- }
-
- /*
- ** Find and return the line segment that goes from A to B. Return NULL
- ** if there is not such line segment
- */
- static TriagSegment *TriagSegSetFind(TriagSegSet *pSet, TriagPoint *A, TriagPoint *B){
- Link *pX;
- TriagSegment *p;
- int h;
- h = hashTriagPoint(A);
- for(pX=pSet->aHash[h]; pX; pX=pX->pNext){
- p = pX->pLinkNode;
- if( sameTriagPoint(&p->from, A) && sameTriagPoint(&p->to, B) ){
- return p;
- }
- }
- return 0;
- }
-
- /*
- ** Remove all segments whose length is less than minLength. For
- ** each segment removed, coalesce the inputs into a single new
- ** point at the center of the segment.
- */
- static void removeShortTriagSegments(TriagSegSet *pSet, double minLength){
- Link *pLoop, *pNext;
- double minLen2;
-
- minLen2 = minLength*minLength;
- for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
- TriagSegment *p;
- TriagPoint from, to, center;
-
- p = pLoop->pLinkNode;
- pNext = pLoop->pNext;
- if( dist2(&p->from, &p->to)<minLen2 ){
- from = p->from;
- to = p->to;
- center.x = rint(0.5*(from.x + to.x));
- center.y = rint(0.5*(from.y + to.y));
- TriagSegSetRemove(pSet, p);
- Odie_Free((char *)p);
- for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
- pNext = pLoop->pNext;
- p = pLoop->pLinkNode;
- if( (p->to.x==from.x && p->to.y==from.y)
- || (p->to.x==to.x && p->to.y==to.y)
- ){
- p->to = center;
- }
- if( (p->from.x==from.x && p->from.y==from.y)
- || (p->from.x==to.x && p->from.y==to.y)
- ){
- p->from = center;
- TriagSegRelink(pSet, p);
- }
- if( p->from.x==p->to.x && p->from.y==p->to.y ){
- TriagSegSetRemove(pSet, p);
- Odie_Free((char *)p);
- }
- }
- pNext = pSet->pAll;
- }
- }
- }
-
- static int WalkTriagSegments(TriagSegSet *pSet) {
- Link *pLoop, *pNext;
- int changed=0;
- for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
- TriagSegment *pAB, *pBC;
- Link *pRight, *pL2;
- int c;
- /* Find an oblique angle ABC */
- pAB = pLoop->pLinkNode;
- pNext = pLoop->pNext;
-
- /*
- ** If we are at an oblique for a non boundary
- ** segment, continue
- */
- if( pAB->notOblique ) continue;
- pBC = TriagSegSetNext(pSet, pAB);
- if( pBC==0 ) {
- /*
- ** Remove an orphan wall
- */
- TriagSegSetRemove(pSet, pAB);
- Odie_Free((char *)pAB);
- changed=1;
- continue;
- }
-
- if( (c = rightOf(&pAB->from, &pAB->to, &pBC->to))>=0 ){
- if( c>0 || !sameTriagPoint(&pAB->from, &pBC->to) ){
- pAB->notOblique = 1;
- continue;
- }
- }
-
- /* If we reach here, it means that ABC is an oblique angle.
- ** Locate all vertices to the right of AB.
- */
- pRight = 0;
- for(pL2=pSet->pAll; pL2; pL2=pL2->pNext){
- TriagSegment *pX = pL2->pLinkNode;
- if( strictlyRightOf(&pAB->from, &pAB->to, &pX->from)<0 ) continue;
- if( sameTriagPoint(&pAB->to, &pX->from) ) continue;
- pX->score = dist2(&pAB->to, &pX->from);
- pX->isRight = rightOf(&pBC->from, &pBC->to, &pX->from);
- LinkInit(pX->tmp, pX);
- LinkInsert(&pRight, &pX->tmp);
- }
- if( pRight==0 ){
- return TCL_ERROR;
- }
-
- /* pRight is a list of vertices to the right of AB. Find the
- ** closest vertex X on this list where the line BX does not intersect
- ** any other segment in the polygon. Then add segments BX and XB.
- */
- while( pRight ){
- Link *pBest=NULL;
- double bestScore;
- int bestRight;
- TriagSegment *pThis,*pX, *pQ;
-
-
- /* Search for the "best" vertex. The best vertex is the
- ** one that is closest. Though if the vertex is to the left
- ** of BC (and thus would create another oblique angle) then
- ** artificially reduce its score because we would prefer not
- ** to use it.
- */
- pBest = pRight;
- pThis=pBest->pLinkNode;
- bestScore = pThis->score;
- bestRight = pThis->isRight;
- for(pL2=pBest->pNext; pL2; pL2=pL2->pNext){
- int better=0;
- pX = pL2->pLinkNode;
- if( pX->isRight>0 && bestRight <=0 ) {
- better=1;
- } else if ( pX->isRight<=0 && bestRight>0 ) {
- better=0;
- } else if( pX->score<bestScore ){
- better=1;
- }
- if(better) {
- bestScore = pX->score;
- bestRight = pX->isRight;
- pBest = pL2;
- }
- }
-
- /* The best vertex is pX */
- pX = pBest->pLinkNode;
- LinkRemove(pBest);
-
- /* Check to see if BX intersects any segment. If it does, then
- ** go back and search for a different X
- */
- for(pL2=pSet->pAll; pL2; pL2=pL2->pNext){
- pQ = pL2->pLinkNode;
- if( pQ!=pAB && pQ!=pX
- && intersect(&pAB->to, &pX->from, &pQ->from, &pQ->to) ){
- break;
- }
- }
- if( pL2 ) continue;
-
- /* It did not intersect. So add BX and XB to the pSet->
- */
- TriagSegSetInsert(pSet, pAB->to.x, pAB->to.y, pX->from.x, pX->from.y, 0);
- TriagSegSetInsert(pSet, pX->from.x, pX->from.y, pAB->to.x, pAB->to.y, 0);
- pRight = 0;
- }
- changed=1;
- if(!pAB->isBoundary) {
- pNext = pSet->pAll;
- }
- }
- if(changed) {
- return TCL_CONTINUE;
- }
- return TCL_OK;
- }
-
- /*
- ** tclcmd: convex_subpolygons_new VECTORS ?MINLENGTH? ?HOLE? ?HOLE? ...
- **
- ** VECTORS is a list of floating-point values. Each group of four values
- ** forms a vector X0,Y0->X1,Y1. The vectors are in no particular order,
- ** but together they form one or more loops. Space to the right of each
- ** vector is within the loop and space to the left is outside.
- **
- ** Loops can be nested. The outer boundary is formed by a clockwise loop
- ** of vectors. Interior holes are formed by counter-clockwise loops.
- **
- ** The output is a list polygons. Each polygon is a list of 3 or more
- ** X,Y coordinate pairs. All polygons are convex and disjoint and they
- ** together cover the input polygon.
- **
- ** Optionally, the user can specify a series of polygons to be subtracted
- ** from the main polygon. These are given as an XY list suitable for
- ** producing a polygon on the tkcanvas
- */
- static int convexNewSubpolyCmd(
- void *pArg,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
- ){
- Tcl_Obj *pOut; /* The output list */
- Tcl_Obj *pSub; /* A sublist for a single polygon */
- int i, idx, n, nb, cnt;
- TriagSegSet set;
- double minLen = 0.0;
-
- if( objc!=2 && objc!=3 && objc<4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "VECTORS ?MINLENGTH? ?HOLE? ?HOLE? ...");
- return TCL_ERROR;
- }
- if( Tcl_ListObjLength(interp, objv[1], &n) ) return TCL_ERROR;
- if( objc>2 ){
- if( Tcl_GetDoubleFromObj(interp, objv[2], &minLen) ) return TCL_ERROR;
- }
- if( n<12 || n%4!=0 ){
- Tcl_AppendResult(interp, "VECTORS argument should contain at least 12 and "
- " a multiple of 4 values", 0);
- return TCL_ERROR;
- }
- memset(&set, 0, sizeof(set));
-
- /*
- ** Insert the polygons the user specified as
- ** the shape of the holes first
- */
- for(idx=3;idx<objc;idx++) {
- double fx,fy,px,py;
-
- if( Tcl_ListObjLength(interp, objv[idx], &nb) ) return TCL_ERROR;
- if( nb > 0 && (nb<6 || nb%2!=0) ){
- TriagSegSetClear(&set);
- Tcl_AppendResult(interp, "HOLES arguments should contain at least 6 and "
- " a multiple of 2 values", 0);
- return TCL_ERROR;
- }
- Tcl_Obj *pObj;
- Tcl_ListObjIndex(0, objv[idx], 0, &pObj);
- if( Tcl_GetDoubleFromObj(interp, pObj, &fx) ){
- TriagSegSetClear(&set);
- return TCL_ERROR;
- }
- Tcl_ListObjIndex(0, objv[idx], 1, &pObj);
- if( Tcl_GetDoubleFromObj(interp, pObj, &fy) ){
- TriagSegSetClear(&set);
- return TCL_ERROR;
- }
- px=fx;
- py=fy;
- for(i=2; i<nb; i+=2){
- double mx,my;
- double nx,ny;
- Tcl_ListObjIndex(0, objv[idx], i, &pObj);
- if( Tcl_GetDoubleFromObj(interp, pObj, &nx) ){
- TriagSegSetClear(&set);
- return TCL_ERROR;
- }
- Tcl_ListObjIndex(0, objv[idx], i+1, &pObj);
- if( Tcl_GetDoubleFromObj(interp, pObj, &ny) ){
- TriagSegSetClear(&set);
- return TCL_ERROR;
- }
- /*
- TriagSegSetInsert(&set, px, py, nx, ny, idx);
- */
- mx=(nx+px)/2.0;
- my=(ny+py)/2.0;
-
- TriagSegSetInsert(&set, px, py, mx, my, idx);
- TriagSegSetInsert(&set, mx, my, nx, ny, idx);
- px=nx;
- py=ny;
- }
- double mx,my;
- mx=(fx+px)/2.0;
- my=(fy+py)/2.0;
- TriagSegSetInsert(&set, px, py, mx, my, idx);
- TriagSegSetInsert(&set, mx, my, fx, fy, idx);
- }
-
- for(i=0; i<n; i+=4){
- int j;
- double x[4];
- TriagPoint A,B,C;
- for(j=0; j<4; j++){
- Tcl_Obj *pObj;
- Tcl_ListObjIndex(0, objv[1], i+j, &pObj);
- if( Odie_GetMatrixElementFromObj(interp, pObj, x, j) ){
- TriagSegSetClear(&set);
- return TCL_ERROR;
- }
- }
- A.x=x[0];
- A.y=x[1];
- C.x=x[2];
- C.y=x[3];
- B.x=(C.x+A.x)/2.0;
- B.y=(C.y+A.y)/2.0;
-
- /*
- ** Do not insert a vector into the wallset if it
- ** matches a vector already given. It's either redundent
- ** or the edge of a hole
- */
- if(!TriagSegSetFind(&set,&A,&C)) {
- TriagSegSetInsert(&set, A.x, A.y, B.x, B.y, 1);
- }
- if(!TriagSegSetFind(&set,&B,&C)) {
- TriagSegSetInsert(&set, B.x, B.y, C.x, C.y, 1);
- }
- }
-
- if( minLen>0.0 ){
- removeShortTriagSegments(&set, minLen);
- }
-
- cnt=0;
- i=TCL_CONTINUE;
- while(i==TCL_CONTINUE) {
- i=WalkTriagSegments(&set);
- cnt++;
- if(cnt>10) {
- break;
- }
- }
- if(i==TCL_CONTINUE) {
- Tcl_AppendResult(interp, "boundary too complex", 0);
- TriagSegSetClear(&set);
- return TCL_ERROR;
- }
- if(i==TCL_ERROR) {
- Tcl_AppendResult(interp, "boundary does not enclose a finite space", 0);
- TriagSegSetClear(&set);
- return TCL_ERROR;
- }
-
- /* Now all polygons should be convex. We just have to generate them. */
- pOut = Tcl_NewObj();
- int npoly=0;
- while( set.nSeg ){
- TriagPoint start;
- TriagSegment *pAB, *pBC;
- int valid = 0;
- int cnt = 0;
- npoly++;
-
- pAB = set.pAll->pLinkNode;
- start = pAB->from;
- /*
- ** Walk along the wallsets, filter out
- ** any that do not include one of the
- ** vectors given as an input of the first
- ** argument
- */
- pSub = Tcl_NewObj();
- while( pAB ){
- Tcl_ListObjAppendElement(0, pSub, Tcl_NewDoubleObj(pAB->to.x));
- Tcl_ListObjAppendElement(0, pSub, Tcl_NewDoubleObj(pAB->to.y));
- if(pAB->isBoundary < 2) valid=1;
- cnt++;
- TriagSegSetRemove(&set, pAB);
- if( sameTriagPoint(&pAB->to, &start) ) {
- break;
- }
- pBC = TriagSegSetNext(&set, pAB);
- Odie_Free((char *)pAB);
- pAB = pBC;
- }
- if( pAB==0 || cnt<3 || !valid){
- Tcl_DecrRefCount(pSub);
- }else{
- Tcl_ListObjAppendElement(0, pOut, pSub);
- }
- }
- TriagSegSetClear(&set);
- Tcl_SetObjResult(interp, pOut);
- return TCL_OK;
- }
-
-
- /*
- ** tclcmd: convex_subpolygons VECTORS ?MINLENGTH? ?HOLE? ?HOLE? ...
- **
- ** VECTORS is a list of floating-point values. Each group of four values
- ** forms a vector X0,Y0->X1,Y1. The vectors are in no particular order,
- ** but together they form one or more loops. Space to the right of each
- ** vector is within the loop and space to the left is outside.
- **
- ** Loops can be nested. The outer boundary is formed by a clockwise loop
- ** of vectors. Interior holes are formed by counter-clockwise loops.
- **
- ** The output is a list polygons. Each polygon is a list of 3 or more
- ** X,Y coordinate pairs. All polygons are convex and disjoint and they
- ** together cover the input polygon.
- **
- ** Optionally, the user can specify a series of polygons to be subtracted
- ** from the main polygon. These are given as an XY list suitable for
- ** producing a polygon on the tkcanvas
- */
- static int convexSubpolyCmd(
- void *pArg,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
- ){
- Tcl_Obj *pOut; /* The output list */
- Tcl_Obj *pSub; /* A sublist for a single polygon */
- int i, idx, n, nb, cnt;
- TriagSegSet set;
- double minLen = 0.0;
-
- if( objc!=2 && objc!=3 && objc<4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "VECTORS ?MINLENGTH? ?HOLE? ?HOLE? ...");
- return TCL_ERROR;
- }
- if( Tcl_ListObjLength(interp, objv[1], &n) ) return TCL_ERROR;
- if( objc>2 ){
- if( Tcl_GetDoubleFromObj(interp, objv[2], &minLen) ) return TCL_ERROR;
- }
- if( n<12 || n%4!=0 ){
- Tcl_AppendResult(interp, "VECTORS argument should contain at least 12 and "
- " a multiple of 4 values", 0);
- return TCL_ERROR;
- }
- memset(&set, 0, sizeof(set));
-
- /*
- ** Insert the polygons the user specified as
- ** the shape of the holes first
- */
- for(idx=3;idx<objc;idx++) {
- double fx,fy,px,py;
-
- if( Tcl_ListObjLength(interp, objv[idx], &nb) ) return TCL_ERROR;
- if( nb > 0 && (nb<6 || nb%2!=0) ){
- TriagSegSetClear(&set);
- Tcl_AppendResult(interp, "HOLES arguments should contain at least 6 and "
- " a multiple of 2 values", 0);
- return TCL_ERROR;
- }
- Tcl_Obj *pObj;
- Tcl_ListObjIndex(0, objv[idx], 0, &pObj);
- if( Tcl_GetDoubleFromObj(interp, pObj, &fx) ){
- TriagSegSetClear(&set);
- return TCL_ERROR;
- }
- Tcl_ListObjIndex(0, objv[idx], 1, &pObj);
- if( Tcl_GetDoubleFromObj(interp, pObj, &fy) ){
- TriagSegSetClear(&set);
- return TCL_ERROR;
- }
- px=fx;
- py=fy;
- for(i=2; i<nb; i+=2){
- double nx,ny;
- Tcl_ListObjIndex(0, objv[idx], i, &pObj);
- if( Tcl_GetDoubleFromObj(interp, pObj, &nx) ){
- TriagSegSetClear(&set);
- return TCL_ERROR;
- }
- Tcl_ListObjIndex(0, objv[idx], i+1, &pObj);
- if( Tcl_GetDoubleFromObj(interp, pObj, &ny) ){
- TriagSegSetClear(&set);
- return TCL_ERROR;
- }
- TriagSegSetInsert(&set, px, py, nx, ny, idx);
- px=nx;
- py=ny;
- }
- TriagSegSetInsert(&set, px, py, fx, fy, idx);
- }
-
- for(i=0; i<n; i+=4){
- int j;
- double x[4];
- TriagPoint A,B;
- for(j=0; j<4; j++){
- Tcl_Obj *pObj;
- Tcl_ListObjIndex(0, objv[1], i+j, &pObj);
- if( Odie_GetMatrixElementFromObj(interp, pObj, x, j) ){
- TriagSegSetClear(&set);
- return TCL_ERROR;
- }
- }
- A.x=x[0];
- A.y=x[1];
- B.x=x[2];
- B.y=x[3];
- /*
- ** Do not insert a vector into the wallset if it
- ** matches a vector already given. It's either redundent
- ** or the edge of a hole
- */
- if(TriagSegSetFind(&set,&A,&B)) continue;
- TriagSegSetInsert(&set, x[0], x[1], x[2], x[3], 1);
- }
-
- if( minLen>0.0 ){
- removeShortTriagSegments(&set, minLen);
- }
-
- cnt=0;
- i=TCL_CONTINUE;
- while(i==TCL_CONTINUE) {
- i=WalkTriagSegments(&set);
- cnt++;
- if(cnt>10) {
- break;
- }
- }
- if(i==TCL_CONTINUE) {
- Tcl_AppendResult(interp, "{boundary too complex}", 0);
- TriagSegSetClear(&set);
- return TCL_ERROR;
- }
- if(i==TCL_ERROR) {
- Tcl_AppendResult(interp, "{boundary does not enclose a finite space}", 0);
- TriagSegSetClear(&set);
- return TCL_ERROR;
- }
-
- int obtuseangles=0;
- /* Now all polygons should be convex. We just have to generate them. */
- pOut = Tcl_NewObj();
- while( set.nSeg ){
- TriagPoint start;
- TriagSegment *pAB, *pBC;
- int valid = 0;
- int cnt = 0;
-
- pAB = set.pAll->pLinkNode;
- start = pAB->from;
- /*
- ** Walk along the wallsets, filter out
- ** any that do not include one of the
- ** vectors given as an input of the first
- ** argument
- */
- pSub = Tcl_NewObj();
- while( pAB ){
- Tcl_ListObjAppendElement(0, pSub, Tcl_NewDoubleObj(pAB->to.x));
- Tcl_ListObjAppendElement(0, pSub, Tcl_NewDoubleObj(pAB->to.y));
- pBC = TriagSegSetNext(&set, pAB);
- if(pAB->isBoundary < 2) valid=1;
- if(pAB->isRight<0) obtuseangles++;
- cnt++;
- TriagSegSetRemove(&set, pAB);
- if( sameTriagPoint(&pAB->to, &start) ) {
- break;
- }
- Odie_Free((char *)pAB);
- pAB = pBC;
- }
- if( pAB==0 || cnt<3 || !valid){
- Tcl_DecrRefCount(pSub);
- }else{
- Tcl_ListObjAppendElement(0, pOut, pSub);
- }
- }
- TriagSegSetClear(&set);
- if(obtuseangles) {
- Tcl_DecrRefCount(pOut);
- convexNewSubpolyCmd(NULL,interp,objc,objv);
- } else {
- Tcl_SetObjResult(interp, pOut);
- }
- return TCL_OK;
- }
- /*
- ** This file implements a TCL object used for tracking polygons. A
- ** single new TCL command named "poly" is defined. This command
- ** has methods for creating, deleting, and taking the intersection
- ** of 2-D polygons. There are comments on the implementation of each
- ** method to describe what the method does.
- **
- ** This module was originally developed to aid in computing the
- ** shared surface area between two compartments on separate decks.
- ** The shared surface area is needed in initializing the fire model
- ** since heat conduction between the two compartments is proportional
- ** to their shared area.
- */
- /* PolygonObj_freeIntRepProc */
- void PolygonObj_freeIntRepProc(Tcl_Obj *objPtr){
- if(objPtr->internalRep.otherValuePtr) {
- Odie_Polygon *pPoly=objPtr->internalRep.otherValuePtr;
- if(pPoly->refCount) {
- pPoly->refCount--;
- }
- if(!pPoly->refCount) {
- Tcl_Free(objPtr->internalRep.otherValuePtr);
- objPtr->internalRep.otherValuePtr=NULL;
- objPtr->typePtr=NULL;
- }
- }
- }
- /* PolygonObj_dupIntRepProc */
- void PolygonObj_dupIntRepProc(Tcl_Obj *srcPtr,Tcl_Obj *dupPtr){
- Odie_Polygon *src=srcPtr->internalRep.otherValuePtr;
- int size=sizeof(*src)+src->nVertex*sizeof(src->v[0]);
- Odie_Polygon *copy=(Odie_Polygon *)Odie_Alloc(size);
-
- memcpy(copy,src,size);
- Tcl_InvalidateStringRep(dupPtr);
- dupPtr->typePtr=&polygon_tclobjtype;
- dupPtr->internalRep.otherValuePtr=copy;
- }
- /* PolygonObj_updateStringRepProc */
- void PolygonObj_updateStringRepProc(Tcl_Obj *objPtr){
- /* Update String Rep */
- char outbuffer[128];
- Tcl_DString result;
- Odie_Polygon *p=objPtr->internalRep.otherValuePtr;
- int i,j;
- Tcl_DStringInit(&result);
- j=p->nVertex-1;
- if(p->v[0][X_IDX]==p->v[j][X_IDX] && p->v[0][Y_IDX]==p->v[j][Y_IDX]) {
- j=p->nVertex-2;
- }
- for(i=0; i<=j; i++){
- sprintf(outbuffer,"%g %g",(float)p->v[i][X_IDX],(float)p->v[i][Y_IDX]);
- Tcl_DStringAppendElement(&result,outbuffer);
- }
- objPtr->length=Tcl_DStringLength(&result);
- objPtr->bytes=Odie_Alloc(objPtr->length+1);
- strcpy(objPtr->bytes,Tcl_DStringValue(&result));
- Tcl_DStringFree(&result);
- }
- /* Odie_Poly_ShimmerOrFree_TclObj */
- int Odie_Poly_ShimmerOrFree_TclObj(Tcl_Obj *objPtr,Odie_Polygon *p){
- if(objPtr->typePtr) {
- if(objPtr->typePtr->setFromAnyProc==&PolygonObj_setFromAnyProc) {
- /*
- ** Object is already of the type requested
- */
- return 1;
- }
- }
- if(Tcl_IsShared(objPtr)) {
- Odie_Free((char *)p);
- return 1;
- }
- if(objPtr->typePtr && objPtr->typePtr->freeIntRepProc) {
- Tcl_FreeInternalRepProc *freeIntRepProc=objPtr->typePtr->freeIntRepProc;
- freeIntRepProc(objPtr);
- }
- objPtr->internalRep.otherValuePtr=p;
- objPtr->typePtr=&polygon_tclobjtype;
- Tcl_IncrRefCount(objPtr);
- return 0;
- }
- /* *Odie_Poly_Create */
- Odie_Polygon *Odie_Poly_Create(int nVertex){
- Odie_Polygon *p;
- p=(Odie_Polygon *)Odie_Alloc(sizeof(*p)+(nVertex+1)*sizeof(p->v[0]));
- p->nVertex=nVertex;
- return p;
- }
- /* PolygonObj_setFromAnyProc */
- int PolygonObj_setFromAnyProc(Tcl_Interp *interp,Tcl_Obj *objPtr){
- /* Set internal rep from any Tcl_Obj */
- if(objPtr->typePtr) {
- if(objPtr->typePtr==&polygon_tclobjtype) {
- /*
- ** Object is already of the type requested
- */
- return TCL_OK;
- }
- }
- Odie_Polygon *p;
- int created=0;
- if(Odie_Polygon_GetFromTclObj(interp,objPtr,&p,&created)) {
- return TCL_ERROR;
- }
- Tcl_InvalidateStringRep(objPtr);
- objPtr->internalRep.otherValuePtr=p;
- objPtr->typePtr=&polygon_tclobjtype;
- return TCL_OK;
- }
- /* *Odie_Polygon_NewTclObj */
- Tcl_Obj *Odie_Polygon_NewTclObj(Odie_Polygon *pPoly){
- Tcl_Obj *pResult;
- pResult=Tcl_NewObj();
- Tcl_InvalidateStringRep(pResult);
- pPoly->refCount++;
- pResult->internalRep.otherValuePtr=pPoly;
- pResult->typePtr=&polygon_tclobjtype;
- return pResult;
- }
- /* Odie_Polygon_From_FaceXYZ */
- int Odie_Polygon_From_FaceXYZ(Tcl_Interp *interp,Tcl_Obj *objPtr,Odie_Polygon **ptr){
- int i,nVertex;
- Tcl_Obj *pElem;
- Odie_Polygon *p;
- Odie_FaceXYZ *poly;
- poly=objPtr->internalRep.otherValuePtr;
- nVertex=poly->nVertex;
- p=Odie_Poly_Create(nVertex);
- for(i=0; i<nVertex; i++){
- VectorXY_Copy(p->v[i],poly->vertex_xyz[i]);
- }
- VectorXY_Copy(p->v[nVertex],poly->vertex_xyz[0]);
-
- if(Odie_Polygon_ComputeArea(interp,p)) goto createfail;
- *ptr=p;
- return TCL_OK;
-
- createfail:
- Odie_Free((char *)p);
- return TCL_ERROR;
- }
- /* Odie_Polygon_GetFromTclObj */
- int Odie_Polygon_GetFromTclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,Odie_Polygon **ptr,int *created){
- Odie_Polygon *p;
- *created=0;
-
- if(objPtr->typePtr) {
- if(objPtr->typePtr==&polygon_tclobjtype && objPtr->internalRep.otherValuePtr) {
- /*
- ** Object is already of the type requested
- */
- *ptr=objPtr->internalRep.otherValuePtr;
- return TCL_OK;
- }
- if(objPtr->typePtr->setFromAnyProc==&Odie_FaceXYZ_setFromAnyProc && objPtr->internalRep.otherValuePtr) {
- *created=1;
- return Odie_Polygon_From_FaceXYZ(interp,objPtr,ptr);
- }
- }
- int k,i;
- if( Tcl_ListObjLength(interp, objPtr, &k) ) return TCL_ERROR;
- if( k<6 ){
- Tcl_AppendResult(interp, "need at least 3 vertices", 0);
- return TCL_ERROR;
- }
- if( k&1 ){
- Tcl_AppendResult(interp, "coordinates should come in pairs", 0);
- return TCL_ERROR;
- }
- *created=1;
- p=(Odie_Polygon *)Odie_Alloc(sizeof(*p)+(k+2)*sizeof(p->v[0]));
- p->nVertex=k/2;
- for(i=0; i<p->nVertex; i++){
- Tcl_Obj *pElem;
- double d;
- Tcl_ListObjIndex(0, objPtr, i*2, &pElem);
- if(Tcl_GetDoubleFromObj(interp, pElem, &d)) goto createfail;
- p->v[i][X_IDX] = d;
- Tcl_ListObjIndex(0, objPtr, i*2+1, &pElem);
- if(Tcl_GetDoubleFromObj(interp, pElem, &d)) goto createfail;
- p->v[i][Y_IDX] = d;
- }
- if(Odie_Polygon_ComputeArea(interp,p)==TCL_OK) {
- *ptr=p;
- return TCL_OK;
- }
-
- createfail:
- Tcl_Free((char *)p);
- return TCL_ERROR;
- }
- /* Odie_IsColinear */
- static inline int Odie_IsColinear(double x1,double y1,double x2,double y2,double x3,double y3){
- /* Detect of two lines are colinear */
- if(floatCompare(x1,x3)==0 && floatCompare(y1,y3)==0) {
- return 1;
- }
- double c=(x3-x1)*(y2-y1)-(y3-y1)*(x2-x1);
- if(fabs(c) < __FLT_EPSILON__) return 1;
- return 0;
- }
- /* dist */
- static inline double dist(double x0, double y0, double x1, double y1){
- /*
- ** Return the distance between two points
- */
- double dx = x1 - x0;
- double dy = y1 - y0;
- return sqrt(dx*dx + dy*dy);
- }
- /* withinPolygon */
- static inline int withinPolygon(Odie_Polygon *p, double x, double y){
- /*
- ** Return -1, 0, or 1 if the point x,y is outside, on, or within
- ** the polygon p.
- */
- int res, i;
- /* Do a bounding box check before getting more ellaborate */
- if( x>p->bbox[BBOX_X1_IDX]
- || x<p->bbox[BBOX_X0_IDX]
- || y>p->bbox[BBOX_Y1_IDX]
- || y<p->bbox[BBOX_Y0_IDX]
- ) return -1;
- res = -1;
- for(i=0; i<p->nVertex-1; i++){
- double x0, y0, x1, y1, yP;
- x0 = p->v[i][X_IDX];
- y0 = p->v[i][Y_IDX];
- x1 = p->v[i+1][X_IDX];
- y1 = p->v[i+1][Y_IDX];
- if( x0==x1 ){
- if( x0==x && ((y0<=y && y1>=y) || (y1<=y && y0>=y)) ){
- res = 0;
- break;
- }
- continue;
- }
- if( x0>x1 ){
- int t = x0;
- x0 = x1;
- x1 = t;
- t = y0;
- y0 = y1;
- y1 = t;
- }
- if( x>=x1 || x<x0 ) continue;
- yP = y1 - (x1-x)*(y1-y0)/(x1-x0);
- if( yP == y ){ res = 0; break; }
- if( yP > y ){ res = -res; }
- }
- return res;
- }
- /* Odie_Polygon_XYWithin */
- int Odie_Polygon_XYWithin(Odie_Polygon *p, double x, double y){
- /*
- ** Return -1, 0, or 1 if the point x,y is outside, on, or within
- ** the polygon p.
- */
- return withinPolygon(p,x,y);
- }
- /* Odie_Polygon_VectorXYWithin */
- int Odie_Polygon_VectorXYWithin(Odie_Polygon *p, VectorXY C){
- /*
- ** Return -1, 0, or +1 if the point P is outside, on the border of, or
- ** fully contained within the subcompartment pSub.
- */
- return withinPolygon(p,C[X_IDX],C[Y_IDX]);
- }
- /* Odie_Polygon_ComputeArea */
- int Odie_Polygon_ComputeArea(Tcl_Interp *interp,Odie_Polygon *p){
- double area=0.0;
- double areacomp=0.0;
- int i;
-
- if( p->v[p->nVertex-1][X_IDX]!=p->v[0][X_IDX] || p->v[p->nVertex-1][Y_IDX]!=p->v[0][Y_IDX] ){
- p->v[p->nVertex][X_IDX] = p->v[0][X_IDX];
- p->v[p->nVertex][Y_IDX] = p->v[0][Y_IDX];
- p->nVertex++;
- }
-
- for(i=0; i<p->nVertex-1; i++){
- area += 0.5*(p->v[i][Y_IDX] + p->v[i+1][Y_IDX])*(p->v[i+1][X_IDX] - p->v[i][X_IDX]);
- }
- if( area<0.0 ){
- int b, e;
- for(b=0, e=p->nVertex-1; b<e; b++, e--){
- double t;
- t = p->v[b][X_IDX];
- p->v[b][X_IDX] = p->v[e][X_IDX];
- p->v[e][X_IDX] = t;
- t = p->v[b][Y_IDX];
- p->v[b][Y_IDX] = p->v[e][Y_IDX];
- p->v[e][Y_IDX] = t;
- }
- area = -area;
- }
- p->area = area;
- p->bbox[BBOX_X0_IDX] = p->bbox[BBOX_X1_IDX] = p->v[0][X_IDX];
- p->bbox[BBOX_Y1_IDX] = p->bbox[BBOX_Y0_IDX] = p->v[0][Y_IDX];
- for(i=1; i<p->nVertex-1; i++){
- double x, y;
- x = p->v[i][X_IDX];
- if( x<p->bbox[BBOX_X0_IDX] ) p->bbox[BBOX_X0_IDX] = x;
- if( x>p->bbox[BBOX_X1_IDX] ) p->bbox[BBOX_X1_IDX] = x;
- y = p->v[i][Y_IDX];
- if( y>p->bbox[BBOX_Y1_IDX] ) p->bbox[BBOX_Y1_IDX] = y;
- if( y<p->bbox[BBOX_Y0_IDX] ) p->bbox[BBOX_Y0_IDX] = y;
- }
- areacomp=(p->bbox[BBOX_X1_IDX] - p->bbox[BBOX_X0_IDX])*(p->bbox[BBOX_Y1_IDX]-p->bbox[BBOX_Y0_IDX])*1.00001;
-
- p->center[X_IDX]=(p->bbox[BBOX_X1_IDX]-p->bbox[BBOX_X0_IDX])*0.5+p->bbox[BBOX_X0_IDX];
- p->center[Y_IDX]=(p->bbox[BBOX_Y1_IDX]-p->bbox[BBOX_Y0_IDX])*0.5+p->bbox[BBOX_Y0_IDX];
- if(area<=areacomp) {
- return TCL_OK;
- } else {
- char errstr[256];
- sprintf(errstr,"Area: %g Calculated: %g\n",area,areacomp);
- Tcl_AppendResult(interp, "Area of polygon wonky ", errstr, 0);
- return TCL_ERROR;
- }
- }
- /* Odie_Poly_Compare */
- int Odie_Poly_Compare(Odie_Polygon *polyA,Odie_Polygon *polyB){
- int i,j,N;
- if(!polyA || !polyB) {
- return 0;
- }
- if(polyA->nVertex!=polyB->nVertex) {
- return 0;
- }
- N=polyA->nVertex;
- for(i=0;i<N;i++) {
- if(VectorXY_SamePoint(polyA->v[i],polyB->v[0])) {
- /* Check in either direction */
- for(j=1;j<N;j++) {
- if(
- VectorXY_SamePoint(polyA->v[(i+j)%N],polyB->v[j])==0
- &&
- VectorXY_SamePoint(polyA->v[(i-j)%N],polyB->v[j])==0
- ) {
- return 0;
- }
- }
- /* If we got here we pass */
- return 1;
- }
- }
- return 0;
-
- }
- /* *Odie_FaceXYZ_ToDict */
- Tcl_Obj *Odie_FaceXYZ_ToDict(Odie_FaceXYZ *pPoly){
- Tcl_Obj *element=Tcl_NewObj();
- {
- Tcl_Obj *value;
- value=Tcl_NewIntObj(pPoly->id);
- Odie_DictObjPut(NULL,element,"id",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewDoubleObj(pPoly->area);
- Odie_DictObjPut(NULL,element,"area",value);
- }
- {
- Tcl_Obj *value;
-
- Odie_MatrixObj *C;
- if(pPoly->is_2d) {
- C=Odie_MatrixObj_Create(MATFORM_bbox_xy);
- VectorXY_BBOX_Copy(C->matrix,pPoly->bbox_uv);
- value=Matrix_To_TclObj(C);
- } else {
- C=Odie_MatrixObj_Create(MATFORM_aabb_xyz);
- VectorXYZ_AABB_Copy(C->matrix,pPoly->bbox_xyz);
- value=Matrix_To_TclObj(C);
- }
-
- Odie_DictObjPut(NULL,element,"bbox",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewIntObj(pPoly->bend);
- Odie_DictObjPut(NULL,element,"bend",value);
- }
- {
- Tcl_Obj *value;
- value=VectorXYZ_To_TclObj(pPoly->center);
- Odie_DictObjPut(NULL,element,"center",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewBooleanObj(pPoly->is_convex);
- Odie_DictObjPut(NULL,element,"is_2d",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewBooleanObj(pPoly->is_convex);
- Odie_DictObjPut(NULL,element,"is_convex",value);
- }
- {
- Tcl_Obj *value;
- value=VectorXYZ_To_TclObj(pPoly->normal);
- Odie_DictObjPut(NULL,element,"normal",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewIntObj(pPoly->nVertex);
- Odie_DictObjPut(NULL,element,"nVertex",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewDoubleObj(pPoly->radius);
- Odie_DictObjPut(NULL,element,"radius",value);
- }
- {
- Tcl_Obj *value;
-
- Odie_MatrixObj *C;
- C=Odie_MatrixObj_Create(MATFORM_affine);
- Odie_Affine4x4_Copy(C->matrix,pPoly->rotation);
- value=Matrix_To_TclObj(C);
-
- Odie_DictObjPut(NULL,element,"rotation",value);
- }
- {
- Tcl_Obj *value;
-
- Odie_MatrixObj *C;
- C=Odie_MatrixObj_Create(MATFORM_affine);
- Odie_Affine4x4_Copy(C->matrix,pPoly->rotation_inv);
- value=Matrix_To_TclObj(C);
-
- Odie_DictObjPut(NULL,element,"rotation_inv",value);
- }
- return element;}
- /* Odie_FaceXYZ_freeIntRepProc */
- void Odie_FaceXYZ_freeIntRepProc(Tcl_Obj *objPtr){
- Odie_Free(objPtr->internalRep.otherValuePtr);
- objPtr->internalRep.otherValuePtr=NULL;
- objPtr->typePtr=NULL;
- }
- /* Odie_FaceXYZ_dupIntRepProc */
- void Odie_FaceXYZ_dupIntRepProc(Tcl_Obj *srcPtr,Tcl_Obj *dupPtr){
- Odie_FaceXYZ *src=srcPtr->internalRep.otherValuePtr;
- Odie_FaceXYZ *copy=Odie_FaceXYZ_Create(src->nVertex);
- memcpy(copy,src,src->alloc_bytes);
- Tcl_InvalidateStringRep(dupPtr);
- dupPtr->typePtr=srcPtr->typePtr;
- dupPtr->internalRep.otherValuePtr=copy;
- }
- /* Odie_FaceXYZ_updateStringProc */
- void Odie_FaceXYZ_updateStringProc(Tcl_Obj *objPtr){
- /* Update String Rep */
- char outbuffer[256];
- Tcl_DString result;
- Odie_FaceXYZ *p=objPtr->internalRep.otherValuePtr;
- int i,n;
- Tcl_DStringInit(&result);
- n=p->nVertex;
-
- /* Express as 3d */
- for(i=0; i<n; i++){
- sprintf(outbuffer,"%g %g %g",(float)p->vertex_xyz[i][X_IDX],(float)p->vertex_xyz[i][Y_IDX],(float)p->vertex_xyz[i][Z_IDX]);
- Tcl_DStringAppendElement(&result,outbuffer);
- }
-
- objPtr->length=Tcl_DStringLength(&result);
- objPtr->bytes=Odie_Alloc(objPtr->length+1);
- strcpy(objPtr->bytes,Tcl_DStringValue(&result));
- Tcl_DStringFree(&result);
- }
- /* Odie_FaceXYZ_setFromAnyProc */
- int Odie_FaceXYZ_setFromAnyProc(Tcl_Interp *interp,Tcl_Obj *objPtr){
- /* Set internal rep from any Tcl_Obj */
- if(objPtr->typePtr) {
- if(objPtr->typePtr->setFromAnyProc==&Odie_FaceXYZ_setFromAnyProc && objPtr->internalRep.otherValuePtr) {
- /*
- ** Object is already of the type requested
- */
- return TCL_OK;
- }
- }
- Odie_FaceXYZ *p;
- int created=0;
- if(Odie_FaceXYZ_GetFromTclObj(interp,objPtr,&p,&created)) {
- return TCL_ERROR;
- }
- Tcl_InvalidateStringRep(objPtr);
- objPtr->internalRep.otherValuePtr=p;
- objPtr->typePtr=&odie_polygon_tclobjtype;
- return TCL_OK;
- }
- /* *Odie_FaceXYZ_NewTclObj */
- Tcl_Obj *Odie_FaceXYZ_NewTclObj(Odie_FaceXYZ *pPolygon){
- Tcl_Obj *pResult;
- pResult=Tcl_NewObj();
- pResult->internalRep.otherValuePtr=pPolygon;
- pResult->typePtr=&odie_polygon_tclobjtype;
- Tcl_InvalidateStringRep(pResult);
- Tcl_IncrRefCount(pResult);
- return pResult;
- }
- /* *Odie_FaceXYZ_Create */
- Odie_FaceXYZ *Odie_FaceXYZ_Create(int nVertex){
- void *ptr;
- Odie_FaceXYZ *p;
- size_t size;
- int maxVertex=nVertex+2; /* Allocate room for an additional 2 vertices */
- if(nVertex<3) {
- nVertex=3;
- maxVertex=nVertex+2;
- }
- size=sizeof(*p)+maxVertex*sizeof(VectorXYZ)+maxVertex*sizeof(VectorXYZ);
- ptr=Odie_Alloc(size);
- p=(Odie_FaceXYZ *)ptr;
- p->alloc_bytes=size;
- p->maxVertex=maxVertex;
- p->nVertex=nVertex;
- p->vertex_uv=(ptr+sizeof(*p));
- p->vertex_xyz=(ptr+sizeof(*p)+maxVertex*sizeof(VectorXYZ));
- return p;
- }
- /* Odie_FaceXYZ_FromXYList */
- int Odie_FaceXYZ_FromXYList(Tcl_Interp *interp,Tcl_Obj *objPtr,Odie_FaceXYZ **ptr){
- int k,i,nVertex;
- Tcl_Obj *pElem;
- Odie_FaceXYZ *p;
- if( Tcl_ListObjLength(interp, objPtr, &k) ) return TCL_ERROR;
- /* Read in a series of doubles a X Y pairs */
- if( k<6 ){
- Tcl_AppendResult(interp, "need at least 3 vertices", 0);
- return TCL_ERROR;
- }
- if( k&1 ){
- Tcl_AppendResult(interp, "coordinates should come in pairs", 0);
- return TCL_ERROR;
- }
- nVertex=k/2;
- p=Odie_FaceXYZ_Create(nVertex);
- for(i=0; i<nVertex; i++){
- double d;
- Tcl_ListObjIndex(0, objPtr, i*2, &pElem);
- if(Tcl_GetDoubleFromObj(interp, pElem, &d)) goto createfail;
- p->vertex_xyz[i][X_IDX] = d;
-
- Tcl_ListObjIndex(0, objPtr, i*2+1, &pElem);
- if(Tcl_GetDoubleFromObj(interp, pElem, &d)) goto createfail;
- p->vertex_xyz[i][Y_IDX] = d;
- p->vertex_xyz[i][Z_IDX] = 0.0;
- }
- if(Odie_FaceXYZ_Compute(interp,p)) goto createfail;
- *ptr=p;
- return TCL_OK;
-
- createfail:
- Odie_Free((char *)p);
- return TCL_ERROR;
- }
- /* Odie_FaceXYZ_FromPoly */
- int Odie_FaceXYZ_FromPoly(Tcl_Interp *interp,Tcl_Obj *objPtr,Odie_FaceXYZ **ptr){
- int k,i,nVertex;
- Tcl_Obj *pElem;
- Odie_FaceXYZ *p;
- Odie_Polygon *poly;
- poly=objPtr->internalRep.otherValuePtr;
- nVertex=poly->nVertex;
- p=Odie_FaceXYZ_Create(nVertex);
- for(i=0; i<nVertex; i++){
- VectorXY_Copy(p->vertex_xyz[i],poly->v[i]);
- p->vertex_xyz[i][Z_IDX] = 0.0;
- }
- if(Odie_FaceXYZ_Compute(interp,p)) goto createfail;
- *ptr=p;
- return TCL_OK;
-
- createfail:
- Odie_Free((char *)p);
- return TCL_ERROR;
- }
- /* Odie_FaceXYZ_FromVectorList */
- int Odie_FaceXYZ_FromVectorList(Tcl_Interp *interp,Tcl_Obj *objPtr,Odie_FaceXYZ **ptr){
- int k,i,nVertex;
- Tcl_Obj *pElem;
- Odie_FaceXYZ *p;
- if( Tcl_ListObjLength(interp, objPtr, &k) ) return TCL_ERROR;
-
- if( k<3 ){
- Tcl_AppendResult(interp, "need at least 3 vertices", 0);
- return TCL_ERROR;
- }
- nVertex=k;
- p=Odie_FaceXYZ_Create(nVertex);
- for(i=0; i<p->nVertex; i++){
- Tcl_ListObjIndex(0, objPtr, i, &pElem);
- if(Odie_GetVectorXYZFromTclObj(interp,pElem,p->vertex_xyz[i])) goto createfail;
- }
- if(Odie_FaceXYZ_Compute(interp,p)) goto createfail;
- *ptr=p;
- return TCL_OK;
-
- createfail:
- Odie_Free((char *)p);
- return TCL_ERROR;
- }
- /* Odie_ConvexPolygon_GetFromTclObj */
- int Odie_ConvexPolygon_GetFromTclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,Odie_FaceXYZ **ptr,int *created){
- int result;
- result=Odie_FaceXYZ_GetFromTclObj(interp,objPtr,ptr,created);
- if(result) {
- return result;
- }
- Odie_FaceXYZ *pPoly=*ptr;
- if(pPoly->is_convex) {
- return TCL_OK;
- }
- if(interp) {
- Tcl_AppendResult(interp,"Polygon is not convex",NULL);
- }
- if(*created) Odie_FaceXYZ_ShimmerOrFree_TclObj(objPtr,*ptr);
- return TCL_ERROR;
- }
- /* Odie_FaceXYZ_GetFromTclObj */
- int Odie_FaceXYZ_GetFromTclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,Odie_FaceXYZ **ptr,int *created){
- *created=1;
- Tcl_Obj *pElem;
- int k,first_element_length;
-
- if(objPtr->typePtr) {
- if(objPtr->typePtr->setFromAnyProc==&Odie_FaceXYZ_setFromAnyProc && objPtr->internalRep.otherValuePtr) {
- /*
- ** Object is already of the type requested
- */
- *ptr=objPtr->internalRep.otherValuePtr;
- *created=0;
- return TCL_OK;
- }
- if(objPtr->typePtr->setFromAnyProc==&PolygonObj_setFromAnyProc && objPtr->internalRep.otherValuePtr) {
- /* Our first element is encoded as an ODIE vector */
- *created=1;
- return Odie_FaceXYZ_FromPoly(interp,objPtr,ptr);
- }
- }
- *created=1;
- if( Tcl_ListObjLength(interp, objPtr, &k) ) return TCL_ERROR;
- if( k<3 ){
- Tcl_AppendResult(interp, "need at least 3 vertices", 0);
- return TCL_ERROR;
- }
- /* See if our first element is a valid XYZ Coordnate */
- Tcl_ListObjIndex(0, objPtr, 0, &pElem);
- if(pElem->typePtr) {
- if(objPtr->typePtr->setFromAnyProc==&MatrixObj_setFromAnyProc && objPtr->internalRep.otherValuePtr) {
- /* Our first element is encoded as an ODIE vector */
- return Odie_FaceXYZ_FromVectorList(interp,objPtr,ptr);
- }
- }
- /* Guess form by the list contents */
- if( Tcl_ListObjLength(interp, pElem, &first_element_length) ) return TCL_ERROR;
- if(first_element_length==1) {
- /* The first element is only 1 element long, guess we have a stream of doubles */
- return Odie_FaceXYZ_FromXYList(interp,objPtr,ptr);
- }
- if(first_element_length==2) {
- /* The first element is 2 element long, guess we have a stream of vectors */
- return Odie_FaceXYZ_FromVectorList(interp,objPtr,ptr);
- }
- if(first_element_length==3) {
- /* The first element is 3 element long, guess we have a stream of vectors */
- return Odie_FaceXYZ_FromVectorList(interp,objPtr,ptr);
- }
- /* Stop trying to quess */
- Tcl_AppendResult(interp, "Cannot intepret input", 0);
- return TCL_ERROR;
- }
- /* Odie_FaceXYZ_ShimmerOrFree_TclObj */
- void Odie_FaceXYZ_ShimmerOrFree_TclObj(Tcl_Obj *objPtr,Odie_FaceXYZ *p){
- if(objPtr->typePtr) {
- if(objPtr->typePtr->setFromAnyProc==&Odie_FaceXYZ_setFromAnyProc) {
- /*
- ** Object is already of the type requested
- */
- return;
- }
- }
- if(Tcl_IsShared(objPtr)) {
- Odie_Free((char *)p);
- return;
- }
- if(objPtr->typePtr && objPtr->typePtr->freeIntRepProc) {
- Tcl_FreeInternalRepProc *freeIntRepProc=objPtr->typePtr->freeIntRepProc;
- freeIntRepProc(objPtr);
- }
- objPtr->internalRep.otherValuePtr=p;
- objPtr->typePtr=&odie_polygon_tclobjtype;
- Tcl_IncrRefCount(objPtr);
- return;
- }
- /* Odie_FaceXYZ_Compute */
- int Odie_FaceXYZ_Compute(Tcl_Interp *interp,Odie_FaceXYZ *p){
- double normal_length=0.0;
- int i,j,k,rmax=0,r1;
- double area=0.0;
- double areacomp=0.0;
- int is2d=1;
- VectorXYZ SUM;
- if(p->nVertex<3) {
- if(interp) {
- Tcl_AppendResult(interp,"Polygons need at least 3 vertices",NULL);
- }
- return TCL_ERROR;
- }
- while(VectorXYZ_SamePoint(p->vertex_xyz[p->nVertex-1],p->vertex_xyz[0])) {
- p->nVertex--;
- if(p->nVertex<=0) {
- return TCL_ERROR;
- }
- }
- VectorXYZ_Copy(p->vertex_xyz[p->nVertex],p->vertex_xyz[0]);
- VectorXYZ_Zero(SUM);
- VectorXYZ_Zero(p->normal);
- VectorXYZ_Zero(p->center);
- VectorXYZ_AABB_Reset(p->bbox_xyz);
- for(i=0;i<p->nVertex;i++) {
- VectorXYZ_AABB_Measure(p->vertex_xyz[i],p->bbox_xyz);
- p->center[X_IDX]+=p->vertex_xyz[i][X_IDX];
- p->center[Y_IDX]+=p->vertex_xyz[i][Y_IDX];
- p->center[Y_IDX]+=p->vertex_xyz[i][Z_IDX];
- }
- p->center[X_IDX] /= p->nVertex;
- p->center[Y_IDX] /= p->nVertex;
- p->center[Z_IDX] /= p->nVertex;
-
- if(fabs(p->bbox_xyz[Z_MAX_IDX])>__FLT_EPSILON__) {
- is2d=0;
- }
- if(fabs(p->bbox_xyz[Z_MIN_IDX])>__FLT_EPSILON__) {
- is2d=0;
- }
- p->is_2d=is2d;
- if(is2d) {
- p->normal[X_IDX]=0.0;
- p->normal[Y_IDX]=0.0;
- p->normal[Z_IDX]=1.0;
- Odie_Affine4x4_Identity(p->rotation);
- Odie_Affine4x4_Identity(p->rotation_inv);
- for(i=0;i<=p->nVertex;i++) {
- VectorXYZ_Copy(p->vertex_uv[i],p->vertex_xyz[i]);
- }
- } else {
- for(i=0,j=1;i<p->nVertex;i++,j++) {
- r1 = VectorXYZ_DistanceSq(p->center, p->vertex_xyz[i]);
- if(r1>rmax) {
- rmax=r1;
- }
- p->normal[X_IDX] += (p->vertex_xyz[j][Y_IDX]-p->vertex_xyz[i][Y_IDX]) * (p->vertex_xyz[j][Z_IDX]+p->vertex_xyz[i][Z_IDX]);
- p->normal[Y_IDX] += (p->vertex_xyz[j][Z_IDX]-p->vertex_xyz[i][Z_IDX]) * (p->vertex_xyz[j][X_IDX]+p->vertex_xyz[i][X_IDX]);
- p->normal[Z_IDX] += (p->vertex_xyz[j][X_IDX]-p->vertex_xyz[i][X_IDX]) * (p->vertex_xyz[j][Y_IDX]+p->vertex_xyz[i][Y_IDX]);
- }
- p->radius=sqrt(rmax);
- normal_length=VectorXYZ_Magnitude(p->normal);
- if(normal_length>0.0) {
- double inv=1.0/normal_length;
- p->normal[X_IDX]*=inv;
- p->normal[Y_IDX]*=inv;
- p->normal[Z_IDX]*=inv;
- }
- AFFINE rotation,translation;
- Odie_Affine_From_Normal(rotation,p->normal);
- Odie_Affine4x4_Translation(translation,p->center);
- Odie_Affine4x4_Multiply(p->rotation_inv,rotation,translation);
- Odie_Affine4x4_Inverse(p->rotation,p->rotation_inv);
- /* Map the Polygon to UV Space */
- for(i=0;i<=p->nVertex;i++) {
- VectorXYZ_MatrixMultiply(p->vertex_uv[i],p->vertex_xyz[i],p->rotation);
- }
- }
- VectorXYZ_Copy(p->vertex_uv[p->nVertex],p->vertex_xyz[0]);
- /* Compute 2d information from the UV coordinates */
- p->is_convex=1;
- for(i=0; i<p->nVertex; i++){
- int bend;
- j=(i+1)%p->nVertex;
- k=(i+2)%p->nVertex;
- bend=VectorXY_BendDirection(p->vertex_uv[i], p->vertex_uv[j], p->vertex_uv[k]);
- if(bend>0 && p->bend<0) {
- p->is_convex=0;
- } else if(bend<0 && p->bend>0) {
- p->is_convex=0;
- }
- p->bend+=bend;
- }
- if(!p->is_convex) {
- /*
- ** A convex polygon is legal,
- ** we just can't answer questions about area and intersections
- */
- return TCL_OK;
- }
- for(i=0; i<p->nVertex; i++){
- area += 0.5*(p->vertex_uv[i][Y_IDX] + p->vertex_uv[i+1][Y_IDX])*(p->vertex_uv[i+1][X_IDX] - p->vertex_uv[i][X_IDX]);
- }
- if( area<0.0 ){
- int b, e;
- for(b=0, e=p->nVertex; b<e; b++, e--){
- double t;
- t = p->vertex_uv[b][X_IDX];
- p->vertex_uv[b][X_IDX] = p->vertex_uv[e][X_IDX];
- p->vertex_uv[e][X_IDX] = t;
- t = p->vertex_uv[b][Y_IDX];
- p->vertex_uv[b][Y_IDX] = p->vertex_uv[e][Y_IDX];
- p->vertex_uv[e][Y_IDX] = t;
- }
- area = -area;
- }
- if(fabs(area)<__FLT_EPSILON__) {
- area=0.0;
- }
- p->area = area;
- p->bbox_uv[BBOX_X0_IDX] = p->bbox_uv[BBOX_X1_IDX] = p->vertex_uv[0][X_IDX];
- p->bbox_uv[BBOX_Y1_IDX] = p->bbox_uv[BBOX_Y0_IDX] = p->vertex_uv[0][Y_IDX];
- for(i=1; i<p->nVertex; i++){
- double x, y;
- x = p->vertex_uv[i][X_IDX];
- if( x<p->bbox_uv[BBOX_X0_IDX] ) p->bbox_uv[BBOX_X0_IDX] = x;
- if( x>p->bbox_uv[BBOX_X1_IDX] ) p->bbox_uv[BBOX_X1_IDX] = x;
- y = p->vertex_uv[i][Y_IDX];
- if( y>p->bbox_uv[BBOX_Y1_IDX] ) p->bbox_uv[BBOX_Y1_IDX] = y;
- if( y<p->bbox_uv[BBOX_Y0_IDX] ) p->bbox_uv[BBOX_Y0_IDX] = y;
- }
- return TCL_OK;
- }
- /* *Odie_FaceXYZ_Simplify */
- Odie_FaceXYZ *Odie_FaceXYZ_Simplify(Odie_FaceXYZ *pPolygonXYZ){
- Odie_FaceXYZ *pNewPolygonXYZ;
- int i,j,k,N;
- pNewPolygonXYZ=Odie_FaceXYZ_Create(pPolygonXYZ->nVertex);
- pNewPolygonXYZ->nVertex=0;
- N=pPolygonXYZ->nVertex;
-
- /* The first vertex always belongs */
- VectorXYZ_Copy(pNewPolygonXYZ->vertex_xyz[0],pPolygonXYZ->vertex_xyz[0]);
- pNewPolygonXYZ->nVertex++;
- i=1;
- j=(i-1) % N;
- k=(i-2) % N;
- while(i<N) {
- /* Skip identical points */
- while(VectorXYZ_SamePoint(pPolygonXYZ->vertex_xyz[i],pPolygonXYZ->vertex_xyz[j]) && i<N) {
- i++;
- }
- /* Skip colinear points */
- while(VectorXYZ_IsColinear(pPolygonXYZ->vertex_xyz[k],pPolygonXYZ->vertex_xyz[j],pPolygonXYZ->vertex_xyz[i]) && i<N) {
- i++;
- }
- VectorXYZ_Copy(pNewPolygonXYZ->vertex_xyz[i],pPolygonXYZ->vertex_xyz[i]);
- pNewPolygonXYZ->nVertex++;
- k=j;
- j=i;
- i++;
- }
- return pNewPolygonXYZ;
- }
- /* Odie_FaceXYZ_Compare */
- static inline int Odie_FaceXYZ_Compare(Odie_FaceXYZ *A,Odie_FaceXYZ *B){
- Odie_FaceXYZ *pPolyA,*pPolyB;
- int i,j=0,result=1;
- if(!A || !B) return 0;
- if(A==B) return 1;
- pPolyA=Odie_FaceXYZ_Simplify(A);
- pPolyB=Odie_FaceXYZ_Simplify(B);
- if(pPolyA->nVertex!=pPolyB->nVertex) {
- result=0; goto finished;
- }
- for(i=0;i<pPolyA->nVertex;i++) {
- if(VectorXYZ_SamePoint(pPolyA->vertex_xyz[i],pPolyB->vertex_xyz[i])) continue;
- /* Check the reverse */
- j=pPolyA->nVertex-i-1;
- if(!VectorXYZ_SamePoint(pPolyA->vertex_xyz[i],pPolyB->vertex_xyz[j])) {
- result=0;
- goto finished;
- }
- result=-1;
- }
- finished:
- Odie_Free(pPolyA);
- Odie_Free(pPolyB);
- return result;
- }
- /* Odie_FaceXYZ_Coplaner */
- static inline int Odie_FaceXYZ_Coplaner(Odie_FaceXYZ *A,Odie_FaceXYZ *B){
- int i,j,ia=0,ja=0,ka=0;
- if(!A || !B) return 0;
- if(A==B) return 1;
- for(i=0;i<A->nVertex;i++) {
- int c;
- ia=i;
- ja=(i+1) % A->nVertex;
- ka=(i+2) % A->nVertex;
- for(j=0;j<B->nVertex;j++) {
- c=VectorXYZ_IsCoplaner(A->vertex_xyz[ia],A->vertex_xyz[ja],A->vertex_xyz[ka],B->vertex_xyz[j]);
- if(!c) {
- return 0;
- }
- }
- }
- return 1;
- }
- /* PolygonUV_Within */
- static inline int PolygonUV_Within(Odie_FaceXYZ *p, double x, double y){
- /*
- ** Return -1, 0, or 1 if the point x,y is outside, on, or within
- ** the polygon p.
- */
- int res, i;
- res = -1;
- for(i=0; i<p->nVertex-1; i++){
- double x0, y0, x1, y1, yP;
- x0 = p->vertex_uv[i][X_IDX];
- y0 = p->vertex_uv[i][Y_IDX];
- x1 = p->vertex_uv[i+1][X_IDX];
- y1 = p->vertex_uv[i+1][Y_IDX];
- if( x0==x1 ){
- if( x0==x && ((y0<=y && y1>=y) || (y1<=y && y0>=y)) ){
- res = 0;
- break;
- }
- continue;
- }
- if( x0>x1 ){
- int t = x0;
- x0 = x1;
- x1 = t;
- t = y0;
- y0 = y1;
- y1 = t;
- }
- if( x>=x1 || x<x0 ) continue;
- yP = y1 - (x1-x)*(y1-y0)/(x1-x0);
- if( yP == y ){ res = 0; break; }
- if( yP > y ){ res = -res; }
- }
- return res;
- }
- /* Odie_FaceXYZ_Within */
- static inline int Odie_FaceXYZ_Within(Odie_FaceXYZ *p, VectorXYZ POINT){
- VectorXYZ a; /* Temporary variable to map coordinates during rotation */
-
- /*
- ** Return -1, 0, or 1 if the point x,y is outside, on, or within
- ** the polygonxyz p.
- */
- if(!VectorXYZ_AABB_Within(POINT,p->bbox_xyz)) {
- return -1;
- }
- /*
- ** If we reach here it means that the closest point will be on the
- ** permiter of the triangle. There are three line faces on the
- ** permiter. Try them all.
- */
- int i, j;
- for(i=0;i<p->nVertex;i++) {
- j=(i+1)%p->nVertex;
- if(VectorXYZ_PointIsOnSegment(POINT,p->vertex_xyz[i], p->vertex_xyz[j])) {
- return 0;
- }
- }
- /*
- ** Translate the coordinate to the same rotation as the polygon
- ** and use 2d checks
- */
- VectorXYZ_MatrixMultiply(a,POINT,p->rotation);
- return PolygonUV_Within(p,a[X_IDX],a[Y_IDX]);
- }
- /* Odie_FaceXYZ_IntersectTest */
- static int Odie_FaceXYZ_IntersectTest(Odie_FaceXYZ *p1,Odie_FaceXYZ *p2){
- double area,x,y;
- area = Odie_FaceXYZ_AreaOfIntersection(p1,p2,&x,&y);
- if(area>0) {
- return 1;
- } else {
- return 0;
- }
- }
- /* Odie_FaceXYZ_AreaOfIntersection */
- static double Odie_FaceXYZ_AreaOfIntersection(Odie_FaceXYZ *p1,Odie_FaceXYZ *p2,double *xin,double *yin){
- double area=0;
- double xInside = 0.0, yInside = 0.0;
- double x0, y0, x1, y1, dx, dy, xP, yP, xC, yC;
- int i, j, cnt;
- int score, bestScore;
- static const int n = 50;
- char hit[50][50];
-
- /* Compute the overlap of the bounding boxes of the two polygons. */
- x0 = p1->bbox_uv[BBOX_X0_IDX] < p2->bbox_uv[BBOX_X0_IDX] ? p2->bbox_uv[BBOX_X0_IDX] : p1->bbox_uv[BBOX_X0_IDX];
- y0 = p1->bbox_uv[BBOX_Y1_IDX] > p2->bbox_uv[BBOX_Y1_IDX] ? p2->bbox_uv[BBOX_Y1_IDX] : p1->bbox_uv[BBOX_Y1_IDX];
- x1 = p1->bbox_uv[BBOX_X1_IDX] > p2->bbox_uv[BBOX_X1_IDX] ? p2->bbox_uv[BBOX_X1_IDX] : p1->bbox_uv[BBOX_X1_IDX];
- y1 = p1->bbox_uv[BBOX_Y0_IDX] < p2->bbox_uv[BBOX_Y0_IDX] ? p2->bbox_uv[BBOX_Y0_IDX] : p1->bbox_uv[BBOX_Y0_IDX];
-
- /* Divide the intersection of the bounding boxes into a n-by-n grid
- ** and count the number of elements in this grid whose centers fall
- ** within both polygons. This will be our approximation for the
- ** intersection of the polygons themselves.
- */
- dx = (x1-x0)/n;
- dy = (y1-y0)/n;
- cnt = 0;
- xC = yC = 0.0;
- for(i=0; i<n; i++){
- xP = x0 + dx*(i+0.5);
- for(j=0; j<n; j++){
- yP = y0 + dy*(j+0.5);
- if( PolygonUV_Within(p1, xP, yP)>0 && PolygonUV_Within(p2, xP, yP)>0 ){
- cnt++;
- hit[i][j] = 1;
- xC += xP;
- yC += yP;
- }else{
- hit[i][j] = 0;
- }
- }
- }
-
- /* We need to find a good approximation for the center of the
- ** overlap. Begin by computing the center of mass for the
- ** overlapping region. Then find the point inside the intersection
- ** that is nearest the center of mass.
- */
- if( cnt>0 ){
- area = cnt*(x1-x0)*(y0-y1)/(n*n);
- xC /= cnt;
- yC /= cnt;
- bestScore = -1.0;
- for(i=0; i<n; i++){
- xP = x0 + dx*(i+0.5);
- for(j=0; j<n; j++){
- if( !hit[i][j] ) continue;
- yP = y0 + dy*(j+0.5);
- score = dist(xP,yP,xC,yC);
- if( score<bestScore || bestScore<0.0 ){
- xInside = xP;
- yInside = yP;
- bestScore = score;
- }
- }
- }
- } else {
- area=0.0;
- }
- *xin=xInside;
- *yin=yInside;
- return area;
- }
- /* SegmentSet_Delete */
- static void SegmentSet_Delete(ClientData clientData){
- SegmentSet *pSet=(SegmentSet *)clientData;
- SegmentSetClear(pSet);
- Odie_Free(pSet);
- }
- /* SegmentSet_Clone */
- static int SegmentSet_Clone(
- Tcl_Interp* interp, /* Tcl interpreter for error reporting */
- ClientData metadata, /* Metadata to be cloned */
- ClientData* newMetaData /* Where to put the cloned metadata */
- ){
- SegmentSet *src=(SegmentSet*)metadata;
- SegmentSet *dest=(SegmentSet*)Odie_Alloc(sizeof(SegmentSet));
- SegmentSetCopy(dest,src);
- *newMetaData=(ClientData*)dest;
- return TCL_OK;
- }
- /* *Segment_To_Dict */
- Tcl_Obj *Segment_To_Dict(Segment *pSeg){
- Tcl_Obj *element=Tcl_NewObj();
- {
- Tcl_Obj *value;
- value=Tcl_NewIntObj(pSeg->id);
- Odie_DictObjPut(NULL,element,"id:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewBooleanObj(pSeg->isVirtual);
- Odie_DictObjPut(NULL,element,"virtual:",value);
- }
- {
- Tcl_Obj *value;
- value=VectorXYZ_To_TclObj(pSeg->from);
- Odie_DictObjPut(NULL,element,"from:",value);
- }
- {
- Tcl_Obj *value;
- value=VectorXYZ_To_TclObj(pSeg->to);
- Odie_DictObjPut(NULL,element,"to:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewBooleanObj(pSeg->isVirtual);
- Odie_DictObjPut(NULL,element,"exported:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewIntObj(pSeg->idLC);
- Odie_DictObjPut(NULL,element,"id_left:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewIntObj(pSeg->idRC);
- Odie_DictObjPut(NULL,element,"id_right:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewBooleanObj(pSeg->isVirtual);
- Odie_DictObjPut(NULL,element,"ignore:",value);
- }
- {
- Tcl_Obj *value;
-
- if(pSeg->boundfwd) {
- value=Tcl_NewIntObj(pSeg->boundfwd->faceid);
- } else {
- value=Tcl_NewIntObj(0);
- }
-
- Odie_DictObjPut(NULL,element,"facefwd:",value);
- }
- {
- Tcl_Obj *value;
-
- if(pSeg->boundback) {
- value=Tcl_NewIntObj(pSeg->boundback->faceid);
- } else {
- value=Tcl_NewIntObj(0);
- }
-
- Odie_DictObjPut(NULL,element,"faceback:",value);
- }
- return element;}
- /* *SegmentSet_Insert_XYZ */
- Segment *SegmentSet_Insert_XYZ(SegmentSet *pSet,int id,VectorXYZ A,VectorXYZ B){
- Segment *pSeg;
- if(id>0) {
- if(SegmentSet_FindById(pSet, id)) return NULL;
- }
- VectorXYZ_GridAlign(A,pSet->grid);
- VectorXYZ_GridAlign(B,pSet->grid);
- if(VectorXYZ_SamePoint(A,B)) return NULL;
- SegmentSet_AddVertex(pSet,A);
- SegmentSet_AddVertex(pSet,B);
- pSeg=Segment_FindByLocation(pSet,A,B);
- if(pSeg) return pSeg;
- pSeg=Segment_Create(pSet,id);
- if(pSeg) {
- Segment_SetToFrom(pSet,pSeg,A,B);
- }
- return pSeg;
- }
- /* SegmentSet_Cleanup_Coincident */
- static int SegmentSet_Cleanup_Coincident(SegmentSet *pSet,Segment *pAB){
- Link *qLoop,*qNext;
- int changes=0;
- for(qLoop=pSet->pAll; qLoop; qLoop=qNext){
- int c;
- Segment *pCD;
- pCD = qLoop->pLinkNode;
- qNext = qLoop->pNext;
- VectorXYZ ICEPT;
-
- VectorXYZ_ClosestPointOnSegment(pAB->from,pAB->to,pCD->from,ICEPT);
- VectorXYZ_GridAlign(ICEPT,pSet->grid);
- if(VectorXYZ_SamePoint(ICEPT,pCD->from)) {
- changes+=SegmentSet_AddVertex(pSet,ICEPT);
- }
- VectorXYZ_ClosestPointOnSegment(pAB->from,pAB->to,pCD->to,ICEPT);
- VectorXYZ_GridAlign(ICEPT,pSet->grid);
- if(VectorXYZ_SamePoint(ICEPT,pCD->to)) {
- changes+=SegmentSet_AddVertex(pSet,ICEPT);
- }
- }
- for(qLoop=pSet->pAll; qLoop; qLoop=qNext){
- int c;
- Segment *pCD;
- pCD = qLoop->pLinkNode;
- qNext = qLoop->pNext;
- VectorXYZ ICEPT1,ICEPT2;
- /* Evaluate lower to higher */
- if(pCD->id == pAB->id) continue;
- c=VectorXYZ_LineLineCoincident(pAB->from,pAB->to,pCD->from,pCD->to,ICEPT1,ICEPT2);
- if(c<=0) continue;
- changes+=SegmentSet_AddVertex(pSet,ICEPT1);
- if(!VectorXYZ_SamePoint(ICEPT1,ICEPT2)) {
- changes+=SegmentSet_AddVertex(pSet,ICEPT2);
- }
- }
- return changes;
- }
- /* Segset_Insert_Polygon */
- int Segset_Insert_Polygon(SegmentSet *pSet,Odie_FaceXYZ *p,int comptid){
- int h,i,j,reversed=0;
- int bend=0;
- if(p->nVertex<3) {
- return TCL_ERROR;
- }
- for(i=0;i<=p->nVertex;i++) {
- VectorXYZ h_uv,i_uv,j_uv;
- j=(i+1)%p->nVertex;
- h=(i-1)%p->nVertex;
- VectorXYZ_MatrixMultiply(h_uv,p->vertex_xyz[h],pSet->rotation);
- VectorXYZ_MatrixMultiply(i_uv,p->vertex_xyz[i],pSet->rotation);
- VectorXYZ_MatrixMultiply(j_uv,p->vertex_xyz[j],pSet->rotation);
- bend+=VectorXY_BendDirection(h_uv, i_uv, j_uv);
- }
- for(i=0;i<=p->nVertex;i++) {
- Segment *pSeg;
- j=(i+1)%p->nVertex;
- h=(i-1)%p->nVertex;
- pSeg=SegmentSet_Insert_XYZ(pSet,-1,p->vertex_xyz[i],p->vertex_xyz[j]);
- if(pSeg) {
- if(VectorXYZ_SamePoint(pSeg->from,p->vertex_xyz[j])) {
- reversed=1;
- }
- pSeg->isVirtual=0;
- /*
- ** Paint the inside edge of the polygon with the comptid
- */
- if(reversed) {
- /* The line inserted into the segment set was backward from what we specified */
- if(bend<=0) {
- /* The polygon was given in a counter clockwise direction */
- pSeg->idRC=comptid;
- } else {
- pSeg->idLC=comptid;
- }
- } else {
- if(bend<=0) {
- /* The polygon was given in a counter clockwise direction */
- pSeg->idRC=comptid;
- } else {
- pSeg->idLC=comptid;
- }
- }
- }
- }
- return TCL_OK;
- }
- /* SegmentSetCopy */
- void SegmentSetCopy(SegmentSet *dest,SegmentSet *src){
- SegmentSetClear(dest);
- memset(dest, 0, sizeof(SegmentSet));
- Link *pLoop, *pNext;
- for(pLoop=src->pAll; pLoop; pLoop=pNext){
- Segment *pAB,*pNewSeg;
- pAB = pLoop->pLinkNode;
- pNext = pLoop->pNext;
- pNewSeg=SegmentSet_Insert_XYZ(dest,pAB->id,pAB->from,pAB->to);
- if(pNewSeg) {
- Segment_Imprint(pAB,pNewSeg);
- }
- }
- }
- /* Segment_OnList */
- static int Segment_OnList(Segment *pSeg, Link *pList){
- while( pList ){
- if( pList->pLinkNode==pSeg ) return 1;
- pList = pList->pNext;
- }
- return 0;
- }
- /* *SegmentSet_FindById */
- static Segment *SegmentSet_FindById(SegmentSet *p, int id){
- int h;
- Link *pLink;
-
- h = hashInt(id);
- for(pLink = p->hashId[h]; pLink; pLink=pLink->pNext){
- Segment *pSeg=pLink->pLinkNode;
- if( pSeg->id==id ) return pSeg;
- }
- return 0;
- }
- /* *Segment_FindByLocation */
- Segment *Segment_FindByLocation(SegmentSet *pSet, VectorXYZ A, VectorXYZ B){
- /*
- ** Find and return the line segment that goes from A to B. Return NULL
- ** if there is not such line segment
- */
- Link *pX;
- Segment *p;
- int h;
- VectorXYZ_GridAlign(A,pSet->grid);
- h = hashVectorXYZ(A);
- for(pX=pSet->hashFrom[h]; pX; pX=pX->pNext){
- p = pX->pLinkNode;
- if( VectorXYZ_SamePoint(p->from, A) && VectorXYZ_SamePoint(p->to, B) ){
- return p;
- }
- if( VectorXYZ_SamePoint(p->to, A) && VectorXYZ_SamePoint(p->from, B) ){
- return p;
- }
- }
- for(pX=pSet->hashTo[h]; pX; pX=pX->pNext){
- p = pX->pLinkNode;
- if( VectorXYZ_SamePoint(p->from, A) && VectorXYZ_SamePoint(p->to, B) ){
- return p;
- }
- if( VectorXYZ_SamePoint(p->to, A) && VectorXYZ_SamePoint(p->from, B) ){
- return p;
- }
- }
- return 0;
- }
- /* Segment_Imprint */
- static void Segment_Imprint(Segment *pSrc,Segment *pDest){
- if(pSrc==pDest) return;
- pDest->isVirtual=pSrc->isVirtual;
- pDest->idLC=pSrc->idLC;
- pDest->idRC=pSrc->idRC;
- }
- /* Segment_SetToFrom */
- static void Segment_SetToFrom(SegmentSet *pSet, Segment *p, VECTORXYZ from, VECTORXYZ to){
- int h;
- VectorXYZ_GridAlign(from,pSet->grid);
- VectorXYZ_GridAlign(to,pSet->grid);
- if(VectorXYZ_SamePoint(from,p->from) && VectorXYZ_SamePoint(to,p->to)) {
- return;
- }
- LinkRemove(&p->pFrom);
- LinkRemove(&p->pTo);
- pSet->modified=1;
- VectorXYZ_Copy(p->from,from);
- VectorXYZ_Copy(p->to,to);
- VectorXY_BBOX_Measure(p->from,pSet->bbox_uv);
- VectorXY_BBOX_Measure(p->to,pSet->bbox_uv);
- h = hashVectorXYZ(p->from);
- LinkInsert(&pSet->hashFrom[h], &p->pFrom);
- h = hashVectorXYZ(p->to);
- LinkInsert(&pSet->hashTo[h], &p->pTo);
- }
- /* *Segment_Create */
- static inline Segment *Segment_Create(SegmentSet *pSet,int newid){
- Link *pLoop,*pNext;
- Segment *p=NULL;
- int id,h;
- for(pLoop=pSet->pFree; pLoop; pLoop=pNext){
- p=pLoop->pLinkNode;
- pNext=pLoop->pNext;
- if(p) {
- LinkRemove(&p->pFree);
- id=p->id;
- memset(p,0,sizeof(*p));
- if(newid<=0) {
- p->id=id;
- } else if(p->id>pSet->nextid) {
- pSet->nextid=p->id;
- }
- break;
- }
- }
- if(!p) {
- p=(Segment *)Odie_Alloc( sizeof(*p) );
- if(newid<=0) {
- pSet->nextid++;
- p->id=pSet->nextid;
- } else if(p->id>pSet->nextid) {
- pSet->nextid=p->id;
- }
- }
- if(!p) {
- return NULL;
- }
- LinkInit(p->pAll, p);
- LinkInit(p->pSet, p);
- LinkInit(p->pHash, p);
- LinkInit(p->pFrom, p);
- LinkInit(p->pTo, p);
-
- LinkInit(p->pFree, p);
- LinkInsert(&pSet->pAll, &p->pAll);
- h = hashInt(p->id);
- LinkInsert(&pSet->hashId[h], &p->pHash);
- pSet->modified=1;
- pSet->nSeg++;
- pSet->pCurrent = p;
- return p;
- }
- /* SegmentSetRemove */
- static inline void SegmentSetRemove(SegmentSet *pSet, Segment *p){
- /*
- ** Remove a segment from the segment set
- */
- pSet->modified=1;
- LinkRemove(&p->pAll);
- /* We intentionally do not remove pSeg->pSet because it might not be
- ** a well-formed list */
- LinkRemove(&p->pHash);
- LinkRemove(&p->pFrom);
- LinkRemove(&p->pTo);
-
- LinkInit(p->pAll, p);
- //LinkInit(p->pSet, p);
- LinkInit(p->pHash, p);
- LinkInit(p->pFrom, p);
- LinkInit(p->pTo, p);
- LinkInsert(&pSet->pFree,&p->pFree);
- pSet->nSeg--;
- if( pSet->pCurrent==p ){
- pSet->pCurrent = pSet->pAll ? pSet->pAll->pLinkNode : 0;
- }
- }
- /* SegRelink */
- static inline void SegRelink(SegmentSet *pSet, Segment *p){
- /*
- ** Call this routine to relink into a segment when the
- ** Seg.from vector changes.
- */
- int h;
- pSet->modified=1;
- LinkRemove(&p->pHash);
- LinkRemove(&p->pFrom);
- LinkRemove(&p->pTo);
- LinkRemove(&p->pFree);
- h = hashInt(p->id);
- LinkInsert(&pSet->hashId[h], &p->pHash);
- h = hashVectorXY(p->from);
- LinkInsert(&pSet->hashFrom[h], &p->pFrom);
- h = hashVectorXY(p->to);
- LinkInsert(&pSet->hashTo[h], &p->pTo);
- }
- /* SegmentSetClear */
- static inline void SegmentSetClear(SegmentSet *pSet){
- /*
- ** Remove all segments from a segment set
- */
- Link *pLoop,*pNext;
- Segment *p;
- SegmentSet_ClearFaceEdgeCache(pSet);
- while( pSet->pAll ){
- assert( pSet->nSeg>0 );
- p=pSet->pAll->pLinkNode;
- SegmentSetRemove(pSet, p);
- }
- for(pLoop=pSet->pFree; pLoop; pLoop=pNext){
- p=pLoop->pLinkNode;
- pNext=pLoop->pNext;
- LinkRemove(&p->pFree);
- Odie_Free((char *)p);
- }
- assert( pSet->nSeg==0 );
- }
- /* SegmentSetStep */
- static inline void SegmentSetStep(SegmentSet *pSet){
- /*
- ** Advance the pSet->pAll pointer so that it is pointing to a different
- ** segment.
- */
- if( pSet->pCurrent ){
- Link *pNext = pSet->pCurrent->pAll.pNext;
- pSet->pCurrent = pNext ? pNext->pLinkNode : 0;
- }
- if( pSet->pCurrent==0 ){
- pSet->pCurrent = pSet->pAll ? pSet->pAll->pLinkNode : 0;
- }
- }
- /* SegmentSet_AddVertex */
- static int SegmentSet_AddVertex(SegmentSet *pSet,VectorXYZ A){
- Link *pLoop,*pNext;
- VectorXYZ B,ICEPT;
- int changes=0;
- VectorXYZ_GridAlign(A,pSet->grid);
- for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
- int delete=0;
- Segment *pAB,*pNew;
- Segment *found;
- pAB = pLoop->pLinkNode;
- pNext=pLoop->pNext;
- if(VectorXYZ_SamePoint(A,pAB->from)) continue;
- if(VectorXYZ_SamePoint(A,pAB->to)) continue;
- VectorXYZ_ClosestPointOnSegment(pAB->from,pAB->to,A,ICEPT);
- if(!VectorXYZ_SamePoint(ICEPT,A)) continue;
- changes++;
- /* Preserve the segment's original destination */
- VectorXYZ_Copy(B,pAB->to);
- found=Segment_FindByLocation(pSet,pAB->from,A);
- if(!found) {
- /* Truncate the first part of the segment */
- Segment_SetToFrom(pSet,pAB,pAB->from,A);
- } else {
- delete=1;
- }
- found=Segment_FindByLocation(pSet,A,B);
- if(!found) {
- if(delete) {
- /*
- ** A segment exists for the first part of this segment
- ** but not the second. Rather than throw this link out
- ** just to re-create it, recycle
- */
- delete=0;
- Segment_SetToFrom(pSet,pAB,A,B);
- } else {
- pNew=SegmentSet_Insert_XYZ(pSet,-1,A,B);
- if(pNew) {
- Segment_Imprint(pAB,pNew);
- }
- }
- }
- if(delete) {
- /* A segment already exists, delete this one */
- SegmentSetRemove(pSet,pAB);
- }
- }
- return changes;
- }
- /* SegmentSet_Cleanup */
- int SegmentSet_Cleanup(SegmentSet *pSet,int looseend){
- Link *pLoop,*pNext;
- Link *qLoop,*qNext;
- Segment *pAB,*pCD;
- int count=0;
- int loop=0;
- int match=0;
- for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
- pAB = pLoop->pLinkNode;
- pNext = pLoop->pNext;
- pAB->test=0;
- }
- /* Cleanup loose ends */
- for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
- VectorXYZ A,B;
- Link *pList;
- int nSeg;
- pAB = pLoop->pLinkNode;
- pNext = pLoop->pNext;
- VectorXYZ_Copy(A,pAB->from);
- VectorXYZ_Copy(B,pAB->to);
- VectorXYZ_GridAlign(A,pSet->grid);
- VectorXYZ_GridAlign(B,pSet->grid);
- Segment_SetToFrom(pSet,pAB,A,B);
- }
- for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
- pAB = pLoop->pLinkNode;
- pNext = pLoop->pNext;
- count+=SegmentSet_Cleanup_Coincident(pSet,pAB);
- }
-
- if(looseend) {
- for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
- Link *pList;
- int nSeg;
- pAB = pLoop->pLinkNode;
- pNext = pLoop->pNext;
- pList = SegmentSet_Segments_AtVertex(pSet, pAB->from,&nSeg);
- if( nSeg < 2 ){
- pAB->test=1;
- match++;
- }
- pList = SegmentSet_Segments_AtVertex(pSet, pAB->to,&nSeg);
- if( nSeg < 2 ){
- pAB->test=1;
- match++;
- }
- }
- /* Cleanup overlapping walls */
- for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
- pAB = pLoop->pLinkNode;
- pNext = pLoop->pNext;
- if(pAB->test) continue;
- if(VectorXYZ_DistanceSq(pAB->from,pAB->to)<pSet->gridSq) {
- pAB->test=1;
- continue;
- }
- for(qLoop=pNext; qLoop; qLoop=qNext){
- pCD = qLoop->pLinkNode;
- qNext = qLoop->pNext;
- if(pCD->test) continue;
- if(VectorXYZ_SamePoint(pAB->from,pCD->from)) {
- if(VectorXYZ_SamePoint(pAB->to,pCD->to)) {
- if(pAB->isVirtual>pCD->isVirtual) {
- pAB->test=1;
- } else if(pAB->id>pCD->id) {
- pAB->test=1;
- } else {
- pCD->test=1;
- }
- continue;
- }
- }
- if(VectorXYZ_SamePoint(pAB->from,pCD->from)) {
- if(VectorXYZ_SamePoint(pAB->to,pCD->to)) {
- if(pAB->isVirtual>pCD->isVirtual) {
- pAB->test=1;
- } else if(pAB->id>pCD->id) {
- pAB->test=1;
- } else {
- pCD->test=1;
- }
- }
- }
- }
- }
- for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
- pAB = pLoop->pLinkNode;
- pNext = pLoop->pNext;
- if(pAB->test) {
- SegmentSetRemove(pSet,pAB);
- count++;
- }
- }
- }
- return count;
- }
- /* SegmentSet_Interference_Check */
- static int SegmentSet_Interference_Check(SegmentSet *pSet,VectorXYZ A,VectorXYZ B){
- Link *qLoop,*qNext;
- int onsegment=0;
- for(qLoop=pSet->pAll; qLoop; qLoop=qNext){
- int c;
- Segment *pTest;
- VectorXYZ ICEPT1,ICEPT2;
- qNext = qLoop->pNext;
- pTest = qLoop->pLinkNode;
- if((VectorXYZ_DistanceSq(A,pTest->from) < pSet->gridSq) && (VectorXYZ_DistanceSq(B,pTest->to) < pSet->gridSq)) return 3;
- if((VectorXYZ_DistanceSq(A,pTest->to) < pSet->gridSq) && (VectorXYZ_DistanceSq(B,pTest->from) < pSet->gridSq)) return 3;
- if(VectorXYZ_PointIsOnSegment(A,pTest->from,pTest->to)) {
- onsegment++;
- continue;
- }
- c=VectorXYZ_LineLineCoincident(A,B,pTest->from,pTest->to,ICEPT1,ICEPT2);
- if(c>0) {
- return c;
- }
- }
- /* If the ray did not touch any segment return a unique error code */
- if(onsegment==0) {
- return 16;
- }
- return 0;
- }
- /* SegmentSet_Edge_Connection */
- static int SegmentSet_Edge_Connection(SegmentSet *pSet,VectorXYZ A,int comptid,VectorXYZ RESULT){
- Link *pLoop,*pNext;
- Segment *pAB,*pBest=NULL;
- VectorXYZ ICEPT;
- double pBestDist=HUGE_VAL;
- for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
- double score;
- int interference;
- pAB = pLoop->pLinkNode;
- pNext = pLoop->pNext;
- if(comptid!=0 && pAB->idRC!=comptid && pAB->idLC!=comptid) {
- continue;
- }
- VectorXYZ_ClosestPointOnSegment(pAB->from,pAB->to,A,ICEPT);
- VectorXYZ_GridAlign(ICEPT,pSet->grid);
- score=VectorXYZ_DistanceSq(A,ICEPT);
- if(score<pSet->gridSq) continue;
- interference=SegmentSet_Interference_Check(pSet,A,ICEPT);
- if(interference>0) continue;
- if(!pBest || score<pBestDist) {
- pBest=pAB;
- pBestDist=score;
- VectorXYZ_Copy(RESULT,ICEPT);
- }
- }
- if(pBest) {
- return TCL_OK;
- }
- return TCL_ERROR;
- }
- /* Segment_Compute_UV */
- inline extern void Segment_Compute_UV(SegmentSet *pSet,Segment *pSeg,VectorXYZ uvfrom,VectorXYZ uvto){
- VectorXYZ_MatrixMultiply(uvfrom,pSeg->from,pSet->rotation);
- VectorXYZ_MatrixMultiply(uvto,pSeg->to,pSet->rotation);
- }
- /* SegmentSet_Convex_Connection */
- static int SegmentSet_Convex_Connection(SegmentSet *pSet,Segment *pAB,int back,VectorXYZ RESULT){
- Link *pLoop;
- Segment *pCD,*pBest=NULL;
- VectorXYZ A,B,AB,C,ICEPT,A_UV,B_UV,C_UV;
- double pBestAngle=4*M_PI;
- double pBestDist=HUGE_VAL;
- double angle,rangle,len;
- double rightangle=M_PI*0.5;
- int ortho=0,i;
-
- /* Try to ray cast the vector and find an intercept continuing along the line */
- if(back) {
- VectorXYZ_Copy(A,pAB->to);
- VectorXYZ_Copy(B,pAB->from);
- } else {
- VectorXYZ_Copy(A,pAB->from);
- VectorXYZ_Copy(B,pAB->to);
- }
- VectorXYZ_MatrixMultiply(A_UV,A,pSet->rotation);
- VectorXYZ_MatrixMultiply(B_UV,B,pSet->rotation);
- VectorXYZ_Subtract(AB,A_UV,B_UV);
- len=pSet->grid;
- angle=atan2(AB[Y_IDX],AB[X_IDX]);
- for(i=-1;i<1;i++) {
- rangle=angle+(M_PI*0.5*i);
- rangle-=fmod(rangle,M_PI*0.5);
- C_UV[X_IDX]=A_UV[X_IDX]+cos(rangle)*len;
- C_UV[Y_IDX]=A_UV[Y_IDX]+sin(rangle)*len;
- C_UV[Z_IDX]=A_UV[Z_IDX];
- VectorXYZ_MatrixMultiply(C,C_UV,pSet->rotation_inv);
- for(pLoop=pSet->pAll; pLoop; pLoop=pLoop->pNext){
- double x,y;
- int c;
- VectorXYZ ICEPT1,ICEPT2;
- pCD = pLoop->pLinkNode;
- if(pCD->ignore) continue;
- if(pCD==pAB) continue;
- if(VectorXYZ_SamePoint(pAB->from,pCD->from)) continue;
- if(VectorXYZ_SamePoint(pAB->from,pCD->to)) continue;
- if(VectorXYZ_SamePoint(pAB->to,pCD->from)) continue;
- if(VectorXYZ_SamePoint(pAB->to,pCD->to)) continue;
- c=VectorXYZ_LineLineIntersect(A,C,pCD->from,pCD->to,ICEPT1,ICEPT2,&x,&y);
- if(c>0) {
- int interference;
- double score;
- if(!VectorXYZ_PointIsOnSegment(ICEPT1,pCD->from,pCD->to)) {
- interference=16;
- } else {
- interference=SegmentSet_Interference_Check(pSet,A,ICEPT1);
- }
- if(interference<=0) {
- if(fabs(angle-rangle)<pBestAngle) {
- score=VectorXYZ_Distance(A,ICEPT1);
- if(score>(pSet->grid*10) && (!pBest || score<pBestDist)) {
- pBest=pCD;
- pBestDist=score;
- VectorXYZ_Copy(RESULT,ICEPT1);
- pBestAngle=rangle;
- }
- }
- }
- if(!VectorXYZ_PointIsOnSegment(ICEPT2,pCD->from,pCD->to)) {
- interference=16;
- } else {
- interference=SegmentSet_Interference_Check(pSet,A,ICEPT2);
- }
- if(interference<=0) {
- if(fabs(angle-rangle)<pBestAngle) {
- score=VectorXYZ_DistanceSq(A,ICEPT2);
- if(score>(pSet->grid*10) && (!pBest || score<pBestDist)) {
- pBest=pCD;
- pBestDist=score;
- VectorXYZ_Copy(RESULT,ICEPT2);
- pBestAngle=rangle;
- }
- }
- }
- }
- }
- }
- if(pBest) {
- return TCL_OK;
- }
- return TCL_ERROR;
- }
- /* SegmentSetNextBend */
- static int SegmentSetNextBend(
- SegmentSet *pSet,
- Segment *pAB,
- int backwards,
- Segment **ppSeg, /* OUT: First segment clockwise from xR,yR->xV,yV */
- int *pfBack, /* OUT: True if output segment goes backwards */
- int *pfBend, /* OUT: Bend direction */
- double *pfAngle
- ){
- Segment *pSegThis;
- int thisBack,thisBend;
- double thisAngle;
- pSegThis=pAB;
- thisBack=backwards;
- thisBend=0;
- while(thisBend==0) {
- if(SegmentSetNext(pSet, pSegThis, thisBack,ppSeg,pfBack,pfBend,pfAngle)) {
- return TCL_ERROR;
- }
- thisBack=*pfBack;
- thisBend=*pfBend;
- if(thisBend==0) {
- pSegThis->isBoundary=1;
- }
- pSegThis=*ppSeg;
- }
- return TCL_OK;
- }
- /* SegmentSet_SelfCheck */
- static int SegmentSet_SelfCheck(Tcl_Interp *interp, SegmentSet *p){
- Link *pLink;
- Segment *pSeg;
- int h;
- char zErr[200];
-
- for(pLink=p->pAll; pLink; pLink=pLink->pNext){
- pSeg = pLink->pLinkNode;
- h = hashInt(pSeg->id);
- if(!Segment_OnList(pSeg, p->hashId[h]) ){
- sprintf(zErr, "segment %d missing from hashId[%d]", pSeg->id, h);
- Tcl_SetResult(interp, zErr, TCL_VOLATILE);
- return TCL_ERROR;
- }
- h = hashCoord(pSeg->from[X_IDX], pSeg->from[Y_IDX]);
- if(!Segment_OnList(pSeg, p->hashFrom[h]) ){
- sprintf(zErr, "segment %d missing from hashFrom[%d]", pSeg->id, h);
- Tcl_SetResult(interp, zErr, TCL_VOLATILE);
- return TCL_ERROR;
- }
- h = hashCoord(pSeg->to[X_IDX], pSeg->to[Y_IDX]);
- if(!Segment_OnList(pSeg, p->hashTo[h]) ){
- sprintf(zErr, "segment %d missing from hashTo[%d]", pSeg->id, h);
- Tcl_SetResult(interp, zErr, TCL_VOLATILE);
- return TCL_ERROR;
- }
- }
- return TCL_OK;
- }
- /* *SegmentSet_Segments_AtVertex */
- static Link *SegmentSet_Segments_AtVertex(SegmentSet *p, VectorXYZ point,int *nSeg){
- Link *pList = 0;
- Link *pI;
- int h,count=0;
- VectorXYZ_GridAlign(point,p->grid);
- h = hashVectorXYZ(point);
- for(pI=p->hashFrom[h]; pI; pI=pI->pNext){
- Segment *pSeg = pI->pLinkNode;
- if( pSeg->ignore_fwd ) continue;
- if(VectorXYZ_SamePoint(point,pSeg->from)) {
- //assert( !segmentOnList(pSeg, pList) );
- count++;
- LinkInit(pSeg->pSet, pSeg);
- LinkInsert(&pList, &pSeg->pSet);
- }
- }
- for(pI=p->hashTo[h]; pI; pI=pI->pNext){
- Segment *pSeg = pI->pLinkNode;
- if( pSeg->ignore_back ) continue;
- if(VectorXYZ_SamePoint(point,pSeg->to)) {
- //assert( !segmentOnList(pSeg, pList) );
- count++;
- LinkInit(pSeg->pSet, pSeg);
- LinkInsert(&pList, &pSeg->pSet);
- }
- }
- *nSeg=count;
- return pList;
- }
- /* SegmentSetNext */
- static int SegmentSetNext(
- SegmentSet *pSet,
- Segment *pAB,
- int backwards,
- Segment **ppSeg, /* OUT: First segment clockwise from xR,yR->xV,yV */
- int *pfBack, /* OUT: True if output segment goes backwards */
- int *pfBend, /* OUT: Bend direction */
- double *pfAngle
- ){
- VectorXYZ remote,vertex,remote_uv,vertex_uv;
- Link *pI,*vList;
- int i,best=-1;
- int nSeg=0;
- struct {
- Segment *pSeg;
- int isBack;
- double angle;
- int bend;
- int edge;
- VectorXYZ uv_remote;
- } *aSeg, aSegStatic[20];
-
- /*
- pAB->ignore_fwd=1;
- pAB->ignore_back=1;
- */
- if(backwards) {
- VectorXYZ_Copy(remote,pAB->to);
- VectorXYZ_Copy(vertex,pAB->from);
- } else {
- VectorXYZ_Copy(remote,pAB->from);
- VectorXYZ_Copy(vertex,pAB->to);
- }
- VectorXYZ_MatrixMultiply(remote_uv,remote,pSet->rotation);
- VectorXYZ_MatrixMultiply(vertex_uv,vertex,pSet->rotation);
- vList=SegmentSet_Segments_AtVertex(pSet,vertex,&nSeg);
- if(nSeg==0) {
- *ppSeg=NULL;
- *pfBack=0;
- *pfBend=2;
- *pfAngle=2*M_PI;
- return TCL_ERROR;
- }
- if( nSeg<=sizeof(aSegStatic)/sizeof(aSegStatic[0]) ){
- aSeg = aSegStatic;
- }else{
- aSeg = (void *)Odie_Alloc( nSeg*sizeof(*aSeg) );
- }
- for(pI=vList, i=0; pI; i++, pI=pI->pNext){
- Segment *pSeg;
- aSeg[i].pSeg = pSeg = pI->pLinkNode;
- if( VectorXYZ_SamePoint(pSeg->from,vertex)) {
- aSeg[i].isBack = 0;
- aSeg[i].edge=pSeg->isVirtual||(pSeg->idRC>0);
- VectorXYZ_MatrixMultiply(aSeg[i].uv_remote,pSeg->to,pSet->rotation);
- } else {
- aSeg[i].isBack = 1;
- aSeg[i].edge=pSeg->isVirtual||(pSeg->idLC>0);
- VectorXYZ_MatrixMultiply(aSeg[i].uv_remote,pSeg->from,pSet->rotation);
- }
- if(VectorXYZ_SamePoint(aSeg[i].uv_remote,remote)) {
- aSeg[i].angle = 2*M_PI;
- aSeg[i].bend = -2;
- } else {
- aSeg[i].angle = VectorXY_Angle_Three_Point(remote_uv, vertex_uv, aSeg[i].uv_remote);
- aSeg[i].bend = VectorXY_BendDirection(remote_uv, vertex_uv, aSeg[i].uv_remote);
- }
- }
- best=0;
- for(i=1;i<nSeg;i++) {
- if(aSeg[i].angle<aSeg[best].angle) {
- best=i;
- }
- }
- *ppSeg=aSeg[best].pSeg;
- *pfBack=aSeg[best].isBack;
- *pfBend=aSeg[best].bend;
- *pfAngle=aSeg[best].angle;
- if( aSeg!=aSegStatic ){
- Tcl_Free((char *) aSeg );
- }
- return TCL_OK;
- }
- /* SegmentSet_ClearFaceEdgeCache */
- static void SegmentSet_ClearFaceEdgeCache(SegmentSet *pSet){
- if(!pSet->aBoundary) return;
- Odie_Free(pSet->aBoundary);
- pSet->aBoundary=NULL;
- pSet->modified=0;
- }
- /* FaceBoundary_Mark_Degenerate */
- static void FaceBoundary_Mark_Degenerate(FaceBoundary *pFace,int code){
- FaceBoundary *qFace,*pFaceNext;
- for(qFace=pFace;qFace;qFace=pFaceNext) {
- pFaceNext=qFace->pNext;
- qFace->pNext=NULL;
- qFace->isloop=0;
- qFace->faceid=qFace->id;
- }
- pFace->faceid=pFace->id;
- pFace->nSeg=1;
- pFace->isloop=code;
- pFace->pNext=NULL;
- }
- /* SegmentSet_BuildFaceEdgeCache_ExpandRight */
- static int SegmentSet_BuildFaceEdgeCache_ExpandRight(SegmentSet *pSet,int faceid,int stage){
- FaceBoundary *sFace;
- FaceBoundary *pFace;
- FaceBoundary *oFace=NULL;
- Link *pLoop;
- VectorXYZ start;
- Segment *pSeg,*pAB,*pBC;
- int pbcback,pbcbend,idx;
- double pbcangle;
-
- sFace=pFace=&pSet->aBoundary[faceid];
- /*
- ** If this boundary is part of a loop, or the end of a loop continue
- */
- if(sFace->pNext || sFace->isloop>0) {
- return 0;
- }
- /*
- ** Don't expand the backface of real walls until stage 2
- */
- if(stage<1 && !sFace->pSeg->isVirtual) {
- if(sFace->outside_edge) return 0;
- }
-
- /*
- ** Detect degenerate loops if they wrap back to a different point
- ** than our starting point. Reset the flag we use to detect that.
- */
- for(idx=0;idx<(pSet->nSeg*2);idx++) {
- pSet->aBoundary[idx].parsed=0;
- pSet->aBoundary[idx].pSeg->ignore=0;
- pSet->aBoundary[idx].pSeg->ignore_fwd=0;
- pSet->aBoundary[idx].pSeg->ignore_back=0;
- pSet->aBoundary[idx].angle=0;
- }
- sFace->nSeg=1;
- sFace->facebend=0;
-
- pSeg=pAB=sFace->pSeg;
- if(pFace->backwards) {
- VectorXYZ_Copy(start,pSeg->to);
- } else {
- VectorXYZ_Copy(start,pSeg->from);
- }
- while(pAB) {
- int atstart=0;
- if(SegmentSetNext(pSet,pAB,pFace->backwards,&pBC,&pbcback,&pbcbend,&pbcangle)) {
- /*
- ** If this case occurs, we reached the end of the line without
- ** returning to the start. Mark this section as degenerate
- */
- FaceBoundary_Mark_Degenerate(sFace,3);
- return 1;
- }
- if(!pBC) {
- FaceBoundary_Mark_Degenerate(sFace,4);
- return 1;
- }
- /*
- ** If we have returned to the start mark the beginning and end
- ** of the loop
- */
- if(pbcback) {
- oFace=pBC->boundback;
- atstart=VectorXYZ_SamePoint(start,pBC->to);
- } else {
- oFace=pBC->boundfwd;
- atstart=VectorXYZ_SamePoint(start,pBC->from);
- }
- if(oFace==sFace || atstart) {
- sFace->isloop=1;
- sFace->nSeg++;
- if(sFace->nSeg<3) {
- FaceBoundary_Mark_Degenerate(sFace,0);
- } else {
- pFace->faceid=faceid;
- pFace->pNext=oFace;
- pFace->isloop=2;
- }
- return 1;
- }
- if(oFace->parsed) {
- /*
- ** This loop has encountered a knot
- */
- FaceBoundary_Mark_Degenerate(sFace,0);
- return 1;
- }
- if(oFace->faceid!=oFace->id) {
- /*
- ** This loop has bumped up against a different loop
- ** Try to find another vertex
- */
- if(stage<2) {
- FaceBoundary_Mark_Degenerate(sFace,0);
- return 1;
- } else {
- if(oFace->backwards) {
- oFace->pSeg->ignore_back=1;
- } else {
- oFace->pSeg->ignore_fwd=1;
- }
- continue;
- }
- }
- if(VectorXYZ_SamePoint(pAB->from,pBC->to)) {
- if(VectorXYZ_SamePoint(pBC->from,pAB->to)) {
- if(oFace->backwards) {
- oFace->pSeg->ignore_back=1;
- } else {
- oFace->pSeg->ignore_fwd=1;
- }
- continue;
- }
- }
- sFace->facebend+=pbcbend;
- oFace->parsed=1;
-
- /*
- ** Add this segment to the end of the list and
- ** mark the segment as part of the same face
- */
- pFace->faceid=faceid;
- pFace->pNext=oFace;
- oFace->faceid=faceid;
- oFace->bend=pbcbend;
- oFace->angle=pbcangle;
- sFace->nSeg++;
- pAB=pBC;
- pFace=oFace;
- }
- return 1;
- }
- /* SegmentSet_BuildFaceEdgeCache */
- static void SegmentSet_BuildFaceEdgeCache(SegmentSet *pSet){
- Link *pLoop;
- int nBound=0;
- int i,changes=0,count=0;
- size_t asize;
- if(pSet->modified) {
- SegmentSet_ClearFaceEdgeCache(pSet);
- SegmentSet_Cleanup(pSet,0);
- } else {
- /* Return immediately if the cache already exists */
- if(pSet->aBoundary) {
- return;
- }
- }
- nBound=(pSet->nSeg*2);
- asize=sizeof(FaceBoundary)*nBound;
- pSet->aBoundary=(FaceBoundary *)Odie_Alloc(asize);
- i=nBound=0;
- for(pLoop=pSet->pAll; pLoop; pLoop=pLoop->pNext){
- Segment *pSeg=pLoop->pLinkNode;
- if(!pSeg->idRC && !pSeg->idLC) {
- pSeg->isVirtual=1;
- }
- pSeg->ignore_fwd=0;
- pSeg->ignore_back=0;
-
-
- pSeg->boundfwd=&pSet->aBoundary[i];
- pSet->aBoundary[i].id=i;
- pSet->aBoundary[i].pSeg=pSeg;
- pSet->aBoundary[i].nSeg=0;
- pSet->aBoundary[i].backwards=0;
- pSet->aBoundary[i].isloop=0;
- pSet->aBoundary[i].facebend=0;
- pSet->aBoundary[i].pNext=NULL;
- pSet->aBoundary[i].bend=2;
- if(pSeg->idLC<0) {
- pSet->aBoundary[i].inside_edge=0;
- pSet->aBoundary[i].outside_edge=1;
- } else {
- if(pSeg->idLC>0) {
- pSet->aBoundary[i].inside_edge=1;
- pSet->aBoundary[i].outside_edge=0;
- } else if(pSeg->idRC>0) {
- pSet->aBoundary[i].inside_edge=0;
- pSet->aBoundary[i].outside_edge=1;
- }
- }
- i++;
- pSeg->boundback=&pSet->aBoundary[i];
- pSet->aBoundary[i].id=i;
- pSet->aBoundary[i].pSeg=pSeg;
- pSet->aBoundary[i].nSeg=0;
- pSet->aBoundary[i].backwards=1;
- pSet->aBoundary[i].isloop=0;
- pSet->aBoundary[i].facebend=0;
- pSet->aBoundary[i].pNext=NULL;
- pSet->aBoundary[i].bend=2;
- if(pSeg->idRC<0) {
- pSet->aBoundary[i].inside_edge=0;
- pSet->aBoundary[i].outside_edge=1;
- } else {
- if(pSeg->idRC>0) {
- pSet->aBoundary[i].inside_edge=1;
- pSet->aBoundary[i].outside_edge=0;
- } else if(pSeg->idLC>0) {
- pSet->aBoundary[i].inside_edge=0;
- pSet->aBoundary[i].outside_edge=1;
- }
- }
- i++;
- }
-
- nBound=i;
- /* Incubation stage. Let the clear cut winners take shape */
- changes=0;
- /* On the first pass ignore backfaces for "real" panels */
- for(count=0;count<nBound;count++) {
- if(count>0 && changes==0) {
- break;
- }
- changes=0;
- for(i=0;i<nBound;i++) {
- changes+=SegmentSet_BuildFaceEdgeCache_ExpandRight(pSet,i,0);
- }
- }
- /* On the second pass include backfaces for real panels */
- for(count=0;count<nBound;count++) {
- if(count>0 && changes==0) {
- break;
- }
- changes=0;
- for(i=0;i<nBound;i++) {
- changes+=SegmentSet_BuildFaceEdgeCache_ExpandRight(pSet,i,1);
- }
- }
- /* On the second pass include backfaces for real panels */
- for(count=0;count<nBound;count++) {
- if(count>0 && changes==0) {
- break;
- }
- changes=0;
- for(i=0;i<nBound;i++) {
- changes+=SegmentSet_BuildFaceEdgeCache_ExpandRight(pSet,i,2);
- }
- }
- }
- /*
- ** This widget translates 3-D coordinates onto a flat canvas by splitting
- ** the 3-D space into layers and stacking the layers on the canvas.
- **
- ** The layers are decks of the ship. The highest layer (or deck) is drawn
- ** at the top of the page. The next layer down is drawn below the top layer.
- ** and so forth down the canvas. In other words, the 3D object is drawn
- ** by showing a set of 2D slices where each slice is viewed from above.
- **
- ** The original 3D coordinates are called "actual" coordinates. When
- ** translated into the 2D canvas they are called "canvas" coordinates.
- **
- ** The actual coordinate system is right-handed. The X axis increases to
- ** the right. The Y axis increases going up. The Z axis comes out of the
- ** page at the viewer. The canvas coordinate system is left-handed. The
- ** X axis increase to the right but the Y axis increases going down.
- **
- ** A plotter is a object with methods. The details of the available
- ** methods and what each does are described in comments before the
- ** implementation of each method.
- */
- /* Plotter_Delete */
- static void Plotter_Delete(ClientData clientData){
- /*
- ** This routine is called when a plotter is deleted. All the memory and
- ** other resources allocated by this plotter is recovered.
- */
- Plotter *p = (Plotter*)clientData;
- Odie_Free((char *)p);
- }
- /* Plotter_Clone */
- static int Plotter_Clone(
- Tcl_Interp* interp, /* Tcl interpreter for error reporting */
- ClientData metadata, /* Metadata to be cloned */
- ClientData* newMetaData /* Where to put the cloned metadata */
- ){
- Tcl_SetObjResult(interp,
- Tcl_NewStringObj("PLOTTERs are not clonable", -1));
- /* For now... */
- return TCL_ERROR;
- }
- /* Plotter_xCanvasToActual */
- static inline double Plotter_xCanvasToActual(Plotter *p,double cx){
- return (cx+p->rXOffset)*p->rZoom;
- }
- /* Plotter_yCanvasToActual */
- static inline double Plotter_yCanvasToActual(Plotter *p,double cy){
- return -1.0*(cy+p->rYOffset)*p->rZoom;
- }
- /* Plotter_xActualToCanvas */
- static inline double Plotter_xActualToCanvas(Plotter *p,double ax){
- /*
- ** Convert a Y coordinate from actual to canvas coordinates for a
- ** given deck.
- */
- return (ax/p->rZoom)-p->rXOffset;
- }
- /* Plotter_yActualToCanvas */
- static inline double Plotter_yActualToCanvas(Plotter *p,double ay){
- /*
- ** Convert a Y coordinate from actual to canvas coordinates for a
- ** given deck.
- */
- return -1.0*(ay/p->rZoom)-p->rYOffset;
- }
- /*
- ** This widget translates 3-D coordinates onto a flat canvas by splitting
- ** the 3-D space into layers and stacking the layers on the canvas.
- **
- ** The layers are decks of the ship. The highest layer (or deck) is drawn
- ** at the top of the page. The next layer down is drawn below the top layer.
- ** and so forth down the canvas. In other words, the 3D object is drawn
- ** by showing a set of 2D slices where each slice is viewed from above.
- **
- ** The original 3D coordinates are called "actual" coordinates. When
- ** translated into the 2D canvas they are called "canvas" coordinates.
- **
- ** The actual coordinate system is right-handed. The X axis increases to
- ** the right. The Y axis increases going up. The Z axis comes out of the
- ** page at the viewer. The canvas coordinate system is left-handed. The
- ** X axis increase to the right but the Y axis increases going down.
- **
- ** A slicer is a object with methods. The details of the available
- ** methods and what each does are described in comments before the
- ** implementation of each method.
- */
- /* Slicer_Delete */
- static void Slicer_Delete(ClientData clientData){
- /*
- ** This routine is called when a slicer is deleted. All the memory and
- ** other resources allocated by this slicer is recovered.
- */
- Slicer *p = (Slicer*)clientData;
- int i;
- for(i=0; i<p->nSlice; i++){
- Odie_Free((char *)p->a[i].zName);
- Odie_Free((char *)p->a[i].xz);
- }
- Odie_Free((char *)p->a);
- Odie_Free((char *)p);
- }
- /* Slicer_Clone */
- static int Slicer_Clone(
- Tcl_Interp* interp, /* Tcl interpreter for error reporting */
- ClientData metadata, /* Metadata to be cloned */
- ClientData* newMetaData /* Where to put the cloned metadata */
- ){
- Tcl_SetObjResult(interp,
- Tcl_NewStringObj("SLICERs are not clonable", -1));
- /* For now... */
- return TCL_ERROR;
- }
- /* Slicer_xCanvasToActual */
- static double Slicer_xCanvasToActual(Slicer *p,struct OneSlice *pS, double cx){
- double ax;
- if(p->nSlice==1) {
- ax = cx*p->rZoom;
- } else {
- ax = cx*p->rZoom - pS->rXShift;
- }
- return ax;
- }
- /* Slicer_yCanvasToActual */
- static double Slicer_yCanvasToActual(Slicer *p,struct OneSlice *pS, double cy){
- double ay;
- if(p->nSlice==1) {
- ay=-cy*p->rZoom;
- } else {
- ay = pS->mxY + (pS->mnY-pS->mxY)*(cy-pS->top)/(pS->btm-pS->top);
- }
- return ay;
- }
- /* Slicer_xActualToCanvas */
- static double Slicer_xActualToCanvas(Slicer *p,struct OneSlice *pS, double ax){
- /*
- ** Convert a X coordinate from actual to canvas coordinates for a
- ** given deck.
- */
- double cx;
- if(p->nSlice==1) {
- cx = ax/p->rZoom;
- } else {
- cx = (ax+pS->rXShift)/p->rZoom;
- }
- return cx;
- }
- /* Slicer_yActualToCanvas */
- static double Slicer_yActualToCanvas(Slicer *p,struct OneSlice *pS, double ay){
- /*
- ** Convert a Y coordinate from actual to canvas coordinates for a
- ** given deck.
- */
- double cy;
- if(p->nSlice==1) {
- cy=-ay/p->rZoom;
- } else {
- cy = pS->top + (pS->btm-pS->top)*(ay-pS->mxY)/(pS->mnY-pS->mxY);
- }
- return cy;
- }
- /* Slicer_deckHeight */
- static double Slicer_deckHeight(struct OneSlice *p, double rX){
- /*
- ** Return the height above baseline for the deck location rX.
- */
- int i;
- double *xz;
- if(!p) {
- return 0.0;
- }
- if( p->nXZ<4 ){
- return p->z;
- }
- xz = p->xz;
- if( rX<=xz[0] ){
- return xz[1];
- }
- for(i=2; i<p->nXZ; i+=2){
- if( rX<=xz[i] ){
- assert( xz[i]>xz[i-2] );
- return xz[i-1] + (xz[i+1]-xz[i-1])*(rX-xz[i-2])/(xz[i]-xz[i-2]);
- }
- }
- return xz[p->nXZ-1];
- }
- /* *Slicer_deckAt */
- static struct OneSlice *Slicer_deckAt(Slicer *p, double rX, double rZ){
- /*
- ** Return a pointer to the particular deck at actual coordinates
- ** X, Z
- */
- int i;
- struct OneSlice *pBest;
- double bestHeight;
- if( p->nSlice==0 ) return 0;
- pBest = &p->a[0];
- bestHeight = Slicer_deckHeight(pBest, rX);
- for(i=1; i<p->nSlice; i++){
- double dh = Slicer_deckHeight(&p->a[i],rX);
- if( dh>bestHeight && dh<=rZ ){
- pBest = &p->a[i];
- bestHeight = dh;
- }
- }
- return pBest;
- }
- /* *Slicer_deckAbove */
- static struct OneSlice *Slicer_deckAbove(Slicer *p, struct OneSlice *pRef){
- /*
- ** Return a pointer to the deck immediately above the given deck.
- ** Return NULL if the given deck is topmost.
- */
- int i;
- struct OneSlice *pBest = 0;
- if( p->nSlice==0 ) return 0;
- for(i=0; i<p->nSlice; i++){
- struct OneSlice *pTest = &p->a[i];
- if( pTest->z<=pRef->z ) continue;
- if( pBest==0 || pBest->z>pTest->z ){
- pBest = pTest;
- }
- }
- return pBest;
- }
- /* *Slicer_deckBelow */
- static struct OneSlice *Slicer_deckBelow(Slicer *p, struct OneSlice *pRef){
- /*
- ** Return a pointer to the deck immediately above the given deck.
- ** Return NULL if the given deck is topmost.
- */
- int i;
- struct OneSlice *pBest = 0;
- if( p->nSlice==0 ) return 0;
- for(i=0; i<p->nSlice; i++){
- struct OneSlice *pTest = &p->a[i];
- if( pTest->z>=pRef->z ) continue;
- if( pBest==0 || pBest->z<pTest->z ){
- pBest = pTest;
- }
- }
- return pBest;
- }
- /* Slicer_computeTopAndBottom */
- static void Slicer_computeTopAndBottom(Slicer *p){
- /*
- ** Recompute the values of p->a[].top and p->a[].btm for all slices in
- ** the given slicer.
- */
- int i;
- double rY = 0.0;
- double rBound = -9.9e99;
- for(i=p->nSlice-1; i>=0; i--){
- double h = (p->a[i].mxY - p->a[i].mnY)/p->rZoom;
- p->a[i].upperbound = rBound;
- p->a[i].top = rY;
- p->a[i].btm = rY + h;
- rY = p->a[i].btm + 0.3*h;
- rBound = p->a[i].btm + 0.15*h;
- }
-
- if( p->nSlice==0 ) return;
-
- /* Calculate the above and below for each deck */
-
- for(i=0; i<p->nSlice; i++){
- struct OneSlice *pThis = &p->a[i];
- struct OneSlice *pBest = 0;
-
- pBest=Slicer_deckAbove(p,pThis);
- if(pBest) {
- pThis->above=pBest->did;
- } else {
- pThis->above=0;
- }
- pBest=Slicer_deckBelow(p,pThis);
- if(pBest) {
- pThis->below=pBest->did;
- } else {
- pThis->below=0;
- }
- }
- }
- /* Slicer_getDeck */
- static int Slicer_getDeck(
- Tcl_Interp *interp, /* Put error messages here */
- Slicer *p, /* The slicer */
- double rX, /* X coord used to find deck if pObj is a Z coord */
- Tcl_Obj *pObj, /* Either a deck name or a Z coordinate */
- struct OneSlice **ppS /* Write the slice pointer here */
- ){
- /*
- ** pObj is either the name of a deck or a Z coordinate. If it is a
- ** deck name, find the deck and write a pointer to it in *ppS. If
- ** it is a Z coordinate, use that coordinate together with rX to
- ** find the deck and write it into *ppS. If an error occurs, put
- ** an error message on the TCL interpreter and return TCL_ERROR.
- ** Return TCL_OK on success.
- */
- double rZ;
- const char *zName;
- int i;
- if(p->nSlice==1) {
- *ppS=&p->a[0];
- return TCL_OK;
- }
- if( Tcl_GetDoubleFromObj(0, pObj, &rZ)==TCL_OK ){
- *ppS = Slicer_deckAt(p, rX, rZ);
- return TCL_OK;
- }
- zName = Tcl_GetStringFromObj(pObj, 0);
- for(i=0; i<p->nSlice; i++){
- if( strcmp(zName, p->a[i].zName)==0 ){
- *ppS = &p->a[i];
- return TCL_OK;
- }
- }
- Tcl_AppendResult(interp, "no such deck: ", zName, 0);
- return TCL_ERROR;
- }
- /* Slicer_getDeckId */
- static int Slicer_getDeckId(
- Tcl_Interp *interp, /* Put error messages here */
- Slicer *p, /* The slicer */
- Tcl_Obj *pObj, /* Either a deck name or a Z coordinate */
- struct OneSlice **ppS /* Write the slice pointer here */
- ){
- /*
- ** pObj is either the name of a deck or a Z coordinate. If it is a
- ** deck name, find the deck and write a pointer to it in *ppS. If
- ** it is a Z coordinate, use that coordinate together with rX to
- ** find the deck and write it into *ppS. If an error occurs, put
- ** an error message on the TCL interpreter and return TCL_ERROR.
- ** Return TCL_OK on success.
- */
- int did;
- const char *zName;
- int i;
- if(p->nSlice==1) {
- *ppS=&p->a[0];
- return TCL_OK;
- }
- if( Tcl_GetIntFromObj(interp, pObj, &did)==TCL_OK ){
- for(i=0; i<p->nSlice; i++){
- if( did == p->a[i].did ){
- *ppS = &p->a[i];
- return TCL_OK;
- }
- }
- Tcl_AppendResult(interp, "no such deckid: ", 0);
- return TCL_ERROR;
- }
- zName = Tcl_GetStringFromObj(pObj, 0);
- for(i=0; i<p->nSlice; i++){
- if( strcmp(zName, p->a[i].zName)==0 ){
- *ppS = &p->a[i];
- return TCL_OK;
- }
- }
- Tcl_AppendResult(interp, "no such deck: ", zName, 0);
- return TCL_ERROR;
- }
- /* *Slicer_GetSlicerFromObj */
- Slicer *Slicer_GetSlicerFromObj(Tcl_Interp *interp,Tcl_Obj *tclobj){
- Tcl_Object pObj;
- Slicer *pSlicer=NULL;
- pObj=Tcl_GetObjectFromObj(interp,tclobj);
- if(!pObj) {
- return NULL;
- }
- pSlicer=(Slicer *)Tcl_ObjectGetMetadata(pObj,&SlicerDataType);
- return pSlicer;
- }
- /* *Slicer_getDeck_FromInt */
- static inline struct OneSlice *Slicer_getDeck_FromInt(
- Slicer *p,
- int did
- ){
- int i;
- if(p->nSlice==1) {
- return &p->a[0];
- }
- for(i=0; i<p->nSlice; i++){
- if( did == p->a[i].did ){
- return &p->a[i];
- }
- }
- return NULL;
- }
- /* slicer_drawline_do */
- static int slicer_drawline_do(
- Tcl_Interp *interp,
- Slicer *p,
- int coord_count,
- int *deckCoord,double *xCoord,double *yCoord,
- struct OneSlice **apDeck,
- Tcl_Obj *canvas,
- const char *zKTag,
- const char *zXTag,
- const char *zBTag
- ){
- int i;
-
- Tcl_Obj *pVTag; /* The "sNNN" tag added to all line segments */
-
- Tcl_Obj *aLineArg[20]; /* Element of "create line" TCL command */
- int nLineArg; /* Number of used entries in aLineArg[] */
- Tcl_Obj *aBendArg[20]; /* Cmd to bends penetractions */
- int nBendArg;
-
- nBendArg = 0;
- if(zBTag) {
- aBendArg[0] = canvas;
- aBendArg[1] = ODIE_CONSTANT_STRING("create");
- aBendArg[2] = ODIE_CONSTANT_STRING("oval");
- for(i=3; i<=6; i++){
- aBendArg[i] = Tcl_NewObj();
- }
- aBendArg[7] = ODIE_CONSTANT_STRING("-tags");
- for(i=0; i<=7; i++){
- Tcl_IncrRefCount(aBendArg[i]);
- }
- nBendArg = 9;
- }
- aLineArg[0] = canvas;
- aLineArg[1] = ODIE_CONSTANT_STRING("create");
- aLineArg[2] = ODIE_CONSTANT_STRING("line");
- for(i=3; i<=6; i++){
- aLineArg[i] = Tcl_NewObj();
- }
- aLineArg[7] = ODIE_CONSTANT_STRING("-tags");
- for(i=0; i<=7; i++){
- Tcl_IncrRefCount(aLineArg[i]);
- }
- nLineArg = 9;
-
-
-
- for(i=1; i<coord_count; i++){
- char zBuf[30];
- double x0, y0, x1, y1;
-
- x0 = Slicer_xActualToCanvas(p,apDeck[i-1],xCoord[i-1]);
- x1 = Slicer_xActualToCanvas(p,apDeck[i],xCoord[i]);
- y0 = Slicer_yActualToCanvas(p,apDeck[i-1],yCoord[i-1]);
- y1 = Slicer_yActualToCanvas(p,apDeck[i], yCoord[i]);
- Tcl_SetDoubleObj(aLineArg[3], x0);
- Tcl_SetDoubleObj(aLineArg[4], y0);
- Tcl_SetDoubleObj(aLineArg[5], x1);
- Tcl_SetDoubleObj(aLineArg[6], y1);
- if( apDeck[i]!=apDeck[i-1] && zXTag ){
- sprintf(zBuf, "%s s%d", zXTag, i);
- } else {
- sprintf(zBuf, "%s s%d", zKTag, i);
- }
- pVTag = Tcl_NewStringObj(zBuf, -1);
- Tcl_IncrRefCount(pVTag);
- aLineArg[8]=pVTag;
-
- if(i<(coord_count-1) && nBendArg) {
- char bBuf[30];
- Tcl_Obj *pBTag; /* The "nNNN" tag added to all line bend points */
- sprintf(bBuf, "%s b%d", zBTag, i);
- pBTag = Tcl_NewStringObj(bBuf, -1);
- Tcl_IncrRefCount(pVTag);
- Tcl_SetDoubleObj(aBendArg[3], x1-4);
- Tcl_SetDoubleObj(aBendArg[4], y1-4);
- Tcl_SetDoubleObj(aBendArg[5], x1+4);
- Tcl_SetDoubleObj(aBendArg[6], y1+4);
- aBendArg[8] = pBTag;
- Tcl_EvalObjv(interp, nBendArg, aBendArg, 0);
- }
- Tcl_EvalObjv(interp, nLineArg, aLineArg, 0);
- }
- for(i=0; i<=7; i++){
- Tcl_DecrRefCount(aLineArg[i]);
- if( i<nBendArg ) Tcl_DecrRefCount(aBendArg[i]);
- }
- for(i=9; i<nLineArg; i++){
- Tcl_DecrRefCount(aLineArg[i]);
- }
- for(i=9; i<nBendArg; i++){
- Tcl_DecrRefCount(aBendArg[i]);
- }
- return TCL_OK;
- }
- /* Slicer_Location_zabs */
- static inline double Slicer_Location_zabs(Slicer *p,struct OneSlice *pS,double x0,double dheight){
- struct OneSlice *pAbove;
- if(dheight >= 0) {
- return dheight+Slicer_deckHeight(pS,x0);
- }
- pAbove=Slicer_deckAbove(p,pS);
- if(pAbove) {
- return Slicer_deckHeight(pAbove,x0)+dheight;
- }
- return Slicer_deckHeight(pS,x0)+p->upper_height+dheight;
- }
- /* Location_zdeck */
- static inline double Location_zdeck(Slicer *p,struct OneSlice *pS,double x0,double dheight){
- struct OneSlice *pAbove;
- if(dheight >= 0) {
- return dheight;
- }
- pAbove=Slicer_deckAbove(p,pS);
- if(pAbove) {
- return Slicer_deckHeight(pAbove,x0)-Slicer_deckHeight(pS,x0)+dheight;
- }
- return p->upper_height+dheight;
- }
- /* Slicer_Find_Deckid_And_Offset */
- int Slicer_Find_Deckid_And_Offset(Slicer *pSlicer,double x0,double y0,double z0,int *deckid,double *zoff){
- struct OneSlice *ppS,*pAbove;
- double zdeck;
- *zoff=0.0;
- *deckid=0;
- if(!pSlicer) {
- return TCL_ERROR;
- }
- ppS=Slicer_deckAt(pSlicer,x0,z0);
- if(!ppS) {
- return TCL_ERROR;
- }
- *deckid=ppS->did;
- zdeck=Slicer_deckHeight(ppS,x0);
- *zoff=z0-zdeck;
- return TCL_OK;
- }
- /* Slicer_Absolute_Z */
- double Slicer_Absolute_Z(Slicer *pSlicer,int deckid,double x0,double y0,double zoff){
- struct OneSlice *ppS,*pAbove;
- double zresult=0.0;
- if(!pSlicer) {
- return 0;
- }
- ppS=Slicer_getDeck_FromInt(pSlicer,deckid);
- if(!ppS) {
- return 0;
- }
- if(zoff < 0.0) {
- pAbove = Slicer_deckAbove(pSlicer, ppS);
- if(pAbove) {
- zresult=Slicer_deckHeight(pAbove,x0)+zoff;
- } else {
- zresult=Slicer_deckHeight(ppS,x0)+2000+zoff;
- }
- } else {
- zresult=Slicer_deckHeight(ppS,x0)+zoff;
- }
- return zresult;
- }
- /*
- ** This file implements a TCL object that keeps track of the walls and
- ** bulkheads on a single deck of a ship.
- **
- ** This widget assumes a right-handed coordinate system if zoom is positive
- ** and a left-handed coordinate system is zoom is negative. The Tk canvas
- ** widget uses a left-handed coordinate system all the time. The READI
- ** database uses a right-handed coordinate system all the time. This module
- ** can be used to translate by setting zoom to +1.0 for database I/O and
- ** to -$g(zoom) for canvas I/O.
- **
- ** This module uses a purely 2-D model. It can only handle a single
- ** deck at a time. If a multi-deck model needs to be displayed then
- ** that multi-deck model should first be flattened into a stack of
- ** individual decks in the same plane using the separate "slicer" object.
- **
- ** This file implements a single new constructor tcl command named "wallset".
- ** The wallset command creates a new wallset object. Methods on this
- ** wallset object are used to manage the object.
- **
- ** The details of the various methods and what they do are provided in
- ** header comments above the implementation of each method.
- */
- #ifndef M_PI
- # define M_PI 3.1415926535898
- #endif
-
- /*
- ** Remove all of the ComptBox entries from the wallset.
- */
- static void clearComptBoxCache(Wallset *pWS){
- ComptBox *p = pWS->pComptBox;
- while( p ){
- ComptBox *pNext = p->pNext;
- Tcl_Free((char *)p);
- p = pNext;
- }
- pWS->pComptBox = 0;
- }
-
- /*
- ** This routine is invoked when the TCL command that implements a
- ** wallset is deleted. Free all memory associated with that
- ** wallset.
- */
- static void destroyWallset(void *pArg){
- Wallset *p = (Wallset*)pArg;
- Link *pLink = p->pAll;
- clearComptBoxCache(p);
- while( pLink ){
- Segment *pSeg = pLink->pLinkNode;
- pLink = pSeg->pAll.pNext;
- Tcl_Free((char *) pSeg );
- }
- Tcl_Free((char *) p );
- }
-
- /*
- ** Clear the Segment.ignore flag on all segments within a wallset.
- */
- static void ignoreNone(Wallset *p){
- #if 0
- Link *pLink;
- for(pLink=p->pAll; pLink; pLink=pLink->pNext){
- pLink->pSeg->ignore = 0;
- }
- #endif
- }
-
- /*
- ** Return a pointer to the segment with the given ID. Return NULL
- ** if there is no such segment.
- */
- static Segment *findSegment(Wallset *p, int id){
- int h;
- Link *pLink;
-
- h = hashInt(id);
- for(pLink = p->hashId[h]; pLink; pLink=pLink->pNext){
- Segment *pSeg=pLink->pLinkNode;
- if( pSeg->id==id ) return pSeg;
- }
- return 0;
- }
-
- /*
- ** Scan all segments looking for the vertex or vertices that are nearest
- ** to x,y. Return a pointer to a Segment.set that is the list of matching
- ** segments. Also write the nearest point into *pX,*pY.
- **
- ** The returned list uses the Segment.set link.
- */
- static Link *nearestVertex(
- Wallset *p, /* The wallset to be scanned */
- double x, double y, /* Search for points near to this point */
- double *pX, double *pY /* Write nearest vertex here */
- ){
- double nx, ny;
- double min = -1.0;
- Link *pList = 0;
- Link *pI;
-
- nx = x = roundCoord(x);
- ny = y = roundCoord(y);
- for(pI=p->pAll; pI; pI=pI->pNext){
- double dx, dy, dist;
- Segment *pSeg = pI->pLinkNode;
- dx = x - pSeg->from[X_IDX];
- dy = y - pSeg->from[Y_IDX];
- dist = dx*dx + dy*dy;
- if( min<0.0 || dist<=min ){
- if( min<0.0 || nx!=pSeg->from[X_IDX] || ny!=pSeg->from[Y_IDX] ){
- pList = 0;
- nx = pSeg->from[X_IDX];
- ny = pSeg->from[Y_IDX];
- min = dist;
- }
- LinkInit(pSeg->pSet, pSeg);
- LinkInsert(&pList, &pSeg->pSet);
- }
- dx = x - pSeg->to[X_IDX];
- dy = y - pSeg->to[Y_IDX];
- dist = dx*dx + dy*dy;
- if( dist<=min ){
- if( nx!=pSeg->to[X_IDX] || ny!=pSeg->to[Y_IDX] ){
- pList = 0;
- nx = pSeg->to[X_IDX];
- ny = pSeg->to[Y_IDX];
- min = dist;
- }
- LinkInit(pSeg->pSet, pSeg);
- LinkInsert(&pList, &pSeg->pSet);
- }
- }
- *pX = nx;
- *pY = ny;
- return pList;
- }
-
- /*
- ** Scan all segments looking for the point on a segment that is nearest
- ** to x,y. Return a pointer to a Segment.set that is the list of matching
- ** segments. This set might contain multiple members if the nearest point
- ** is actually a vertex shared by two or more segments. Write the nearest
- ** point into *pX, *pY.
- **
- ** /// Ignore any segment that has its Segment.ignore flag set. -- removed
- **
- ** The returned list uses the Segment.set list.
- */
- static Link *nearestPoint(
- Wallset *p, /* The wallset to be scanned */
- double x, double y, /* Search for points near to this point */
- double *pX, double *pY /* Write nearest vertex here */
- ){
- double nx, ny;
- double min = -1.0;
- Link *pList = 0;
- Link *pI;
-
- nx = x = roundCoord(x);
- ny = y = roundCoord(y);
- for(pI=p->pAll; pI; pI=pI->pNext){
- double dx, dy, dist;
- Segment *pSeg;
- double acx, acy; /* Vector from x0,y0 to x,y */
- double abx, aby; /* Vector from x0,y0 to x1,y1 */
- double rx, ry; /* Nearest point on x0,y0->to[X_IDX],y1 to x,y */
- double r;
-
- pSeg = pI->pLinkNode;
- /* if( pSeg->ignore ) continue; */
- acx = x - pSeg->from[X_IDX];
- acy = y - pSeg->from[Y_IDX];
- abx = pSeg->to[X_IDX] - pSeg->from[X_IDX];
- aby = pSeg->to[Y_IDX] - pSeg->from[Y_IDX];
- r = (acx*abx + acy*aby)/(abx*abx + aby*aby);
- if( r<=0 ){
- rx = pSeg->from[X_IDX];
- ry = pSeg->from[Y_IDX];
- }else if( r>=1 ){
- rx = pSeg->to[X_IDX];
- ry = pSeg->to[Y_IDX];
- }else{
- rx = pSeg->from[X_IDX] + abx*r;
- ry = pSeg->from[Y_IDX] + aby*r;
- }
- rx = roundCoord(rx);
- ry = roundCoord(ry);
- dx = x - rx;
- dy = y - ry;
- dist = dx*dx + dy*dy;
- if( min<0.0 || dist<=min ){
- if( min<0.0 || nx!=rx || ny!=ry ){
- pList = 0;
- nx = rx;
- ny = ry;
- min = dist;
- }
- LinkInit(pSeg->pSet, pSeg);
- LinkInsert(&pList, &pSeg->pSet);
- }
- }
- *pX = nx;
- *pY = ny;
- return pList;
- }
-
- /*
- ** Return TRUE if the value x is in between x1 and x2.
- */
- static int between(double x, double x1, double x2){
- if( x1<x2 ){
- return x>=x1 && x<=x2;
- }else{
- return x>=x2 && x<=x1;
- }
- }
-
- /*
- ** Return TRUE if the given segment is on the given list
- */
- static int segmentOnList(Segment *pSeg, Link *pList){
- while( pList ){
- if( pList->pLinkNode==pSeg ) return 1;
- pList = pList->pNext;
- }
- return 0;
- }
-
- /*
- ** Return a list of all segments which have an end at the given vertex.
- ** The returned list uses Segment.set
- */
- static Link *segmentsAtVertex(Wallset *p, double x, double y){
- Link *pList = 0;
- Link *pI;
- int h;
-
- x = roundCoord(x);
- y = roundCoord(y);
- h = hashCoord(x, y);
- for(pI=p->hashFrom[h]; pI; pI=pI->pNext){
- Segment *pSeg = pI->pLinkNode;
- /* if( pSeg->ignore ) continue; */
- if( floatCompare(x, pSeg->from[X_IDX])==0 && floatCompare(y, pSeg->from[Y_IDX])==0 ){
- assert( !segmentOnList(pSeg, pList) );
- LinkInit(pSeg->pSet, pSeg);
- LinkInsert(&pList, &pSeg->pSet);
- }
- }
- for(pI=p->hashTo[h]; pI; pI=pI->pNext){
- Segment *pSeg = pI->pLinkNode;
- /* if( pSeg->ignore ) continue; */
- if( floatCompare(x, pSeg->to[X_IDX])==0 && floatCompare(y, pSeg->to[Y_IDX])==0 ){
- assert( !segmentOnList(pSeg, pList) );
- LinkInit(pSeg->pSet, pSeg);
- LinkInsert(&pList, &pSeg->pSet);
- }
- }
- return pList;
- }
-
- /*
- ** The point xV,yV is a vertex in the wallset. This routine locates
- ** a segment connected to that vertex which is the first segment in
- ** a clockwise direction from xR,yR->xV,yV. A pointer to the segment
- ** is written into *ppSeg. If the output segment moves backwards
- ** (in other words if x1,y1 of the segment is connected at xV,yV)
- ** then *pfBack is true.
- **
- ** If a suitable segment is found, 0 is returned. Non-zero is returned
- ** if no suitable segment could be found.
- **
- ** This routine uses the Segment.set list internally.
- */
- static int nextCwSegment(
- Wallset *p, /* The wallset */
- double xR, double yR, /* Remote end of input segment */
- double xV, double yV, /* Vertex (near end of input segment) */
- Segment **ppSeg, /* OUT: First segment clockwise from xR,yR->xV,yV */
- int *pfBack /* OUT: True if output segment goes backwards */
- ){
- Link *pList, *pI;
- double rRef, rBest;
- int i, nSeg, iBest;
- Segment *pSeg;
- struct {
- Segment *pSeg;
- int isBack;
- double rAngle;
- } *aSeg, aSegStatic[20];
-
- /* Find all segments at xV,yV */
- pList = segmentsAtVertex(p, xV, yV);
- for(pI=pList, nSeg=0; pI; nSeg++, pI=pI->pNext){}
- if( nSeg==0 ) return 1;
- if( nSeg<=sizeof(aSegStatic)/sizeof(aSegStatic[0]) ){
- aSeg = aSegStatic;
- }else{
- aSeg = (void *)Odie_Alloc( nSeg*sizeof(*aSeg) );
- }
- for(pI=pList, i=0; pI; i++, pI=pI->pNext){
- aSeg[i].pSeg = pSeg = pI->pLinkNode;
- aSeg[i].isBack = floatCompare(xV, pSeg->to[X_IDX])==0
- && floatCompare(yV, pSeg->to[Y_IDX])==0;
- }
-
- /* Find the reference angle */
- rRef = atan2(yR-yV, xR-xV)*180.0/M_PI;
-
- /* Find angles on all segments */
- for(i=0; i<nSeg; i++){
- pSeg = aSeg[i].pSeg;
- if( aSeg[i].isBack ){
- aSeg[i].rAngle = atan2(pSeg->from[Y_IDX]-pSeg->to[Y_IDX], pSeg->from[X_IDX]-pSeg->to[X_IDX])*180.0/M_PI;
- }else{
- aSeg[i].rAngle = atan2(pSeg->to[Y_IDX]-pSeg->from[Y_IDX], pSeg->to[X_IDX]-pSeg->from[X_IDX])*180.0/M_PI;
- }
- }
-
- /* Subtract 360 to any segment angle that is less than the reference angle */
- for(i=0; i<nSeg; i++){
- if( aSeg[i].rAngle<rRef ) aSeg[i].rAngle += 360;
- }
-
- /* Choose the segment with the largest angle */
- rBest = aSeg[0].rAngle;
- iBest = 0;
- for(i=1; i<nSeg; i++){
- if( aSeg[i].rAngle>rBest ){
- iBest = i;
- rBest = aSeg[i].rAngle;
- }
- }
- *ppSeg = aSeg[iBest].pSeg;
- *pfBack = aSeg[iBest].isBack;
- if( aSeg!=aSegStatic ){
- Tcl_Free((char *) aSeg );
- }
-
- return 0;
- }
-
- /*
- ** Consider a line beginning at x0,y0 then going from x1,y1 to x2,y2.
- ** x1,y1 is an elbow in the line. This routine returns -1 if the
- ** elbow bends to the right, and +1 if it bends to the left. zero is
- ** returned if the elbow does not bend at all.
- */
- static int bendDirection(
- double x0, double y0,
- double x1, double y1,
- double x2, double y2
- ){
- /* Algorithm: Rotate x0,y0->to[X_IDX],y1 90 degrees counter-clockwise. Take
- ** the dot product with x1,y1->x2,y2. The dot produce will be the product
- ** of two (non-negative) magnitudes and the cosine of the angle. So if
- ** the dot product is positive, the bend is to the left, or to the right if
- ** the dot product is negative.
- */
- double r = (y0-y1)*(x2-x1) + (x1-x0)*(y2-y1);
- return r<0.0 ? +1 : (r>0.0 ? -1 : 0);
- }
-
- /*
- ** Given an interior point xI,yI, this routine finds a segment on the
- ** boundary that contains the interior point. That segment is returned
- ** in *ppSeg. *pfLeft is set to true if the interior point is to the left
- ** of the segment and false if it is to the right.
- **
- ** Zero is returned on success. Non-zero is returned if no suitable
- ** boundary could be located. Non-zero might be returned, for example,
- ** if xI,yI is positioned directly on top of a wall or if there are no
- ** walls in the wallset.
- **
- ** // Any segment marked with Segment.ignore is ignored for purposes of
- ** // this routine. -- removed
- **
- ** This routine uses the Segment.set list internally.
- */
- static int firstBoundarySegment(
- Wallset *p, /* The wallset */
- double xI, double yI, /* An interior point */
- Segment **ppSeg, /* OUT: A segment on the boundary containing xI,yI */
- int *pfLeft /* OUT: True if xI,yI is to the left side *ppSeg */
- ){
- Link *pList;
- double xN, yN;
-
- /* Find nearest point, xN,yN */
- pList = nearestPoint(p, xI, yI, &xN, &yN);
- if( pList==0 ) return 1;
- if( pList->pNext ){
- /* xN,yN is a vertex...
- ** Locate the first segment clockwise from xI,yI->xN,yN and return
- */
- return nextCwSegment(p, xI, yI, xN, yN, ppSeg, pfLeft);
- }else{
- /* xN,yN is a point on single line segment...
- */
- Segment *pSeg;
- pSeg = *ppSeg = pList->pLinkNode;
- *pfLeft = bendDirection(pSeg->from[X_IDX], pSeg->from[Y_IDX], xN, yN, xI, yI)>0;
- }
- return 0;
- }
-
- /*
- ** Fill the given Boundary array with a list of segments (with
- ** Segment.ignore set to false) that form a closed circuit. The
- ** first entry in aBound[] has already been filled in by the
- ** calling function and is used to seed the search.
- **
- ** At most nBound slots in aBound[] will be used. The return value
- ** is the number of slots in aBound[] that would have been used if those
- ** slots had been available. A return of 0 indicates that no boundary
- ** is available.
- **
- ** If the checkIsPrimary flag is true and the aBound[0] entry is not
- ** the primary segment for the compartment, then the aBound[] is not
- ** completely filled in and the routine returns 0;
- */
- static int completeBoundary(
- Wallset *p, /* The wallset */
- int checkIsPrimary, /* Abort if aBound[0] is not the primary segment */
- int nBound, /* Number of slots available in aBound[] */
- Boundary *aBound /* IN-OUT: Write results into aBound[1...] */
- ){
- int cnt = 1;
- Segment *pSeg, *pS;
- int isLeft;
- int isBack;
- double xR, yR, xV, yV;
-
- pS = pSeg = aBound[0].pSeg;
- isLeft = aBound[0].backwards;
- if( !isLeft ){
- xR = pSeg->from[X_IDX];
- yR = pSeg->from[Y_IDX];
- xV = pSeg->to[X_IDX];
- yV = pSeg->to[Y_IDX];
- }else{
- xV = pSeg->from[X_IDX];
- yV = pSeg->from[Y_IDX];
- xR = pSeg->to[X_IDX];
- yR = pSeg->to[Y_IDX];
- }
- while( nextCwSegment(p,xR,yR,xV,yV,&pS,&isBack)==0 &&
- (isBack!=isLeft || pS!=pSeg) ){
- if( checkIsPrimary ){
- if( pS->id<pSeg->id ) return 0;
- if( pS->id==pSeg->id && !isLeft ) return 0;
- }
- if( isBack ){
- xV = pS->from[X_IDX];
- yV = pS->from[Y_IDX];
- xR = pS->to[X_IDX];
- yR = pS->to[Y_IDX];
- }else{
- xR = pS->from[X_IDX];
- yR = pS->from[Y_IDX];
- xV = pS->to[X_IDX];
- yV = pS->to[Y_IDX];
- }
- if( nBound>cnt ){
- aBound[cnt].pSeg = pS;
- aBound[cnt].backwards = isBack;
- }
- cnt++;
- if( cnt>1000 /* 00 */ ) return -cnt; /* Avoid an infinite loop */
- }
- return cnt;
- }
-
- /*
- ** Compute the "spin" on a boundary. A positive value means the
- ** circulation is to counter-clockwise and a negative value means the
- ** circulation is clockwise. For boundaries, a positive
- ** value means the region is internal and a negative value means
- ** the region is external.
- */
- static double spin(Boundary *aBound, int nBound){
- double sum = 0;
- int i;
- for(i=0; i<nBound; i++){
- double x0, y0, x1, y1;
- double dx, dy;
- Segment *pSeg = aBound->pSeg;
- if( aBound->backwards ){
- x0 = pSeg->to[X_IDX];
- y0 = pSeg->to[Y_IDX];
- x1 = pSeg->from[X_IDX];
- y1 = pSeg->from[Y_IDX];
- }else{
- x0 = pSeg->from[X_IDX];
- y0 = pSeg->from[Y_IDX];
- x1 = pSeg->to[X_IDX];
- y1 = pSeg->to[Y_IDX];
- }
- aBound++;
- dx = x1-x0;
- dy = y1-y0;
- sum += x0*dy - y0*dx;
- }
- return sum;
- }
-
- /*
- ** The input is two linked lists of ComptBox structures where each
- ** list is sorted by increasing area. Combine these two lists into
- ** a single sorted linked list.
- */
- static ComptBox *mergeComptBox(ComptBox *p1, ComptBox *p2){
- ComptBox head;
- ComptBox *pTail = &head;
- ComptBox *p;
- while( p1 && p2 ){
- if( p1->area<=p2->area ){
- p = p1->pNext;
- pTail->pNext = p1;
- pTail = p1;
- p1 = p;
- }else{
- p = p2->pNext;
- pTail->pNext = p2;
- pTail = p2;
- p2 = p;
- }
- }
- if( p1 ){
- pTail->pNext = p1;
- }else{
- pTail->pNext = p2;
- }
- return head.pNext;
- }
-
- /*
- ** Construct the ComptBox cache. For each compartment (where a compartment
- ** is a closed circuit of Segments) make an entry on the Wallset.pComptBox
- ** list.
- **
- ** If the ComptBox cache already exists, this routine is a no-op.
- */
- static void buildComptBoxCache(Wallset *p){
- Link *pI;
- int i;
- ComptBox *aSort[30];
-
- /* Return immediately if the cache already exists */
- if( p->pComptBox ) return;
-
- /* Compute a linked list of all compartment boxes */
- for(pI=p->pAll; pI; pI=pI->pNext){
- int i, j, n;
- Boundary aBound[1000];
-
- aBound[0].pSeg = pI->pLinkNode;
- for(j=0; j<2; j++){
- aBound[0].backwards = j;
- n = completeBoundary(p, 1, sizeof(aBound)/sizeof(aBound[0]), aBound);
- if( n>0 && spin(aBound,n)>0.0 ){
- double dx, dy;
- Segment *pSeg = pI->pLinkNode;
- ComptBox *pNew = (ComptBox *)Odie_Alloc( sizeof(*pNew) );
- pNew->pNext = p->pComptBox;
- pNew->bbox[BBOX_X0_IDX] = pNew->bbox[BBOX_X1_IDX] = pSeg->from[X_IDX];
- pNew->bbox[BBOX_Y1_IDX] = pNew->bbox[BBOX_Y0_IDX] = pSeg->from[Y_IDX];
- pNew->prim = aBound[0];
- for(i=1; i<n; i++){
- Segment *pSeg = aBound[i].pSeg;
- if( pSeg->from[X_IDX]<pNew->bbox[BBOX_X0_IDX] ) pNew->bbox[BBOX_X0_IDX] = pSeg->from[X_IDX];
- if( pSeg->from[X_IDX]>pNew->bbox[BBOX_X1_IDX] ) pNew->bbox[BBOX_X1_IDX] = pSeg->from[X_IDX];
- if( pSeg->from[Y_IDX]<pNew->bbox[BBOX_Y0_IDX] ) pNew->bbox[BBOX_Y0_IDX] = pSeg->from[Y_IDX];
- if( pSeg->from[Y_IDX]>pNew->bbox[BBOX_Y1_IDX] ) pNew->bbox[BBOX_Y1_IDX] = pSeg->from[Y_IDX];
- if( pSeg->to[X_IDX]<pNew->bbox[BBOX_X0_IDX] ) pNew->bbox[BBOX_X0_IDX] = pSeg->to[X_IDX];
- if( pSeg->to[X_IDX]>pNew->bbox[BBOX_X1_IDX] ) pNew->bbox[BBOX_X1_IDX] = pSeg->to[X_IDX];
- if( pSeg->to[Y_IDX]<pNew->bbox[BBOX_Y0_IDX] ) pNew->bbox[BBOX_Y0_IDX] = pSeg->to[Y_IDX];
- if( pSeg->to[Y_IDX]>pNew->bbox[BBOX_Y1_IDX] ) pNew->bbox[BBOX_Y1_IDX] = pSeg->to[Y_IDX];
- }
- dx = pNew->bbox[BBOX_X1_IDX] - pNew->bbox[BBOX_X0_IDX];
- dy = pNew->bbox[BBOX_Y1_IDX] - pNew->bbox[BBOX_Y0_IDX];
- pNew->area = sqrt(dx*dx+dy*dy);
- p->pComptBox = pNew;
- }
- }
- }
-
- /* Sort the list into order of increasing area */
- for(i=0; i<sizeof(aSort)/sizeof(aSort[0]); i++) aSort[i] = 0;
- while( p->pComptBox ){
- ComptBox *pBox = p->pComptBox;
- p->pComptBox = pBox->pNext;
- pBox->pNext = 0;
- for(i=0; i<sizeof(aSort)/sizeof(aSort[0])-1 && aSort[i]!=0; i++){
- pBox = mergeComptBox(aSort[i], pBox);
- aSort[i] = 0;
- }
- aSort[i] = mergeComptBox(aSort[i], pBox);
- }
- for(i=0; i<sizeof(aSort)/sizeof(aSort[0]); i++){
- p->pComptBox = mergeComptBox(aSort[i], p->pComptBox);
- }
- }
-
- /*
- ** Test to see if the point x,y is contained within the given
- ** boundary or is on the outside of the boundary.
- */
- static int pointWithinBoundary(
- Boundary *aBound, /* The boundary */
- int nBound, /* Number of segments in the boundary */
- double x, double y /* The point to test */
- ){
- int inside = 0;
- int i;
- for(i=0; i<nBound; i++){
- double x0, y0, x1, y1;
- Segment *p = aBound[i].pSeg;
- x0 = p->from[X_IDX];
- y0 = p->from[Y_IDX];
- x1 = p->to[X_IDX];
- y1 = p->to[Y_IDX];
- if( x0==x1 ) continue;
- if( (x0>x && x1>x) || (x0<x && x1<x) ) continue;
- if( y1 - (x1-x)*(y1-y0)/(x1-x0) >= y ) inside = !inside;
- }
- return inside;
- }
-
- /*
- ** Find a boundary which contains xI, yI. If the size of the boundary
- ** is set to 0, that means no such boundary exists.
- */
- static int findBoundary(
- Wallset *p, /* The wallset */
- double xI, double yI, /* A point that the boundary should be near */
- int nBound, /* Number of slots available in aBound[] */
- Boundary *aBound /* OUT: Write results here */
- ){
- int n = 0;
- ComptBox *pBox;
-
- buildComptBoxCache(p);
- for(pBox=p->pComptBox; pBox; pBox=pBox->pNext){
- if( xI<pBox->bbox[BBOX_X0_IDX] || xI>pBox->bbox[BBOX_X1_IDX] || yI<pBox->bbox[BBOX_Y0_IDX] || yI>pBox->bbox[BBOX_Y1_IDX] ) continue;
- aBound[0] = pBox->prim;
- n = completeBoundary(p, 0, nBound, aBound);
- if( n>0 && pointWithinBoundary(aBound, n, xI, yI) ) break;
- n = 0;
- }
- return n;
- }
-
-
- /*
- ** Do an check of the integrity of the internal data structures. If
- ** a problem is found, leave an error message in interp->result and
- ** return TCL_ERROR. Return TCL_OK if everything is OK.
- */
- static int selfCheck(Tcl_Interp *interp, Wallset *p){
- Link *pLink;
- Segment *pSeg;
- int h;
- char zErr[200];
-
- for(pLink=p->pAll; pLink; pLink=pLink->pNext){
- pSeg = pLink->pLinkNode;
- h = hashInt(pSeg->id);
- if(!segmentOnList(pSeg, p->hashId[h]) ){
- sprintf(zErr, "segment %d missing from hashId[%d]", pSeg->id, h);
- Tcl_SetResult(interp, zErr, TCL_VOLATILE);
- return TCL_ERROR;
- }
- h = hashCoord(pSeg->from[X_IDX], pSeg->from[Y_IDX]);
- if(!segmentOnList(pSeg, p->hashFrom[h]) ){
- sprintf(zErr, "segment %d missing from hashFrom[%d]", pSeg->id, h);
- Tcl_SetResult(interp, zErr, TCL_VOLATILE);
- return TCL_ERROR;
- }
- h = hashCoord(pSeg->to[X_IDX], pSeg->to[Y_IDX]);
- if(!segmentOnList(pSeg, p->hashTo[h]) ){
- sprintf(zErr, "segment %d missing from hashTo[%d]", pSeg->id, h);
- Tcl_SetResult(interp, zErr, TCL_VOLATILE);
- return TCL_ERROR;
- }
- }
- return TCL_OK;
- }
-
- /*
- ** The maximum number of segments in a boundary
- */
- #define MX_BOUND 1000
-
- /* Wallset_Delete */
- static void Wallset_Delete(ClientData clientData){
- Wallset *p = (Wallset *)clientData;
- Link *pLink = p->pAll;
- clearComptBoxCache(p);
- while( pLink ){
- Segment *pSeg = pLink->pLinkNode;
- pLink = pSeg->pAll.pNext;
- Tcl_Free((char *) pSeg );
- }
- Tcl_Free((char *) p );
- }
- /* Wallset_Clone */
- static int Wallset_Clone(
- Tcl_Interp* interp, /* Tcl interpreter for error reporting */
- ClientData metadata, /* Metadata to be cloned */
- ClientData* newMetaData /* Where to put the cloned metadata */
- ){
- Tcl_SetObjResult(interp,
- Tcl_NewStringObj("WALLSETs are not clonable", -1));
- /* For now... */
- return TCL_ERROR;
- }
- /* *PolygonHullVertex_ById */
- static PolygonHullVertex *PolygonHullVertex_ById(PolygonHull *pHull, int id){
- PolygonHullVertex *pVertex;
- pVertex = (PolygonHullVertex*)readiHashFind(&pHull->VertexHash, 0, id);
- return pVertex;
- }
- /* *PolygonHullVertex_ByCoords */
- static PolygonHullVertex *PolygonHullVertex_ByCoords(PolygonHull *pHull, VectorXYZ A){
- int h;
- Link *pLink;
- HashElem *i;
- PolygonHullVertex *pVertex;
- h = hashCoord3d(A[X_IDX],A[Y_IDX],A[X_IDX]);
- for(pLink = pHull->VertexHashCoords[h]; pLink; pLink=pLink->pNext){
- pVertex=pLink->pLinkNode;
- if(VectorXYZ_SamePoint(pVertex->center,A)) {
- return pVertex;
- }
- }
- /* The hash checks sometimes miss. Search all */
- for(i=readiHashFirst(&pHull->VertexHash); i; i=readiHashNext(i)) {
- PolygonHullVertex *pVertex=(PolygonHullVertex *)readiHashData(i);
- if(VectorXYZ_SamePoint(pVertex->center,A)) {
- return pVertex;
- }
- }
- return NULL;
- }
- /* *PolygonHullVertex_Create */
- static PolygonHullVertex *PolygonHullVertex_Create(
- PolygonHull *pHull,
- int id,
- VectorXYZ point
- ){
- int hx;
- PolygonHullVertex *pVertex;
- pVertex = (PolygonHullVertex *)Odie_Alloc( sizeof(PolygonHullVertex) );
- if( pVertex==NULL ) return NULL;
- if(id<0) {
- pHull->VertexNextId++;
- id=pHull->VertexNextId;
- } else if (id>=pHull->VertexNextId) {
- pHull->VertexNextId=id;
- }
- pVertex->id=id;
- LinkInit(pVertex->pHashVertexCoords, pVertex);
- readiHashInsert(&pHull->VertexHash, 0, id, pVertex);
-
- pVertex->center[X_IDX]=point[X_IDX];
- pVertex->center[Y_IDX]=point[Y_IDX];
- pVertex->center[Z_IDX]=point[Z_IDX];
- hx=hashCoord3d(point[X_IDX],point[Y_IDX],point[Z_IDX]);
- LinkInsert(&pHull->VertexHashCoords[hx], &pVertex->pHashVertexCoords);
- return pVertex;
- }
- /* PolygonHullVertex_Remove */
- static void PolygonHullVertex_Remove(PolygonHullVertex *pVertex){
- Link *pLink;
- for(pLink=pVertex->pHashFace;pLink;pLink=pLink->pNext) {
- PolygonHullFace *pFace=pLink->pLinkNode;
- if(pFace) {
- PolygonHullFace_Remove(pFace);
- }
- }
- LinkRemove(&pVertex->pHashVertexCoords);
- }
- /* *PolygonHullFace_VertexInject */
- static const char *PolygonHullFace_VertexInject(PolygonHullFace *pFace,PolygonHullVertex *pThisVertex){
- PolygonHullVertex *pVertex,*pPrior=NULL,*pFirst;
- PolygonHullFace_SerializeEdges(pFace);
- pFirst=pFace->pNextVertex;
- for(pVertex=pFirst;pVertex;pVertex=pVertex->pNextVertex) {
- if(VectorXYZ_SamePoint(pVertex->center,pThisVertex->center)) {
- /* Vertex already exists in polygon noop */
- return NULL;
- }
- pPrior=pVertex;
- }
- for(pVertex=pFirst;pVertex;pVertex=pVertex->pNextVertex) {
- if(VectorXYZ_PointIsOnSegment(pThisVertex->center,pPrior->center,pVertex->center)) {
- pThisVertex->pNextVertex=pVertex;
- if(pVertex==pFirst) {
- /* Head Insert */
- pFace->pNextVertex=pThisVertex;
- return NULL;
- } else {
- /* Mid segment insert */
- pPrior->pNextVertex=pThisVertex;
- return NULL;
- }
- }
- pPrior=pVertex;
- }
- /* Oh brother... */
- return "Could not break edge";
- }
- /* *PolygonHullFace_To_Dict */
- Tcl_Obj *PolygonHullFace_To_Dict(PolygonHullFace *pFace){
- Tcl_Obj *element=Tcl_NewObj();
- {
- Tcl_Obj *value;
- value=Tcl_NewIntObj(pFace->id);
- Odie_DictObjPut(NULL,element,"id:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewIntObj(pFace->nVertex);
- Odie_DictObjPut(NULL,element,"nVertex:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewIntObj(pFace->wallid);
- Odie_DictObjPut(NULL,element,"wallid:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewIntObj(pFace->deckid);
- Odie_DictObjPut(NULL,element,"deckid:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewIntObj(pFace->typeid);
- Odie_DictObjPut(NULL,element,"typeid:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewBooleanObj(pFace->is_wall);
- Odie_DictObjPut(NULL,element,"is_wall:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewBooleanObj(pFace->is_exterior);
- Odie_DictObjPut(NULL,element,"is_exterior:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewIntObj(pFace->is_virtual);
- Odie_DictObjPut(NULL,element,"is_virtual:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewIntObj(pFace->idLC);
- Odie_DictObjPut(NULL,element,"idLC:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewIntObj(pFace->idRC);
- Odie_DictObjPut(NULL,element,"idRC:",value);
- }
- {
- Tcl_Obj *value;
- value=VectorXYZ_To_TclObj(pFace->center);
- Odie_DictObjPut(NULL,element,"center:",value);
- }
- {
- Tcl_Obj *value;
- value=VectorXYZ_To_TclObj(pFace->normal);
- Odie_DictObjPut(NULL,element,"normal:",value);
- }
- {
- Tcl_Obj *value;
- value=Tcl_NewDoubleObj(pFace->radius);
- Odie_DictObjPut(NULL,element,"radius:",value);
- }
- {
- Tcl_Obj *value;
-
- char outbuf[64];
- int i;
- value=Tcl_NewObj();
- for(i=0;i<6;i++) {
- sprintf(outbuf,"%.3f",(float)pFace->bbox[i]);
- Tcl_ListObjAppendElement(NULL,value,Tcl_NewStringObj(outbuf,-1));
- }
-
- Odie_DictObjPut(NULL,element,"bbox:",value);
- }
- return element;}
- /* *PolygonHullFace_Create */
- static PolygonHullFace *PolygonHullFace_Create(
- PolygonHull *pHull,
- int id
- ){
- PolygonHullFace *pFace;
- pFace = (PolygonHullFace *)Odie_Alloc( sizeof(PolygonHullFace) );
- if( pFace==NULL ) return NULL;
- if(id<0) {
- pHull->FaceNextId++;
- id=pHull->FaceNextId;
- } else if (id>=pHull->FaceNextId) {
- pHull->FaceNextId=id;
- }
- pFace->id=id;
- readiHashInsert(&pHull->FaceHash, 0, id, pFace);
-
- pFace->id = id;
- pFace->pActive = pHull->pActive;
- pHull->pActive = pFace;
-
- LinkInit(pFace->pSet, pFace);
- return pFace;
- }
- /* *PolygonHull_mergeFaceList */
- static PolygonHullFace *PolygonHull_mergeFaceList(PolygonHullFace *a, PolygonHullFace *b){
- PolygonHullFace head, *pTail;
- pTail = &head;
- while( a && b ){
- if( a->dist <= b->dist ){
- pTail->pNext = a;
- pTail = a;
- a = a->pNext;
- }else{
- pTail->pNext = b;
- pTail = b;
- b = b->pNext;
- }
- }
- if( a ){
- pTail->pNext = a;
- }else if( b ){
- pTail->pNext = b;
- }else{
- pTail->pNext = 0;
- }
- return head.pNext;
- }
- /* *PolygonHull_sortFaceList */
- static PolygonHullFace *PolygonHull_sortFaceList(PolygonHullFace *pList){
- int i;
- PolygonHullFace *p;
- PolygonHullFace *ap[NBUCKET];
- for(i=0; i<NBUCKET; i++){ ap[i] = 0; }
- while( pList ){
- p = pList;
- pList = p->pNext;
- p->pNext = 0;
- for(i=0; i<NBUCKET-1; i++){
- if( ap[i] ){
- p = PolygonHull_mergeFaceList(ap[i], p);
- ap[i] = 0;
- }else{
- ap[i] = p;
- break;
- }
- }
- if( i==NBUCKET ){
- ap[i] = PolygonHull_mergeFaceList(ap[i],p);
- }
- }
- p = 0;
- for(i=0; i<NBUCKET; i++){
- p = PolygonHull_mergeFaceList(ap[i], p);
- }
- return p;
- }
- /* *PolygonHullFace_ById */
- static PolygonHullFace *PolygonHullFace_ById(PolygonHull *pHull, int id){
- PolygonHullFace *pFace;
- pFace = (PolygonHullFace*)readiHashFind(&pHull->FaceHash, 0, id);
- return pFace;
- }
- /* PolygonHull_findFace */
- static int PolygonHull_findFace(
- Tcl_Interp *interp, /* Leave any error message here */
- PolygonHull *pHull,
- Tcl_Obj *pObj, /* The PolygonHullFace ID */
- PolygonHullFace **ppHullFace /* Write PolygonHullFace pointer here */
- ){
- int id;
- if( Tcl_GetIntFromObj(interp, pObj, &id) ) return TCL_ERROR;
- *ppHullFace = PolygonHullFace_ById(pHull,id);
- if( *ppHullFace==0 ){
- Tcl_AppendResult(interp, "no such PolygonHullFace", 0);
- return TCL_ERROR;
- }
- PolygonHullFace_Compute(*ppHullFace);
- return TCL_OK;
- }
- /* PolygonHullFace_Remove */
- static void PolygonHullFace_Remove(PolygonHullFace *pFace){
- int i;
- if(!pFace) return;
- LinkRemove(&pFace->pSet);
-
- if(pFace->aVertex) {
- for(i=0;i<pFace->nVertex;i++) {
- if(pFace->aVertex[i]==0) continue;
- LinkRemove(&pFace->pVertex[i]);
- }
- Odie_Free((char *)pFace->aVertex);
- }
- if(pFace->pVertex) {
- Odie_Free((char *)pFace->pVertex);
- }
- }
- /* PolygonHullFace_SerializeEdges */
- static void PolygonHullFace_SerializeEdges(PolygonHullFace *p){
- int i;
- PolygonHullVertex *pPrior=NULL,*pVertex;
- if(p->pNextVertex) {
- return;
- }
- //printf("PolygonHullFace_SerializeEdges %d %p\n",p->id,p->aVertex);
- for(i=0;i<p->nVertex;i++) {
- pVertex=p->aVertex[i];
- assert(pVertex);
- LinkRemove(&p->pVertex[i]);
- //printf("PolygonHullFace_SerializeEdges %d #%d %p %p\n",p->id,i,pPrior,pVertex);
- pVertex->pNextVertex=NULL;
- if(!pPrior) {
- p->pNextVertex=pVertex;
- } else {
- pPrior->pNextVertex=pVertex;
- }
- pPrior=pVertex;
- }
- //printf("PolygonHullFace_SerializeEdges %d LAST %d %p\n",p->id,i,pPrior);
- if(pPrior) {
- pPrior->pNextVertex=NULL;
- }
- Odie_Free(p->aVertex);
- Odie_Free(p->pVertex);
- p->nVertex=0;
- p->aVertex=NULL;
- p->pVertex=NULL;
-
- }
- /* PolygonHullFace_Compute */
- static void PolygonHullFace_Compute(PolygonHullFace *pFace){
- VectorXYZ one,two;
- int i;
- double r1,rmax;
- int nVertex;
- PolygonHullVertex *pVertex,*pFirst;
- //printf("PolygonHullFace_Compute %d %p %p\n",pFace->id,pFace,pFace->pNextVertex);
- if(!pFace->pNextVertex) {
- return;
- }
- VectorXYZ_AABB_Reset(pFace->bbox);
- nVertex=0;
- /* Count the number of vertices */
- pFirst=pFace->pNextVertex;
- for(pVertex=pFirst;pVertex;pVertex=pVertex->pNextVertex) {
- nVertex++;
- if(nVertex>32) break;
- }
- pFace->nVertex=nVertex;
- /* Allocate the arrays to store the vertices */
- pFace->aVertex=(PolygonHullVertex **)Odie_Alloc(sizeof(PolygonHullVertex *)*pFace->nVertex);
- pFace->pVertex=(Link *)Odie_Alloc(sizeof(Link)*pFace->nVertex);
- pVertex=pFirst;
- for(i=0;i<nVertex;i++) {
- VectorXYZ_AABB_Measure(pVertex->center,pFace->bbox);
- pFace->pNextVertex=pVertex->pNextVertex;
- pFace->aVertex[i]=pVertex;
- LinkInit(pFace->pVertex[i],pFace);
- LinkInsert(&pVertex->pHashFace, &pFace->pVertex[i]);
- pVertex=pVertex->pNextVertex;
- }
- for(i=0;i<nVertex;i++) {
- pVertex=pFace->aVertex[i];
- pVertex->pNextVertex=NULL;
- }
- if(pFace->nVertex==3) {
- VectorXYZ_Subtract(one, pFace->aVertex[1]->center, pFace->aVertex[0]->center);
- VectorXYZ_Subtract(two, pFace->aVertex[2]->center, pFace->aVertex[0]->center);
- pFace->normal[X_IDX] = one[Y_IDX]*two[Z_IDX] - one[Z_IDX]*two[Y_IDX];
- pFace->normal[Y_IDX] = one[Z_IDX]*two[X_IDX] - one[X_IDX]*two[Z_IDX];
- pFace->normal[Z_IDX] = one[X_IDX]*two[Y_IDX] - one[Y_IDX]*two[X_IDX];
- } else {
- int i,j;
- VectorXYZ_Zero(pFace->normal);
- for(i=0,j=1;i<pFace->nVertex;i++,j++) {
- if(j==pFace->nVertex) j=0;
- pFace->normal[X_IDX] += (pFace->aVertex[j]->center[Y_IDX]-pFace->aVertex[i]->center[Y_IDX]) * (pFace->aVertex[j]->center[Z_IDX]+pFace->aVertex[i]->center[Z_IDX]);
- pFace->normal[Y_IDX] += (pFace->aVertex[j]->center[Z_IDX]-pFace->aVertex[i]->center[Z_IDX]) * (pFace->aVertex[j]->center[X_IDX]+pFace->aVertex[i]->center[X_IDX]);
- pFace->normal[Z_IDX] += (pFace->aVertex[j]->center[X_IDX]-pFace->aVertex[i]->center[X_IDX]) * (pFace->aVertex[j]->center[Y_IDX]+pFace->aVertex[i]->center[Y_IDX]);
- }
- }
- VectorXYZ_Normalize(pFace->normal);
- /* Compute the center and radius of the face. */
- VectorXYZ_Zero(pFace->center);
- for(i=0; i<pFace->nVertex; i++){
- pFace->center[X_IDX] += pFace->aVertex[i]->center[X_IDX];
- pFace->center[Y_IDX] += pFace->aVertex[i]->center[Y_IDX];
- pFace->center[Z_IDX] += pFace->aVertex[i]->center[Z_IDX];
- }
- pFace->center[X_IDX] /= pFace->nVertex;
- pFace->center[Y_IDX] /= pFace->nVertex;
- pFace->center[Z_IDX] /= pFace->nVertex;
- rmax=0.0;
- for(i=0; i<pFace->nVertex; i++){
- r1 = VectorXYZ_DistanceSq(pFace->center, pFace->aVertex[i]->center);
- if(r1>rmax) {
- rmax=r1;
- }
- }
- pFace->radiusSq = rmax;
- pFace->radius = sqrt(rmax);
- }
- /* PolygonHull_sqrDistPointToEdge */
- static double PolygonHull_sqrDistPointToEdge(
- VectorXYZ A, VectorXYZ B, /* End points of the line segment */
- VectorXYZ X /* The point to measure distance to */
- ){
- VectorXYZ closest; /* Point on line segment closest to X */
- VectorXYZ_ClosestPointOnSegment(A,B,X,closest);
- return VectorXYZ_DistanceSq(X, closest);
- }
- /* PolygonHull_intersectLineSegFace */
- static double PolygonHull_intersectLineSegFace(
- PolygonHullFace *pFace, /* The triangle we are trying to intersect */
- VectorXYZ pStart, /* Start of the line segment */
- VectorXYZ pEnd, /* End of the line segment */
- VectorXYZ pIntersect /* Point of intersection written here if not NULL */
- ){
- double d;
- int i;
- for(i=2;i<pFace->nVertex;i++) {
- /*
- ** Assuming we are fed convex polygons,
- ** break the surface into triangles
- ** and evaluate each triangle
- */
- d = VectorXYZ_TriangleLineIntersect(pFace->aVertex[0]->center,pFace->aVertex[i-1]->center,pFace->aVertex[i]->center,pStart,pEnd,pIntersect);
- if(d>=0.0) {
- return d;
- }
- }
- return -1.0;
- }
- /* *PolygonHullFace_findHits */
- static PolygonHullFace *PolygonHullFace_findHits(PolygonHull *pHull, VectorXYZ A, VectorXYZ B){
- PolygonHullFace *p, *pList;
- double d1, d2;
- pList = 0;
- for(p=pHull->pActive; p; p=p->pActive){
- d1 = PolygonHull_sqrDistPointToEdge(A, B, p->center);
- d2 = p->radiusSq;
- if( d2<d1 ){
- continue;
- }
- d1 = PolygonHull_intersectLineSegFace(p, A, B,p->intersect);
- if( d1>=0.0 ){
- p->pNext = pList;
- pList = p;
- p->dist = d1;
- }
- }
- return PolygonHull_sortFaceList(pList);
- }
- /* PolygonHull_closestPointOnFace */
- static double PolygonHull_closestPointOnFace(PolygonHullFace *p, VectorXYZ X, VectorXYZ R){
- double d1, d2, distBest=1e99;
- VectorXYZ testPt;
- VectorXYZ a, b; /* End points of line seg parallel to p->normal */
- int i,j;
-
- /* Construct a line segment a->b that is parallel to p->normal and which
- ** passes through X. Make sure the line segment is plenty long
- ** enough so that it will intersect the plane of p.
- */
- d1 = VectorXYZ_Distance(X, p->center)*2;
- d2 = p->normal[X_IDX]*d1;
- a[X_IDX] = X[X_IDX] + d2;
- b[X_IDX] = X[X_IDX] - d2;
- d2 = p->normal[Y_IDX]*d1;
- a[Y_IDX] = X[Y_IDX] + d2;
- b[Y_IDX] = X[Y_IDX] - d2;
- d2 = p->normal[Z_IDX]*d1;
- a[Z_IDX] = X[Z_IDX] + d2;
- b[Z_IDX] = X[Z_IDX] - d2;
-
- /* Figure out if a->b intersects the triangle, and if so where. If
- ** there is an intersection, then this is the closest point.
- */
- if( PolygonHull_intersectLineSegFace(p, a, b, R)>=0.0 ){
- return VectorXYZ_Distance(X,R);
- }
-
- /*
- ** If we reach here it means that the closest point will be on the
- ** permiter of the triangle. There are three line faces on the
- ** permiter. Try them all.
- */
- for(i=0,j=1;i<p->nVertex;i++,j++) {
- if(j==p->nVertex) j=0;
- VectorXYZ_ClosestPointOnSegment(p->aVertex[i]->center, p->aVertex[j]->center, X, testPt);
- d1 = VectorXYZ_Distance(X, testPt);
- if(i==0 || d1<distBest) {
- distBest = d1;
- R[X_IDX]=testPt[X_IDX];
- R[Y_IDX]=testPt[Y_IDX];
- R[Z_IDX]=testPt[Z_IDX];
- }
- }
- return distBest;
- }
- /* *PolygonHullFace_findClosest */
- static PolygonHullFace *PolygonHullFace_findClosest(PolygonHull *pHull,VectorXYZ X, VectorXYZ R, double *pDist){
- double d1;
- double distBest=1e99;
- PolygonHullFace *pBest=NULL;
- VectorXYZ testPt;
- PolygonHullFace *p;
- HashElem *i;
- /* First pass: Locate the triangle whose center is closest to X.
- ** This will be our first guess of what the closest triangle is.
- ** And because it is probably pretty close to the best, it will make
- ** it easy to eliminate other triangles from contention.
- */
- for(i=readiHashFirst(&pHull->FaceHash); i; i=readiHashNext(i)) {
- p = readiHashData(i);
- d1 = VectorXYZ_DistanceSq(p->center, X);
- if( pBest==0 || d1<distBest ){
- pBest = p;
- distBest = d1;
- }
- }
- if( pBest==0 ){
- return 0;
- }
-
- /* Compute the exact distance from X to our first guess at the closest
- ** triangle.
- */
- d1=PolygonHull_closestPointOnFace(pBest, X, R);
- distBest = d1*d1;
-
- /* Do a second pass over the data to see if we can find another
- ** triangle that is closer than pBest. We only need to check
- ** triangle whose center is not further away from X than distBest
- ** plus the triangle radius.
- */
- for(i=readiHashFirst(&pHull->FaceHash); i; i=readiHashNext(i)) {
- p = readiHashData(i);
- if( p==pBest ){
- continue;
- }
- d1 = VectorXYZ_DistanceSq(p->center, X);
- if( d1 - p->radiusSq > distBest ){
- continue;
- }
- d1 = PolygonHull_closestPointOnFace(p, X, testPt);
- if( (d1*d1)<distBest ){
- pBest = p;
- distBest = d1*d1;
- R[X_IDX] = testPt[X_IDX];
- R[Y_IDX] = testPt[Y_IDX];
- R[Z_IDX] = testPt[Z_IDX];
- }
- }
- *pDist = sqrt(distBest);
- return pBest;
- }
- /* *PolygonHullVolume_ById */
- static PolygonHullVolume *PolygonHullVolume_ById(PolygonHull *pHull, int id){
- PolygonHullVolume *pVolume;
- pVolume = readiHashFind(&pHull->VolumeHash, 0, id);
- return pVolume;
- }
- /* *PolygonHullVolume_Create */
- static PolygonHullVolume *PolygonHullVolume_Create(
- PolygonHull *pHull,
- int id
- ){
- PolygonHullVolume *pVolume;
- pVolume = (PolygonHullVolume *)Odie_Alloc( sizeof(PolygonHullVolume) );
- if( pVolume==NULL ) return NULL;
- if(id<0) {
- pHull->VolumeNextId++;
- id=pHull->VolumeNextId;
- } else if (id>=pHull->VolumeNextId) {
- pHull->VolumeNextId=id;
- }
- pVolume->id=id;
- readiHashInsert(&pHull->VolumeHash, 0, id, pVolume);
- return pVolume;
- }
- /* PolygonHullVolume_Unlink */
- static void PolygonHullVolume_Unlink(PolygonHullVolume *pVolume){
- }
- /* PolygonHull_clearSurfaces */
- static void PolygonHull_clearSurfaces(PolygonHull *pHull){
- }
- /* PolygonHull_Reset */
- static void PolygonHull_Reset(PolygonHull *pHull){
- PolygonHull_clearSurfaces(pHull);
- pHull->FaceNextId=0;
- pHull->VertexNextId=0;
- pHull->VolumeNextId=0;
- HashElem *i;
- for(i=readiHashFirst(&pHull->VolumeHash); i; i=readiHashNext(i)) {
- char *ptr=(char *)readiHashData(i);
- Odie_Free((char *)ptr);
- }
- readiHashClear(&pHull->VolumeHash);
- for(i=readiHashFirst(&pHull->FaceHash); i; i=readiHashNext(i)) {
- char *ptr=(char *)readiHashData(i);
- Odie_Free((char *)ptr);
- }
- readiHashClear(&pHull->FaceHash);
- for(i=readiHashFirst(&pHull->VertexHash); i; i=readiHashNext(i)) {
- char *ptr=(char *)readiHashData(i);
- Odie_Free((char *)ptr);
- }
- readiHashClear(&pHull->VertexHash);
- }
- /* PolygonHull_Delete */
- static void PolygonHull_Delete(ClientData clientData){
- PolygonHull *pHull = (PolygonHull *)clientData;
- PolygonHull_Reset(pHull);
- Odie_Free((char *) pHull);
- }
- /* PolygonHull_Clone */
- static int PolygonHull_Clone(
- Tcl_Interp* interp, /* Tcl interpreter for error reporting */
- ClientData metadata, /* Metadata to be cloned */
- ClientData* newMetaData /* Where to put the cloned metadata */
- ){
- Tcl_SetObjResult(interp,
- Tcl_NewStringObj("POLYGONHULLs are not clonable", -1));
- /* For now... */
- return TCL_ERROR;
- }
- /* *Odie_Obj_To_Int */
- Tcl_Obj *Odie_Obj_To_Int(Tcl_Obj *tclObj){
- int sint;
- double s;
- if (Tcl_GetIntFromObj(NULL,tclObj,&sint)==TCL_OK) {
- return tclObj;
- }
- if (Tcl_GetDoubleFromObj(NULL,tclObj,&s)) {
- return tclObj;
- }
- return Tcl_NewIntObj((int)round(s));
- }
- /* Odie_trace_printf */
- void Odie_trace_printf(Tcl_Interp *interp,const char *zFormat, ...){
- /*
- ** Print a trace message
- */
- int n;
- va_list ap;
- char zBuf[4000];
-
- va_start(ap, zFormat);
- strcpy(zBuf, "puts -nonewline \x7b");
- n = strlen(zBuf);
- vsnprintf(&zBuf[n], sizeof(zBuf)-5-n, zFormat, ap);
- strcat(zBuf, "\x7d\n");
- Tcl_Eval(interp, zBuf);
- }
- /*
- *----------------------------------------------------------------------
- *
- * MergeLists -
- *
- * This procedure combines two sorted lists of SortElement structures
- * into a single sorted list.
- *
- * Results:
- * The unified list of SortElement structures.
- *
- * Side effects:
- * If infoPtr->unique is set then infoPtr->numElements may be updated.
- * Possibly others, if a user-defined comparison command does something
- * weird.
- *
- * Note:
- * If infoPtr->unique is set, the merge assumes that there are no
- * "repeated" elements in each of the left and right lists. In that case,
- * if any element of the left list is equivalent to one in the right list
- * it is omitted from the merged list.
- * This simplified mechanism works because of the special way
- * our MergeSort creates the sublists to be merged and will fail to
- * eliminate all repeats in the general case where they are already
- * present in either the left or right list. A general code would need to
- * skip adjacent initial repeats in the left and right lists before
- * comparing their initial elements, at each step.
- *----------------------------------------------------------------------
- */
-
- static SortElement *
- MergeLists(
- SortElement *leftPtr, /* First list to be merged; may be NULL. */
- SortElement *rightPtr, /* Second list to be merged; may be NULL. */
- SortInfo *infoPtr) /* Information needed by the comparison
- * operator. */
- {
- SortElement *headPtr, *tailPtr;
- int cmp;
-
- if (leftPtr == NULL) {
- return rightPtr;
- }
- if (rightPtr == NULL) {
- return leftPtr;
- }
- cmp = SortCompare(leftPtr, rightPtr, infoPtr);
- if (cmp > 0 || (cmp == 0 && infoPtr->unique)) {
- if (cmp == 0) {
- infoPtr->numElements--;
- leftPtr = leftPtr->nextPtr;
- }
- tailPtr = rightPtr;
- rightPtr = rightPtr->nextPtr;
- } else {
- tailPtr = leftPtr;
- leftPtr = leftPtr->nextPtr;
- }
- headPtr = tailPtr;
- if (!infoPtr->unique) {
- while ((leftPtr != NULL) && (rightPtr != NULL)) {
- cmp = SortCompare(leftPtr, rightPtr, infoPtr);
- if (cmp > 0) {
- tailPtr->nextPtr = rightPtr;
- tailPtr = rightPtr;
- rightPtr = rightPtr->nextPtr;
- } else {
- tailPtr->nextPtr = leftPtr;
- tailPtr = leftPtr;
- leftPtr = leftPtr->nextPtr;
- }
- }
- } else {
- while ((leftPtr != NULL) && (rightPtr != NULL)) {
- cmp = SortCompare(leftPtr, rightPtr, infoPtr);
- if (cmp >= 0) {
- if (cmp == 0) {
- infoPtr->numElements--;
- leftPtr = leftPtr->nextPtr;
- }
- tailPtr->nextPtr = rightPtr;
- tailPtr = rightPtr;
- rightPtr = rightPtr->nextPtr;
- } else {
- tailPtr->nextPtr = leftPtr;
- tailPtr = leftPtr;
- leftPtr = leftPtr->nextPtr;
- }
- }
- }
- if (leftPtr != NULL) {
- tailPtr->nextPtr = leftPtr;
- } else {
- tailPtr->nextPtr = rightPtr;
- }
- return headPtr;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * SortCompare --
- *
- * This procedure is invoked by MergeLists to determine the proper
- * ordering between two elements.
- *
- * Results:
- * A negative results means the the first element comes before the
- * second, and a positive results means that the second element should
- * come first. A result of zero means the two elements are equal and it
- * doesn't matter which comes first.
- *
- * Side effects:
- * None, unless a user-defined comparison command does something weird.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- SortCompare(
- SortElement *elemPtr1, SortElement *elemPtr2,
- /* Values to be compared. */
- SortInfo *infoPtr) /* Information passed from the top-level
- * "lsort" command. */
- {
- int order = 0;
-
- if (infoPtr->sortMode == SORTMODE_ASCII) {
- order = strcmp(elemPtr1->index.strValuePtr,
- elemPtr2->index.strValuePtr);
- } else if (infoPtr->sortMode == SORTMODE_ASCII_NC) {
- order = strcasecmp(elemPtr1->index.strValuePtr,
- elemPtr2->index.strValuePtr);
- } else if (infoPtr->sortMode == SORTMODE_DICTIONARY) {
- order = DictionaryCompare(elemPtr1->index.strValuePtr,
- elemPtr2->index.strValuePtr);
- } else if (infoPtr->sortMode == SORTMODE_INTEGER) {
- long a, b;
-
- a = elemPtr1->index.intValue;
- b = elemPtr2->index.intValue;
- order = ((a >= b) - (a <= b));
- } else if (infoPtr->sortMode == SORTMODE_REAL) {
- double a, b;
-
- a = elemPtr1->index.doubleValue;
- b = elemPtr2->index.doubleValue;
- order = ((a >= b) - (a <= b));
- } else {
- Tcl_Obj **objv, *paramObjv[2];
- int objc;
- Tcl_Obj *objPtr1, *objPtr2;
-
- if (infoPtr->resultCode != TCL_OK) {
- /*
- * Once an error has occurred, skip any future comparisons so as
- * to preserve the error message in sortInterp->result.
- */
-
- return 0;
- }
-
-
- objPtr1 = elemPtr1->index.objValuePtr;
- objPtr2 = elemPtr2->index.objValuePtr;
-
- paramObjv[0] = objPtr1;
- paramObjv[1] = objPtr2;
-
- /*
- * We made space in the command list for the two things to compare.
- * Replace them and evaluate the result.
- */
-
- Tcl_ListObjLength(infoPtr->interp, infoPtr->compareCmdPtr, &objc);
- Tcl_ListObjReplace(infoPtr->interp, infoPtr->compareCmdPtr, objc - 2,
- 2, 2, paramObjv);
- Tcl_ListObjGetElements(infoPtr->interp, infoPtr->compareCmdPtr,
- &objc, &objv);
-
- infoPtr->resultCode = Tcl_EvalObjv(infoPtr->interp, objc, objv, 0);
-
- if (infoPtr->resultCode != TCL_OK) {
- Tcl_AddErrorInfo(infoPtr->interp,
- "\n (-compare command)");
- return 0;
- }
-
- /*
- * Parse the result of the command.
- */
-
- if (Tcl_GetIntFromObj(infoPtr->interp,
- Tcl_GetObjResult(infoPtr->interp), &order) != TCL_OK) {
- Tcl_ResetResult(infoPtr->interp);
- Tcl_AppendResult(infoPtr->interp,
- "-compare command returned non-integer result", NULL);
- infoPtr->resultCode = TCL_ERROR;
- return 0;
- }
- }
- if (!infoPtr->isIncreasing) {
- order = -order;
- }
- return order;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * DictionaryCompare
- *
- * This function compares two strings as if they were being used in an
- * index or card catalog. The case of alphabetic characters is ignored,
- * except to break ties. Thus "B" comes before "b" but after "a". Also,
- * integers embedded in the strings compare in numerical order. In other
- * words, "x10y" comes after "x9y", not * before it as it would when
- * using strcmp().
- *
- * Results:
- * A negative result means that the first element comes before the
- * second, and a positive result means that the second element should
- * come first. A result of zero means the two elements are equal and it
- * doesn't matter which comes first.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- DictionaryCompare(
- char *left, char *right) /* The strings to compare. */
- {
- Tcl_UniChar uniLeft, uniRight, uniLeftLower, uniRightLower;
- int diff, zeros;
- int secondaryDiff = 0;
-
- while (1) {
- if (isdigit(UCHAR(*right)) /* INTL: digit */
- && isdigit(UCHAR(*left))) { /* INTL: digit */
- /*
- * There are decimal numbers embedded in the two strings. Compare
- * them as numbers, rather than strings. If one number has more
- * leading zeros than the other, the number with more leading
- * zeros sorts later, but only as a secondary choice.
- */
-
- zeros = 0;
- while ((*right == '0') && (isdigit(UCHAR(right[1])))) {
- right++;
- zeros--;
- }
- while ((*left == '0') && (isdigit(UCHAR(left[1])))) {
- left++;
- zeros++;
- }
- if (secondaryDiff == 0) {
- secondaryDiff = zeros;
- }
-
- /*
- * The code below compares the numbers in the two strings without
- * ever converting them to integers. It does this by first
- * comparing the lengths of the numbers and then comparing the
- * digit values.
- */
-
- diff = 0;
- while (1) {
- if (diff == 0) {
- diff = UCHAR(*left) - UCHAR(*right);
- }
- right++;
- left++;
- if (!isdigit(UCHAR(*right))) { /* INTL: digit */
- if (isdigit(UCHAR(*left))) { /* INTL: digit */
- return 1;
- } else {
- /*
- * The two numbers have the same length. See if their
- * values are different.
- */
-
- if (diff != 0) {
- return diff;
- }
- break;
- }
- } else if (!isdigit(UCHAR(*left))) { /* INTL: digit */
- return -1;
- }
- }
- continue;
- }
-
- /*
- * Convert character to Unicode for comparison purposes. If either
- * string is at the terminating null, do a byte-wise comparison and
- * bail out immediately.
- */
-
- if ((*left != '\0') && (*right != '\0')) {
- left += Tcl_UtfToUniChar(left, &uniLeft);
- right += Tcl_UtfToUniChar(right, &uniRight);
-
- /*
- * Convert both chars to lower for the comparison, because
- * dictionary sorts are case insensitve. Covert to lower, not
- * upper, so chars between Z and a will sort before A (where most
- * other interesting punctuations occur).
- */
-
- uniLeftLower = Tcl_UniCharToLower(uniLeft);
- uniRightLower = Tcl_UniCharToLower(uniRight);
- } else {
- diff = UCHAR(*left) - UCHAR(*right);
- break;
- }
-
- diff = uniLeftLower - uniRightLower;
- if (diff) {
- return diff;
- }
- if (secondaryDiff == 0) {
- if (Tcl_UniCharIsUpper(uniLeft) && Tcl_UniCharIsLower(uniRight)) {
- secondaryDiff = -1;
- } else if (Tcl_UniCharIsUpper(uniRight)
- && Tcl_UniCharIsLower(uniLeft)) {
- secondaryDiff = 1;
- }
- }
- }
- if (diff == 0) {
- diff = secondaryDiff;
- }
- return diff;
- }
-
-
- static int Odie_SortElement_FromObj(
- Tcl_Interp *interp,
- int sortMode,
- Tcl_Obj *valuePtr,
- SortElement *elementPtr
- ) {
- /*
- * Determine the "value" of this object for sorting purposes
- */
- if (sortMode == SORTMODE_ASCII) {
- elementPtr->index.strValuePtr = Tcl_GetString(valuePtr);
- } else if (sortMode == SORTMODE_INTEGER) {
- long a;
-
- if (Tcl_GetLongFromObj(interp, valuePtr, &a) != TCL_OK) {
- return TCL_ERROR;
- }
- elementPtr->index.intValue = a;
- } else if (sortMode == SORTMODE_REAL) {
- double a;
-
- if (Tcl_GetDoubleFromObj(interp, valuePtr, &a) != TCL_OK) {
- return TCL_ERROR;
- }
- elementPtr->index.doubleValue = a;
- } else {
- elementPtr->index.objValuePtr = valuePtr;
- }
- elementPtr->objPtr = valuePtr;
- return TCL_OK;
- }
- /* *Odie_MergeList_ToObj */
- static Tcl_Obj *Odie_MergeList_ToObj(SortElement *elementPtr){
- /*
- ** Converts a linked list of structures into
- ** a Tcl list object
- */
- SortElement *loopPtr;
- Tcl_Obj **newArray;
- int i,len=0;
- loopPtr=elementPtr;
- for (len=0; loopPtr != NULL ; loopPtr = loopPtr->nextPtr) {
- len++;
- }
- newArray = (Tcl_Obj **)Odie_Alloc(sizeof(Tcl_Obj *)*len);
- loopPtr=elementPtr;
- for (i=0; loopPtr != NULL ; loopPtr = loopPtr->nextPtr) {
- Tcl_Obj *objPtr = loopPtr->objPtr;
- newArray[i] = objPtr;
- i++;
- //Tcl_IncrRefCount(objPtr);
- }
- return Tcl_NewListObj(len,newArray);
- }
- /* Odie_Lsearch */
- STUB_EXPORT int Odie_Lsearch(int listLength,Tcl_Obj **listObjPtrs,Tcl_Obj *element){
- int i;
- Tcl_Obj *o;
- if(element==NULL) {
- return -1;
- }
-
- int matchLen;
- char *match=Tcl_GetStringFromObj(element,&matchLen);
-
- int s2len,found;
- const char *s2;
-
- if(matchLen < 0) {
- return -1;
- }
-
- found = 0;
- for(i=0;i<listLength && !found;i++) {
- o=listObjPtrs[i];
- if (o != NULL) {
- s2 = Tcl_GetStringFromObj(o, &s2len);
- } else {
- s2 = "";
- }
- if (matchLen == s2len) {
- found = (strcmp(match, s2) == 0);
- if(found) {
- return i;
- }
- }
- }
- return -1;
- }
- /* *Logicset_To_TclObj */
- STUB_EXPORT Tcl_Obj *Logicset_To_TclObj(Tcl_Obj *set){
- if(set) {
- return Tcl_DuplicateObj(set);
- } else {
- return Tcl_NewObj();
- }
- }
- /* Logicset_LIST_RESET */
- STUB_EXPORT void Logicset_LIST_RESET(Tcl_Obj **set){
- if(*set) {
- Tcl_DecrRefCount(*set);
- }
- *set=Tcl_NewObj();
- }
- /* Logicset_LIST_CONTAINS */
- STUB_EXPORT int Logicset_LIST_CONTAINS(Tcl_Obj **aPtrs,int aLength,Tcl_Obj *element){
- if(element==NULL) return 0;
- if(aLength<1) return 0;
-
- int matchIdx=Odie_Lsearch(aLength,aPtrs,element);
- if(matchIdx>=0) {
- return 1;
- }
- return 0;
- }
- /* Logicset_Sanitize_List */
- STUB_EXPORT void Logicset_Sanitize_List(char *value,int len){
- int i,skipped=0;
- for(i=0;i<len;i++) {
- unsigned char x=value[i];
- skipped++;
- /* Anything outside this range in non-printable, whitespace, or a delimeter */
- if(x<0x30 || x>0x80 || x==0x7D || x==0x7B) {
- value[i]=0x20;
- continue;
- }
- skipped--;
- }
- }
- /* *Logicset_FromObj */
- STUB_EXPORT Tcl_Obj *Logicset_FromObj(Tcl_Obj *rawlist){
- if(!rawlist) {
- return NULL;
- }
- int len;
- char *rawvalue=Tcl_GetStringFromObj(rawlist,&len);
- if(len==0) {
- return NULL;
- }
- Logicset_Sanitize_List(rawvalue,len);
- Tcl_Obj *tempString=Tcl_NewStringObj(rawvalue,len);
-
- int listLength,i;
- Tcl_Obj **listObjPtrs;
- if(Tcl_ListObjGetElements(NULL, tempString, &listLength, &listObjPtrs)) {
- Tcl_DecrRefCount(tempString);
- return NULL;
- }
- if(listLength <= 0) {
- Tcl_DecrRefCount(tempString);
- return NULL;
- }
- Tcl_Obj *listObj=Tcl_NewObj();
- for(i=0;i<listLength;i++) {
- Logicset_Add(listObj,listObjPtrs[i]);
- }
- Tcl_DecrRefCount(tempString);
- return listObj;
- }
- /* Logicset_Add */
- STUB_EXPORT int Logicset_Add(Tcl_Obj *aset,Tcl_Obj *element){
- int listLength;
- int i;
- Tcl_Obj **listObjPtrs;
-
- if(element==NULL) {
- return TCL_OK;
- }
- int matchLen;
- char *match=Tcl_GetStringFromObj(element,&matchLen);
-
- int s2len;
- const char *s2;
-
- if(matchLen < 0) {
- return TCL_ERROR;
- }
- if(Tcl_ListObjGetElements(NULL, aset, &listLength, &listObjPtrs)) {
- return TCL_ERROR;
- }
- /* Check that item isn't in list already */
- int found = 0;
- for(i=0;i<listLength && !found;i++) {
- Tcl_Obj *o=listObjPtrs[i];
- if (o != NULL) {
- s2 = Tcl_GetStringFromObj(o, &s2len);
- } else {
- s2 = "";
- }
- if (matchLen == s2len) {
- found = (strcmp(match, s2) == 0);
- if(found) {
- return TCL_OK;
- }
- }
- }
- for(i=0;i<listLength;i++) {
- int cmp = 0;
- Tcl_Obj *o=listObjPtrs[i];
- if (o != NULL) {
- s2 = Tcl_GetStringFromObj(o, &s2len);
- } else {
- s2 = "";
- }
- cmp = strcmp(match, s2);
- if(cmp==0) {
- return TCL_OK;
- } else if (cmp<0) {
- Tcl_Obj *NewVals[1];
- NewVals[0]=element;
- /* Add the new element here */
- return Tcl_ListObjReplace(NULL,aset,i,0,1,NewVals);
- }
- }
- Tcl_ListObjAppendElement(NULL,aset,element);
- return TCL_OK;
- }
- /* Logicset_Include */
- STUB_EXPORT void Logicset_Include(Tcl_Obj *aset,Tcl_Obj *bset){
- /*
- ** Add all elements of A and B together into a new set
- */
- if(!aset || !bset) {
- return;
- }
- int bLength;
- Tcl_Obj **bPtrs;
- if(Tcl_ListObjGetElements(0, bset, &bLength, &bPtrs)) {
- return;
- }
- if(bLength==0) {
- return;
- }
- if(bLength>1) {
- int i;
- for(i=0;i<bLength;i++) {
- Logicset_Include(aset,bPtrs[i]);
- }
- } else {
- if(Logicset_Add(aset,bPtrs[0])) {
- return;
- }
- }
- return;
- }
- /* Logicset_EXPR_AND */
- STUB_EXPORT int Logicset_EXPR_AND(Tcl_Obj *aset,Tcl_Obj *bset){
- /*
- ** Returns 1 if all elements in B are contained in A
- */
- int aLength;
- Tcl_Obj **aPtrs;
- if(!aset || !bset) return 0;
- if(Tcl_ListObjGetElements(0, aset, &aLength, &aPtrs)) {
- return 0;
- }
- int bLength;
- Tcl_Obj **bPtrs;
- if(Tcl_ListObjGetElements(0, bset, &bLength, &bPtrs)) {
- return 0;
- }
- int i;
- for(i=0;i<bLength;i++) {
- int found=Logicset_LIST_CONTAINS(aPtrs,aLength,bPtrs[i]);
- if(!found) {
- return 0;
- }
- }
- return 1;
- }
- /* Logicset_EXPR_OR */
- STUB_EXPORT int Logicset_EXPR_OR(Tcl_Obj *aset,Tcl_Obj *bset){
- int aLength;
- Tcl_Obj **aPtrs;
- if(!aset || !bset) return 0;
- if(Tcl_ListObjGetElements(0, aset, &aLength, &aPtrs)) {
- return 0;
- }
- int bLength;
- Tcl_Obj **bPtrs;
- if(Tcl_ListObjGetElements(0, bset, &bLength, &bPtrs)) {
- return 0;
- }
- int i;
- for(i=0;i<bLength;i++) {
- int found=Logicset_LIST_CONTAINS(aPtrs,aLength,bPtrs[i]);
- if(found) {
- return 1;
- }
- }
- return 0;
- }
- /* *Logicset_PRODUCT_INTERSECT */
- STUB_EXPORT Tcl_Obj *Logicset_PRODUCT_INTERSECT(Tcl_Obj *aset,Tcl_Obj *bset){
- int aLength;
- Tcl_Obj **aPtrs;
- if(!aset) {
- return bset;
- }
- if(!bset) {
- return aset;
- }
- if(Tcl_ListObjGetElements(0, aset, &aLength, &aPtrs)) return bset;
- int bLength;
- Tcl_Obj **bPtrs;
- if(Tcl_ListObjGetElements(0, bset, &bLength, &bPtrs)) return aset;
- int i,resultlen=0;
- Tcl_Obj *result=Tcl_NewObj();
- for(i=0;i<bLength;i++) {
- int found=Logicset_LIST_CONTAINS(aPtrs,aLength,bPtrs[i]);
- if(found) {
- resultlen++;
- Logicset_Add(result,bPtrs[i]);
- }
- }
- if(!resultlen) {
- Tcl_DecrRefCount(result);
- return NULL;
- }
- return result;
- }
- /* *Logicset_PRODUCT_UNION */
- STUB_EXPORT Tcl_Obj *Logicset_PRODUCT_UNION(Tcl_Obj *aset,Tcl_Obj *bset){
- if(!aset) {
- return bset;
- }
- if(!bset) {
- return aset;
- }
- Tcl_Obj *listObj=Tcl_NewObj();
- Logicset_Include(listObj,aset);
- Logicset_Include(listObj,bset);
- return listObj;
- }
- /* *Logicset_PRODUCT_XOR */
- STUB_EXPORT Tcl_Obj *Logicset_PRODUCT_XOR(Tcl_Obj *aset,Tcl_Obj *bset){
- int aLength;
- Tcl_Obj **aPtrs;
- if(!aset) {
- return bset;
- }
- if(!bset) {
- return aset;
- }
- if(Tcl_ListObjGetElements(0, aset, &aLength, &aPtrs)) return bset;
- int bLength;
- Tcl_Obj **bPtrs;
- if(Tcl_ListObjGetElements(0, bset, &bLength, &bPtrs)) return aset;
- int i,resultlen=0;
- Tcl_Obj *result=Tcl_NewObj();
- for(i=0;i<bLength;i++) {
- int found=Logicset_LIST_CONTAINS(aPtrs,aLength,bPtrs[i]);
- if(!found) {
- resultlen++;
- Logicset_Add(result,bPtrs[i]);
- }
- }
- for(i=0;i<aLength;i++) {
- int found=Logicset_LIST_CONTAINS(bPtrs,bLength,aPtrs[i]);
- if(!found) {
- resultlen++;
- Logicset_Add(result,aPtrs[i]);
- }
- }
- if(!resultlen) {
- Tcl_DecrRefCount(result);
- return NULL;
- }
- Tcl_Obj *resultPtr=Odie_ListObj_Sort(result);
- if(resultPtr!=result) {
- Tcl_DecrRefCount(result);
- }
- return resultPtr;
- }
- /* *Logicset_PRODUCT_MISSING */
- STUB_EXPORT Tcl_Obj *Logicset_PRODUCT_MISSING(Tcl_Obj *aset,Tcl_Obj *bset){
- int aLength;
- Tcl_Obj **aPtrs;
- if(!aset) {
- return NULL;
- }
- if(!bset) {
- return aset;
- }
- if(Tcl_ListObjGetElements(0, aset, &aLength, &aPtrs)) return bset;
- int bLength;
- Tcl_Obj **bPtrs;
- if(Tcl_ListObjGetElements(0, bset, &bLength, &bPtrs)) return aset;
- int i,resultlen=0;
- Tcl_Obj *result=Tcl_NewObj();
- for(i=0;i<aLength;i++) {
- int found=Logicset_LIST_CONTAINS(bPtrs,bLength,aPtrs[i]);
- if(!found) {
- resultlen++;
- Logicset_Add(result,aPtrs[i]);
- }
- }
- if(!resultlen) {
- Tcl_DecrRefCount(result);
- return NULL;
- }
- return result;
- }
- /* *Odie_ListObj_Sort */
- STUB_EXPORT Tcl_Obj *Odie_ListObj_Sort(Tcl_Obj *listObj){
- Tcl_Obj *resultPtr=NULL;
- int i, j, length, sortMode;
- int idx;
- Tcl_Obj **listObjPtrs, *indexPtr;
- SortElement *elementArray, *elementPtr;
- SortInfo sortInfo;
-
- sortInfo.isIncreasing = 1;
- sortInfo.sortMode = SORTMODE_DICTIONARY;
- sortInfo.indexv = NULL;
- sortInfo.unique = 1;
- sortInfo.interp = NULL;
- sortInfo.resultCode = TCL_OK;
-
- /*
- * The subList array below holds pointers to temporary lists built during
- * the merge sort. Element i of the array holds a list of length 2**i.
- */
- # define NUM_LISTS 30
- SortElement *subList[NUM_LISTS+1];
-
-
- sortInfo.resultCode = Tcl_ListObjGetElements(sortInfo.interp, listObj,
- &length, &listObjPtrs);
-
- if(length<2) {
- /*
- ** If the list is zero length, just return
- ** the original pointer
- */
- return listObj;
- }
-
- if (sortInfo.resultCode != TCL_OK || length <= 0) {
- goto done;
- }
-
- sortInfo.numElements = length;
-
- sortMode = sortInfo.sortMode;
- if ((sortMode == SORTMODE_ASCII_NC)
- || (sortMode == SORTMODE_DICTIONARY)) {
- /*
- * For this function's purpose all string-based modes are equivalent
- */
- sortMode = SORTMODE_ASCII;
- }
-
- /*
- * Initialize the sublists. After the following loop, subList[i] will
- * contain a sorted sublist of length 2**i. Use one extra subList at the
- * end, always at NULL, to indicate the end of the lists.
- */
-
- for (j=0 ; j<=NUM_LISTS ; j++) {
- subList[j] = NULL;
- }
-
- /*
- * The following loop creates a SortElement for each list element and
- * begins sorting it into the sublists as it appears.
- */
-
- elementArray = (SortElement *) Odie_Alloc( length * sizeof(SortElement));
-
- for (i=0; i < length; i++){
- idx = i;
- indexPtr = listObjPtrs[idx];
- sortInfo.resultCode=Odie_SortElement_FromObj(sortInfo.interp,sortMode,indexPtr,&elementArray[i]);
- if(sortInfo.resultCode!=TCL_OK) {
- goto done1;
- }
- }
-
- for (i=0; i < length; i++){
- /*
- * Merge this element in the pre-existing sublists (and merge together
- * sublists when we have two of the same size).
- */
-
- elementArray[i].nextPtr = NULL;
- elementPtr = &elementArray[i];
- for (j=0 ; subList[j] ; j++) {
- elementPtr = MergeLists(subList[j], elementPtr, &sortInfo);
- subList[j] = NULL;
- }
- if (j >= NUM_LISTS) {
- j = NUM_LISTS-1;
- }
- subList[j] = elementPtr;
- }
-
- /*
- * Merge all sublists
- */
-
- elementPtr = subList[0];
- for (j=1 ; j<NUM_LISTS ; j++) {
- elementPtr = MergeLists(subList[j], elementPtr, &sortInfo);
- }
-
- /*
- * Now store the sorted elements in the result list.
- */
-
- if (sortInfo.resultCode == TCL_OK) {
- resultPtr=Odie_MergeList_ToObj(elementPtr);
-
- }
-
- done1:
- Odie_Free((char *) elementArray);
-
- done:
- if (sortInfo.sortMode == SORTMODE_COMMAND) {
- Tcl_DecrRefCount(sortInfo.compareCmdPtr);
- Tcl_DecrRefCount(listObj);
- sortInfo.compareCmdPtr = NULL;
- }
- if (sortInfo.resultCode != TCL_OK) {
- return NULL;
- }
- return resultPtr;
- }
- /* Odie_Trace */
- int Odie_Trace(int newvalue){
- OdieTrace=newvalue;
- return OdieTrace;
- }
- /* *Odie_LiteralConstantObj */
- Tcl_Obj *Odie_LiteralConstantObj(int which){
- if(which > ODIE_STATIC_MAX || which < 0) {
- Tcl_IncrRefCount(OdieStatic[ODIE_STATIC_NULL]);
- return OdieStatic[ODIE_STATIC_NULL];
- }
- Tcl_IncrRefCount(OdieStatic[which]);
- return OdieStatic[which];
- }
- /* *Odie_StoreObj */
- Tcl_Obj *Odie_StoreObj(Tcl_Obj *value){
- Tcl_Obj *storedVal;
- double floatVal;
- int intVal,strLen;
- char *stringVal,*strtmp;
- if(!value) {
- storedVal=OdieStatic[ODIE_STATIC_NULL];
- Tcl_IncrRefCount(storedVal);
- nOdieDictSpecNull++;
- return storedVal;
- }
- /* If this value is already shared, just store it and bump the refcount */
- if(Tcl_IsShared(value)) {
- Tcl_IncrRefCount(value);
- nOdieDictSpecRecycled++;
- return value;
- }
- /* Try to map this string to an existing literal */
- stringVal=Tcl_GetString(value);
- storedVal=Odie_constant(stringVal,0);
- if(storedVal) {
- Tcl_IncrRefCount(storedVal);
- nOdieDictSpecShared++;
- return storedVal;
- }
- /* Avoid storing a list or other volitile data */
- strtmp=strchr(stringVal,' ');
- if(!strtmp) {
- strtmp=strchr(stringVal,'/');
- if(!strtmp) {
- storedVal=Odie_constant(stringVal,1);
- Tcl_IncrRefCount(storedVal);
- return storedVal;
- }
- }
- Tcl_IncrRefCount(value);
- return value;
- }
- /* *Odie_constant */
- static Tcl_Obj *Odie_constant(const char *zName,int create){
- int len,isNew=0;
- Tcl_HashEntry *pEntry;
- Tcl_Obj *p;
- if(zName==NULL) {
- return NULL;
- }
- if(create) {
- pEntry=Tcl_CreateHashEntry(&OdieLiteralStringTable,zName,&isNew);
- } else {
- pEntry=Tcl_FindHashEntry(&OdieLiteralStringTable,zName);
- }
- if(isNew) {
- nOdieObjString++;
- len = strlen(zName);
- p=Tcl_NewStringObj(zName,len);
- Tcl_IncrRefCount(p);
- Tcl_SetHashValue(pEntry,(ClientData)p);
- return p;
- }
- if(pEntry) {
- p=(Tcl_Obj*)Tcl_GetHashValue(pEntry);
- return p;
- }
- return NULL;
- }
- /* Odie_SameString */
- int Odie_SameString(char *aPtr,char *bPtr){
- if(aPtr==bPtr) {
- return 1;
- }
- if(!bPtr || !aPtr) {
- return 0;
- }
- if(strcmp(aPtr,bPtr)==0) {
- return 1;
- }
- return 0;
- }
- /* *Odie_LiteralString */
- char *Odie_LiteralString(const char *zName){
- Tcl_Obj *p;
- p=Odie_constant(zName,1);
- return Tcl_GetString(p);
- }
- /* *Odie_LiteralStringObj */
- Tcl_Obj *Odie_LiteralStringObj(const char *zName){
- Tcl_Obj *p;
- p=Odie_constant(zName,1);
- Tcl_IncrRefCount(p);
- return p;
- }
- /* Odie_DictObjPut */
- inline extern int Odie_DictObjPut(Tcl_Interp *interp,Tcl_Obj *pDictObj,const char *pField,Tcl_Obj *pValue){
- int result=TCL_OK;
- if(!pValue) {
- return TCL_OK;
- }
- result=Tcl_DictObjPut(interp,pDictObj,Odie_LiteralStringObj(pField),pValue);
- return result;
- }
- /* *Odie_HashGet */
- Tcl_Obj *Odie_HashGet(Tcl_HashTable *localDict,char *fieldStr){
- Tcl_Obj *valuePtr;
- Tcl_HashEntry *i;
- if(!localDict) {
- return NULL;
- }
- i=Tcl_FindHashEntry(localDict,fieldStr);
- if(!i) {
- return NULL;
- }
- valuePtr=(Tcl_Obj*)Tcl_GetHashValue(i);
- if(!valuePtr) {
- return NULL;
- }
- nOdieDictSpecAccessed++;
- Tcl_IncrRefCount(valuePtr);
- return valuePtr;
- }
- /* Odie_HashPut */
- void Odie_HashPut(Tcl_HashTable **infoDictPtr,const char *key,Tcl_Obj *value){
- Tcl_HashTable *result=*infoDictPtr;
- Tcl_HashEntry *pEntry;
- Tcl_Obj *valuePtr;
- int isNew=0;
- int delete=0,len=0;
- char *valueStr;
- if(value==NULL) {
- delete=1;
- }
- valueStr=Tcl_GetString(value);
- len=strlen(valueStr);
- if(len==0) {
- delete=1;
- }
-
- if(!result && delete) {
- return;
- }
- if(!result) {
- result=(Tcl_HashTable*)Odie_Alloc( sizeof(Tcl_HashTable) );
- Tcl_InitHashTable(result,TCL_STRING_KEYS);
- nOdieHashTable++;
- nOdieHashTableCreated++;
- *infoDictPtr=result;
- }
- if(delete) {
- /* If we were given a null or an empty string, delete */
- pEntry=Tcl_FindHashEntry(result,key);
- if(!pEntry) return;
- nOdieDictSpecDeleted++;
- nOdieDictSpecCount--;
- valuePtr=(Tcl_Obj*)Tcl_GetHashValue(pEntry);
- Tcl_DecrRefCount(valuePtr);
- Tcl_DeleteHashEntry(pEntry);
- return;
- }
- pEntry=Tcl_CreateHashEntry(result,Odie_LiteralString(key),&isNew);
- if(!isNew) {
- valuePtr=(Tcl_Obj*)Tcl_GetHashValue(pEntry);
- nOdieDictSpecModified++;
- Tcl_DecrRefCount(valuePtr);
- } else {
- nOdieDictSpecCreated++;
- nOdieDictSpecCount++;
- }
- valuePtr=Odie_StoreObj(value);
- Tcl_SetHashValue(pEntry,valuePtr);
- return;
- }
- /* Odie_HashFree */
- void Odie_HashFree(Tcl_HashTable **infoDictPtr){
- if(*infoDictPtr) {
- Tcl_HashSearch searchPtr;
- Tcl_HashEntry *i;
- Tcl_HashTable *ptr=*infoDictPtr;
- for(i=Tcl_FirstHashEntry(ptr,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
- Tcl_Obj *valuePtr=(Tcl_Obj *)Tcl_GetHashValue(i);
- Tcl_DecrRefCount(valuePtr);
- nOdieDictSpecCount--;
- nOdieDictSpecDeleted++;
- }
- nOdieHashTableDeleted++;
- nOdieHashTable--;
- Tcl_DeleteHashTable(ptr);
- Tcl_Free((char*)ptr);
- }
- *infoDictPtr=NULL;
- }
- /* Odie_constant_inject */
- static void Odie_constant_inject(Tcl_Obj *value){
- int len,isNew=0;
- char *zName=Tcl_GetString(value);
- Tcl_HashEntry *pEntry;
- pEntry=Tcl_CreateHashEntry(&OdieLiteralStringTable,zName,&isNew);
- if(isNew) {
- nOdieObjString++;
- Tcl_IncrRefCount(value);
- Tcl_SetHashValue(pEntry,(ClientData)value);
- }
- }
- /* Odie_RoidFromString */
- Roid Odie_RoidFromString(char *idstring,short charcode){
- char prefix[32];
- int id;
- int result;
-
- if(!idstring) {
- return -1;
- }
- result=sscanf(idstring,"%d",&id);
- if(result>0) {
- return id;
- }
- result=sscanf(idstring,"%c%d",prefix,&id);
- if(result>0) {
- return id;
- }
- return -1;
- }
- /* *Irm_NewLocationObj */
- Tcl_Obj *Irm_NewLocationObj(Irm_Location *loc){
- Tcl_Obj *pResult = Tcl_NewObj();
- Tcl_ListObjAppendElement(NULL, pResult, Odie_LiteralIntObj(loc->deckid));
- Tcl_ListObjAppendElement(NULL, pResult, Tcl_NewIntObj(loc->x));
- Tcl_ListObjAppendElement(NULL, pResult, Tcl_NewIntObj(loc->y));
- return pResult;
- }
- /* Location_FromName */
- int Location_FromName(char *stringVal,int *did,double *x,double *y,double *z){
- /*
- ** Obtain location from name
- */
- #ifdef build_IRM
- int deckid=0;
- char type=0;
- int roid;
- int found=0;
- int result=sscanf(stringVal,"%c%d-%d",&type,&roid,&deckid);
- #endif
- Irm_Location temp;
- temp.deckid=0;
- temp.x=0;
- temp.y=0;
- #ifdef build_IRM
- if(result==2 || result==3) {
- switch(type) {
- case 'c': {
- if(CrewRoute_ComptCenter(roid,deckid,&temp)) {
- if(deckid) {
- temp.deckid=deckid;
- } else {
- temp.deckid=1;
- }
- temp.x=0;
- temp.y=0;
- }
- found=1;
- break;
- }
- case 'e': {
- SimNode *pDest=SimNode_ById(roid,0);
- if(pDest) {
- SimNode_StructLocation(&temp,pDest);
- found=1;
- }
- break;
- }
- case 'p': {
- Portal *pDest=Portal_ById(roid,0);
- if(pDest) {
- Portal_StructLocation(&temp,pDest);
- found=1;
- }
- break;
- }
- case 'v': {
- Crew *pDest=Crew_ById(roid,0);
- if(pDest) {
- Crew_StructLocation(&temp,pDest);
- found=1;
- }
- break;
- }
- }
- }
- if (!found) {
- Entity *pDest=Entity_ByName(stringVal,0);
- if(!pDest) {
- return TCL_ERROR;
- }
- Entity_StructLocation(&temp,pDest);
- }
- #else
- Entity *pDest=Entity_ByName(stringVal,0);
- if(!pDest) {
- return TCL_ERROR;
- }
- Entity_StructLocation(&temp,pDest);
- #endif
- *did=temp.deckid;
- *x=temp.x;
- *y=temp.y;
- *z=temp.zoff;
- return TCL_OK;
- }
- /* Location_FromTclObj */
- int Location_FromTclObj(Tcl_Interp *interp, Tcl_Obj *pList,int *did,double *x,double *y){
- int listlen;
- Tcl_Obj **elist;
- double z;
- if(Tcl_ListObjGetElements(interp,pList,&listlen,&elist)) {
- return TCL_ERROR;
- }
- if(listlen == 1) {
- /*
- ** Obtain location from name
- */
- char *stringVal=Tcl_GetString(pList);
- if (Location_FromName(stringVal,did,x,y,&z)) {
- Tcl_AppendResult(interp, "Unknown entity ", stringVal, 0);
- return TCL_ERROR;
- }
- return TCL_OK;
- }
- if(listlen < 3 || listlen > 4) {
- Tcl_AppendResult(interp, "Could not interpret location ", Tcl_GetString(pList), 0);
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, elist[0], did) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, elist[1], x) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, elist[2], y) ) return TCL_ERROR;
- return TCL_OK;
- }
- /* Location_Base_FromTclObj */
- int Location_Base_FromTclObj(Tcl_Interp *interp, Tcl_Obj *pList,int *did,double *x,double *y,double *z){
- int listlen;
- Tcl_Obj **elist;
-
- if(Tcl_ListObjGetElements(interp,pList,&listlen,&elist)) {
- return TCL_ERROR;
- }
- if(listlen == 1) {
- /*
- ** Obtain location from name
- */
- char *stringVal=Tcl_GetString(pList);
- if (Location_FromName(stringVal,did,x,y,z)) {
- Tcl_AppendResult(interp, "Unknown entity ", stringVal, 0);
- return TCL_ERROR;
- }
- return TCL_OK;
- }
- if(listlen < 3 || listlen > 4) {
- Tcl_AppendResult(interp, "Could not interpret location ", Tcl_GetString(pList), 0);
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, elist[0], did) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, elist[1], x) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, elist[2], y) ) return TCL_ERROR;
- *z=0.0;
- if(listlen==4) {
- if( Tcl_GetDoubleFromObj(interp, elist[3], z) ) return TCL_ERROR;
- }
- return TCL_OK;
- }
- /* location_match */
- int location_match(Irm_Location *a,Irm_Location *b,int tolerance){
- /*
- ** Returns a 0 if the two points are "close enough"
- */
- int d;
- if(a==b) {
- return 1;
- }
- if(a->deckid!=b->deckid) {
- return 0;
- }
- d=a->x - b->x;
- if(d<-tolerance||d>tolerance) {
- return 0;
- }
- d=a->y - b->y;
- if(d<-tolerance||d>tolerance) {
- return 0;
- }
- return 1;
- }
- /* irm_gridhash_decompose */
- void irm_gridhash_decompose(Tcl_WideInt gridhash,int *style,int *rdeckid,int *rgx,int *rgy){
- Tcl_WideInt mask;
- int gy,gx,deckid;
- int isHex=0;
-
- /* Unpack the coordinates */
- mask=gridhash;
- gx=mask & 0xFFFF;
- if(gx & 0x8000) {
- /* Restore negative */
- gx-=0xffff;
- gx--;
- }
-
- mask>>=16;
- gy=mask & 0xFFF;
- if(gy & 0x800) {
- /* Restore negative */
- gy-=0xfff;
- gy--;
- }
-
- mask>>=12;
- deckid=mask & 0x3F;
-
- mask>>=6;
- isHex=mask;
-
- *style=isHex;
- *rdeckid=deckid;
- *rgx=gx;
- *rgy=gy;
- }
- /* irm_gridhash_compose */
- Tcl_WideInt irm_gridhash_compose (int style,int deckid,int gx,int gy){
- Tcl_WideInt result;
- result=(style&1);
- result<<=6;
- /* Encode the coordinate packed into a 32 bit integer */
- result|=(0x3F & deckid);
- result<<=12;
- result|=(0xFFF & gy);
- result<<=16;
- result|=(0xFFFF & gx);
- return result;
- }
- /* irm_squaregrid_hash */
- Tcl_WideInt irm_squaregrid_hash(int grid,int deckid,int x,int y){
- int gx,gy;
- gy=(int)round(y/grid);
- gx=(int)round(x/grid);
-
- return irm_gridhash_compose(0,deckid,gx,gy);
- }
- /* irm_hexgrid_hash */
- Tcl_WideInt irm_hexgrid_hash(int grid,int deckid,int x,int y){
- int gx,gy;
-
- gy=(int)round(y/grid);
- if(abs(gy)%2==1){
- gx=(int)round((x-grid/2)/grid);
- } else {
- gx=(int)round(x/grid);
- }
- return irm_gridhash_compose(1,deckid,gx,gy);
- }
- /* irm_gridhash_location */
- void irm_gridhash_location(Irm_Location *lPtr,Tcl_WideInt gridhash,int gridsize){
- int gy,gx,deckid;
- int isHex=0;
- irm_gridhash_decompose(gridhash,&isHex,&deckid,&gx,&gy);
-
- lPtr->deckid=deckid;
- lPtr->y=gy*gridsize;
- if(isHex) {
- if(abs(gy)%2==1) {
- lPtr->x=gx*gridsize+(gridsize/2);
- } else {
- lPtr->x=gx*gridsize;
- }
- } else {
- lPtr->x=gx*gridsize;
- }
- }
- /* Simulator_Init */
- void Simulator_Init(Simulator *p){}
- /* Simulator_Reset */
- void Simulator_Reset(Simulator *p){}
- /* Structure Entity */
-
- const struct OdieParamNameMap Entity_paramNameMap[] = {
- { "active", CSTRUCT_ENTITY_ACTIVE, PTYPE_INT },
- { "changed", CSTRUCT_ENTITY_CHANGED, PTYPE_INT },
- { "class", CSTRUCT_ENTITY_CLASS, PTYPE_FLOAT },
- { "drawn", CSTRUCT_ENTITY_DRAWN, PTYPE_INT },
- { "groupid", CSTRUCT_ENTITY_GROUPID, PTYPE_INT },
- { "hidden", CSTRUCT_ENTITY_HIDDEN, PTYPE_INT },
- { "highlight", CSTRUCT_ENTITY_HIGHLIGHT, PTYPE_INT },
- { "is_type", CSTRUCT_ENTITY_IS_TYPE, PTYPE_INT },
- { "moved", CSTRUCT_ENTITY_MOVED, PTYPE_INT },
- { "nchild", CSTRUCT_ENTITY_NCHILD, PTYPE_INT },
- { "oncount", CSTRUCT_ENTITY_ONCOUNT, PTYPE_INT },
- { "open", CSTRUCT_ENTITY_OPEN, PTYPE_INT },
- { "parent", CSTRUCT_ENTITY_PARENT, PTYPE_INT },
- { "redraw", CSTRUCT_ENTITY_REDRAW, PTYPE_INT },
- { "repaint", CSTRUCT_ENTITY_REPAINT, PTYPE_INT },
- { "synthetic", CSTRUCT_ENTITY_SYNTHETIC, PTYPE_INT },
- { "trace", CSTRUCT_ENTITY_TRACE, PTYPE_INT },
- { "visible", CSTRUCT_ENTITY_VISIBLE, PTYPE_INT },
- };
- const struct OdieParamNameMap Entity_canonicalNameMap[] = {
- { "active", CSTRUCT_ENTITY_ACTIVE, PTYPE_INT },
- { "changed", CSTRUCT_ENTITY_CHANGED, PTYPE_INT },
- { "class", CSTRUCT_ENTITY_CLASS, PTYPE_FLOAT },
- { "drawn", CSTRUCT_ENTITY_DRAWN, PTYPE_INT },
- { "groupid", CSTRUCT_ENTITY_GROUPID, PTYPE_INT },
- { "hidden", CSTRUCT_ENTITY_HIDDEN, PTYPE_INT },
- { "highlight", CSTRUCT_ENTITY_HIGHLIGHT, PTYPE_INT },
- { "is_type", CSTRUCT_ENTITY_IS_TYPE, PTYPE_INT },
- { "moved", CSTRUCT_ENTITY_MOVED, PTYPE_INT },
- { "nchild", CSTRUCT_ENTITY_NCHILD, PTYPE_INT },
- { "oncount", CSTRUCT_ENTITY_ONCOUNT, PTYPE_INT },
- { "open", CSTRUCT_ENTITY_OPEN, PTYPE_INT },
- { "parent", CSTRUCT_ENTITY_PARENT, PTYPE_INT },
- { "redraw", CSTRUCT_ENTITY_REDRAW, PTYPE_INT },
- { "repaint", CSTRUCT_ENTITY_REPAINT, PTYPE_INT },
- { "synthetic", CSTRUCT_ENTITY_SYNTHETIC, PTYPE_INT },
- { "trace", CSTRUCT_ENTITY_TRACE, PTYPE_INT },
- { "visible", CSTRUCT_ENTITY_VISIBLE, PTYPE_INT },
- };
-
-
- #include <math.h>
- #include <string.h>
-
- #define ENTITY_SEARCH_NCOUNT 15
-
- static const char *ENTITY_SEARCH_strs[] = {
- "active",
- "class",
- "comptid",
- "deckid",
- "drawn",
- "groupid",
- "hidden",
- "highlight",
- "moved",
- "redraw",
- "repaint",
- "synthetic",
- "trace",
- "typeid",
- "visible",
- 0
- };
- enum ENTITY_SEARCH_enum {
- ENTITY_SEARCH_ACTIVE,
- ENTITY_SEARCH_CLASS,
- ENTITY_SEARCH_COMPTID,
- ENTITY_SEARCH_DECKID,
- ENTITY_SEARCH_DRAWN,
- ENTITY_SEARCH_GROUPID,
- ENTITY_SEARCH_HIDDEN,
- ENTITY_SEARCH_HIGHLIGHT,
- ENTITY_SEARCH_MOVED,
- ENTITY_SEARCH_REDRAW,
- ENTITY_SEARCH_REPAINT,
- ENTITY_SEARCH_SYNTHETIC,
- ENTITY_SEARCH_TRACE,
- ENTITY_SEARCH_TYPEID,
- ENTITY_SEARCH_VISIBLE
- };
- /* SimType_Walk_Parent */
- int SimType_Walk_Parent(Entity *p){
- /*
- ** Subroutine to decend into children of a simtype
- */
- Entity *parent;
- if(!p) {
- return 0;
- }
- if(p->public_hidden) {
- return -1;
- }
- if(p->public_active==2) {
- return -1;
- }
- if(p->public_active==1) {
- return 1;
- }
- if(p->public_visible) {
- return 1;
- }
- if(p->public_parent) {
- parent=SimType_ById(p->public_parent,0);
- if(parent) {
- return SimType_Walk_Parent(parent);
- }
- }
- return 0;
- }
- /* *Entity_ById */
- Entity *Entity_ById(char prefix,Roid id,int createFlag){
- Entity *p;
- char zName[32];
- sprintf(zName, "%c%d", prefix, id);
- p=Entity_ByName(zName,createFlag);
- if(createFlag) {
- if(!p->id) {
- p->id=id;
- }
- }
- return p;
- }
- /* *Entity_ByName */
- Entity *Entity_ByName(const char *zName,int createFlag){
- Tcl_HashEntry *pEntry;
-
- assert( zName!=0 );
- if(CurrentSim->GlobalSim) {
- pEntry=Tcl_FindHashEntry(&CurrentSim->GlobalSim->EntityIdSet,zName);
- } else {
- pEntry=Tcl_FindHashEntry(&CurrentSim->EntityIdSet,zName);
- }
- if(pEntry) {
- return (Entity*)Tcl_GetHashValue(pEntry);
- }
- if(createFlag) {
- return EntityCreate(zName);
- }
- return NULL;
- }
- /* *Entity_ExportField */
- Tcl_Obj *Entity_ExportField(Entity *e,Tcl_HashTable *local,char *field,int nullcode){
- Tcl_Obj *result=Entity_GetField(e,local,field);
-
- if(result) {
- return result;
- }
- if(nullcode==ODIE_NULL_ZERO) {
- return Tcl_NewBooleanObj(0);
- }
- if(nullcode==ODIE_NULL_EMPTY) {
- return Tcl_NewObj();
- }
- return NULL;
- }
- /* *Entity_First */
- Tcl_HashEntry *Entity_First(Simulator *sim,Tcl_HashSearch *search){
- if(sim->GlobalSim) {
- return Tcl_FirstHashEntry(&sim->GlobalSim->EntityIdSet,search);
- } else {
- return Tcl_FirstHashEntry(&sim->EntityIdSet,search);
- }
- }
- /* *Entity_GetDict */
- Tcl_Obj *Entity_GetDict(Entity *e,Tcl_HashTable *local){
- Tcl_HashTable *localDict=NULL;
- Tcl_Obj *pResult=NULL;
- Entity *p=NULL;
- Entity *pStack[10];
- int i,count=-1;
-
- p=e;
- while(p && count<10) {
- count++;
- pStack[count]=p;
- p=p->pType;
- }
- /*
- ** Add the minimum specs for the class
- */
- for(i=count;i>=0;i--) {
- p=pStack[i];
- localDict=p->infoDict;
- if(localDict) {
- Tcl_HashSearch searchPtr;
- Tcl_HashEntry *i;
- for(i=Tcl_FirstHashEntry(localDict,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
- if(!pResult) pResult=Tcl_NewDictObj();
- Odie_DictObjPut(0,pResult,Tcl_GetHashKey(localDict,i),Tcl_GetHashValue(i));
- }
- }
- }
- localDict=local;
- if(localDict) {
- Tcl_HashSearch searchPtr;
- Tcl_HashEntry *i;
- for(i=Tcl_FirstHashEntry(localDict,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
- if(!pResult) pResult=Tcl_NewDictObj();
- Odie_DictObjPut(0,pResult,Tcl_GetHashKey(localDict,i),Tcl_GetHashValue(i));
- }
- }
- return pResult;
- }
- /* *Entity_GetField */
- Tcl_Obj *Entity_GetField(Entity *e,Tcl_HashTable *local,char *field){
- Tcl_Obj *result=NULL;
- Entity *p=NULL;
-
- result=Odie_HashGet(local,field);
- if(result) {
- return result;
- }
- p=e;
- while(p) {
- result=Odie_HashGet(p->infoDict,field);
- if(result) {
- return result;
- }
- if(p) p=p->pType;
- }
- return NULL;
- }
- /* *Entity_GroupToTclObj */
- Tcl_Obj *Entity_GroupToTclObj(Entity *pNode){
- Roid groupid;
- if(!pNode) {
- return Tcl_NewBooleanObj(0);
- }
- groupid=Entity_StructGetGroup(pNode);
- if(!groupid) {
- return Tcl_NewBooleanObj(0);
- }
- return Irm_NewRoidObj(groupid);
- }
- /* *Entity_Identify */
- Tcl_Obj *Entity_Identify(Entity *pNode){
- if(!pNode) {
- return Tcl_NewObj();
- }
- if(pNode->public_is_type) {
- return Irm_NewRoidObj(pNode->id);
- }
- if(pNode->name!=NULL) {
- return Odie_LiteralStringObj(pNode->name);
- } else {
- return Irm_NewRoidObj(pNode->id);
- }
- }
- /* *Entity_IdentifyCompartment */
- Entity *Entity_IdentifyCompartment(Tcl_Obj *entryPtr){
- Entity *comptPtr=NULL;
- int intval;
- if(entryPtr==NULL) {
- return NULL;
- }
- if(Tcl_GetIntFromObj(NULL,entryPtr,&intval)==TCL_OK) {
- if(intval<=0) {
- return NULL;
- }
- comptPtr=Entity_ById('c',intval,0);
- } else {
- comptPtr=Entity_ByName(Tcl_GetString(entryPtr),0);
- }
- return comptPtr;
- }
- /* *Entity_PublicId */
- Tcl_Obj *Entity_PublicId(Entity *pNode){
- char idstring[64];
- if(!pNode) {
- return Irm_NewRoidObj(0);
- }
- if(pNode->pType) {
- if(pNode->pType->name!=NULL) {
- return Odie_LiteralStringObj(pNode->pType->name);
- }
- }
- sprintf(idstring,"%d",pNode->id);
- return Odie_LiteralStringObj(idstring);
- }
- /* *Entity_SpecHashGet */
- Tcl_Obj *Entity_SpecHashGet(Entity *p,Tcl_Obj* key,int nulltype){
- return Entity_ExportField(p->pType,p->infoDict,Tcl_GetString(key),nulltype);
- }
- /* *Entity_StructGet */
- Tcl_Obj *Entity_StructGet(Entity *pNode,int field){
- switch (field) {
- case CSTRUCT_ENTITY_HIDDEN: return Odie_LiteralIntObj(pNode->public_hidden);
- case CSTRUCT_ENTITY_IS_TYPE: return Odie_LiteralIntObj(pNode->public_is_type);
- case CSTRUCT_ENTITY_REDRAW: return Odie_LiteralIntObj(pNode->public_redraw);
- case CSTRUCT_ENTITY_ACTIVE: return Odie_LiteralIntObj(pNode->public_active);
- case CSTRUCT_ENTITY_GROUPID: return Irm_NewRoidObj(pNode->public_groupid);
- case CSTRUCT_ENTITY_TRACE: return Odie_LiteralIntObj(pNode->public_trace);
- case CSTRUCT_ENTITY_REPAINT: return Odie_LiteralIntObj(pNode->public_repaint);
- case CSTRUCT_ENTITY_VISIBLE: return Odie_LiteralIntObj(pNode->public_visible);
- case CSTRUCT_ENTITY_MOVED: return Odie_LiteralIntObj(pNode->public_moved);
- case CSTRUCT_ENTITY_CHANGED: return Odie_LiteralIntObj(pNode->public_changed);
- case CSTRUCT_ENTITY_OPEN: return Odie_LiteralIntObj(pNode->public_open);
- case CSTRUCT_ENTITY_CLASS: {
- char zBuf[2];
- zBuf[0]=pNode->public_class;
- zBuf[1]=0;
- return Odie_LiteralStringObj(zBuf);
- }
-
- case CSTRUCT_ENTITY_PARENT: return Irm_NewRoidObj(pNode->public_parent);
- case CSTRUCT_ENTITY_SYNTHETIC: return Odie_LiteralIntObj(pNode->public_synthetic);
- case CSTRUCT_ENTITY_HIGHLIGHT: return Odie_LiteralIntObj(pNode->public_highlight);
- case CSTRUCT_ENTITY_DRAWN: return Odie_LiteralIntObj(pNode->public_drawn);
- case CSTRUCT_ENTITY_NCHILD: return Odie_LiteralIntObj(pNode->public_nchild);
- case CSTRUCT_ENTITY_ONCOUNT: return Odie_LiteralIntObj(pNode->public_oncount);
- }
- return NULL;
- }
- /* *Entity_StructGetType */
- Entity *Entity_StructGetType(Entity *p){
- return p->pType;
- }
- /* *Entity_StructToDict */
- Tcl_Obj *Entity_StructToDict(Tcl_Interp *interp,Entity *p,int virtual){
- Tcl_Obj *pResult=NULL;
- int i;
- if(virtual) {
- pResult=Entity_GetDict(p->pType,p->infoDict);
- }
- if(!pResult) {
- pResult=Tcl_NewObj();
- }
- /* Finaly, Add the Tcl Data */
- for(i=0;i<CSTRUCT_ENTITY_Count;i++) {
- Tcl_Obj *newElement=Entity_StructGet(p,i);
- Odie_DictObjPut(interp,pResult,Entity_paramNameMap[i].zName,newElement);
- }
- if(virtual) {
- Entity_StructAddLocation(interp,p,pResult);
- }
- return pResult;
- }
- /* *Entity_StructTypeIdToTclObj */
- Tcl_Obj *Entity_StructTypeIdToTclObj(Entity *pNode){
- if(!pNode) {
- return Irm_NewRoidObj(0);
- }
- if(!pNode->pType) {
- return Irm_NewRoidObj(0);
- }
- return Irm_NewRoidObj(pNode->pType->id);
- }
- /* *Entity_TypeToTclObj */
- Tcl_Obj *Entity_TypeToTclObj(Entity *pNode){
- Entity *pType;
- if(!pNode) {
- return Tcl_NewBooleanObj(0);
- }
- pType=Entity_StructGetType(pNode);
- if(!pType) {
- return Tcl_NewBooleanObj(0);
- }
- return Irm_NewRoidObj(pType->id);
- }
- /* *EntityCreate */
- Entity *EntityCreate(const char *zName){
- int len,isNew;
- Tcl_HashEntry *pEntry;
- Entity *p;
- if(CurrentSim->GlobalSim) {
- pEntry = Tcl_CreateHashEntry(&CurrentSim->GlobalSim->EntityIdSet, zName, &isNew);
- } else {
- pEntry = Tcl_CreateHashEntry(&CurrentSim->EntityIdSet, zName, &isNew);
- }
- if(isNew) {
- len = strlen(zName);
- p = (Entity *)Odie_Alloc( sizeof(*p)+len+1 );
- strcpy(p->name, zName);
- p->public_class=zName[0];
- Entity_StructAlloc(p);
- Tcl_SetHashValue(pEntry,(ClientData)p);
- return p;
- }
- if(pEntry) {
- p=(Entity *)Tcl_GetHashValue(pEntry);
- return p;
- }
- return NULL;
- }
- /* Entity_ApplySettings */
- void Entity_ApplySettings(Entity *pNode){
- if(pNode->public_class=='e') {
- Tcl_Obj *comptidObj=Entity_GetField(NULL,pNode->infoDict,"comptid");
- if(comptidObj) {
- /*
- ** If a local spec for "comptid" is given, use that
- ** as an implied "comptdid" statement
- */
- pNode->comptPtr=Entity_IdentifyCompartment(comptidObj);
- }
- }
- }
- /* Entity_BuildMatch */
- int Entity_BuildMatch(Tcl_Interp *interp,Tcl_Obj *matchvar,int *matchStruct){
- int llength,idx;
-
- /*
- ** Default to universal match
- */
- for(idx=0;idx<ENTITY_SEARCH_NCOUNT;idx++) {
- matchStruct[idx]=-1;
- }
- /* Handle a null */
- if(!matchvar) {
- return TCL_OK;
- }
-
- if( Tcl_ListObjLength(interp, matchvar, &llength) ) return TCL_ERROR;
- if( llength%2!=0 ){
- Tcl_AppendResult(interp, "Search params must be a key/value list "
- "valid keys: visible hidden class redraw highlighted", 0);
- return TCL_ERROR;
- }
-
- for(idx=0; idx<llength-1; idx+=2){
- int field;
- int value;
- Tcl_Obj *pObj;
-
- Tcl_ListObjIndex(0, matchvar, idx, &pObj);
- if( Tcl_GetIndexFromObj(interp, pObj, ENTITY_SEARCH_strs, "option", 0, &field) ){
- return TCL_ERROR;
- }
- Tcl_ListObjIndex(0, matchvar, idx+1, &pObj);
- if(field==ENTITY_SEARCH_CLASS) {
- char *str,prefix;
- str=Tcl_GetString(pObj);
- if(str) {
- prefix=str[0];
- matchStruct[field]=prefix;
- }
- } else {
- if(Tcl_GetIntFromObj(interp, pObj, &value)) {
- return TCL_ERROR;
- }
- matchStruct[field]=value;
- }
- }
- return TCL_OK;
- }
- /* Entity_Delete */
- void Entity_Delete(Entity *p){
- Entity_StructFree(p);
- Odie_Free((char *)p);
- }
- /* Entity_FromTclObj */
- int Entity_FromTclObj(Tcl_Interp *interp, Tcl_Obj *pObj, Entity **ppEntity){
- *ppEntity = NULL;
- int i;
- if( Tcl_GetIntFromObj(interp, pObj, &i) == TCL_OK ) {
- *ppEntity = SimType_ById(i, 0);
- if(*ppEntity) {
- return TCL_OK;
- }
- }
- Tcl_ResetResult(interp);
- *ppEntity = Entity_ByName(Tcl_GetString(pObj),0);
-
- if( *ppEntity==0 ){
- Tcl_AppendResult(interp, "no such entity: ",
- Tcl_GetString(pObj), 0);
- return TCL_ERROR;
- }
- return TCL_OK;
- }
- /* Entity_Module_Advance */
- void Entity_Module_Advance(Simulator *ActiveSim,int clocktime){
- /* Default empty implementation */
- }
- /* Entity_Module_Free */
- void Entity_Module_Free(Simulator *sim){
- Tcl_HashSearch searchPtr;
- Tcl_HashEntry *i;
-
- if(!sim->module_entity) return;
- for(i=Entity_First(sim,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
- Entity *p = (Entity*)Tcl_GetHashValue(i);
- Entity_StructFree(p);
- Odie_Free((char *)p);
- }
- for(i=SimType_First(sim,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
- Entity *p = (Entity*)Tcl_GetHashValue(i);
- Entity_StructFree(p);
- Odie_Free((char *)p);
- }
- Tcl_DeleteHashTable(&sim->EntityIdSet);
- Tcl_DeleteHashTable(&sim->SimTypeIdSet);
- sim->module_entity=0;
- }
- /* Entity_Module_Init */
- void Entity_Module_Init(Simulator *sim){}
- /* Entity_Module_Rewind */
- void Entity_Module_Rewind(Simulator *sim){
- Tcl_HashSearch searchPtr;
- Tcl_HashEntry *i;
-
- if(!sim->module_entity) return;
- for(i=Entity_First(sim,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
- Entity *p = (Entity*)Tcl_GetHashValue(i);
- p->public_redraw=1;
- p->public_repaint=1;
- }
- }
- /* Entity_Node_ApplyLocation */
- void Entity_Node_ApplyLocation(Entity *pNode){
- #ifdef build_IRM
- Entity *comptPtr;
- int cid,sid,c;
- c=CrewrouteSubcompartmentAt(pNode->x,pNode->y,pNode->deckid,&sid,&cid,NULL,NULL);
- comptPtr=Entity_ById('c',c,0);
- pNode->public_moved=1;
- if(comptPtr) {
- pNode->comptPtr=comptPtr;
- } else {
- pNode->comptPtr=NULL;
- }
- #endif
- }
- /* Entity_Node_GetLink */
- void Entity_Node_GetLink(Tcl_Obj *pResult,Entity *pNode,char *linktype){}
- /* Entity_nodeeval */
- int Entity_nodeeval(Tcl_Interp *interp,Entity *p,Tcl_Obj *body,int writeback){
- Tcl_Obj *id;
- int i,len;
- Tcl_Obj *varv[CSTRUCT_ENTITY_Count*2];
- int result;
-
- Entity_StructWith(interp,p,1,varv);
- id=Entity_Identify(p);
- Tcl_ObjSetVar2(interp,Odie_LiteralStringObj("id"),NULL,id,0);
- Tcl_ObjSetVar2(interp,Odie_LiteralStringObj("typeid"),NULL,Entity_TypeToTclObj(p),0);
- Tcl_ObjSetVar2(interp,Odie_LiteralStringObj("groupid"),NULL,Entity_GroupToTclObj(p),0);
- /*
- for(i=0;i<CSTRUCT_ENTITY_Count*2;i++) {
- Tcl_IncrRefCount(varv[i]);
- }
- */
- result=Tcl_EvalObjEx(interp, body, 0);
-
- if(result!=TCL_OK) {
- return result;
- }
- if(writeback){
- /*
- ** Read values back into the dict
- ** For now, we limit writeback to state variables
- ** And we don't care about garbage values
- */
- int changed=0;
- for(i=0;i<CSTRUCT_ENTITY_Count*2;i+=2) {
- Tcl_Obj *newValue;
- int offset;
- int type;
- newValue=Tcl_ObjGetVar2(interp,varv[i],(Tcl_Obj*)NULL,0);
- if(newValue==varv[i+1]) {
- /* Undocumented, unsanctioned, but it works in practice
- ** If the pointer hasn't changed, neither has the value
- */
- continue;
- }
- if(!newValue) {
- /* Variable must have been unset... move along */
- continue;
- }
- if( Entity_StructValueOffset(0, varv[i], &offset, &type) == TCL_OK ) {
- Entity_StructSet(interp,p,offset,newValue);
- changed++;
- }
- }
- if(changed) {
- Entity_ApplySettings(p);
- }
- }
- /*
- for(i=0;i<CSTRUCT_ENTITY_Count*2;i++) {
- Tcl_DecrRefCount(varv[i]);
- }
- */
- return TCL_OK;
- }
- /* Entity_Rewind */
- void Entity_Rewind(Entity *p, int revert){}
- /* Entity_SetFromObj */
- int Entity_SetFromObj(Tcl_Interp *interp,Entity *pType, Tcl_Obj *field, Tcl_Obj *value){
- /* Manipulate the DICT representation */
- int err,type,offset=-1;
- /* Reset any cached group pointer */
- pType->gType=NULL;
- if( Entity_StructValueOffset(interp, field, &offset, &type) == TCL_OK ) {
- err=Entity_StructSet(interp,pType->pType,offset,value);
- if(err==TCL_OK) {
- Entity_ApplySettings(pType->pType);
- }
- return err;
- }
- Odie_HashPut(&pType->infoDict,Tcl_GetString(field),value);
- return TCL_OK;
- }
- /* Entity_SpecHashClear */
- void Entity_SpecHashClear(Entity *p){
- Odie_HashFree(&p->infoDict);
- }
- /* Entity_SpecHashPut */
- void Entity_SpecHashPut(Entity *p,Tcl_Obj *key,Tcl_Obj *value){
- Odie_HashPut(&p->infoDict,Tcl_GetString(key),value);
- }
- /* Entity_StructAddLocation */
- void Entity_StructAddLocation(Tcl_Interp *interp,Entity *p, Tcl_Obj *pValueDict){
- Tcl_Obj *tempval;
- #ifdef build_IRM
- if(p->public_class=='k') {
- /* Always provide a path if not given
- ** And only trust the local dict
- */
- Tcl_Obj *pathobj=Entity_ExportField(NULL,p->infoDict,"path",ODIE_NULL_EMPTY);
- Odie_DictObjPut(0,pValueDict,"path",pathobj);
- } else {
- if(p->attached_to) {
- switch (p->attached_type) {
- case CSTRUCT_crew: {
- return Crew_StructAddLocation(interp,p->attached_to,pValueDict);
- }
- case CSTRUCT_entity: {
- return Entity_StructAddLocation(interp,p->attached_to,pValueDict);
- }
- case CSTRUCT_portal: {
- return Portal_StructAddLocation(interp,p->attached_to,pValueDict);
- }
- case CSTRUCT_simnode: {
- return SimNode_StructAddLocation(interp,p->attached_to,pValueDict);
- }
- }
- }
- Odie_DictObjPut(0,pValueDict,"deckid",Odie_LiteralIntObj(p->deckid));
- if(p->deckid) {
- tempval=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp, tempval, Odie_LiteralIntObj(p->deckid));
- Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->x));
- Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->y));
- Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->zoff));
- Odie_DictObjPut(interp,pValueDict,"center",tempval);
- }
- tempval=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->nx));
- Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->ny));
- Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->nz));
- Odie_DictObjPut(0,pValueDict,"orientation",tempval);
- if(p->comptPtr) {
- Odie_DictObjPut(0,pValueDict,"compartment",Entity_Identify(p->comptPtr));
- }
- }
- #else
- Odie_DictObjPut(0,pValueDict,"deckid",Odie_LiteralIntObj(p->deckid));
- if(p->deckid) {
- tempval=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp, tempval, Odie_LiteralIntObj(p->deckid));
- Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->x));
- Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->y));
- Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->zoff));
- Odie_DictObjPut(interp,pValueDict,"center",tempval);
- }
- tempval=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->nx));
- Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->ny));
- Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->nz));
- Odie_DictObjPut(0,pValueDict,"orientation",tempval);
- if(p->comptPtr) {
- Odie_DictObjPut(0,pValueDict,"compartment",Entity_Identify(p->comptPtr));
- }
- #endif
- }
- /* Entity_StructAlloc */
- void Entity_StructAlloc(Entity *p){}
- /* Entity_StructAttachLocation */
- int Entity_StructAttachLocation(Tcl_Interp *interp,Entity *pNat,Tcl_Obj *nodeName){
- char type=0;
- int roid;
- char *stringVal=Tcl_GetString(nodeName);
- int result=sscanf(stringVal,"%c%d",&type,&roid);
-
- if(result!=2) {
- pNat->attached_type=0;
- pNat->attached_to=NULL;
- return TCL_OK;
- }
- #ifdef build_IRM
- switch(type) {
- case 'c': {
- Compartment *pDest;
- if(Compartment_FromTclObj(interp,nodeName,&pDest)) return TCL_ERROR;
- pNat->attached_type=CSTRUCT_compartment;
- pNat->attached_to=pDest;
- return TCL_OK;
- }
- case 'e': {
- SimNode *pDest;
- if(SimNode_FromTclObj(interp,nodeName,&pDest)) return TCL_ERROR;
- pNat->attached_type=CSTRUCT_simnode;
- pNat->attached_to=pDest;
- return TCL_OK;
- }
- case 'p': {
- Portal *pDest;
- if(Portal_FromTclObj(interp,nodeName,&pDest)) return TCL_ERROR;
- pNat->attached_type=CSTRUCT_portal;
- pNat->attached_to=pDest;
- return TCL_OK;
- }
- case 'v': {
- Crew *pDest;
- if(Crew_FromTclObj(interp,nodeName,&pDest)) return TCL_ERROR;
- pNat->attached_type=CSTRUCT_crew;
- pNat->attached_to=pDest;
- return TCL_OK;
- }
- default: {
- Entity *pDest;
- if(Entity_FromTclObj(interp,nodeName,&pDest)) {
- return TCL_ERROR;
- }
- pNat->attached_type=CSTRUCT_entity;
- pNat->attached_to=pDest;
- return TCL_OK;
- }
- }
- return TCL_ERROR;
- #else
- Entity *pDest;
- if(Entity_FromTclObj(interp,nodeName,&pDest)) {
- return TCL_ERROR;
- }
- pNat->attached_type=CSTRUCT_entity;
- pNat->attached_to=pDest;
- return TCL_OK;
- #endif
- }
- /* Entity_StructChanged */
- int Entity_StructChanged(Entity *p){ return 0; }
- /* Entity_StructFree */
- void Entity_StructFree(Entity *p){
- Odie_HashFree(&p->infoDict);
- p->infoDict=NULL;
- }
- /* Entity_StructFree_Private */
- void Entity_StructFree_Private(Entity *p){}
- /* Entity_StructGetGroup */
- Roid Entity_StructGetGroup(Entity *p){
- Roid groupid=-1;
- if(p->public_groupid>0) {
- return p->public_groupid;
- }
-
- if(p->pType) {
- groupid=SimType_StructGetGroup(p->pType);
- if(groupid>0) {
- return groupid;
- }
- }
- /*
- ** Nodes defaults to the compartment they are within
- ** If no group is given through the type or adopted type
- */
- if(p->comptPtr) {
- groupid=Entity_StructGetGroup(p->comptPtr);
- if(groupid>0) {
- return groupid;
- }
- }
- return 0;
- }
- /* Entity_StructLocation */
- void Entity_StructLocation (Irm_Location *lstruct,Entity *p){
- #ifdef build_IRM
- if(p->attached_to) {
- switch (p->attached_type) {
- case CSTRUCT_crew: {
- return Crew_StructLocation(lstruct,p->attached_to);
- }
- case CSTRUCT_entity: {
- return Entity_StructLocation(lstruct,p->attached_to);
- }
- case CSTRUCT_portal: {
- return Portal_StructLocation(lstruct,p->attached_to);
- }
- case CSTRUCT_simnode: {
- return SimNode_StructLocation(lstruct,p->attached_to);
- }
- }
- }
- #endif
- lstruct->deckid=p->deckid;
- lstruct->x=p->x;
- lstruct->y=p->y;
- lstruct->zoff=p->zoff;
- }
- /* Entity_StructMatches */
- int Entity_StructMatches(Entity *p,int *matchSearch){
-
- if(matchSearch[ENTITY_SEARCH_CLASS]>=0) {
- if(matchSearch[ENTITY_SEARCH_CLASS]!=(int)p->public_class) return 0;
- }
- if(matchSearch[ENTITY_SEARCH_DECKID]>=0) {
- if(matchSearch[ENTITY_SEARCH_DECKID]!=(int)p->deckid) return 0;
- }
- if(matchSearch[ENTITY_SEARCH_DRAWN]>=0) {
- if(matchSearch[ENTITY_SEARCH_DRAWN]!=(int)p->public_drawn) return 0;
- }
-
- if(matchSearch[ENTITY_SEARCH_COMPTID]>=0) {
- Entity *gPtr=p->comptPtr;
- if(!gPtr) {
- return 0;
- } else {
- if(gPtr->id != matchSearch[ENTITY_SEARCH_COMPTID]) {
- return 0;
- }
- }
- }
-
- if(matchSearch[ENTITY_SEARCH_GROUPID]>=0) {
- Roid groupid=Entity_StructGetGroup(p);
- if(groupid != matchSearch[ENTITY_SEARCH_GROUPID]) {
- return 0;
- }
- }
-
- if(matchSearch[ENTITY_SEARCH_HIDDEN]>=0) {
- if(matchSearch[ENTITY_SEARCH_HIDDEN]!=p->public_hidden) return 0;
- }
- if(matchSearch[ENTITY_SEARCH_ACTIVE]>=0) {
- if(matchSearch[ENTITY_SEARCH_ACTIVE]!=p->public_active) return 0;
- }
- if(matchSearch[ENTITY_SEARCH_HIGHLIGHT]>=0) {
- if(matchSearch[ENTITY_SEARCH_HIGHLIGHT]!=p->public_highlight) return 0;
- }
- if(matchSearch[ENTITY_SEARCH_MOVED]>=0) {
- if(matchSearch[ENTITY_SEARCH_MOVED]!=p->public_moved) return 0;
- }
- if(matchSearch[ENTITY_SEARCH_REDRAW]>=0) {
- if(matchSearch[ENTITY_SEARCH_REDRAW]!=p->public_redraw) return 0;
- }
-
- if(matchSearch[ENTITY_SEARCH_REPAINT]>=0) {
- if(matchSearch[ENTITY_SEARCH_REPAINT]!=p->public_repaint) return 0;
- }
- if(matchSearch[ENTITY_SEARCH_SYNTHETIC]>=0) {
- if(matchSearch[ENTITY_SEARCH_SYNTHETIC]!=p->public_synthetic) return 0;
- }
-
- if(matchSearch[ENTITY_SEARCH_TYPEID]>=0) {
- if(!p->pType) {
- return 0;
- } else {
- if(p->pType->id != matchSearch[ENTITY_SEARCH_TYPEID]) {
- return 0;
- }
- }
- }
- if(matchSearch[ENTITY_SEARCH_TRACE]>=0) {
- if(matchSearch[ENTITY_SEARCH_TRACE]!=p->public_trace) return 0;
- }
- if(matchSearch[ENTITY_SEARCH_VISIBLE]>=0) {
- if(matchSearch[ENTITY_SEARCH_VISIBLE]!=p->public_visible) return 0;
- }
- return 1;
- }
- /* Entity_StructSet */
- int Entity_StructSet(Tcl_Interp *interp,Entity *pNode,int field,Tcl_Obj *value){
-
- if(field < 0 ) {
- return TCL_ERROR;
- }
-
- switch (field) {
- case CSTRUCT_ENTITY_HIDDEN: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_hidden=intValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_IS_TYPE: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_is_type=intValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_REDRAW: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_redraw=intValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_ACTIVE: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_active=intValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_GROUPID: {
- Roid roidValue;
- if(Irm_GetRoidFromObj(interp,value,&roidValue)) return TCL_ERROR;
- pNode->public_groupid=(Roid)roidValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_TRACE: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_trace=intValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_REPAINT: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_repaint=intValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_VISIBLE: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_visible=intValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_MOVED: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_moved=intValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_CHANGED: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_changed=intValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_OPEN: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_open=intValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_CLASS: {
- char *str;
- str=Tcl_GetString(value);
- if(str) {
- pNode->public_class=str[0];
- }
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_PARENT: {
- Roid roidValue;
- if(Irm_GetRoidFromObj(interp,value,&roidValue)) return TCL_ERROR;
- pNode->public_parent=(Roid)roidValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_SYNTHETIC: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_synthetic=intValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_HIGHLIGHT: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_highlight=intValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_DRAWN: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_drawn=intValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_NCHILD: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_nchild=intValue;
- return TCL_OK;
- }
- case CSTRUCT_ENTITY_ONCOUNT: {
- int intValue;
- double floatValue;
- if(Tcl_GetIntFromObj(interp,value,&intValue)) {
- Tcl_ResetResult(interp);
- if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
- intValue=(int)floatValue;
- }
- pNode->public_oncount=intValue;
- return TCL_OK;
- }
- }
- return TCL_OK;
- }
- /* Entity_StructSetGroup */
- void Entity_StructSetGroup(Entity *p,Roid groupid){
- p->public_groupid=groupid;
- }
- /* Entity_StructSetType */
- void Entity_StructSetType(Entity *p,Entity *pType){
- p->pType=pType;
- if(pType) {
- if(pType->public_class=='g') {
- p->gType=pType;
- }
- }
- }
- /* Entity_StructSizeZ */
- int Entity_StructSizeZ(Entity *pNode){
- int zheight=TypeSpec_GetInt(pNode,"size.z");
- return zheight;
- }
- /* Entity_StructValueOffset */
- int Entity_StructValueOffset(Tcl_Interp *interp,Tcl_Obj *pObj,int *pIndex,int *pType){
- /*
- ** Given the name of one of the arState[] values in the Entity structure,
- ** return the index of the particular arState[]. Return TCL_OK.
- **
- ** Leave an error message in interp and return TCL_ERROR if
- ** anything goes wrong.
- */
-
- int lo, hi, mid, c, max, i;
- int nName;
- const char *zName;
- const struct OdieParamNameMap *aParam = Entity_canonicalNameMap;
-
- lo = 0;
- hi = max = CSTRUCT_ENTITY_AliasCount - 1;
- zName = Tcl_GetStringFromObj(pObj, &nName);
- mid = (lo+hi)/2;
- if(nName>32) {
- nName=32;
- }
- while( lo<=hi ){
- mid = (lo+hi)/2;
- c = strncmp(zName, aParam[mid].zName, nName);
- if( c<0 ){
- hi = mid-1;
- }else if( c>0 ){
- lo = mid+1;
- }else if(
- (mid>0 && strncmp(zName, aParam[mid-1].zName, nName)==0) ||
- (mid<max && strncmp(zName, aParam[mid+1].zName, nName)==0)
- ){
- i = mid;
- while( i>0 && strncmp(zName, aParam[i-1].zName, nName)==0 ){
- i--;
- }
- if( strlen(aParam[i].zName)==nName ){
- *pIndex = aParam[i].iCode;
- *pType = aParam[i].pType;
- return TCL_OK;
- }
- if(interp) {
- Tcl_AppendResult(interp, "ambiguous parameter:", 0);
- do{
- Tcl_AppendResult(interp, " ", aParam[i++].zName, 0);
- }while( i<=max && strncmp(zName, aParam[i].zName, nName)==0 );
- }
- return TCL_ERROR;
- }else{
- *pIndex = aParam[mid].iCode;
- *pType = aParam[mid].pType;
- return TCL_OK;
- }
- }
- if(interp) {
- Tcl_AppendResult(interp, "unknown parameter \"", zName,
- "\" - nearby choices:", 0);
- for(i=mid-3; i<mid+3; i++){
- if( i<0 || i>max ) continue;
- Tcl_AppendResult(interp, " ", aParam[i].zName, 0);
- }
- }
- return TCL_ERROR;
- }
- /* Entity_StructWith */
- void Entity_StructWith(Tcl_Interp *interp,Entity *p,int virtual,Tcl_Obj **objvPtr){
- int i;
- if (virtual) {
- Entity_With(interp,p->pType,NULL);
- }
- /* Finaly, Add the Tcl Data */
- for(i=0;i<CSTRUCT_ENTITY_Count;i++) {
- Tcl_Obj *newElement=Entity_StructGet(p,i);
- Tcl_Obj *fieldName=Odie_LiteralStringObj(Entity_paramNameMap[i].zName);
- if(objvPtr) {
- objvPtr[i*2]=fieldName;
- objvPtr[i*2+1]=newElement;
- }
- Tcl_ObjSetVar2(interp,fieldName,NULL,newElement,0);
- }
- if(virtual) {
- Entity_StructWithLocation(interp,p);
- }
- }
- /* Entity_StructWithLocation */
- void Entity_StructWithLocation(Tcl_Interp *interp,Entity *pNode){}
- /* Entity_Unlink */
- void Entity_Unlink(Entity *objPtr){
- Tcl_HashEntry *pEntry;
-
- if (!objPtr) return;
- if(CurrentSim->GlobalSim) {
- pEntry=Tcl_FindHashEntry(&CurrentSim->GlobalSim->EntityIdSet,(const char *)objPtr->name);
- } else {
- pEntry=Tcl_FindHashEntry(&CurrentSim->EntityIdSet,(const char *)objPtr->name);
- }
- if(pEntry) {
- Tcl_DeleteHashEntry(pEntry);
- }
- #ifdef build_IRM
- if(objPtr->public_class=='v') {
- Crew *pNode=Crew_ById(objPtr->id,0);
- if(pNode) {
- Crew_Unlink(pNode);
- Crew_Delete(pNode);
- }
- }
- if(objPtr->public_class=='p') {
- Portal *pNode=Portal_ById(objPtr->id,0);
- if(pNode) {
- Portal_Unlink(pNode);
- Portal_Delete(pNode);
- }
- }
- if(objPtr->public_class=='k') {
- SimLink *pNode=SimLink_ById(objPtr->id,0);
- if(pNode) {
- SimLink_Unlink(pNode);
- SimLink_Delete(pNode);
- }
- }
- if(objPtr->public_class=='e') {
- SimNode *pNode=SimNode_ById(objPtr->id,0);
- if(pNode) {
- if(pNode->aLink->pCommon->public_rupture_node == pNode->id) {
- /*
- ** Run link repair for rupture nodes instead of delete simnode
- */
- SimLink_Repair(NULL,pNode->aLink->pCommon);
- } else {
- SimNode_Unlink(pNode);
- SimNode_Delete(pNode);
- }
- }
- }
- #endif
- }
- /* Entity_With */
- void Entity_With(Tcl_Interp *interp,Entity *e,Tcl_HashTable *local){
- Tcl_HashTable *localDict=NULL;
- Entity *p=NULL;
- Entity *pStack[10];
- int i,count=-1;
-
- p=e;
- while(p && count<10) {
- count++;
- pStack[count]=p;
- p=p->pType;
- }
- /*
- ** Add the minimum specs for the class
- */
- for(i=count;i>=0;i--) {
- p=pStack[i];
- localDict=p->infoDict;
- if(localDict) {
- Tcl_HashSearch searchPtr;
- Tcl_HashEntry *i;
- for(i=Tcl_FirstHashEntry(localDict,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
- Tcl_Obj *pKey,*pValue;
- pKey=Odie_LiteralStringObj(Tcl_GetHashKey(localDict,i));
- pValue=(Tcl_Obj *)Tcl_GetHashValue(i);
- Tcl_ObjSetVar2(interp,pKey,NULL,pValue,0);
- }
- }
- }
- localDict=local;
- if(localDict) {
- Tcl_HashSearch searchPtr;
- Tcl_HashEntry *i;
- for(i=Tcl_FirstHashEntry(localDict,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
- Tcl_Obj *pKey,*pValue;
- pKey=Odie_LiteralStringObj(Tcl_GetHashKey(localDict,i));
- pValue=(Tcl_Obj *)Tcl_GetHashValue(i);
- Tcl_ObjSetVar2(interp,pKey,NULL,pValue,0);
- }
- }
- }
- #define ENTITY_SEARCH_NCOUNT 15
- /* *SimType_ById */
- Entity *SimType_ById(Roid id, int createFlag){
- /*
- ** Return a pointer to a SimType with the given ID. Return NULL
- ** if there is no such type. Create a new one if the createFlag
- ** is true and the type does not previously exist.
- */
- Tcl_HashEntry *pEntry;
- if(CurrentSim->GlobalSim) {
- pEntry=Tcl_FindHashEntry(&CurrentSim->GlobalSim->SimTypeIdSet,(char *)id);
- } else {
- pEntry=Tcl_FindHashEntry(&CurrentSim->SimTypeIdSet,(char *)id);
- }
- if(pEntry) {
- return (Entity*)Tcl_GetHashValue(pEntry);
- }
- if(createFlag) {
- int isNew;
- Entity *p;
- if(CurrentSim->GlobalSim) {
- pEntry = Tcl_CreateHashEntry(&CurrentSim->GlobalSim->SimTypeIdSet,(char *)id, &isNew);
- } else {
- pEntry = Tcl_CreateHashEntry(&CurrentSim->SimTypeIdSet,(char *)id, &isNew);
- }
- p = (Entity *)Odie_Alloc( sizeof(*p) );
- p->id = id;
- p->pType=NULL;
- Entity_StructAlloc(p);
- p->public_is_type=1;
- Tcl_SetHashValue(pEntry,(ClientData)p);
-
- return p;
- }
- return NULL;
- }
- /* *SimType_ByName */
- Entity *SimType_ByName(char *idstring, int createFlag){
- Roid i=-1;
- i=Odie_RoidFromString(idstring,'y');
-
- if(i<0) {
- return NULL;
- }
- return SimType_ById(i,createFlag);
- }
- /* *SimType_First */
- Tcl_HashEntry *SimType_First(Simulator *sim,Tcl_HashSearch *search){
- /*
- ** Return the first entity in a list of them all
- */
- if(sim->GlobalSim) {
- return Tcl_FirstHashEntry(&sim->GlobalSim->SimTypeIdSet,search);
- } else {
- return Tcl_FirstHashEntry(&sim->SimTypeIdSet,search);
- }
- }
- /* *SimType_GroupToTclObj */
- Tcl_Obj *SimType_GroupToTclObj(Entity *pNode){
- Roid groupid;
- if(!pNode) {
- return Tcl_NewBooleanObj(0);
- }
- groupid=SimType_StructGetGroup(pNode);
- if(!groupid) {
- return Tcl_NewBooleanObj(0);
- }
- return Irm_NewRoidObj(groupid);
- }
- /* *SimType_Identify */
- Tcl_Obj *SimType_Identify(Entity *pNode){
- if(!pNode) {
- return Irm_NewRoidObj(0);
- }
- return Irm_NewRoidObj(pNode->id);
- }
- /* *SimType_PublicId */
- Tcl_Obj *SimType_PublicId(Entity *pNode){
- char idstring[64];
- if(!pNode) {
- return Irm_NewRoidObj(0);
- }
- if(pNode->pType) {
- if(pNode->pType->name!=NULL) {
- return Odie_LiteralStringObj(pNode->pType->name);
- }
- }
- sprintf(idstring,"y%d",pNode->id);
- return Odie_LiteralStringObj(idstring);
- }
- /* *SimType_StructGetType */
- Entity *SimType_StructGetType(Entity *p){
- if(p->pType) {
- return Entity_StructGetType(p->pType);
- }
- return NULL;
- }
- /* *SimType_StructToDict */
- Tcl_Obj *SimType_StructToDict(Tcl_Interp *interp,Entity *p,int virtual){
- Tcl_Obj *pResult=NULL;
- if (virtual) {
- pResult=Entity_GetDict(p->pType,NULL);
- }
- return pResult;
- }
- /* *SimType_TypeToTclObj */
- Tcl_Obj *SimType_TypeToTclObj(Entity *pNode){
- Entity *pType;
- if(!pNode) {
- return Tcl_NewBooleanObj(0);
- }
- pType=SimType_StructGetType(pNode);
- if(!pType) {
- return Tcl_NewBooleanObj(0);
- }
- return Irm_NewRoidObj(pType->id);
- }
- /* SimType_ApplySettings */
- inline extern void SimType_ApplySettings(Entity *p){
- /* Default implementation does nothing */
- }
- /* SimType_FromTclObj */
- int SimType_FromTclObj(Tcl_Interp *interp, Tcl_Obj *pObj, Entity **ppEntity){
- /*
- ** Find a SimType given a Tcl_Obj that contains the SimType ID.
- ** Leave an error message in interp and return TCL_ERROR if anything
- ** goes wrong.
- */
- Roid i=-1;
- i=Odie_RoidFromString(Tcl_GetString(pObj),'y');
-
- if(i<0) {
- if(interp) {
- Tcl_AppendResult(interp, "no such SimType: ",
- Tcl_GetStringFromObj(pObj, 0), 0);
- }
- }
- *ppEntity = SimType_ById(i, 0);
- if( *ppEntity==0 ){
- if(interp) {
- Tcl_AppendResult(interp, "no such SimType: ",
- Tcl_GetStringFromObj(pObj, 0), 0);
- }
- return TCL_ERROR;
- }
- return TCL_OK;
- }
- /* SimType_Module_Advance */
- void SimType_Module_Advance(Simulator *ActiveSim,int clocktime){}
- /* SimType_nodeeval */
- int SimType_nodeeval(Tcl_Interp *interp,Entity *p,Tcl_Obj *body,int writeback){
- Tcl_Obj *id;
- int i,len;
- Tcl_Obj *varv[CSTRUCT_ENTITY_Count*2];
- int result;
-
- Entity_StructWith(interp,p,1,varv);
- id=SimType_Identify(p);
- Tcl_ObjSetVar2(interp,Odie_LiteralStringObj("id"),NULL,id,0);
- Tcl_ObjSetVar2(interp,Odie_LiteralStringObj("typeid"),NULL,SimType_TypeToTclObj(p),0);
- Tcl_ObjSetVar2(interp,Odie_LiteralStringObj("groupid"),NULL,SimType_GroupToTclObj(p),0);
- /*
- for(i=0;i<CSTRUCT_ENTITY_Count*2;i++) {
- Tcl_IncrRefCount(varv[i]);
- }
- */
- result=Tcl_EvalObjEx(interp, body, 0);
-
- if(result!=TCL_OK) {
- return result;
- }
- if(writeback){
- /*
- ** Read values back into the dict
- ** For now, we limit writeback to state variables
- ** And we don't care about garbage values
- */
- int changed=0;
- for(i=0;i<CSTRUCT_ENTITY_Count*2;i+=2) {
- Tcl_Obj *newValue;
- int offset;
- int type;
- newValue=Tcl_ObjGetVar2(interp,varv[i],(Tcl_Obj*)NULL,0);
- if(newValue==varv[i+1]) {
- /* Undocumented, unsanctioned, but it works in practice
- ** If the pointer hasn't changed, neither has the value
- */
- continue;
- }
- if(!newValue) {
- /* Variable must have been unset... move along */
- continue;
- }
- if( Entity_StructValueOffset(0, varv[i], &offset, &type) == TCL_OK ) {
- Entity_StructSet(interp,p,offset,newValue);
- changed++;
- }
- }
- if(changed) {
- Entity_ApplySettings(p);
- }
- }
- /*
- for(i=0;i<CSTRUCT_ENTITY_Count*2;i++) {
- Tcl_DecrRefCount(varv[i]);
- }
- */
- return TCL_OK;
- }
- /* SimType_Rewind */
- void SimType_Rewind(Entity *p, int revert){}
- /* SimType_StructGetGroup */
- Roid SimType_StructGetGroup(Entity *p){
- if(!p) {
- return 0;
- }
- if (p->public_class=='g') {
- return p->id;
- }
- if(p->public_groupid) {
- return p->public_groupid;
- }
- if(p->public_parent) {
- Entity *pType=SimType_ById(p->public_parent,0);
- if(pType) {
- if (pType->public_class=='g') {
- return pType->id;
- }
- /* Otherwise, keep looking for parents */
- return SimType_StructGetGroup(pType);
- }
- }
- return 0;
- }
- /* SimType_StructSetGroup */
- void SimType_StructSetGroup(Entity *p,Roid groupid){
- p->public_groupid=groupid;
- }
- /* SimType_StructSetType */
- void SimType_StructSetType(Entity *p,Entity *pType){
- if(!p->pType) {
- return;
- }
- Entity_StructSetType(p->pType,pType);
- }
- /* SimType_StructWith */
- void SimType_StructWith(Tcl_Interp *interp,Entity *p,int virtual){
- if (virtual) {
- Entity_With(interp,p->pType,p->infoDict);
- }
- }
- /* SimType_Unlink */
- void SimType_Unlink(Entity *objPtr){
- Tcl_HashEntry *pEntry;
- if(CurrentSim->GlobalSim) {
- pEntry=Tcl_FindHashEntry(&CurrentSim->GlobalSim->SimTypeIdSet,(char *)objPtr->id);
- } else {
- pEntry=Tcl_FindHashEntry(&CurrentSim->SimTypeIdSet,(char *)objPtr->id);
- }
- if(pEntry) {
- Tcl_DeleteHashEntry(pEntry);
- }
- }
- /* TypeSpec_SetInt */
- void TypeSpec_SetInt(Entity *pType,char *field, int value){
- Tcl_Obj *newValue;
- if(!pType) return;
- newValue=Tcl_NewIntObj(value);
- Odie_HashPut(&pType->infoDict,field,newValue);
- //Tcl_DecrRefCount(newValue);
- }
- /* TypeSpec_SetReal */
- void TypeSpec_SetReal(Entity *pType,char *field, IrmReal value){
- Tcl_Obj *newValue;
- if(!pType) return;
- double fabsvalue=fabs(value);
- if(fabsvalue == value && fabsvalue < 10 ) {
- TypeSpec_SetInt(pType,field,(int)value);
- return;
- }
- newValue=Tcl_NewDoubleObj((double)value);
- Odie_HashPut(&pType->infoDict,field,newValue);
- //Tcl_DecrRefCount(newValue);
- }
- /* TypeSpec_SetWideInt */
- void TypeSpec_SetWideInt(Entity *pType, char *field, Tcl_WideInt value){
- Tcl_Obj *newValue;
- if(!pType) return;
- if(value > -10 && value < 10) {
- TypeSpec_SetInt(pType,field,(int)value);
- return;
- }
- newValue=Tcl_NewWideIntObj(value);
- Odie_HashPut(&pType->infoDict,field,newValue);
- //Tcl_DecrRefCount(newValue);
- }
- /* TypeSpec_Exists */
- IrmReal TypeSpec_Exists(Entity *pType, char *field){
- Tcl_Obj *result=NULL;
- if(field && pType) {
- result=Entity_GetField(pType->pType,pType->infoDict,field);
- }
- if(result) {
- return 1;
- }
- return 0;
- }
- /* TypeSpec_GetReal */
- IrmReal TypeSpec_GetReal(Entity *pType, char *field){
- Tcl_Obj *result=NULL;
- if(field && pType) {
- result=Entity_GetField(pType->pType,pType->infoDict,field);
- }
- if(result) {
- double s;
- if (Tcl_GetDoubleFromObj(NULL,result,&s)==TCL_OK) {
- return s;
- }
- }
- return 0.0;
- }
- /* TypeSpec_GetReal_Or_Default */
- IrmReal TypeSpec_GetReal_Or_Default(Entity *pType, char *field,IrmReal defaultValue){
- Tcl_Obj *result=NULL;
- if(field && pType) {
- result=Entity_GetField(pType->pType,pType->infoDict,field);
- }
- if(result) {
- double s;
- if (Tcl_GetDoubleFromObj(NULL,result,&s)==TCL_OK) {
- return s;
- }
- }
- return defaultValue;
- }
- /* TypeSpec_GetInt */
- int TypeSpec_GetInt(Entity *pType, char *field){
- Tcl_Obj *result=NULL;
- if(field && pType) {
- result=Entity_GetField(pType->pType,pType->infoDict,field);
- }
- if(result) {
- int sint;
- double s;
- if (Tcl_GetIntFromObj(NULL,result,&sint)==TCL_OK) {
- return sint;
- }
- if (Tcl_GetDoubleFromObj(NULL,result,&s)==TCL_OK) {
- return (int)round(s);
- }
- }
- return 0;
- }
- /* TypeSpec_GetInt_or_Default */
- int TypeSpec_GetInt_or_Default(Entity *pType, char *field,int dValue){
- Tcl_Obj *result=NULL;
- if(field && pType) {
- result=Entity_GetField(pType->pType,pType->infoDict,field);
- }
- if(result) {
- int sint;
- double s;
- if (Tcl_GetIntFromObj(NULL,result,&sint)==TCL_OK) {
- return sint;
- }
- if (Tcl_GetDoubleFromObj(NULL,result,&s)==TCL_OK) {
- return (int)round(s);
- }
- }
- return dValue;
- }
- /* TypeSpec_WideInt */
- Tcl_WideInt TypeSpec_WideInt(Entity *pType, char *field){
- Tcl_Obj *result=NULL;
- if(field && pType) {
- result=Entity_GetField(pType->pType,pType->infoDict,field);
- }
- if(result) {
- Tcl_WideInt c;
- if(Tcl_GetWideIntFromObj(NULL,result,&c)==TCL_OK) {
- return c;
- }
- }
- return 0;
- }
- /* *TypeSpec_GetTclObj */
- Tcl_Obj *TypeSpec_GetTclObj(Entity *pType, char *field){
- Tcl_Obj *result=NULL;
-
- if(field && pType) {
- result=Entity_GetField(pType->pType,pType->infoDict,field);
- }
- if(result) {
- return result;
- }
- return Tcl_NewObj();
- }
- /* *TypeSpec_GetTclObj_OR_NULL */
- Tcl_Obj *TypeSpec_GetTclObj_OR_NULL(Entity *pType, char *field){
- Tcl_Obj *result=NULL;
-
- if(field && pType) {
- result=Entity_GetField(pType->pType,pType->infoDict,field);
- }
- return result;
- }
- /* *TypeSpec_GetLogicSet */
- Tcl_Obj *TypeSpec_GetLogicSet(Entity *pType, char *field){
- if(field && pType) {
- return Entity_GetField(pType->pType,pType->infoDict,field);
- }
- return NULL;
- }
- /* END generate-cfile-functions */
- /* BEGIN generate-cfile-tclapi */
- /* Tcl Proc ::odiemath::distance */
- static int TclCmd_odiemath_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- int i;
- double result;
- if( objc<1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "i1 i2 ?j1 j2? ?k1 k2?");
- return TCL_ERROR;
- }
- result=0.0;
- for(i=1;i<objc;i+=2) {
- double a,b,dx;
- if(Tcl_GetDoubleFromObj(interp,objv[i],&a)) return TCL_ERROR;
- if(i+1>=objc) {
- Tcl_AppendResult(interp, "Odd number of arguments",(char*)0);
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[i+1],&b)) return TCL_ERROR;
- dx=b-a;
- result=result+dx*dx;
- }
- result=sqrt(result);
- Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::dist3d */
- static int TclCmd_odiemath_dist3d(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double result,ax,ay,az,bx,by,bz,dx,dy,dz;
- if( objc!=7 ){
- Tcl_WrongNumArgs(interp, 1, objv, "x0 y0 z0 x1 y1 z1");
- return TCL_ERROR;
- }
- result=0.0;
- if(Tcl_GetDoubleFromObj(interp,objv[1],&ax)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&ay)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[3],&az)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[4],&bx)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[5],&by)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[6],&bz)) return TCL_ERROR;
- dx=bx-ax;
- dy=by-ay;
- dz=bz-az;
-
- result=sqrt(dx*dx + dy*dy + dz*dz);
- Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::grid_hex */
- static int TclCmd_odiemath_grid_hex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double grid, x, y;
- int gx,gy;
- Tcl_Obj *pResult;
-
- if( objc != 4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "gridsize x y");
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&grid)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&x)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[3],&y)) return TCL_ERROR;
- pResult=Tcl_NewObj();
- gy=(int)round(y/grid);
- if(gy%2==1){
- gx=(int)round((x-grid/2)/grid);
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*gx+grid/2));
- } else {
- gx=(int)round(x/grid);
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*gx));
- }
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*gy));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::grid_round */
- static int TclCmd_odiemath_grid_round(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double x,q;
- int i;
- Tcl_Obj *pResult;
- pResult=Tcl_NewObj();
- for(i=1;i<objc;i++) {
- if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) {
- Tcl_DecrRefCount(pResult);
- return TCL_ERROR;
- }
- q=OdieGrain*round(x/OdieGrain);
- if(x-q>(OdieGrain*0.5)) {
- q+=OdieGrain;
- }
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(q));
- }
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::grid_square */
- static int TclCmd_odiemath_grid_square(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double grid;
- double x;
- double y;
- Tcl_Obj *pResult;
- if( objc < 3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "gridsize x y...");
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&grid)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&x)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[3],&y)) return TCL_ERROR;
- pResult=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*round(x/grid)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*round(y/grid)));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::list_round */
- static int TclCmd_odiemath_list_round(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- int i, n;
- double factor;
- Tcl_Obj *pResult;
- if( objc < 3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "gridsize list\ngridsize element ?element?...");
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&factor)) return TCL_ERROR;
- if(objc==3) {
- if( Tcl_ListObjLength(interp, objv[2], &n) ) return TCL_ERROR;
- pResult=Tcl_NewObj();
- for(i=0;i<n;i++) {
- double thisval,remainder;
- Tcl_Obj *pObj;
- Tcl_ListObjIndex(0, objv[2], i, &pObj);
- if(Tcl_GetDoubleFromObj(interp,pObj,&thisval)) {
- Tcl_DecrRefCount(pResult);
- return TCL_ERROR;
- }
- remainder=fmod(thisval,factor);
- Tcl_ListObjAppendElement(interp, pResult, ODIE_NewFuzzyObj(thisval-remainder));
- }
- } else {
- pResult=Tcl_NewObj();
- for(i=2;i<objc;i++) {
- double thisval,remainder;
- if(Tcl_GetDoubleFromObj(interp,objv[i],&thisval)) {
- Tcl_DecrRefCount(pResult);
- return TCL_ERROR;
- }
- remainder=fmod(thisval,factor);
- Tcl_ListObjAppendElement(interp, pResult, ODIE_NewFuzzyObj(thisval-remainder));
- }
- }
- Tcl_SetObjResult(interp,pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::list_to_int */
- static int TclCmd_odiemath_list_to_int(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Tcl_Obj *pResult=Tcl_NewObj();
- int i;
- for(i=1;i<objc;i++) {
- double thisval;
- if(Tcl_GetDoubleFromObj(interp,objv[i],&thisval)) return TCL_ERROR;
- Tcl_ListObjAppendElement(interp, pResult, Tcl_NewIntObj((int)thisval));
- }
- Tcl_SetObjResult(interp,pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::matrix_rotate_angle */
- static int TclCmd_odiemath_matrix_rotate_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Tcl_Obj *pResult=Tcl_NewObj();
- double angle;
- if( (objc != 2) && (objc != 3) ){
- Tcl_WrongNumArgs(interp, 1, objv, "angle ?units?");
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&angle)) return TCL_ERROR;
- if(objc==3) {
- /* Scale by the unit */
- char *units;
- units=Tcl_GetString(objv[2]);
- if(units[0]=='d') {
- angle=angle/180.0*M_PI;
- } else if (units[0]=='g') {
- angle=angle/200.0*M_PI;
- } else if (units[0]=='r') {
- } else {
- Tcl_AppendResult(interp, "Unknown unit ", units, " use d[egrees], r[adians], or g[radients]. Radians are assumed",(char*)0);
- return TCL_ERROR;
- }
- }
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sin(angle)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(-sin(angle)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(0.0));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(0.0));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::matrix_rotate_normal */
- static int TclCmd_odiemath_matrix_rotate_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Tcl_Obj *pResult=Tcl_NewObj();
- double nx,ny,angle;
-
- if( objc != 3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "nx ny");
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&nx)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&ny)) return TCL_ERROR;
- angle=atan2(ny,nx);
-
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sin(angle)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(-sin(angle)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(0.0));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(0.0));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::normal */
- static int TclCmd_odiemath_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double x0,y0,x1,y1;
- double L,dx,dy;
- Tcl_Obj *pResult;
- if( objc != 5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "x0 y0 x1 y1");
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&x0)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&y0)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[3],&x1)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[4],&y1)) return TCL_ERROR;
-
- dx=x1-x0;
- dy=y1-y0;
- L=sqrt(dx*dx+dy*dy);
- pResult=Tcl_NewObj();
- if(ODIE_Real_Is_Zero(L)) {
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(100));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(0));
- } else {
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj((int)100*(dx/L)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj((int)100*(dy/L)));
- }
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::perpendicular */
- static int TclCmd_odiemath_perpendicular(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double x0,y0,x1,y1;
- double L,dx,dy;
- Tcl_Obj *pResult;
- if( objc != 5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "x0 y0 x1 y1");
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&x0)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&y0)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[3],&x1)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[4],&y1)) return TCL_ERROR;
-
- dx=y1-y0;
- dy=x0-x1;
- L=sqrt(dx*dx+dy*dy);
- pResult=Tcl_NewObj();
- if(ODIE_Real_Is_Zero(L)) {
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(100));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(0));
- } else {
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj((int)100*(dx/L)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj((int)100*(dy/L)));
- }
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::normal_2d */
- static int TclCmd_odiemath_normal_2d(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double nx,ny,norm;
- int ox,oy;
- Tcl_Obj *pResult;
- if( objc < 3 ){
- ox=100;
- oy=0;
- } else {
- if(Tcl_GetDoubleFromObj(interp,objv[1],&nx)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&ny)) return TCL_ERROR;
- norm=sqrt(nx*nx+ny*ny);
- if(norm<=0.0) {
- ox=100.0;
- oy=0.0;
- } else {
- ox=100*nx/norm;
- oy=100*ny/norm;
- }
- }
- pResult=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(ox));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(oy));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::parallel_segment */
- static int TclCmd_odiemath_parallel_segment(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double x0,y0,x1,y1,offset;
- double L,dx,dy;
- Tcl_Obj *pResult;
- if( objc != 6 ){
- Tcl_WrongNumArgs(interp, 1, objv, "x0 y0 x1 y1 offset");
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&x0)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&y0)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[3],&x1)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[4],&y1)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[5],&offset)) return TCL_ERROR;
-
- dx=x0-x1;
- dy=y0-y1;
- L=sqrt(dx*dx+dy*dy);
- if(ODIE_Real_Is_Zero(dx)) {
- offset*=-1.0;
- }
- pResult=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(x0+offset*dy/L));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(y0+offset*dx/L));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(x1+offset*dy/L));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(y1+offset*dx/L));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::vector_length */
- static int TclCmd_odiemath_vector_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- int i;
- double result,sum=0.0;
- if( objc<1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "x ?y? ?z? ?...?");
- return TCL_ERROR;
- }
- result=0.0;
- for(i=1;i<objc;i++) {
- double a;
- if(Tcl_GetDoubleFromObj(interp,objv[i],&a)) return TCL_ERROR;
- sum+=a*a;
- }
- result=sqrt(sum);
- Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::vector_rotate_and_size */
- static int TclCmd_odiemath_vector_rotate_and_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- /*
- ** Apply Matrices
- */
- Tcl_Obj *pResult=Tcl_NewObj();
- int i;
- double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0};
- double nx,ny,scalex,scaley,angle;
-
- if( objc < 7 ){
- Tcl_WrongNumArgs(interp, 1, objv, "normalx normaly sizex sizey x1 y1 ?x2 y2?...");
- return TCL_ERROR;
- }
-
- if(Tcl_GetDoubleFromObj(interp,objv[1],&nx)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&ny)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[3],&scalex)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[4],&scaley)) return TCL_ERROR;
-
- angle=atan2(ny,nx);
- matA[0]=cos(angle);
- matA[1]=sin(angle);
- matA[2]=-sin(angle);
- matA[3]=cos(angle);
- matA[4]=0.0;
- matA[5]=0.0;
-
- scalex*=0.5;
- scaley*=0.5;
- for(i=5;i<objc;i+=2) {
- double x,y,sx,sy,newx,newy;
- if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
- sx=x*scalex;
- sy=y*scaley;
- newx=matA[0]*sx+matA[1]*sy+matA[4];
- newy=matA[2]*sx+matA[3]*sy+matA[5];
-
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
- }
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::vector_scale */
- static int TclCmd_odiemath_vector_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Tcl_Obj *pResult=Tcl_NewObj();
- int i;
- double scalex,scaley;
-
- if( objc < 5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "sizex sizey x1 y1 ?x2 y2?...");
- return TCL_ERROR;
- }
-
- if(Tcl_GetDoubleFromObj(interp,objv[1],&scalex)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&scaley)) return TCL_ERROR;
-
- scalex*=0.5;
- scaley*=0.5;
- for(i=3;i<objc;i+=2) {
- double x,y,sx,sy;
- if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
- sx=x*scalex;
- sy=y*scaley;
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sx));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sy));
- }
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::vector_translate_and_zoom */
- static int TclCmd_odiemath_vector_translate_and_zoom(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- /*
- ** Apply Matrices
- */
-
- Tcl_Obj *pResult=Tcl_NewObj();
- int i;
- double zoom;
- double centerx,centery;
-
- if( objc < 6 ){
- Tcl_WrongNumArgs(interp, 1, objv, "zoom centerx centery x1 y1 ?x2 y2?...");
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&zoom)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],¢erx)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[3],¢ery)) return TCL_ERROR;
- for(i=4;i<objc;i+=2) {
- double x,y,newx,newy;
- if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
- newx=(x/zoom)+centerx;
- newy=(y/zoom)+centery;
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
- }
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::grid */
- static int TclCmd_odiemath_grid(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- if( objc > 1 ){
- if(Tcl_GetDoubleFromObj(interp,objv[1],&OdieGrain)) return TCL_ERROR;
- }
- Tcl_SetObjResult(interp,Tcl_NewDoubleObj(OdieGrain));
- return TCL_OK;
- }
- /* Tcl Proc ::odiemath::tolerance */
- static int TclCmd_odiemath_tolerance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- if( objc > 1 ){
- if(Tcl_GetDoubleFromObj(interp,objv[1],&OdieTolerance)) return TCL_ERROR;
- }
- Tcl_SetObjResult(interp,Tcl_NewDoubleObj(OdieTolerance));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::aabb::create */
- static int TclCmd_odie_aabb_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- MATOBJ *C;
- C=Odie_MatrixObj_Create(MATFORM_aabb_xyz);
- VectorXYZ_AABB_Reset(C->matrix);
- if(objc==7) {
- int i;
- for(i=1;i<objc;i++) {
- if(Tcl_GetDoubleFromObj(interp,objv[1],&C->matrix[i-1])) return TCL_ERROR;
- }
- } else if(objc>1) {
- int i;
- VectorXYZ point;
- for(i=1;i<objc;i++) {
- if(Odie_GetVectorXYZFromTclObj(interp,objv[i],point)) return TCL_ERROR;
- VectorXYZ_AABB_Measure(point,C->matrix);
- }
- }
- Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::aabb::overlap_two_vectors */
- static int TclCmd_odie_aabb_overlap_two_vectors(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXYZ a1,a2,b1,b2;
- double c;
- if( objc != 5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "A1 A2 B1 B2");
- return TCL_ERROR;
- }
- if(Odie_GetVectorXYZFromTclObj(interp,objv[1],a1)) return TCL_ERROR;
- if(Odie_GetVectorXYZFromTclObj(interp,objv[2],a2)) return TCL_ERROR;
- if(Odie_GetVectorXYZFromTclObj(interp,objv[3],b1)) return TCL_ERROR;
- if(Odie_GetVectorXYZFromTclObj(interp,objv[4],b2)) return TCL_ERROR;
- c=VectorXYZ_BBOX_Overlap_TwoVectors(a1,a2,b1,b2);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(c));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::aabb::measure */
- static int TclCmd_odie_aabb_measure(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- MATOBJ *C;
- Tcl_Obj *varname,*pResult;
- int i;
- VectorXYZ point;
- if( objc < 2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BBOX VECTORXYZ ?VECTORXYZ..?");
- return TCL_ERROR;
- }
- varname=Tcl_ObjGetVar2(interp,objv[1],NULL,0);
- if(Odie_GetMatrixFromTclObj(interp,varname,MATFORM_aabb_xyz,&C)) return TCL_ERROR;
- VectorXYZ_AABB_Normalize(C->matrix);
- for(i=2;i<objc;i++) {
- if(Odie_GetVectorXYZFromTclObj(interp,objv[i],point)) return TCL_ERROR;
- VectorXYZ_AABB_Measure(point,C->matrix);
- }
- Tcl_InvalidateStringRep(varname);
- return TCL_OK;
- }
- /* Tcl Proc ::odie::aabb::faces */
- static int TclCmd_odie_aabb_faces(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double VALUES[6];
- double scale=1.0;
- Tcl_Obj *pResult,*pRow;
- if( objc != 2 && objc != 3 && objc != 7 && objc != 8){
- Tcl_WrongNumArgs(interp, 1, objv, "AABB ?SCALE?\nx0 y0 z0 x1 y1 z1 ?SCALE?");
- return TCL_ERROR;
- }
- if(objc==2 || objc==3) {
- MATOBJ *A;
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_aabb_xyz,&A)) return TCL_ERROR;
- if(objc==3) {
- if(Tcl_GetDoubleFromObj(interp,objv[2],&scale)) {
- scale=1.0;
- }
- }
- VALUES[X_MIN_IDX]=A->matrix[X_MIN_IDX];
- VALUES[Y_MIN_IDX]=A->matrix[Y_MIN_IDX];
- VALUES[Z_MIN_IDX]=A->matrix[Z_MIN_IDX];
- VALUES[X_MAX_IDX]=A->matrix[X_MAX_IDX];
- VALUES[Y_MAX_IDX]=A->matrix[Y_MAX_IDX];
- VALUES[Z_MAX_IDX]=A->matrix[Z_MAX_IDX];
- } else {
- if(objc==8) {
- if(Tcl_GetDoubleFromObj(interp,objv[7],&scale)) {
- scale=1.0;
- }
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&VALUES[0])!=TCL_OK) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&VALUES[1])!=TCL_OK) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[3],&VALUES[2])!=TCL_OK) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[4],&VALUES[3])!=TCL_OK) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[5],&VALUES[4])!=TCL_OK) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[6],&VALUES[5])!=TCL_OK) return TCL_ERROR;
- }
- pResult=Tcl_NewObj();
- pRow=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pResult,pRow);
- pRow=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pResult,pRow);
- pRow=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pResult,pRow);
- pRow=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pResult,pRow);
- pRow=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pResult,pRow);
- pRow=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
- Tcl_ListObjAppendElement(interp,pResult,pRow);
- Tcl_SetObjResult(interp,pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odie::aabb::from_vectorxyz */
- static int TclCmd_odie_aabb_from_vectorxyz(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- MATOBJ *A,*C;
- if( objc < 2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BBOX\nor\nA B ?C...?");
- return TCL_ERROR;
- }
- if(objc==2) {
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_aabb_xyz,&C)) return TCL_ERROR;
- VectorXYZ_AABB_Normalize(C->matrix);
- } else {
- int i;
- C=Odie_MatrixObj_Create(MATFORM_aabb_xyz);
- VectorXYZ_AABB_Reset(C->matrix);
- for(i=1;i<objc;i++) {
- if(Odie_GetMatrixFromTclObj(interp,objv[i],MATFORM_vectorxyz,&A)) return TCL_ERROR;
- VectorXYZ_AABB_Measure(A->matrix,C->matrix);
- }
- }
- Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::aabb::from_line */
- static int TclCmd_odie_aabb_from_line(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXYZ A,B;
- VectorXYZ AA,BB;
-
- Tcl_Obj *pResult=Tcl_NewObj();
-
- if( objc != 3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "A B");
- return TCL_ERROR;
- }
- if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
- if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
- AA[X_IDX]=min(A[X_IDX],B[X_IDX]);
- AA[Y_IDX]=min(A[Y_IDX],B[Y_IDX]);
- AA[Z_IDX]=min(A[Z_IDX],B[Z_IDX]);
- BB[X_IDX]=max(A[X_IDX],B[X_IDX]);
- BB[Y_IDX]=max(A[Y_IDX],B[Y_IDX]);
- BB[Z_IDX]=max(A[Z_IDX],B[Z_IDX]);
- pResult=Tcl_NewObj();;
- Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(AA));
- Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(BB));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odie::aabb::from_center_size */
- static int TclCmd_odie_aabb_from_center_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXYZ center,size;
- VectorXYZ AA,BB;
-
- Tcl_Obj *pResult=Tcl_NewObj();
-
- if( objc != 3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "center size");
- return TCL_ERROR;
- }
- if(Odie_GetVectorXYZFromTclObj(interp,objv[1],center)) return TCL_ERROR;
- if(Odie_GetVectorXYZFromTclObj(interp,objv[2],size)) return TCL_ERROR;
- size[X_IDX]*=0.5;
- size[Y_IDX]*=0.5;
- size[Z_IDX]*=0.5;
- pResult=Tcl_NewObj();
- VectorXYZ_Subtract(AA,center,size);
- VectorXYZ_Add(BB,center,size);
- Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(AA));
- Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(BB));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odie::aabb::intersect */
- static int TclCmd_odie_aabb_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- MATOBJ *A,*B;
- int c;
- if( objc != 3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "AABB AABB");
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_aabb_xyz,&A)) return TCL_ERROR;
- if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_aabb_xyz,&B)) return TCL_ERROR;
- c=AABB_AABB_Intersect(A->matrix,B->matrix);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(c));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::aabb::within */
- static int TclCmd_odie_aabb_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- MATOBJ *A,*B;
- double c;
- if( objc != 3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "AABB POINT");
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_aabb_xyz,&A)) return TCL_ERROR;
- if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_vectorxyz,&B)) return TCL_ERROR;
- c=VectorXYZ_AABB_Within(B->matrix,A->matrix);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(c));
- return TCL_OK;
- }
- /* Tcl Proc ::affine2d::apply */
- static int TclCmd_affine2d_apply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Tcl_Obj *pResult=Tcl_NewObj();
- int i;
- double matA[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
-
- if( objc < 4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "matrix x1 y1 ?x2 y2?...");
- return TCL_ERROR;
- }
- for(i=0;i<6;i++) {
- Tcl_Obj *temp;
- if(Tcl_ListObjIndex(interp, objv[1], i, &temp)) return TCL_ERROR;
- if(Odie_GetMatrixElementFromObj(interp,temp,matA,i)) return TCL_ERROR;
- }
-
- for(i=2;i<objc;i+=2) {
- double x,y,newx,newy;
- if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
- newx=matA[0]*x+matA[1]*y+matA[4];
- newy=matA[2]*x+matA[3]*y+matA[5];
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
- }
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::affine2d::combine */
- static int TclCmd_affine2d_combine(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- int i,idx;
- Tcl_Obj *pResult=Tcl_NewObj();
- double matA[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
- double matB[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
-
- if( objc < 2){
- Tcl_WrongNumArgs(interp, 1, objv, "transformA transformB ?transformC?...");
- return TCL_ERROR;
- }
-
- for(i=0;i<6;i++) {
- Tcl_Obj *temp;
- if(Tcl_ListObjIndex(interp, objv[1], i, &temp)) return TCL_ERROR;
- if(Odie_GetMatrixElementFromObj(interp,temp,matA,i)) return TCL_ERROR;
- }
- for(idx=2;idx<objc;idx++) {
- for(i=0;i<6;i++) {
- Tcl_Obj *temp;
- if(Tcl_ListObjIndex(interp, objv[idx], i, &temp)) return TCL_ERROR;
- if(Odie_GetMatrixElementFromObj(interp,temp,matB,i)) return TCL_ERROR;
- }
- matA[0]=matA[0]*matB[0]+matA[2]*matB[2]; /* [expr {$a*$i+$c*$j}] */
- matA[1]=matA[1]*matB[0]+matA[3]*matB[2]; /* [expr {$b*$i+$d*$j}] */
- matA[2]=matA[0]*matB[2]+matA[2]*matB[3]; /* [expr {$a*$k+$c*$l}] */
- matA[3]=matA[1]*matB[2]+matA[3]*matB[3]; /* [expr {$b*$k+$d*$l}] */
- matA[4]=matA[4]*matB[0]+matA[5]*matB[1]+matB[4]; /* [expr {$e*$i+$f*$j+$m}] */
- matA[5]=matA[4]*matB[2]+matA[5]*matB[3]+matB[5]; /* [expr {$e*$k+$f*$l+$n}]] */
- }
- for(i=0;i<6;i++) {
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(matA[i]));
- }
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::affine2d::rotation_from_angle */
- static int TclCmd_affine2d_rotation_from_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Tcl_Obj *pResult=Tcl_NewObj();
- double angle;
- if( (objc != 2) && (objc != 3) ){
- Tcl_WrongNumArgs(interp, 1, objv, "angle ?units?");
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&angle)) return TCL_ERROR;
- if(objc==3) {
- /* Scale by the unit */
- char *units;
- units=Tcl_GetString(objv[2]);
- if(units[0]=='d') {
- angle=angle/180.0*M_PI;
- } else if (units[0]=='g') {
- angle=angle/200.0*M_PI;
- } else if (units[0]=='r') {
- } else {
- Tcl_AppendResult(interp, "Unknown unit ", units, " use d[egrees], r[adians], or g[radients]. Radians are assumed",(char*)0);
- return TCL_ERROR;
- }
- }
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sin(angle)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(-sin(angle)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
- Tcl_ListObjAppendElement(interp,pResult,ODIE_REAL_ZERO());
- Tcl_ListObjAppendElement(interp,pResult,ODIE_REAL_ZERO());
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::affine2d::rotation_from_normal */
- static int TclCmd_affine2d_rotation_from_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Tcl_Obj *pResult=Tcl_NewObj();
- double nx,ny,angle;
-
- if( objc != 3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "nx ny");
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&nx)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&ny)) return TCL_ERROR;
- angle=atan2(ny,nx);
-
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sin(angle)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(-sin(angle)));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
- Tcl_ListObjAppendElement(interp,pResult,ODIE_REAL_ZERO());
- Tcl_ListObjAppendElement(interp,pResult,ODIE_REAL_ZERO());
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::affine4x4::compare */
- static int TclCmd_affine4x4_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Odie_MatrixObj *A,*B;
- int c;
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_affine,&A)) return TCL_ERROR;
- if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_affine,&B)) return TCL_ERROR;
- c=affine_Compare(A->matrix,B->matrix);
- Tcl_SetObjResult(interp,Tcl_NewBooleanObj(c));
- return TCL_OK;
- }
- /* Tcl Proc ::affine4x4::identity */
- static int TclCmd_affine4x4_identity(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- /*
- ** description: Pushes an affine identity matrix onto the stack
- */
- Odie_MatrixObj *C;
- C=Odie_MatrixObj_Create(MATFORM_affine);
- Odie_Affine4x4_Identity(C->matrix);
- Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::affine4x4::translation */
- static int TclCmd_affine4x4_translation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- /*
- ** description:
- ** Convert a displacement vector (X Y Z) into an affine transformation
- */
- Odie_MatrixObj *A,*C;
- if(objc != 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "VECTORXYZ" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz,&A)) return TCL_ERROR;
- C=Odie_MatrixObj_Create(MATFORM_affine);
- Odie_Affine4x4_Translation(C->matrix,A->matrix);
- Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::affine4x4::scale */
- static int TclCmd_affine4x4_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- /*
- ** description:
- ** Convert a scale vector (X Y Z) into an affine transformation
- */
- Odie_MatrixObj *A,*C;
- if(objc != 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "VECTORXYZ" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz,&A)) return TCL_ERROR;
- C=Odie_MatrixObj_Create(MATFORM_affine);
- Odie_Affine4x4_Scale(C->matrix,A->matrix);
- Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::affine4x4::rotate_nutation */
- static int TclCmd_affine4x4_rotate_nutation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double theta;
- Odie_MatrixObj *RESULT;
- if(objc != 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "RADIANS" );
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&theta)) return TCL_ERROR;
- RESULT=Odie_MatrixObj_Create(MATFORM_affine);
- affine_rotate_nutation(RESULT->matrix,theta);
- Tcl_SetObjResult(interp,Matrix_To_TclObj(RESULT));
- return TCL_OK;
- }
- /* Tcl Proc ::affine4x4::rotate_precession */
- static int TclCmd_affine4x4_rotate_precession(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double phi;
- Odie_MatrixObj *RESULT;
- Tcl_Obj *pResult;
- if(objc != 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "RADIANS" );
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&phi)) return TCL_ERROR;
- RESULT=Odie_MatrixObj_Create(MATFORM_affine);
- affine_rotate_precession(RESULT->matrix,phi);
- Tcl_SetObjResult(interp,Matrix_To_TclObj(RESULT));
- return TCL_OK;
- }
- /* Tcl Proc ::affine4x4::rotate_spin */
- static int TclCmd_affine4x4_rotate_spin(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double psi;
- Odie_MatrixObj *RESULT;
- if(objc != 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "RADIANS" );
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&psi)) return TCL_ERROR;
- RESULT=Odie_MatrixObj_Create(MATFORM_affine);
- affine_rotate_spin(RESULT->matrix,psi);
- Tcl_SetObjResult(interp,Matrix_To_TclObj(RESULT));
- return TCL_OK;
- }
- /* Tcl Proc ::affine4x4::from_euler */
- static int TclCmd_affine4x4_from_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- /*
- ** description:
- ** Convert a rotation vector (X Y Z) into an affine transformation
- */
- Odie_MatrixObj *A,*C;
- if(objc != 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "EULER" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_euler,&A)) return TCL_ERROR;
- C=Odie_MatrixObj_Create(MATFORM_affine);
- affine_Rotate_From_Euler(C->matrix,A->matrix);
- Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::affine4x4::multiply */
- static int TclCmd_affine4x4_multiply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- /*
- ** description:
- ** Multiply 2 4x4 matrices. Used to combine 2 affine transformations.
- ** Note: Some affine transformations need to be performed in a particular
- ** order to make sense.
- */
- Odie_MatrixObj *A,*B,*C;
- if(objc < 3) {
- Tcl_WrongNumArgs( interp, 1, objv, "A B" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_affine,&A)) return TCL_ERROR;
- if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_affine,&B)) return TCL_ERROR;
- C=Odie_MatrixObj_Create(MATFORM_affine);
- Odie_Affine4x4_Multiply(C->matrix,A->matrix,B->matrix);
- Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::affine4x4::multiply_inplace */
- static int TclCmd_affine4x4_multiply_inplace(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- /*
- ** description:
- ** Multiply 2 4x4 matrices. Used to combine 2 affine transformations.
- ** Note: Some affine transformations need to be performed in a particular
- ** order to make sense.
- */
- Odie_MatrixObj *A,*B,*C;
- Tcl_Obj *varname;
- if(objc < 3) {
- Tcl_WrongNumArgs( interp, 1, objv, "VARNAME AFFINE" );
- return TCL_ERROR;
- }
- Tcl_ResetResult(interp);
- varname=Tcl_ObjGetVar2(interp,objv[1],NULL,0);
- if(Odie_GetMatrixFromTclObj(interp,varname,MATFORM_affine,&A)) return TCL_ERROR;
- if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_affine,&B)) return TCL_ERROR;
- Odie_Affine4x4_Multiply(A->matrix,A->matrix,B->matrix);
- Tcl_InvalidateStringRep(varname);
- return TCL_OK;
- }
- /* Tcl Proc ::affine4x4::inverse */
- static int TclCmd_affine4x4_inverse(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- /*
- ** description:
- ** Multiply 2 4x4 matrices. Used to combine 2 affine transformations.
- ** Note: Some affine transformations need to be performed in a particular
- ** order to make sense.
- */
- Odie_MatrixObj *A,*C;
- if(objc < 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "A" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_affine,&A)) return TCL_ERROR;
- C=Odie_MatrixObj_Create(MATFORM_affine);
- Odie_Affine4x4_Inverse(C->matrix,A->matrix);
- Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::affine4x4::from_normal */
- static int TclCmd_affine4x4_from_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- /*
- ** description:
- ** Convert a displacement normal vector (X Y Z) into an affine transformation
- */
- Odie_MatrixObj *A,*C;
- if(objc != 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "VECTORXYZ" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz,&A)) return TCL_ERROR;
- C=Odie_MatrixObj_Create(MATFORM_affine);
- Odie_Affine_From_Normal(C->matrix,A->matrix);
- Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::bbox::create */
- static int TclCmd_odie_bbox_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- MATOBJ *C;
- C=Odie_MatrixObj_Create(MATFORM_bbox_xy);
- VectorXY_BBOX_Reset(C->matrix);
- if(objc>1) {
- int i;
- VectorXY point;
- for(i=1;i<objc;i++) {
- if(Odie_GetVectorXYFromTclObj(interp,objv[i],point)) return TCL_ERROR;
- VectorXY_BBOX_Measure(point,C->matrix);
- }
- }
- Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::bbox::measure */
- static int TclCmd_odie_bbox_measure(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- MATOBJ *C;
- Tcl_Obj *varname,*pResult;
- int i;
- VectorXY point;
- if( objc < 3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BBOX VECTORXY ?VECTORXY..?");
- return TCL_ERROR;
- }
- varname=Tcl_ObjGetVar2(interp,objv[1],NULL,0);
- if(varname) {
- if(Odie_GetMatrixFromTclObj(interp,varname,MATFORM_bbox_xy,&C)) return TCL_ERROR;
- } else {
- C=Odie_MatrixObj_Create(MATFORM_bbox_xy);
- VectorXY_BBOX_Reset(C->matrix);
- }
- for(i=2;i<objc;i++) {
- if(Odie_GetVectorXYFromTclObj(interp,objv[i],point)) return TCL_ERROR;
- VectorXY_BBOX_Measure(point,C->matrix);
- }
- pResult=Matrix_To_TclObj(C);
- Tcl_ObjSetVar2(interp,objv[1],NULL,pResult,0);
- Tcl_SetObjResult(interp,pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odie::bbox::elements */
- static int TclCmd_odie_bbox_elements(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- MATOBJ *C;
- Tcl_Obj *pResult;
- if( objc != 2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BBOX");
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_bbox_xy,&C)) return TCL_ERROR;
- pResult=Tcl_NewObj();
- Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(C->matrix[BBOX_X0_IDX]));
- Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(C->matrix[BBOX_Y1_IDX]));
- Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(C->matrix[BBOX_X1_IDX]));
- Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(C->matrix[BBOX_Y0_IDX]));
- Tcl_SetObjResult(interp,pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odie::bbox::intersect */
- static int TclCmd_odie_bbox_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- MATOBJ *A,*B;
- int c;
- if( objc != 3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BBOX BBOX");
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_bbox_xy,&A)) return TCL_ERROR;
- if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_bbox_xy,&B)) return TCL_ERROR;
- c=BBOX_BBOX_Intersect(A->matrix,B->matrix);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(c));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::bbox::within */
- static int TclCmd_odie_bbox_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXY A;
- MATOBJ *C;
- int result;
- if( objc != 3 && objc != 4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BBOX ?XY| X? ?y?");
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_bbox_xy,&C)) return TCL_ERROR;
- if(objc==3) {
- if(Odie_GetVectorXYFromTclObj(interp,objv[2],A)) return TCL_ERROR;
- } else {
- double a1,a2;
-
- if(Tcl_GetDoubleFromObj(interp,objv[2],&a1)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[3],&a2)) return TCL_ERROR;
- A[X_IDX]=a1;
- A[Y_IDX]=a2;
- }
- result=VectorXY_Within_BBOX(A,C->matrix);
- Tcl_SetObjResult(interp,Tcl_NewBooleanObj(result));
- return TCL_OK;
- }
- /* Tcl Proc ::quaternion::add */
- static int TclCmd_quaternion_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- QUATERNION A,B,C;
- if(objc < 3) {
- Tcl_WrongNumArgs( interp, 1, objv, "A B" );
- return TCL_ERROR;
- }
- if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
- if(Odie_GetQuaternionFromTclObj(interp,objv[2],B)) return TCL_ERROR;
- Quaternion_Add(C,A,B);
- Tcl_SetObjResult(interp,Quaternion_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::quaternion::subtract */
- static int TclCmd_quaternion_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- QUATERNION A,B,C;
- if(objc < 3) {
- Tcl_WrongNumArgs( interp, 1, objv, "A B" );
- return TCL_ERROR;
- }
- if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
- if(Odie_GetQuaternionFromTclObj(interp,objv[2],B)) return TCL_ERROR;
- Quaternion_Subtract(C,A,B);
- Tcl_SetObjResult(interp,Quaternion_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::quaternion::multiply */
- static int TclCmd_quaternion_multiply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- QUATERNION A,B,C;
- if(objc < 3) {
- Tcl_WrongNumArgs( interp, 1, objv, "A B" );
- return TCL_ERROR;
- }
- if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
- if(Odie_GetQuaternionFromTclObj(interp,objv[2],B)) return TCL_ERROR;
- Quaternion_Multiply(C,A,B);
- Tcl_SetObjResult(interp,Quaternion_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::quaternion::divide */
- static int TclCmd_quaternion_divide(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- QUATERNION A,B,C;
- if(objc < 3) {
- Tcl_WrongNumArgs( interp, 1, objv, "A B" );
- return TCL_ERROR;
- }
- if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
- if(Odie_GetQuaternionFromTclObj(interp,objv[2],B)) return TCL_ERROR;
- Quaternion_Divide(C,A,B);
- Tcl_SetObjResult(interp,Quaternion_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::quaternion::square_root */
- static int TclCmd_quaternion_square_root(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- QUATERNION A,C;
- if(objc < 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "A" );
- return TCL_ERROR;
- }
- if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
- Quaternion_Square_Root(C,A);
- Tcl_SetObjResult(interp,Quaternion_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::quaternion::square */
- static int TclCmd_quaternion_square(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- QUATERNION A,C;
- if(objc < 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "A" );
- return TCL_ERROR;
- }
- if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
- Quaternion_Square(C,A);
- Tcl_SetObjResult(interp,Quaternion_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::quaternion::from_euler */
- static int TclCmd_quaternion_from_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Odie_MatrixObj *A;
- QUATERNION C;
- if(objc < 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "A" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_euler,&A)) return TCL_ERROR;
- EulerRotation_To_Quaternion(C,A->matrix[EULER_HEADING],A->matrix[EULER_ATTITUDE],A->matrix[EULER_BANK]);
- Tcl_SetObjResult(interp,Quaternion_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::vectorxyz::rotate_by_quaternion */
- static int TclCmd_vectorxyz_rotate_by_quaternion(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- QUATERNION A;
- VectorXYZ B,C;
- if(objc < 3) {
- Tcl_WrongNumArgs( interp, 1, objv, "QUATERNION VECTOR ?VECTOR ...?" );
- return TCL_ERROR;
- }
- if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
- if (objc==3) {
- if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
- VectorXYZ_Rotate_by_Quaternion(C,A,B);
- Tcl_SetObjResult(interp,VectorXYZ_To_TclObj(C));
- } else {
- Tcl_Obj *pResult=Tcl_NewObj();
- int i;
- for(i=2;i<objc;i++) {
- if(Odie_GetVectorXYZFromTclObj(interp,objv[i],B)) return TCL_ERROR;
- VectorXYZ_Rotate_by_Quaternion(C,A,B);
- Tcl_ListObjAppendElement(interp,pResult,VectorXYZ_To_TclObj(C));
- }
- Tcl_SetObjResult(interp,pResult);
- }
- return TCL_OK;
- }
- /* Tcl Proc ::quaternion::to_euler */
- static int TclCmd_quaternion_to_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- QUATERNION A;
- VectorXYZ C;
- Odie_MatrixObj *RESULT;
- if(objc < 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "A" );
- return TCL_ERROR;
- }
- if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
- Quaternion_To_EulerRotation(C,A);
- RESULT=Odie_MatrixObj_Create(MATFORM_euler);
- RESULT->matrix[X_IDX]=A[X_IDX];
- RESULT->matrix[Y_IDX]=A[Y_IDX];
- RESULT->matrix[Z_IDX]=A[Z_IDX];
- Tcl_SetObjResult(interp,Matrix_To_TclObj(RESULT));
- return TCL_OK;
- }
- /* Tcl Proc ::quaternion::from_normal */
- static int TclCmd_quaternion_from_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXYZ FROM,TO;
- Odie_MatrixObj *RESULT;
- if(objc != 2 && objc !=3) {
- Tcl_WrongNumArgs( interp, 1, objv, "?FROM? TO" );
- return TCL_ERROR;
- }
- if(objc==2) {
- FROM[X_IDX]=0.0;
- FROM[Y_IDX]=0.0;
- FROM[Z_IDX]=-1.0;
- if(Odie_GetVectorXYZFromTclObj(interp,objv[1],TO)) return TCL_ERROR;
- } else {
- if(Odie_GetVectorXYZFromTclObj(interp,objv[1],FROM)) return TCL_ERROR;
- if(Odie_GetVectorXYZFromTclObj(interp,objv[2],TO)) return TCL_ERROR;
- }
- RESULT=Odie_MatrixObj_Create(MATFORM_quaternion);
- Quaternion_From_Normal(RESULT->matrix,FROM,TO);
- Tcl_SetObjResult(interp,Matrix_To_TclObj(RESULT));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::tolerance */
- static int TclCmd_odie_tolerance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- if(objc==2) {
- double newval;
- if(Tcl_GetDoubleFromObj(interp,objv[1],&newval)) return TCL_ERROR;
- Vector_Set_Tolerance(newval);
- }
- Tcl_SetObjResult(interp,Tcl_NewDoubleObj(Vector_Tolerance));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::vector::to_list */
- static int TclCmd_odie_vector_to_list(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Odie_MatrixObj *A;
- int idx;
- int size_a;
- if(objc != 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "A" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
- size_a=A->rows*A->cols;
- Tcl_Obj **pList=NULL;
-
- pList=Odie_Alloc(sizeof(Tcl_Obj)*size_a);
- for(idx=0;idx<size_a;idx++) {
- pList[idx]=Tcl_NewDoubleObj(*(A->matrix+idx));
- }
- Tcl_SetObjResult(interp,Tcl_NewListObj(size_a,pList));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::vector::index */
- static int TclCmd_odie_vector_index(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Odie_MatrixObj *A;
- int i=-1,j=-1,idx,n=0;
- int size_a;
- Tcl_Obj **pList=NULL;
-
- if(objc != 3 && objc != 4) {
- Tcl_WrongNumArgs( interp, 1, objv, "A i ?j?" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
- if(Tcl_GetIntFromObj(interp,objv[2],&i)) return TCL_ERROR;
- size_a=A->rows*A->cols;
-
- if(i<0) {
- i=0;
- }
- if(i>=size_a) {
- i=size_a-1;
- }
- if(objc==3) {
- j=i;
- } else{
- if(Tcl_GetIntFromObj(interp,objv[3],&j)) return TCL_ERROR;
- }
- if ( j < 0 ) {
- j=size_a-1;
- } else if (j<=i) {
- Tcl_SetObjResult(interp,Tcl_NewDoubleObj(*(A->matrix+i)));
- return TCL_OK;
- }
- if(j>=size_a) {
- j=size_a-1;
- }
- n=(j-i)+1;
- pList=Odie_Alloc(sizeof(Tcl_Obj)*n);
- for(idx=i;idx<=j;idx++) {
- pList[idx]=Tcl_NewDoubleObj(*(A->matrix+idx));
- }
- Tcl_SetObjResult(interp,Tcl_NewListObj(n,pList));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::vector::add */
- static int TclCmd_odie_vector_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Odie_MatrixObj *A,*B,*C;
- int i,size_c;
- if(objc < 3) {
- Tcl_WrongNumArgs( interp, 1, objv, "A B" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
- if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_null,&B)) return TCL_ERROR;
- C=Odie_Matrix_To_Fit(A,B);
- size_c=C->rows*C->cols;
- for(i=0;i<size_c;i++) {
- *(C->matrix+i) = *(A->matrix+i) + *(B->matrix+i);
- }
- Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::vector::is_null */
- static int TclCmd_odie_vector_is_null(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Odie_MatrixObj *A,*B,*C;
- int i,size_c;
- if(objc < 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "VECTOR" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) {
- Tcl_ResetResult(interp);
- Tcl_SetObjResult(interp,Tcl_NewBooleanObj(1));
- return TCL_OK;
- }
- int size=A->rows*A->cols;
- if(size<2) {
- Tcl_SetObjResult(interp,Tcl_NewBooleanObj(1));
- return TCL_OK;
- } else {
- Tcl_SetObjResult(interp,Tcl_NewBooleanObj(0));
- }
- return TCL_OK;
- }
- /* Tcl Proc ::odie::vector::subtract */
- static int TclCmd_odie_vector_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Odie_MatrixObj *A,*B,*C;
- int i,size_c;
- if(objc < 3) {
- Tcl_WrongNumArgs( interp, 1, objv, "A B" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
- if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_null,&B)) return TCL_ERROR;
- C=Odie_Matrix_To_Fit(A,B);
- size_c=C->rows*C->cols;
- for(i=0;i<size_c;i++) {
- *(C->matrix+i) = *(A->matrix+i) - *(B->matrix+i);
- }
- Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::vector::midpoint */
- static int TclCmd_odie_vector_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Odie_MatrixObj *A,*B,*C;
- int i,size_c;
- if(objc < 3) {
- Tcl_WrongNumArgs( interp, 1, objv, "A B" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
- if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_null,&B)) return TCL_ERROR;
- C=Odie_Matrix_To_Fit(A,B);
- size_c=C->rows*C->cols;
- for(i=0;i<size_c;i++) {
- *(C->matrix+i) = (*(A->matrix+i) - *(B->matrix+i))*0.5 + *(A->matrix+i);
- }
- Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::vector::reciprocal */
- static int TclCmd_odie_vector_reciprocal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Odie_MatrixObj *A,*RESULT;
- int i;
- int size_a;
- if(objc != 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "A" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
- RESULT=Odie_Matrix_To_Fit(A,A);
- size_a=A->rows*A->cols;
- for(i=0;i<size_a;i++) {
- *(RESULT->matrix+i) = 1.0 / *(A->matrix+i);
- }
- Tcl_SetObjResult(interp,Matrix_To_TclObj(RESULT));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::vector::dot_product */
- static int TclCmd_odie_vector_dot_product(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Odie_MatrixObj *A,*B;
- int i;
- int size_a;
- int size_b;
- if(objc < 3) {
- Tcl_WrongNumArgs( interp, 1, objv, "A B" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
- if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_null,&B)) return TCL_ERROR;
- size_a=A->rows*A->cols;
- size_b=B->rows*B->cols;
- double result=0;
- for(i=0;i<size_a && i<size_b;i++) {
- result += *(A->matrix+i) * *(B->matrix+i);
- }
- Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::vector::to_matrix */
- static int TclCmd_odie_vector_to_matrix(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Odie_MatrixObj *A;
- if(objc < 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "A" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
- Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::vector::to_fuzzy */
- static int TclCmd_odie_vector_to_fuzzy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Odie_MatrixObj *A;
- int i,size_a;
- Tcl_Obj *pResult;
- if(objc < 2) {
- Tcl_WrongNumArgs( interp, 1, objv, "A" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
- pResult=Tcl_NewObj();
- size_a=A->rows*A->cols;
- for(i=0;i<size_a;i++) {
- Tcl_ListObjAppendElement(interp,pResult,ODIE_NewFuzzyObj(*(A->matrix+i)));
- }
- Tcl_SetObjResult(interp,pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odie::vector::scale */
- static int TclCmd_odie_vector_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Odie_MatrixObj *A,*B,*C=NULL,*RESULT;
- int i,size_a,size_b,size_c;
- if(objc!=3 && objc !=4) {
- Tcl_WrongNumArgs( interp, 1, objv, "A SCALE ?TRANSLATE?" );
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
- if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_null,&B)) return TCL_ERROR;
- size_a=A->rows*A->cols;
- size_b=B->rows*B->cols;
- if(size_b > 1 && size_b!=size_a) {
- Tcl_AppendResult(interp, "B is not a scaler, or arguments are not of the same size", 0);
- return TCL_ERROR;
- }
-
- if(objc==4) {
- if(Odie_GetMatrixFromTclObj(interp,objv[3],MATFORM_null,&C)) return TCL_ERROR;
- size_c=C->rows*C->cols;
- if(size_c!=size_a) {
- Tcl_AppendResult(interp, "TRANS is not the same size", 0);
- return TCL_ERROR;
- }
- }
- RESULT=Odie_Matrix_Duplicate(A);
- if(size_b==1) {
- double scaler=*(B->matrix+0);
- for(i=0;i<size_a;i++) {
- *(RESULT->matrix+i) *= scaler;
- }
- } else {
- for(i=0;i<size_a;i++) {
- *(RESULT->matrix+i) *= *(B->matrix+i);
- }
- }
- if(C) {
- for(i=0;i<size_a;i++) {
- *(RESULT->matrix+i) -= *(C->matrix+i);
- }
- }
-
- Tcl_SetObjResult(interp,Matrix_To_TclObj(RESULT));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::vector::length */
- static int TclCmd_odie_vector_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- int i,size;
- Odie_MatrixObj *A;
- double result,sum=0.0;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "vector");
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
- size=A->rows*A->cols;
- result=0.0;
- for(i=1;i<size;i++) {
- double a=*(A->matrix+1);
- sum+=a*a;
- }
- result=sqrt(sum);
- Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::vector::length_squared */
- static int TclCmd_odie_vector_length_squared(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- int i,size;
- Odie_MatrixObj *A;
- double result,sum=0.0;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "vector");
- return TCL_ERROR;
- }
- if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
- size=A->rows*A->cols;
- result=0.0;
- for(i=1;i<size;i++) {
- double a=*(A->matrix+1);
- sum+=a*a;
- }
- result=sum;
- Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
- return TCL_OK;
- }
- /* Tcl Proc ::odie::grid */
- static int TclCmd_odie_grid(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double grid,grain;
- int gridint,i,asint=0;
- Tcl_Obj *pResult;
- if( objc < 3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "grid DBL ...");
- return TCL_ERROR;
- }
- asint=1;
- if(Tcl_GetIntFromObj(interp,objv[1],&gridint)) {
- asint=0;
- if(Tcl_GetDoubleFromObj(interp,objv[1],&grid)) return TCL_ERROR;
- } else {
- grid=(double)gridint;
- }
- pResult=Tcl_NewObj();
- grain=grid*0.5;
- for(i=2;i<objc;i++) {
- double thisval,remainder;
- if(Tcl_GetDoubleFromObj(interp,objv[i],&thisval)) {
- Tcl_DecrRefCount(pResult);
- return TCL_ERROR;
- }
- thisval=Vector_GridScaler(thisval,grid,grain);
- if(asint) {
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(thisval));
- } else {
- remainder=fmod(thisval,grid);
- Tcl_ListObjAppendElement(interp, pResult, ODIE_NewFuzzyObj(thisval-remainder));
- }
- }
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::odie::gridvar */
- static int TclCmd_odie_gridvar(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double grid,grain,val;
- int gridint,i,asint=0;
- if( objc < 3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "gridsize DBLVAR ...");
- return TCL_ERROR;
- }
- asint=1;
- if(Tcl_GetIntFromObj(interp,objv[1],&gridint)) {
- asint=0;
- if(Tcl_GetDoubleFromObj(interp,objv[1],&grid)) return TCL_ERROR;
- } else {
- grid=(double)gridint;
- }
- grain=grid*0.5;
- for(i=2;i<objc;i++) {
- double thisval,remainder;
- Tcl_Obj *varname;
- varname=Tcl_ObjGetVar2(interp,objv[i],NULL,0);
- if(varname==NULL) continue;
- if(Tcl_GetDoubleFromObj(interp,varname,&val)) continue;
- thisval=Vector_GridScaler(val,grid,grain);
- if(asint) {
- Tcl_ObjSetVar2(interp,objv[i],NULL,Tcl_NewIntObj(thisval),0);
- } else {
- remainder=fmod(thisval,grid);
- Tcl_ObjSetVar2(interp,objv[i],NULL,ODIE_NewFuzzyObj(thisval-remainder),0);
- }
- }
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::compare */
- static int TclCmd_vector2d_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXY A, B;
- int c;
- if( objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1");
- return TCL_ERROR;
- }
- if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
- c=VectorXY_SamePoint(A,B);
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(c));
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::add */
- static int TclCmd_vector2d_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXY A, B, P;
- Tcl_Obj *pResult;
- if( objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1");
- return TCL_ERROR;
- }
- if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
- VectorXY_Add(P,A,B);
- pResult=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[X_IDX]));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Y_IDX]));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::subtract */
- static int TclCmd_vector2d_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXY A, B, P;
- Tcl_Obj *pResult;
- if( objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1");
- return TCL_ERROR;
- }
- if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
- VectorXY_Subtract(P,A,B);
- pResult=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[X_IDX]));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Y_IDX]));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::midpoint */
- static int TclCmd_vector2d_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXY A, B, P;
- Tcl_Obj *pResult;
- if( objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1");
- return TCL_ERROR;
- }
- if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
- VectorXY_Midpoint(P,A,B);
- pResult=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[X_IDX]));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Y_IDX]));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::affine_apply */
- static int TclCmd_vector2d_affine_apply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Tcl_Obj *pResult;
- int i;
- double matA[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
-
- if( objc < 4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "matrix x1 y1 ?x2 y2?...");
- return TCL_ERROR;
- }
- for(i=0;i<6;i++) {
- Tcl_Obj *temp;
- if(Tcl_ListObjIndex(interp, objv[1], i, &temp)) return TCL_ERROR;
- if(Odie_GetMatrixElementFromObj(interp,temp,matA,i)) return TCL_ERROR;
- }
- pResult=Tcl_NewObj();
- for(i=2;i<objc;i+=2) {
- double x,y,newx,newy;
- if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) {
- Tcl_DecrRefCount(pResult);
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) {
- Tcl_DecrRefCount(pResult);
- return TCL_ERROR;
- }
- newx=matA[0]*x+matA[1]*y+matA[4];
- newy=matA[2]*x+matA[3]*y+matA[5];
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
- }
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::angle */
- static int TclCmd_vector2d_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXY A, B, P;
- if( objc!=7 ){
- Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2");
- return TCL_ERROR;
- }
- if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[5], P, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[6], P, Y_IDX) ) return TCL_ERROR;
- Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_Angle_Three_Point(A, B, P)));
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::distance */
- static int TclCmd_vector2d_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double result,ax,ay,bx,by,dx,dy;
- if( objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "x0 y0 x1 y1");
- return TCL_ERROR;
- }
- result=0.0;
- if(Tcl_GetDoubleFromObj(interp,objv[1],&ax)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&ay)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[3],&bx)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[4],&by)) return TCL_ERROR;
- dx=bx-ax;
- dy=by-ay;
-
- result=sqrt(dx*dx + dy*dy);
- Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::dotproduct */
- static int TclCmd_vector2d_dotproduct(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXY A, B, P;
- if( objc!=7 ){
- Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2");
- return TCL_ERROR;
- }
- if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[5], P, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[6], P, Y_IDX) ) return TCL_ERROR;
- Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_Dot_Product(A, B, P)));
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::crossproduct */
- static int TclCmd_vector2d_crossproduct(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXY A, B, P;
- if( objc!=7 ){
- Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2");
- return TCL_ERROR;
- }
- if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[5], P, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[6], P, Y_IDX) ) return TCL_ERROR;
- Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_crossProduct(A, B, P)));
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::rightof */
- static int TclCmd_vector2d_rightof(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- /*
- ** tclcmd: triag_test_rightof X0 Y0 X1 Y1 X2 Y2
- **
- ** A TCL command for testing the rightOf() function.
- */
- VectorXY A, B, P;
- if( objc!=7 ){
- Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2");
- return TCL_ERROR;
- }
- if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[5], P, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[6], P, Y_IDX) ) return TCL_ERROR;
- Tcl_SetObjResult(interp, Tcl_NewIntObj(VectorXY_BendDirection(A, B, P)));
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::rotate_and_size */
- static int TclCmd_vector2d_rotate_and_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- /*
- ** Apply Matrices
- */
- Tcl_Obj *pResult;
- int i;
- double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0};
- double nx,ny,scalex,scaley,angle;
-
- if( objc < 7 ){
- Tcl_WrongNumArgs(interp, 1, objv, "normalx normaly sizex sizey x1 y1 ?x2 y2?...");
- return TCL_ERROR;
- }
-
- if(Tcl_GetDoubleFromObj(interp,objv[1],&nx)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&ny)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[3],&scalex)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[4],&scaley)) return TCL_ERROR;
-
- angle=atan2(ny,nx);
- matA[0]=cos(angle);
- matA[1]=sin(angle);
- matA[2]=-sin(angle);
- matA[3]=cos(angle);
- matA[4]=0.0;
- matA[5]=0.0;
-
- scalex*=0.5;
- scaley*=0.5;
- pResult=Tcl_NewObj();
- for(i=5;i<objc;i+=2) {
- double x,y,sx,sy,newx,newy;
- if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) {
- Tcl_DecrRefCount(pResult);
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) {
- Tcl_DecrRefCount(pResult);
- return TCL_ERROR;
- }
- sx=x*scalex;
- sy=y*scaley;
- newx=matA[0]*sx+matA[1]*sy+matA[4];
- newy=matA[2]*sx+matA[3]*sy+matA[5];
-
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
- }
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::scale */
- static int TclCmd_vector2d_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Tcl_Obj *pResult;
- int i;
- double scalex,scaley;
-
- if( objc < 5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "sizex sizey x1 y1 ?x2 y2?...");
- return TCL_ERROR;
- }
-
- if(Tcl_GetDoubleFromObj(interp,objv[1],&scalex)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],&scaley)) return TCL_ERROR;
- pResult=Tcl_NewObj();
- scalex*=0.5;
- scaley*=0.5;
- for(i=3;i<objc;i+=2) {
- double x,y,sx,sy;
- if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) {
- Tcl_DecrRefCount(pResult);
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) {
- Tcl_DecrRefCount(pResult);
- return TCL_ERROR;
- }
- sx=x*scalex;
- sy=y*scaley;
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sx));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sy));
- }
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::translate_and_zoom */
- static int TclCmd_vector2d_translate_and_zoom(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- /*
- ** Apply Matrices
- */
- Tcl_Obj *pResult;
- int i;
- double zoom;
- double centerx,centery;
-
- if( objc < 6 ){
- Tcl_WrongNumArgs(interp, 1, objv, "zoom centerx centery x1 y1 ?x2 y2?...");
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[1],&zoom)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[2],¢erx)) return TCL_ERROR;
- if(Tcl_GetDoubleFromObj(interp,objv[3],¢ery)) return TCL_ERROR;
- pResult=Tcl_NewObj();
- for(i=4;i<objc;i+=2) {
- double x,y,newx,newy;
- if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) {
- Tcl_DecrRefCount(pResult);
- return TCL_ERROR;
- }
- if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) {
- Tcl_DecrRefCount(pResult);
- return TCL_ERROR;
- }
- newx=(x/zoom)+centerx;
- newy=(y/zoom)+centery;
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
- }
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::point_on_segment */
- static int TclCmd_vector2d_point_on_segment(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double x1,y1,x2,y2,x3,y3;
- if( objc != 7 ){
- Tcl_WrongNumArgs(interp, 1, objv, "point_on_segment x y x1 y1 x2 y2");
- return TCL_ERROR;
- }
- if (Tcl_GetDoubleFromObj(interp,objv[1],&x1)) return TCL_ERROR;
- if (Tcl_GetDoubleFromObj(interp,objv[2],&y1)) return TCL_ERROR;
- if (Tcl_GetDoubleFromObj(interp,objv[3],&x2)) return TCL_ERROR;
- if (Tcl_GetDoubleFromObj(interp,objv[4],&y2)) return TCL_ERROR;
- if (Tcl_GetDoubleFromObj(interp,objv[5],&x3)) return TCL_ERROR;
- if (Tcl_GetDoubleFromObj(interp,objv[6],&y3)) return TCL_ERROR;
- Tcl_SetObjResult(interp, Tcl_NewIntObj(Vector2d_PointIsOnSegment(x1,y1,x2,y2,x3,y3)));
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::line_circle_intersect */
- static int TclCmd_vector2d_line_circle_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double ax1,ax2,ay1,ay2;
- double bx1,by1,brad;
- double ix,iy;
-
- if(objc<8) {
- Tcl_WrongNumArgs(interp, 1, objv, "ax1 ay1 ax2 ay2 bx1 by1 brad");
- return TCL_ERROR;
- }
-
- if( Tcl_GetDoubleFromObj(interp, objv[1], &ax1) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[2], &ay1) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[3], &ax2) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[4], &ay2) ) return TCL_ERROR;
-
- if( Tcl_GetDoubleFromObj(interp, objv[5], &bx1) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[6], &by1) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[7], &brad) ) return TCL_ERROR;
-
- if(ODIE_Math_LineCircleIntersect(ax1,ay1,ax2,ay2,bx1,by1,brad,&ix,&iy)) {
- Tcl_Obj *pResult;
- pResult = Tcl_NewObj();
- Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ix));
- Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(iy));
- Tcl_SetObjResult(interp, pResult);
- }
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::line_intersect */
- static int TclCmd_vector2d_line_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double ax1,ax2,ay1,ay2;
- double bx1,bx2,by1,by2;
- double ix,iy;
-
- if(objc<9) {
- Tcl_WrongNumArgs(interp, 1, objv, "ax1 ay1 ax2 ay2 bx1 by1 bx2 by2");
- return TCL_ERROR;
- }
-
- if( Tcl_GetDoubleFromObj(interp, objv[1], &ax1) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[2], &ay1) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[3], &ax2) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[4], &ay2) ) return TCL_ERROR;
-
- if( Tcl_GetDoubleFromObj(interp, objv[5], &bx1) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[6], &by1) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[7], &bx2) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[8], &by2) ) return TCL_ERROR;
-
- if(ODIE_Math_LineLineIntersect(ax1,ay1,ax2,ay2,bx1,by1,bx2,by2,&ix,&iy)) {
- Tcl_Obj *pResult;
- pResult = Tcl_NewObj();
- Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ix));
- Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(iy));
- Tcl_SetObjResult(interp, pResult);
- }
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::line_overlap */
- static int TclCmd_vector2d_line_overlap(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- Tcl_Obj *pResult;
- double ax1,ax2,ay1,ay2;
- double bx1,bx2,by1,by2;
-
- if(objc<9) {
- Tcl_WrongNumArgs(interp, 1, objv, "ax1 ay1 ax2 ay2 bx1 by1 bx2 by2");
- return TCL_ERROR;
- }
-
- if( Tcl_GetDoubleFromObj(interp, objv[1], &ax1) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[2], &ay1) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[3], &ax2) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[4], &ay2) ) return TCL_ERROR;
-
- if( Tcl_GetDoubleFromObj(interp, objv[5], &bx1) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[6], &by1) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[7], &bx2) ) return TCL_ERROR;
- if( Tcl_GetDoubleFromObj(interp, objv[8], &by2) ) return TCL_ERROR;
-
- /*
- ** ignore if the segments connect at endpoints
- if(ax1==bx1 && ay1==by1) return TCL_OK;
- if(ax1==bx2 && ay1==by2) return TCL_OK;
- if(ax2==bx1 && ay2==by1) return TCL_OK;
- if(ax2==bx2 && ay2==by2) return TCL_OK;
- */
-
- pResult = Tcl_NewIntObj(Vector2d_LineLineCoincident(ax1,ay1,ax2,ay2,bx1,by1,bx2,by2));
- Tcl_SetObjResult(interp, pResult);
-
- return TCL_OK;
- }
- /* Tcl Proc ::vector2d::colinear */
- static int TclCmd_vector2d_colinear(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- double x1,y1,x2,y2,x3,y3;
- if( objc != 7 ){
- Tcl_WrongNumArgs(interp, 1, objv, "colinear x1 y1 x2 y2 x3 y3");
- return TCL_ERROR;
- }
- if (Tcl_GetDoubleFromObj(interp,objv[1],&x1)) return TCL_ERROR;
- if (Tcl_GetDoubleFromObj(interp,objv[2],&y1)) return TCL_ERROR;
- if (Tcl_GetDoubleFromObj(interp,objv[3],&x2)) return TCL_ERROR;
- if (Tcl_GetDoubleFromObj(interp,objv[4],&y2)) return TCL_ERROR;
- if (Tcl_GetDoubleFromObj(interp,objv[5],&x3)) return TCL_ERROR;
- if (Tcl_GetDoubleFromObj(interp,objv[6],&y3)) return TCL_ERROR;
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Vector2d_IsColinear(x1,y1,x2,y2,x3,y3)));
- return TCL_OK;
- }
- /* Tcl Proc ::vector3d::compare */
- static int TclCmd_vector3d_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXY A, B;
- int c;
- if( objc!=7 ){
- Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 Z0 X1 Y1 Z1");
- return TCL_ERROR;
- }
- if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[3], A, Z_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[4], B, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[5], B, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[6], B, Z_IDX) ) return TCL_ERROR;
- c=VectorXYZ_SamePoint(A,B);
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(c));
- return TCL_OK;
- }
- /* Tcl Proc ::vector3d::add */
- static int TclCmd_vector3d_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXYZ A, B, P;
- Tcl_Obj *pResult;
- if( objc!=7 ){
- Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 Z0 X1 Y1 Z1");
- return TCL_ERROR;
- }
- if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[3], A, Z_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[4], B, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[5], B, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[6], B, Z_IDX) ) return TCL_ERROR;
- VectorXYZ_Add(P,A,B);
- pResult=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[X_IDX]));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Y_IDX]));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Z_IDX]));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::vector3d::subtract */
- static int TclCmd_vector3d_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- VectorXYZ A, B, P;
- Tcl_Obj *pResult;
- if( objc!=7 ){
- Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 Z0 X1 Y1 Z1");
- return TCL_ERROR;
- }
- if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[3], A, Z_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[4], B, X_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[5], B, Y_IDX) ) return TCL_ERROR;
- if( Odie_GetMatrixElementFromObj(interp, objv[6], B, Z_IDX) ) return TCL_ERROR;
- VectorXYZ_Subtract(P,A,B);
- pResult=Tcl_NewObj();
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[X_IDX]));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Y_IDX]));
- Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Z_IDX]));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
- }
- /* Tcl Proc ::vector3d::orthagonal */
- static int TclCmd_vector3d_orthagonal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
- int result;
- VectorXY A, B;
- if( objc!=7 ){
- Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 Z0 X1 Y1 Z1");
- return TCL_ERROR;
- }
-