Posted to tcl by hypnotoad at Tue Oct 09 23:50:43 GMT 2018view raw

  1. /*
  2. ** This file is generated by the /Users/seandeelywoods/build/odie/odielib/make.tcl script
  3. ** any changes will be overwritten the next time it is run
  4. */
  5.  
  6. /* This file was generated by practcl */
  7.  
  8. #include <tcl.h>
  9. #include <tclOO.h>
  10. #include "odielibc.h"
  11. #include <assert.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14. #include <stdlib.h>
  15. #include "inline_list.h"
  16. #include <limits.h>
  17. #include <float.h>
  18. #include <strings.h>
  19. /* BEGIN generate-cfile-header */
  20. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/hash/hash.tcl generate-cfile-header */
  21. /****** This file is copied from SQLite and modified *******
  22. **
  23. ** 2001 September 22
  24. **
  25. ** The author disclaims copyright to this source code. In place of
  26. ** a legal notice, here is a blessing:
  27. **
  28. ** May you do good and not evil.
  29. ** May you find forgiveness for yourself and forgive others.
  30. ** May you share freely, never taking more than you give.
  31. **
  32. *************************************************************************
  33. ** This is the implementation of generic hash-tables
  34. ** used in SQLite.
  35. **
  36. */
  37. #define uptr unsigned int
  38. #define Addr(X) ((uptr)X)
  39. #define readiMalloc malloc
  40. #define readiFree free
  41. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/hash/hash.tcl generate-cfile-header */
  42. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/btree/btree.tcl generate-cfile-header */
  43. static void TreeClearNode(TreeElem *p, void (*xFree)(void*));
  44. static TreeElem *TreeFindNthElem(Tree *tree, int n);
  45. static void TreeBalance(TreeElem **ppElem);
  46. static void *TreeInsertElement(Tree *pTree, void *key, void *data);
  47. static TreeElem *TreeDeleteNthElem(TreeElem **ppTop, int N);
  48. static TreeElem *TreeDeleteElem(Tree *tree, const void *key);
  49. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/btree/btree.tcl generate-cfile-header */
  50. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/odiemath/odiemath.tcl generate-cfile-header */
  51. double OdieGrain=2.5;
  52. double OdieTolerance=0.001;
  53. static inline int Odie_GetMatrixElementFromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,double *R,int idx);
  54. static inline unsigned int hashInt(int x);
  55. static inline long intCoord(double x);
  56. static inline unsigned int hashPoint(VECTORXY p);
  57. static inline unsigned int hashVectorXY(VECTORXY p);
  58. static inline unsigned int hashVectorXYZ(VECTORXYZ p);
  59. static inline double roundCoord(double x);
  60. static inline int hashCoord(double x, double y);
  61. static inline int hashCoord3d(double x, double y,double z);
  62. static inline int floatCompare(double x0, double x1);
  63. static inline void GridCoord(double *x, double *y);
  64. static int TclCmd_odiemath_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  65. static int TclCmd_odiemath_dist3d(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  66. static int TclCmd_odiemath_grid_hex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  67. static int TclCmd_odiemath_grid_round(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  68. static int TclCmd_odiemath_grid_square(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  69. static int TclCmd_odiemath_list_round(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  70. static int TclCmd_odiemath_list_to_int(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  71. static int TclCmd_odiemath_matrix_rotate_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  72. static int TclCmd_odiemath_matrix_rotate_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  73. static int TclCmd_odiemath_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  74. static int TclCmd_odiemath_perpendicular(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  75. static int TclCmd_odiemath_normal_2d(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  76. static int TclCmd_odiemath_parallel_segment(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  77. static int TclCmd_odiemath_vector_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  78. static int TclCmd_odiemath_vector_rotate_and_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  79. static int TclCmd_odiemath_vector_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  80. static int TclCmd_odiemath_vector_translate_and_zoom(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  81. static int TclCmd_odiemath_grid(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  82. static int TclCmd_odiemath_tolerance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  83. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/odiemath/odiemath.tcl generate-cfile-header */
  84. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/module.ini generate-cfile-header */
  85. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/aabb.tcl generate-cfile-header */
  86. static inline void VectorXYZ_AABB_Normalize(AABBXYZ R);
  87. static void VectorXYZ_AABB_Copy(AABBXYZ dest,AABBXYZ src);
  88. static inline int VectorXYZ_AABB_Within(VectorXYZ POINT,AABBXYZ R);
  89. static inline int VectorXYZ_BBOX_Overlap_TwoVectors(VectorXYZ A1,VectorXYZ A2,VectorXYZ B1,VectorXYZ B2);
  90. static inline int AABB_AABB_Intersect(AABBXYZ A,AABBXYZ B);
  91. static inline void VectorXYZ_AABB_Measure(VectorXYZ POINT,AABBXYZ R);
  92. static inline void AABB_AABB_Combine(AABBXYZ B,AABBXYZ A);
  93. static inline void VectorXYZ_AABB_Reset(AABBXYZ R);
  94. static int TclCmd_odie_aabb_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  95. static int TclCmd_odie_aabb_overlap_two_vectors(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  96. static int TclCmd_odie_aabb_measure(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  97. static int TclCmd_odie_aabb_faces(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  98. static int TclCmd_odie_aabb_from_vectorxyz(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  99. static int TclCmd_odie_aabb_from_line(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  100. static int TclCmd_odie_aabb_from_center_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  101. static int TclCmd_odie_aabb_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  102. static int TclCmd_odie_aabb_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  103. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/aabb.tcl generate-cfile-header */
  104. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/affine2d.tcl generate-cfile-header */
  105. static int TclCmd_affine2d_apply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  106. static int TclCmd_affine2d_combine(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  107. static int TclCmd_affine2d_rotation_from_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  108. static int TclCmd_affine2d_rotation_from_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  109. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/affine2d.tcl generate-cfile-header */
  110. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/affine3d.tcl generate-cfile-header */
  111. static inline int affine_Compare(AFFINE A,AFFINE B);
  112. static inline void affine_rotate_spin(AFFINE RESULT,SCALER psi);
  113. static void Odie_Affine_From_Normal(AFFINE RESULT,VectorXYZ NORMAL);
  114. static int TclCmd_affine4x4_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  115. static int TclCmd_affine4x4_identity(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  116. static int TclCmd_affine4x4_translation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  117. static int TclCmd_affine4x4_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  118. static int TclCmd_affine4x4_rotate_nutation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  119. static int TclCmd_affine4x4_rotate_precession(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  120. static int TclCmd_affine4x4_rotate_spin(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  121. static int TclCmd_affine4x4_from_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  122. static int TclCmd_affine4x4_multiply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  123. static int TclCmd_affine4x4_multiply_inplace(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  124. static int TclCmd_affine4x4_inverse(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  125. static int TclCmd_affine4x4_from_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  126. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/affine3d.tcl generate-cfile-header */
  127. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/bbox.tcl generate-cfile-header */
  128. static inline void VectorXY_BBOX_Copy(BBOXXY dest,BBOXXY src);
  129. static inline void VectorXY_BBOX_Reset(BBOXXY R);
  130. static inline int VectorXY_IsBetween_BBOX(VectorXY POINT,VectorXY A,VectorXY B);
  131. static inline int VectorXY_Within_BBOX(VectorXY POINT,BBOXXY bbox);
  132. static inline int XY_Within_BBOX(double x, double y,BBOXXY bbox);
  133. static inline void VectorXY_BBOX_Measure(VectorXY POINT,BBOXXY bbox);
  134. static inline int BBOX_BBOX_Intersect(BBOXXY A,BBOXXY B);
  135. static int TclCmd_odie_bbox_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  136. static int TclCmd_odie_bbox_measure(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  137. static int TclCmd_odie_bbox_elements(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  138. static int TclCmd_odie_bbox_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  139. static int TclCmd_odie_bbox_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  140. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/bbox.tcl generate-cfile-header */
  141. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/quaternion.tcl generate-cfile-header */
  142. static inline void Quaternion_From_Normal(QUATERNION RESULT,VectorXYZ from,VectorXYZ to);
  143. static int TclCmd_quaternion_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  144. static int TclCmd_quaternion_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  145. static int TclCmd_quaternion_multiply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  146. static int TclCmd_quaternion_divide(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  147. static int TclCmd_quaternion_square_root(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  148. static int TclCmd_quaternion_square(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  149. static int TclCmd_quaternion_from_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  150. static int TclCmd_vectorxyz_rotate_by_quaternion(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  151. static int TclCmd_quaternion_to_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  152. static int TclCmd_quaternion_from_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  153. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/quaternion.tcl generate-cfile-header */
  154. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector.tcl generate-cfile-header */
  155. static double Vector_Tolerance=0.01;
  156. static double Vector_Tolerance_Sq=0.0001;
  157. static Odie_MatrixObj *Odie_Matrix_To_Fit(Odie_MatrixObj *A,Odie_MatrixObj *B);
  158. static inline double Vector_GridScaler(double x,double grid,double grain);
  159. static int TclCmd_odie_tolerance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  160. static int TclCmd_odie_vector_to_list(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  161. static int TclCmd_odie_vector_index(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  162. static int TclCmd_odie_vector_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  163. static int TclCmd_odie_vector_is_null(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  164. static int TclCmd_odie_vector_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  165. static int TclCmd_odie_vector_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  166. static int TclCmd_odie_vector_reciprocal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  167. static int TclCmd_odie_vector_dot_product(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  168. static int TclCmd_odie_vector_to_matrix(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  169. static int TclCmd_odie_vector_to_fuzzy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  170. static int TclCmd_odie_vector_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  171. static int TclCmd_odie_vector_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  172. static int TclCmd_odie_vector_length_squared(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  173. static int TclCmd_odie_grid(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  174. static int TclCmd_odie_gridvar(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  175. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector.tcl generate-cfile-header */
  176. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector2d.tcl generate-cfile-header */
  177. /*
  178. ** Routines in this file are designed to work with double numbers
  179. ** directly. Useful for screen operations where X Y lists are used
  180. */
  181. static inline int Vector2d_PointIsOnSegment(double x,double y,double x1,double y1,double x2,double y2);
  182. static int TclCmd_vector2d_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  183. static int TclCmd_vector2d_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  184. static int TclCmd_vector2d_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  185. static int TclCmd_vector2d_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  186. static int TclCmd_vector2d_affine_apply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  187. static int TclCmd_vector2d_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  188. static int TclCmd_vector2d_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  189. static int TclCmd_vector2d_dotproduct(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  190. static int TclCmd_vector2d_crossproduct(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  191. static int TclCmd_vector2d_rightof(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  192. static int TclCmd_vector2d_rotate_and_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  193. static int TclCmd_vector2d_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  194. static int TclCmd_vector2d_translate_and_zoom(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  195. static int TclCmd_vector2d_point_on_segment(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  196. static int TclCmd_vector2d_line_circle_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  197. static int TclCmd_vector2d_line_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  198. static int TclCmd_vector2d_line_overlap(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  199. static int TclCmd_vector2d_colinear(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  200. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector2d.tcl generate-cfile-header */
  201. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector3d.tcl generate-cfile-header */
  202. static int TclCmd_vector3d_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  203. static int TclCmd_vector3d_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  204. static int TclCmd_vector3d_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  205. static int TclCmd_vector3d_orthagonal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  206. static int TclCmd_vector3d_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  207. static int TclCmd_vector3d_distanceSq(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  208. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector3d.tcl generate-cfile-header */
  209. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorn.tcl generate-cfile-header */
  210. static int TclCmd_vectorN_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  211. static int TclCmd_vectorN_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  212. static int TclCmd_vectorN_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  213. static int TclCmd_vectorN_scalevar(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  214. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorn.tcl generate-cfile-header */
  215. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorxy.tcl generate-cfile-header */
  216. static inline void VectorXY_GridAlign(VECTORXYZ A,double grid);
  217. static inline void VectorXY_Midpoint(VECTORXY C,VECTORXY A,VECTORXY B);
  218. static int TclCmd_vectorxy_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  219. static int TclCmd_vectorxy_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  220. static int TclCmd_vectorxy_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  221. static int TclCmd_vectorxy_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  222. static int TclCmd_vectorxy_add_stream(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  223. static int TclCmd_vectorxy_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  224. static int TclCmd_vectorxy_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  225. static int TclCmd_vectorxy_toint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  226. static int TclCmd_vectorxy_crossproduct(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  227. static int TclCmd_vectorxy_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  228. static int TclCmd_vectorxy_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  229. static int TclCmd_vectorxy_normalize(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  230. static int TclCmd_vectorxy_dotproduct(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  231. static int TclCmd_vectorxy_rightof(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  232. static int TclCmd_vectorxy_rotate_and_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  233. static int TclCmd_vectorxy_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  234. static int TclCmd_vectorxy_translate_and_zoom(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  235. static int TclCmd_vectorxy_flatten(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  236. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorxy.tcl generate-cfile-header */
  237. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorxyz.tcl generate-cfile-header */
  238. static inline void VectorXYZ_Scale(VECTOR A,SCALER S);
  239. static inline void VectorXYZ_Zero(VECTORXYZ A);
  240. static inline void VectorXYZ_GridAlign(VECTORXYZ A,double grid);
  241. static inline void VectorXYZ_Copy(VECTORXYZ B,VECTORXYZ A);
  242. static inline int VectorXYZ_SamePoint(VECTORXYZ A,VECTORXYZ B);
  243. static inline int VectorXYZ_IsZero(VECTORXYZ A);
  244. static inline void VectorXYZ_Cross_Product(VectorXYZ C,VectorXYZ A,VectorXYZ B);
  245. static inline void VectorXYZ_Add(VECTORXYZ C,VECTORXYZ A,VECTORXYZ B);
  246. static inline void VectorXYZ_Subtract(VECTORXYZ C,VECTORXYZ A,VECTORXYZ B);
  247. static inline int VectorXYZ_IsOrthagonal(VECTORXYZ A,VECTORXYZ B);
  248. static inline void VectorXYZ_Midpoint(VECTORXYZ C,VECTORXYZ A,VECTORXYZ B);
  249. static inline double VectorXYZ_Distance(VECTORXYZ A,VECTORXYZ B);
  250. static inline double VectorXYZ_DistanceSq(VECTORXYZ A,VECTORXYZ B);
  251. static inline double VectorXYZ_Dot_Product(VectorXYZ A,VectorXYZ B);
  252. static inline void VectorXYZ_MatrixMultiply(VECTORXYZ R,VECTORXYZ A,AFFINE M);
  253. static inline double VectorXYZ_MagnitudeSq(VECTOR A);
  254. static inline double VectorXYZ_Magnitude(VECTOR A);
  255. static inline double VectorXYZ_MagnitudeInvSqr(VECTOR A);
  256. static inline int VectorXYZ_Normalize(VectorXYZ A);
  257. static inline int VectorXYZ_PointIsOnSegment(VectorXYZ POINT,VectorXYZ A,VectorXYZ B);
  258. static inline int VectorXYZ_AxisOfNormal(VectorXYZ NORMAL);
  259. static inline int VectorXYZ_NormalStrictAxisAligned(VectorXYZ NORMAL);
  260. static inline int VectorXYZ_AxisAligned(VectorXYZ A,VectorXYZ B,VectorXYZ C);
  261. static inline int VectorXYZ_BendDirection(VectorXYZ A,VectorXYZ B,VectorXYZ C);
  262. static inline double VectorXYZ_Angle_Three_Point(VectorXYZ A,VectorXYZ B,VectorXYZ C,VectorXYZ normal);
  263. static inline int VectorXYZ_IsColinear(VectorXYZ A,VectorXYZ B,VectorXYZ C);
  264. static inline int VectorXYZ_IsCoplaner(VectorXYZ x1,VectorXYZ x2,VectorXYZ x3,VectorXYZ x4);
  265. static inline int VectorXYZ_LineLineCoincident(
  266. VectorXYZ A1, VectorXYZ A2, VectorXYZ B1, VectorXYZ B2,
  267. VectorXYZ ICEPT1, VectorXYZ ICEPT2
  268. );
  269. static inline int VectorXYZ_LineLineIntersect(
  270. VectorXYZ p1, VectorXYZ p2, VectorXYZ p3, VectorXYZ p4,
  271. VectorXYZ pA, VectorXYZ pB, double *mua, double *mub
  272. );
  273. static double VectorXYZ_ClosestPointOnSegment (
  274. VectorXYZ A, VectorXYZ B, /* End points of the line segment */
  275. VectorXYZ X, /* The point outside the line */
  276. VectorXYZ R /* Write closest point on line segment here */
  277. );
  278. static int VectorXYX_solve3by3(double *m);
  279. static double VectorXYZ_TriangleLineIntersect(
  280. VectorXYZ A, VectorXYZ B, VectorXYZ C, /* The triangle we are trying to intersect */
  281. VectorXYZ pStart, /* Start of the line segment */
  282. VectorXYZ pEnd, /* End of the line segment */
  283. VectorXYZ pIntersect /* Point of intersection written here if not NULL */
  284. );
  285. static inline void VectorXYZ_Normal_of_Three_Points(VectorXYZ normal,VectorXYZ A,VectorXYZ B,VectorXYZ C);
  286. static int TclCmd_vectorxyz_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  287. static int TclCmd_vectorxyz_zero(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  288. static int TclCmd_vectorxyz_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  289. static int TclCmd_vectorxyz_polygon_normal_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  290. static int TclCmd_vectorxyz_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  291. static int TclCmd_vectorxyz_toint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  292. static int TclCmd_vectorxyz_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  293. static int TclCmd_vectorxyz_add_inplace(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  294. static int TclCmd_vectorxyz_orthagonal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  295. static int TclCmd_vectorxyz_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  296. static int TclCmd_vectorxyz_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  297. static int TclCmd_vectorxyz_cross_product(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  298. static int TclCmd_vectorxyz_dot_product(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  299. static int TclCmd_vectorxyz_transform(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  300. static int TclCmd_vectorxyz_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  301. static int TclCmd_vectorxyz_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  302. static int TclCmd_vectorxyz_distanceSq(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  303. static int TclCmd_vectorxyz_length_inv_sqr(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  304. static int TclCmd_vectorxyz_normalize(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  305. static int TclCmd_vectorxyz_point_on_segment(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  306. static int TclCmd_vectorxyz_point_on_segment_x(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  307. static int TclCmd_vectorxyz_axis_of_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  308. static int TclCmd_vectorxyz_bend_direction(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  309. static int TclCmd_vectorxyz_angle_three_points(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  310. static int TclCmd_vectorxyz_colinear(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  311. static int TclCmd_vectorxyz_coplaner(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  312. static int TclCmd_vectorxyz_linelinecoincident_int(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  313. static int TclCmd_vectorxyz_linelinecoincident(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  314. static int TclCmd_vectorxyz_linelineintersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  315. static int TclCmd_vectorxyz_linelineintersect_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  316. static int TclCmd_vectorxyz_sizeof(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  317. static int TclCmd_vectorxyz_closest_point_on_segment(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  318. static int TclCmd_vectorxyz_point_in_triangle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  319. static int TclCmd_vectorxyz_triangle_line_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  320. static int TclCmd_vectorxyz_line_sphere_intersect_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  321. static int TclCmd_vectorxyz_line_sphere_intersect_area(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  322. static int TclCmd_vectorxyz_line_sphere_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  323. static int TclCmd_vectorxyz_polygon_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  324. static int TclCmd_vectorxyz_polygon_center(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  325. static int TclCmd_vectorxyz_flatten(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  326. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorxyz.tcl generate-cfile-header */
  327. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/cmatrixforms.tcl generate-cfile-header */
  328. const MatrixForm MatrixForms[] = {
  329. { MATFORM_null, "null", 0 , 0, "A matrix of arbitrary size", NULL },
  330. { MATFORM_aabb_xyz, "aabb_xyz", 6, 1, "An axis aligned bounding box in 3 dimensions", NULL },
  331. { MATFORM_affine, "affine", 4, 4, "A 4x4 affine matrix", Matrix_To_affine },
  332. { MATFORM_bbox_xy, "bbox_xy", 4, 1, "A 2 dimensional vector: X Y", Matrix_To_cartesian },
  333. { MATFORM_cylindrical, "cylindrical", 3, 1, "A 3 dimensional vector: RADIUS THETA Z", Matrix_To_cylindrical },
  334. { MATFORM_euler, "euler", 3, 1, "A 3 dimensional rotation: X Y Z", NULL },
  335. { MATFORM_heading, "heading", 3, 1, "A 3 dimensional rotation: yaw pitch roll", NULL },
  336. { MATFORM_mat2, "mat2", 2, 2, "A 2x2 matrix", NULL },
  337. { MATFORM_mat3, "mat3", 3, 3, "A 3x3 matrix", NULL },
  338. { MATFORM_mat4, "mat4", 4, 4, "A 4x4 matrix", NULL },
  339. { MATFORM_polar, "polar", 2, 1, "A 2 dimensional vector: RADIUS THETA", Matrix_To_cylindrical },
  340. { MATFORM_quaternion, "quaternion", 4, 1, "A quaternion: W X Y Z", Matrix_To_quaternion },
  341. { MATFORM_scaler, "scaler", 1, 1, "A scaler (1x1)", NULL },
  342. { MATFORM_spherical, "spherical", 3, 1, "A 3 dimensional vector: RADIUS THETA PHI", Matrix_To_spherical },
  343. { MATFORM_unknown, "unknown", 0 , 0, "A matrix of arbitrary size (but less than 4x4)", NULL },
  344. { MATFORM_vector_xy, "vector_xy", 2, 1, "A 2 dimensional vector: X Y", Matrix_To_cartesian },
  345. { MATFORM_vector_xyz, "vector_xyz", 3, 1, "A 3 dimensional vector: X Y Z", Matrix_To_cartesian },
  346. { MATFORM_vector_xyzw, "vector_xyzw", 4, 1, "A 4 dimensional vector: X Y Z W", Matrix_To_cartesian }
  347. };
  348. /* Module wide constants */
  349. const Tcl_ObjType *NumArrayType;
  350. const Tcl_ObjType *odieMatrixType;
  351. static int TclCmd_matrix_to_aabb_xyz(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  352. static int TclCmd_matrix_to_affine(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  353. static int TclCmd_matrix_to_bbox_xy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  354. static int TclCmd_matrix_to_cylindrical(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  355. static int TclCmd_matrix_to_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  356. static int TclCmd_matrix_to_heading(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  357. static int TclCmd_matrix_to_mat2(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  358. static int TclCmd_matrix_to_mat3(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  359. static int TclCmd_matrix_to_mat4(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  360. static int TclCmd_matrix_to_null(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  361. static int TclCmd_matrix_to_polar(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  362. static int TclCmd_matrix_to_quaternion(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  363. static int TclCmd_matrix_to_scaler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  364. static int TclCmd_matrix_to_spherical(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  365. static int TclCmd_matrix_to_unknown(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  366. static int TclCmd_matrix_to_vector_xy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  367. static int TclCmd_matrix_to_vector_xyz(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  368. static int TclCmd_matrix_to_vector_xyzw(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  369. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/cmatrixforms.tcl generate-cfile-header */
  370. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/module.ini generate-cfile-header */
  371. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/fuzzy/fuzzy.tcl generate-cfile-header */
  372. #ifdef _MSC_VER
  373. # define Odie_IsInfinite(d) (!(_finite((d))))
  374. # define Odie_IsNaN(d) (_isnan((d)))
  375. #else
  376. # define Odie_IsInfinite(d) ((d) > DBL_MAX || (d) < -DBL_MAX)
  377. # ifdef NO_ISNAN
  378. # define Odie_IsNaN(d) ((d) != (d))
  379. # else
  380. # define Odie_IsNaN(d) (isnan(d))
  381. # endif
  382. #endif
  383.  
  384. static int TclCmd_tcl_mathfunc_to_fuzzy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  385. static int TclCmd_tcl_mathfunc_fuzzy_abs(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  386. static int TclCmd_tcl_mathfunc_fuzzy_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  387. static int TclCmd_tcl_mathfunc_fuzzy_is_zero(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  388. static int TclCmd_tcl_mathfunc_fuzzy_gt_zero(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  389. static int TclCmd_tcl_mathfunc_fuzzy_epsilon(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  390. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/fuzzy/fuzzy.tcl generate-cfile-header */
  391. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/module.ini generate-cfile-header */
  392. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/triangulate.tcl generate-cfile-header */
  393. #ifndef IRM_EPSILON
  394. #define IRM_EPSILON FLT_EPSILON
  395. #endif
  396.  
  397. #ifndef M_PI
  398. # define M_PI 3.1415926535898
  399. #endif
  400.  
  401. static int TclCmd_triag_test_rightof(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  402. static int TclCmd_triag_test_dotprod(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  403. static int TclCmd_triag_test_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  404. static int TclCmd_triag_test_ideal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  405. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/triangulate.tcl generate-cfile-header */
  406. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygon.tcl generate-cfile-header */
  407. static inline int Odie_IsColinear(double x1,double y1,double x2,double y2,double x3,double y3);
  408. static inline double dist(double x0, double y0, double x1, double y1);
  409. static inline int withinPolygon(Odie_Polygon *p, double x, double y);
  410. static int TclCmd_polygon_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  411. static int TclCmd_polygon_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  412. static int TclCmd_polygon_simplify(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  413. static int TclCmd_polygon_area(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  414. static int TclCmd_polygon_bbox(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  415. static int TclCmd_polygon_info(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  416. static int TclCmd_polygon_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  417. static int TclCmd_polygon_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  418. static int TclCmd_polygon_center(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  419. static int TclCmd_polygon_canvascoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  420. static int TclCmd_polygon_coords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  421. static int TclCmd_polygon_xycoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  422. static int TclCmd_polygon_edges(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  423. static int TclCmd_polygon_bend(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  424. static int TclCmd_polygon_is_convex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  425. static int TclCmd_polygon_segments(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  426. static int TclCmd_polygon_rectangle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  427. static int TclCmd_polygon_vector_place(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  428. static int TclCmd_polygon_hexagon(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  429. static int TclCmd_polygon_poly_place(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  430. static int TclCmd_polygon_drawobj_orientation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  431. static int TclCmd_polygon_corners(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  432. static int TclCmd_polygon_hexgrid_location(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  433. static int TclCmd_polygon_hexgrid_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  434. static int TclCmd_polygon_squaregrid_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  435. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygon.tcl generate-cfile-header */
  436. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygonxyz.tcl generate-cfile-header */
  437. static inline int Odie_FaceXYZ_Compare(Odie_FaceXYZ *A,Odie_FaceXYZ *B);
  438. static inline int Odie_FaceXYZ_Coplaner(Odie_FaceXYZ *A,Odie_FaceXYZ *B);
  439. static inline int PolygonUV_Within(Odie_FaceXYZ *p, double x, double y);
  440. static inline int Odie_FaceXYZ_Within(Odie_FaceXYZ *p, VectorXYZ POINT);
  441. static int Odie_FaceXYZ_IntersectTest(Odie_FaceXYZ *p1,Odie_FaceXYZ *p2);
  442. static double Odie_FaceXYZ_AreaOfIntersection(Odie_FaceXYZ *p1,Odie_FaceXYZ *p2,double *xin,double *yin);
  443. static int TclCmd_polygonxyz_info(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  444. static int TclCmd_polygonxyz_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  445. static int TclCmd_polygonxyz_createxy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  446. static int TclCmd_polygonxyz_simplify(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  447. static int TclCmd_polygonxyz_id(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  448. static int TclCmd_polygonxyz_area(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  449. static int TclCmd_polygonxyz_bbox(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  450. static int TclCmd_polygonxyz_bend(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  451. static int TclCmd_polygonxyz_center(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  452. static int TclCmd_polygonxyz_is_2d(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  453. static int TclCmd_polygonxyz_is_convex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  454. static int TclCmd_polygonxyz_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  455. static int TclCmd_polygonxyz_nVertex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  456. static int TclCmd_polygonxyz_radius(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  457. static int TclCmd_polygonxyz_rotation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  458. static int TclCmd_polygonxyz_rotation_inv(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  459. static int TclCmd_polygonxyz_axis_of_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  460. static int TclCmd_polygonxyz_canvascoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  461. static int TclCmd_polygonxyz_coords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  462. static int TclCmd_polygonxyz_intcoordsxy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  463. static int TclCmd_polygonxyz_intcoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  464. static int TclCmd_polygonxyz_edges(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  465. static int TclCmd_polygonxyz_triangles(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  466. static int TclCmd_polygonxyz_uvcoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  467. static int TclCmd_polygonxyz_xycoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  468. static int TclCmd_polygonxyz_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  469. static int TclCmd_polygonxyz_coplaner(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  470. static int TclCmd_polygonxyz_flipped(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  471. static int TclCmd_polygonxyz_side(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  472. static int TclCmd_polygonxyz_intersect_test(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  473. static int TclCmd_polygonxyz_intersect_test_uv(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  474. static int TclCmd_polygonxyz_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  475. static int TclCmd_polygonxyz_intersect_uv(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  476. static int TclCmd_polygonxyz_points_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  477. static int TclCmd_polygonxyz_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  478. static int TclCmd_polygonxyz_within_set(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  479. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygonxyz.tcl generate-cfile-header */
  480. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/segset.tcl generate-cfile-header */
  481. static void SegmentSet_Delete(ClientData clientData);
  482. static int SegmentSet_Clone(
  483. Tcl_Interp* interp, /* Tcl interpreter for error reporting */
  484. ClientData metadata, /* Metadata to be cloned */
  485. ClientData* newMetaData /* Where to put the cloned metadata */
  486. );
  487. static int SegmentSet_Cleanup_Coincident(SegmentSet *pSet,Segment *pAB);
  488. static int Segment_OnList(Segment *pSeg, Link *pList);
  489. static Segment *SegmentSet_FindById(SegmentSet *p, int id);
  490. static void Segment_Imprint(Segment *pSrc,Segment *pDest);
  491. static void Segment_SetToFrom(SegmentSet *pSet, Segment *p, VECTORXYZ from, VECTORXYZ to);
  492. static inline Segment *Segment_Create(SegmentSet *pSet,int newid);
  493. static inline void SegmentSetRemove(SegmentSet *pSet, Segment *p);
  494. static inline void SegRelink(SegmentSet *pSet, Segment *p);
  495. static inline void SegmentSetClear(SegmentSet *pSet);
  496. static inline void SegmentSetStep(SegmentSet *pSet);
  497. static int SegmentSet_AddVertex(SegmentSet *pSet,VectorXYZ A);
  498. static int SegmentSet_Interference_Check(SegmentSet *pSet,VectorXYZ A,VectorXYZ B);
  499. static int SegmentSet_Edge_Connection(SegmentSet *pSet,VectorXYZ A,int comptid,VectorXYZ RESULT);
  500. static int SegmentSet_Convex_Connection(SegmentSet *pSet,Segment *pAB,int back,VectorXYZ RESULT);
  501. static int SegmentSetNextBend(
  502. SegmentSet *pSet,
  503. Segment *pAB,
  504. int backwards,
  505. Segment **ppSeg, /* OUT: First segment clockwise from xR,yR->xV,yV */
  506. int *pfBack, /* OUT: True if output segment goes backwards */
  507. int *pfBend, /* OUT: Bend direction */
  508. double *pfAngle
  509. );
  510. static int SegmentSet_SelfCheck(Tcl_Interp *interp, SegmentSet *p);
  511. static Link *SegmentSet_Segments_AtVertex(SegmentSet *p, VectorXYZ point,int *nSeg);
  512. static int SegmentSetNext(
  513. SegmentSet *pSet,
  514. Segment *pAB,
  515. int backwards,
  516. Segment **ppSeg, /* OUT: First segment clockwise from xR,yR->xV,yV */
  517. int *pfBack, /* OUT: True if output segment goes backwards */
  518. int *pfBend, /* OUT: Bend direction */
  519. double *pfAngle
  520. );
  521. static void SegmentSet_ClearFaceEdgeCache(SegmentSet *pSet);
  522. static void FaceBoundary_Mark_Degenerate(FaceBoundary *pFace,int code);
  523. static int SegmentSet_BuildFaceEdgeCache_ExpandRight(SegmentSet *pSet,int faceid,int stage);
  524. static void SegmentSet_BuildFaceEdgeCache(SegmentSet *pSet);
  525. static int OOMethod_SegmentSet_segment_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  526. static int OOMethod_SegmentSet_SegmentSet_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  527. static int OOMethod_SegmentSet_modified(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  528. static int OOMethod_SegmentSet_segment_count(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  529. static int OOMethod_SegmentSet_bbox(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  530. static int OOMethod_SegmentSet_segment_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  531. static int OOMethod_SegmentSet_segment_add(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  532. static int OOMethod_SegmentSet_segment_add_virtual(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  533. static int OOMethod_SegmentSet_polygon_add(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  534. static int OOMethod_SegmentSet_vertex_add(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  535. static int OOMethod_SegmentSet_segment_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  536. static int OOMethod_SegmentSet_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  537. static int OOMethod_SegmentSet_cleanup(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  538. static int OOMethod_SegmentSet_cleanup_looseend(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  539. static int OOMethod_SegmentSet_edge_connection(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  540. static int OOMethod_SegmentSet_check_intersecting(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  541. static int OOMethod_SegmentSet_check_coincident(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  542. static int OOMethod_SegmentSet_segment_linelineintersect(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  543. static int OOMethod_SegmentSet_segment_coincident(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  544. static int OOMethod_SegmentSet_segment_find(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  545. static int OOMethod_SegmentSet_vertex_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  546. static int OOMethod_SegmentSet_segment_next(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  547. static int OOMethod_SegmentSet_check_oblique(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  548. static int OOMethod_SegmentSet_check_looseends(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  549. static int OOMethod_SegmentSet_fix_looseends(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  550. static int OOMethod_SegmentSet_grid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  551. static int OOMethod_SegmentSet_segment_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  552. static int OOMethod_SegmentSet_segment_coords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  553. static int OOMethod_SegmentSet_segment_uvcoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  554. static int OOMethod_SegmentSet_selfcheck(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  555. static int OOMethod_SegmentSet_uv_transform(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  556. static int OOMethod_SegmentSet_polygons_xyz(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  557. static int OOMethod_SegmentSet_polygons(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  558. static int OOMethod_SegmentSet_polygon_faces(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  559. static int OOMethod_SegmentSet_polygon_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  560. static int SegmentSet_OO_Init(Tcl_Interp *interp);
  561. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/segset.tcl generate-cfile-header */
  562. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/shapes.tcl generate-cfile-header */
  563. static int TclCmd_shapes_corners(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  564. static int TclCmd_shapes_drawobj_orientation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  565. static int TclCmd_shapes_poly_hex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  566. static int TclCmd_shapes_poly_place(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  567. static int TclCmd_shapes_polygon_to_vectors(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  568. static int TclCmd_shapes_rectangle_as_polygon(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  569. static int TclCmd_shapes_rectangle_as_vectors(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  570. static int TclCmd_shapes_vector_place(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  571. static int TclCmd_shapes_hexagon(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  572. static int TclCmd_shapes_canvas(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  573. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/shapes.tcl generate-cfile-header */
  574. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/plotter.tcl generate-cfile-header */
  575. static void Plotter_Delete(ClientData clientData);
  576. static int Plotter_Clone(
  577. Tcl_Interp* interp, /* Tcl interpreter for error reporting */
  578. ClientData metadata, /* Metadata to be cloned */
  579. ClientData* newMetaData /* Where to put the cloned metadata */
  580. );
  581. static inline double Plotter_xCanvasToActual(Plotter *p,double cx);
  582. static inline double Plotter_yCanvasToActual(Plotter *p,double cy);
  583. static inline double Plotter_xActualToCanvas(Plotter *p,double ax);
  584. static inline double Plotter_yActualToCanvas(Plotter *p,double ay);
  585. static int OOMethod_Plotter_actualcoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  586. static int OOMethod_Plotter_canvascoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  587. static int OOMethod_Plotter_centerset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  588. static int OOMethod_Plotter_xoffset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  589. static int OOMethod_Plotter_yoffset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  590. static int OOMethod_Plotter_zoom(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  591. static int OOMethod_Plotter_constructor(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  592. static int Plotter_OO_Init(Tcl_Interp *interp);
  593. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/plotter.tcl generate-cfile-header */
  594. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/slicer.tcl generate-cfile-header */
  595. static void Slicer_Delete(ClientData clientData);
  596. static int Slicer_Clone(
  597. Tcl_Interp* interp, /* Tcl interpreter for error reporting */
  598. ClientData metadata, /* Metadata to be cloned */
  599. ClientData* newMetaData /* Where to put the cloned metadata */
  600. );
  601. static double Slicer_xCanvasToActual(Slicer *p,struct OneSlice *pS, double cx);
  602. static double Slicer_yCanvasToActual(Slicer *p,struct OneSlice *pS, double cy);
  603. static double Slicer_xActualToCanvas(Slicer *p,struct OneSlice *pS, double ax);
  604. static double Slicer_yActualToCanvas(Slicer *p,struct OneSlice *pS, double ay);
  605. static double Slicer_deckHeight(struct OneSlice *p, double rX);
  606. static struct OneSlice *Slicer_deckAt(Slicer *p, double rX, double rZ);
  607. static struct OneSlice *Slicer_deckAbove(Slicer *p, struct OneSlice *pRef);
  608. static struct OneSlice *Slicer_deckBelow(Slicer *p, struct OneSlice *pRef);
  609. static void Slicer_computeTopAndBottom(Slicer *p);
  610. static int Slicer_getDeck(
  611. Tcl_Interp *interp, /* Put error messages here */
  612. Slicer *p, /* The slicer */
  613. double rX, /* X coord used to find deck if pObj is a Z coord */
  614. Tcl_Obj *pObj, /* Either a deck name or a Z coordinate */
  615. struct OneSlice **ppS /* Write the slice pointer here */
  616. );
  617. static int Slicer_getDeckId(
  618. Tcl_Interp *interp, /* Put error messages here */
  619. Slicer *p, /* The slicer */
  620. Tcl_Obj *pObj, /* Either a deck name or a Z coordinate */
  621. struct OneSlice **ppS /* Write the slice pointer here */
  622. );
  623. static inline struct OneSlice *Slicer_getDeck_FromInt(
  624. Slicer *p,
  625. int did
  626. );
  627. static int slicer_drawline_do(
  628. Tcl_Interp *interp,
  629. Slicer *p,
  630. int coord_count,
  631. int *deckCoord,double *xCoord,double *yCoord,
  632. struct OneSlice **apDeck,
  633. Tcl_Obj *canvas,
  634. const char *zKTag,
  635. const char *zXTag,
  636. const char *zBTag
  637. );
  638. static inline double Slicer_Location_zabs(Slicer *p,struct OneSlice *pS,double x0,double dheight);
  639. static inline double Location_zdeck(Slicer *p,struct OneSlice *pS,double x0,double dheight);
  640. static int OOMethod_Slicer_drawline(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  641. static int OOMethod_Slicer_above(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  642. static int OOMethod_Slicer_below(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  643. static int OOMethod_Slicer_deckid_to_name(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  644. static int OOMethod_Slicer_deckname_to_id(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  645. static int OOMethod_Slicer_bbox_to_location(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  646. static int OOMethod_Slicer_bbox_to_midpoint(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  647. static int OOMethod_Slicer_xyz_to_location(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  648. static int OOMethod_Slicer_location_to_xyz(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  649. static int OOMethod_Slicer_location_z(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  650. static int OOMethod_Slicer_distance(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  651. static int OOMethod_Slicer_actualcoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  652. static int OOMethod_Slicer_canvascoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  653. static int OOMethod_Slicer_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  654. static int OOMethod_Slicer_deck_at_xyz(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  655. static int OOMethod_Slicer_deckid_at_xyx(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  656. static int OOMethod_Slicer_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  657. static int OOMethod_Slicer_makedlist(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  658. static int OOMethod_Slicer_find(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  659. static int OOMethod_Slicer_finddid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  660. static int OOMethod_Slicer_flatheight(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  661. static int OOMethod_Slicer_headroom(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  662. static int OOMethod_Slicer_ceiling(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  663. static int OOMethod_Slicer_height(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  664. static int OOMethod_Slicer_deckheight(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  665. static int OOMethod_Slicer_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  666. static int OOMethod_Slicer_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  667. static int OOMethod_Slicer_profile(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  668. static int OOMethod_Slicer_xoffset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  669. static int OOMethod_Slicer_zoom(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  670. static int OOMethod_Slicer_upper_height(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  671. static int OOMethod_Slicer_Slicer_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  672. static int Slicer_OO_Init(Tcl_Interp *interp);
  673. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/slicer.tcl generate-cfile-header */
  674. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/wallset.tcl generate-cfile-header */
  675. static void Wallset_Delete(ClientData clientData);
  676. static int Wallset_Clone(
  677. Tcl_Interp* interp, /* Tcl interpreter for error reporting */
  678. ClientData metadata, /* Metadata to be cloned */
  679. ClientData* newMetaData /* Where to put the cloned metadata */
  680. );
  681. static int OOMethod_Wallset_atvertex(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  682. static int OOMethod_Wallset_boundary(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  683. static int OOMethod_Wallset_closure(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  684. static int OOMethod_Wallset_closure_polygon(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  685. static int OOMethod_Wallset_closure_check(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  686. static int OOMethod_Wallset_comptlist(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  687. static int OOMethod_Wallset_corners(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  688. static int OOMethod_Wallset_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  689. static int OOMethod_Wallset_firstboundary(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  690. static int OOMethod_Wallset_foreach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  691. static int OOMethod_Wallset_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  692. static int OOMethod_Wallset_rawinfo(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  693. static int OOMethod_Wallset_insert(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  694. static int OOMethod_Wallset_primary(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  695. static int OOMethod_Wallset_intersect(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  696. static int OOMethod_Wallset_left(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  697. static int OOMethod_Wallset_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  698. static int OOMethod_Wallset_looseends(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  699. static int OOMethod_Wallset_nearest(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  700. static int OOMethod_Wallset_nextcwwall(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  701. static int OOMethod_Wallset_right(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  702. static int OOMethod_Wallset_selfcheck(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  703. static int OOMethod_Wallset_zoom(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  704. static int OOMethod_Wallset_constructor(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  705. static int Wallset_OO_Init(Tcl_Interp *interp);
  706. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/wallset.tcl generate-cfile-header */
  707. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/faceset.tcl generate-cfile-header */
  708. static PolygonHullVertex *PolygonHullVertex_ById(PolygonHull *pHull, int id);
  709. static PolygonHullVertex *PolygonHullVertex_ByCoords(PolygonHull *pHull, VectorXYZ A);
  710. static PolygonHullVertex *PolygonHullVertex_Create(
  711. PolygonHull *pHull,
  712. int id,
  713. VectorXYZ point
  714. );
  715. static void PolygonHullVertex_Remove(PolygonHullVertex *pVertex);
  716. static const char *PolygonHullFace_VertexInject(PolygonHullFace *pFace,PolygonHullVertex *pThisVertex);
  717. static PolygonHullFace *PolygonHullFace_Create(
  718. PolygonHull *pHull,
  719. int id
  720. );
  721. static PolygonHullFace *PolygonHull_mergeFaceList(PolygonHullFace *a, PolygonHullFace *b);
  722. static PolygonHullFace *PolygonHull_sortFaceList(PolygonHullFace *pList);
  723. static PolygonHullFace *PolygonHullFace_ById(PolygonHull *pHull, int id);
  724. static int PolygonHull_findFace(
  725. Tcl_Interp *interp, /* Leave any error message here */
  726. PolygonHull *pHull,
  727. Tcl_Obj *pObj, /* The PolygonHullFace ID */
  728. PolygonHullFace **ppHullFace /* Write PolygonHullFace pointer here */
  729. );
  730. static void PolygonHullFace_Remove(PolygonHullFace *pFace);
  731. static void PolygonHullFace_SerializeEdges(PolygonHullFace *p);
  732. static void PolygonHullFace_Compute(PolygonHullFace *pFace);
  733. static double PolygonHull_sqrDistPointToEdge(
  734. VectorXYZ A, VectorXYZ B, /* End points of the line segment */
  735. VectorXYZ X /* The point to measure distance to */
  736. );
  737. static double PolygonHull_intersectLineSegFace(
  738. PolygonHullFace *pFace, /* The triangle we are trying to intersect */
  739. VectorXYZ pStart, /* Start of the line segment */
  740. VectorXYZ pEnd, /* End of the line segment */
  741. VectorXYZ pIntersect /* Point of intersection written here if not NULL */
  742. );
  743. static PolygonHullFace *PolygonHullFace_findHits(PolygonHull *pHull, VectorXYZ A, VectorXYZ B);
  744. static double PolygonHull_closestPointOnFace(PolygonHullFace *p, VectorXYZ X, VectorXYZ R);
  745. static PolygonHullFace *PolygonHullFace_findClosest(PolygonHull *pHull,VectorXYZ X, VectorXYZ R, double *pDist);
  746. static PolygonHullVolume *PolygonHullVolume_ById(PolygonHull *pHull, int id);
  747. static PolygonHullVolume *PolygonHullVolume_Create(
  748. PolygonHull *pHull,
  749. int id
  750. );
  751. static void PolygonHullVolume_Unlink(PolygonHullVolume *pVolume);
  752. static void PolygonHull_clearSurfaces(PolygonHull *pHull);
  753. static void PolygonHull_Reset(PolygonHull *pHull);
  754. static void PolygonHull_Delete(ClientData clientData);
  755. static int PolygonHull_Clone(
  756. Tcl_Interp* interp, /* Tcl interpreter for error reporting */
  757. ClientData metadata, /* Metadata to be cloned */
  758. ClientData* newMetaData /* Where to put the cloned metadata */
  759. );
  760. static int OOMethod_PolygonHull_vertex_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  761. static int OOMethod_PolygonHull_vertex_coords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  762. static int OOMethod_PolygonHull_vertex_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  763. static int OOMethod_PolygonHull_vertex_idlist(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  764. static int OOMethod_PolygonHull_vertex_inject(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  765. static int OOMethod_PolygonHull_vertex_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  766. static int OOMethod_PolygonHull_vertex_at(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  767. static int OOMethod_PolygonHull_face_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  768. static int OOMethod_PolygonHull_face_exists(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  769. static int OOMethod_PolygonHull_face_active(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  770. static int OOMethod_PolygonHull_face_center(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  771. static int OOMethod_PolygonHull_face_polygon(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  772. static int OOMethod_PolygonHull_face_vertices(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  773. static int OOMethod_PolygonHull_face_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  774. static int OOMethod_PolygonHull_face_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  775. static int OOMethod_PolygonHull_face_intersect(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  776. static int OOMethod_PolygonHull_face_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  777. static int OOMethod_PolygonHull_face_nearest(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  778. static int OOMethod_PolygonHull_face_radius(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  779. static int OOMethod_PolygonHull_face_normal(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  780. static int OOMethod_PolygonHull_face_side(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  781. static int OOMethod_PolygonHull_face_volume(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  782. static int OOMethod_PolygonHull_faces_at(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  783. static int OOMethod_PolygonHull_face_within(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  784. static int OOMethod_PolygonHull_volume_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  785. static int OOMethod_PolygonHull_volume_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  786. static int OOMethod_PolygonHull_volume_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  787. static int OOMethod_PolygonHull_volume_faces(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  788. static int OOMethod_PolygonHull_volume_group(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  789. static int OOMethod_PolygonHull_volume_center(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  790. static int OOMethod_PolygonHull_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  791. static int OOMethod_PolygonHull_PolygonHull_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  792. static int PolygonHull_OO_Init(Tcl_Interp *interp);
  793. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/faceset.tcl generate-cfile-header */
  794. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/module.ini generate-cfile-header */
  795. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/listcmd/listcmd.tcl generate-cfile-header */
  796. static int TclCmd_get(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  797. static int TclCmd_list_to_int(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  798. static int TclCmd_ladd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  799. static int TclCmd_ldelete(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  800. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/listcmd/listcmd.tcl generate-cfile-header */
  801. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/logicset/logicset.tcl generate-cfile-header */
  802. #define UCHAR(c) ((unsigned char) (c))
  803. #define TclFormatInt(buf, n) sprintf((buf), "%ld", (long)(n))
  804.  
  805. #define MEM_DEBUG 0
  806.  
  807. /*
  808. * Macros used to cast between pointers and integers (e.g. when storing an int
  809. * in ClientData), on 64-bit architectures they avoid gcc warning about "cast
  810. * to/from pointer from/to integer of different size".
  811. */
  812.  
  813. #if !defined(INT2PTR) && !defined(PTR2INT)
  814. # if defined(HAVE_INTPTR_T) || defined(intptr_t)
  815. # define INT2PTR(p) ((void *)(intptr_t)(p))
  816. # define PTR2INT(p) ((int)(intptr_t)(p))
  817. # else
  818. # define INT2PTR(p) ((void *)(p))
  819. # define PTR2INT(p) ((int)(p))
  820. # endif
  821. #endif
  822. #if !defined(UINT2PTR) && !defined(PTR2UINT)
  823. # if defined(HAVE_UINTPTR_T) || defined(uintptr_t)
  824. # define UINT2PTR(p) ((void *)(uintptr_t)(p))
  825. # define PTR2UINT(p) ((unsigned int)(uintptr_t)(p))
  826. # else
  827. # define UINT2PTR(p) ((void *)(p))
  828. # define PTR2UINT(p) ((unsigned int)(p))
  829. # endif
  830. #endif
  831.  
  832. #define VERSION "1.0"
  833.  
  834. /*
  835. ** Internal call required for munging integers
  836. */
  837. #ifndef _TCLINT
  838. /*
  839. * The structure used as the internal representation of Tcl list objects. This
  840. * struct is grown (reallocated and copied) as necessary to hold all the
  841. * list's element pointers. The struct might contain more slots than currently
  842. * used to hold all element pointers. This is done to make append operations
  843. * faster.
  844. *
  845. * We only need this when compiling as a seperate library from tcl
  846. */
  847.  
  848. typedef struct List {
  849. int refCount;
  850. int maxElemCount; /* Total number of element array slots. */
  851. int elemCount; /* Current number of list elements. */
  852. int canonicalFlag; /* Set if the string representation was
  853. * derived from the list representation. May
  854. * be ignored if there is no string rep at
  855. * all.*/
  856. Tcl_Obj *elements; /* First list element; the struct is grown to
  857. * accomodate all elements. */
  858. } List;
  859. #endif
  860. /*
  861. * During execution of the "lsort" command, structures of the following type
  862. * are used to arrange the objects being sorted into a collection of linked
  863. * lists.
  864. */
  865.  
  866. typedef struct SortElement {
  867. union {
  868. char *strValuePtr;
  869. long intValue;
  870. double doubleValue;
  871. Tcl_Obj *objValuePtr;
  872. } index;
  873. Tcl_Obj *objPtr; /* Object being sorted, or its index. */
  874. struct SortElement *nextPtr;/* Next element in the list, or NULL for end
  875. * of list. */
  876. } SortElement;
  877.  
  878.  
  879. typedef struct SortInfo {
  880. int isIncreasing; /* Nonzero means sort in increasing order. */
  881. int sortMode; /* The sort mode. One of SORTMODE_* values * defined below. */
  882. Tcl_Obj *compareCmdPtr; /* The Tcl comparison command when sortMode is
  883. * SORTMODE_COMMAND. Pre-initialized to hold
  884. * base of command. */
  885. int *indexv; /* If the -index option was specified, this
  886. * holds the indexes contained in the list
  887. *
  888. * supplied as an argument to that option.
  889. * NULL if no indexes supplied, and points to
  890. * singleIndex field when only one
  891. * supplied.
  892. */
  893. int indexc; /* Number of indexes in indexv array. */
  894. int singleIndex; /* Static space for common index case. */
  895. int unique;
  896. int numElements;
  897. Tcl_Interp *interp; /* The interpreter in which the sort is being
  898. * done.
  899. */
  900. int resultCode; /* Completion code for the lsort command. If
  901. * an error occurs during the sort this is
  902. * changed from TCL_OK to TCL_ERROR. */
  903. } SortInfo;
  904.  
  905. /*
  906. * These function pointer types are used with the "lsearch" and "lsort"
  907. * commands to facilitate the "-nocase" option.
  908. */
  909.  
  910. typedef int (*SortStrCmpFn_t) (const char *, const char *);
  911. typedef int (*SortMemCmpFn_t) (const void *, const void *, size_t);
  912.  
  913. /*
  914. * The "lsort" command needs to pass certain information down to the function
  915. * that compares two list elements, and the comparison function needs to pass
  916. * success or failure information back up to the top-level "lsort" command.
  917. * The following structure is used to pass this information.
  918. */
  919.  
  920.  
  921. /*
  922. * The "sortMode" field of the SortInfo structure can take on any of the
  923. * following values.
  924. */
  925.  
  926. #define SORTMODE_ASCII 0
  927. #define SORTMODE_INTEGER 1
  928. #define SORTMODE_REAL 2
  929. #define SORTMODE_COMMAND 3
  930. #define SORTMODE_DICTIONARY 4
  931. #define SORTMODE_ASCII_NC 8
  932.  
  933. /*
  934. * Magic values for the index field of the SortInfo structure. Note that the
  935. * index "end-1" will be translated to SORTIDX_END-1, etc.
  936. */
  937.  
  938. #define SORTIDX_NONE -1 /* Not indexed; use whole value. */
  939. #define SORTIDX_END -2 /* Indexed from end. */
  940.  
  941. /*
  942. * Forward declarations for procedures defined in this file:
  943. */
  944.  
  945. static int DictionaryCompare(char *left, char *right);
  946. static SortElement * MergeLists(SortElement *leftPtr, SortElement *rightPtr,
  947. SortInfo *infoPtr);
  948. static int SortCompare(SortElement *firstPtr, SortElement *second,
  949. SortInfo *infoPtr);
  950. static Tcl_Obj *Odie_MergeList_ToObj(SortElement *elementPtr);
  951. static int TclCmd_logicset_union(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  952. static int TclCmd_logicset_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  953. static int TclCmd_logicset_contains(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  954. static int TclCmd_logicset_empty(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  955. static int TclCmd_logicset_expr_and(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  956. static int TclCmd_logicset_expr_or(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  957. static int TclCmd_logicset_product_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  958. static int TclCmd_logicset_product_union(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  959. static int TclCmd_logicset_product_xor(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  960. static int TclCmd_logicset_product_missing(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  961. static int TclCmd_logicset_remove(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  962. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/logicset/logicset.tcl generate-cfile-header */
  963. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/literal/literal.tcl generate-cfile-header */
  964. /*
  965. ** constant.c
  966. ** Series of routines to minimize memory usage through the use
  967. ** of shared strings
  968. */
  969.  
  970. static Tcl_HashTable OdieLiteralStringTable;
  971. static Tcl_Obj *OdieStatic[14];
  972. static unsigned int nOdieObjString = 0;
  973. static unsigned int nOdieHashTable = 0;
  974. static unsigned int nOdieHashTableCreated = 0;
  975. static unsigned int nOdieHashTableDeleted = 0;
  976. static unsigned int nOdieDictSpecCount = 0;
  977. static unsigned int nOdieDictSpecCreated = 0;
  978. static unsigned int nOdieDictSpecDeleted = 0;
  979. static unsigned int nOdieDictSpecShared = 0;
  980. static unsigned int nOdieDictSpecNull = 0;
  981. static unsigned int nOdieDictSpecRecycled = 0;
  982. static unsigned int nOdieDictSpecModified = 0;
  983. static unsigned int nOdieDictSpecAccessed = 0;
  984.  
  985. static int OdieTrace=0;
  986.  
  987. typedef struct constObj {
  988. char *string;
  989. Tcl_Obj *tclobj;
  990. } constObj;
  991. static Tcl_Obj *Odie_constant(const char *zName,int create);
  992. static void Odie_constant_inject(Tcl_Obj *value);
  993. static int TclCmd_literal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  994. static int TclCmd_literal_dump(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  995. static int TclCmd_literal_stats(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  996. static int TclCmd_constant_string(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  997. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/literal/literal.tcl generate-cfile-header */
  998. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/module.ini generate-cfile-header */
  999. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/param.tcl generate-cfile-header */
  1000. Tcl_Interp *local_interp = NULL;
  1001. Simulator *CurrentSim = NULL;
  1002. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/param.tcl generate-cfile-header */
  1003. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/location.tcl generate-cfile-header */
  1004. static int TclCmd_location_grid_square(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  1005. static int TclCmd_location_gridhash_square(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  1006. static int TclCmd_location_location_gridhash(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  1007. static int TclCmd_location_grid_hex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  1008. static int TclCmd_location_gridhash_hex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  1009. static int TclCmd_location_gridhash_adjacent(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  1010. static int TclCmd_location_object(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  1011. static int TclCmd_location_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  1012. static int TclCmd_location_match(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
  1013. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/location.tcl generate-cfile-header */
  1014. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simulator.tcl generate-cfile-header */
  1015. static int OOMethod_Simulator_C_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1016. static int Simulator_OO_Init(Tcl_Interp *interp);
  1017. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simulator.tcl generate-cfile-header */
  1018. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/entity.tcl generate-cfile-header */
  1019. #define CSTRUCT_agent 1
  1020. #define CSTRUCT_compartment 2
  1021. #define CSTRUCT_crew 3
  1022. #define CSTRUCT_entity 4
  1023. #define CSTRUCT_objective 5
  1024. #define CSTRUCT_portal 6
  1025. #define CSTRUCT_routecompartment 7
  1026. #define CSTRUCT_routeportal 8
  1027. #define CSTRUCT_simlink 9
  1028. #define CSTRUCT_simnode 10
  1029. #define CSTRUCT_simulator 11
  1030. #define CSTRUCT_Count 11
  1031. #define CSTRUCT_ENTITY_AliasCount 19
  1032.  
  1033. #define ENTITY_ACTIVE_NULL 0 /* Not Checked */
  1034. #define ENTITY_ACTIVE_SHOW 1 /* Mark Checked */
  1035. #define ENTITY_ACTIVE_HIDE 2 /* Marked Hidden */
  1036. #define ENTITY_CLASS_AGENT a /* Agent */
  1037. #define ENTITY_CLASS_COMPARTMENT c /* Compartment */
  1038. #define ENTITY_CLASS_EQUIPMENT e /* Equipment */
  1039. #define ENTITY_CLASS_LINK l /* Conduit, Cable or Link */
  1040. #define ENTITY_CLASS_MATERIAL m /* Material */
  1041. #define ENTITY_CLASS_PORTAL p /* Portal */
  1042. #define ENTITY_CLASS_ROLLUP r /* Deactivation Rollup */
  1043. #define ENTITY_CLASS_HUMAN v /* Human */
  1044. #define ENTITY_CLASS_WALL w /* Wall Type */
  1045. #define ENTITY_CLASS_TREE x /* Type Tree Branch */
  1046. #define ENTITY_CLASS_GENERIC y /* Generic Type */
  1047. #define CSTRUCT_ENTITY_ACTIVE 0
  1048. #define CSTRUCT_ENTITY_CHANGED 1
  1049. #define CSTRUCT_ENTITY_CLASS 2
  1050. #define CSTRUCT_ENTITY_DRAWN 3
  1051. #define CSTRUCT_ENTITY_GROUPID 4
  1052. #define CSTRUCT_ENTITY_HIDDEN 5
  1053. #define CSTRUCT_ENTITY_HIGHLIGHT 6
  1054. #define CSTRUCT_ENTITY_IS_TYPE 7
  1055. #define CSTRUCT_ENTITY_MOVED 8
  1056. #define CSTRUCT_ENTITY_NCHILD 9
  1057. #define CSTRUCT_ENTITY_ONCOUNT 10
  1058. #define CSTRUCT_ENTITY_OPEN 11
  1059. #define CSTRUCT_ENTITY_PARENT 12
  1060. #define CSTRUCT_ENTITY_REDRAW 13
  1061. #define CSTRUCT_ENTITY_REPAINT 14
  1062. #define CSTRUCT_ENTITY_SYNTHETIC 15
  1063. #define CSTRUCT_ENTITY_TRACE 16
  1064. #define CSTRUCT_ENTITY_VISIBLE 17
  1065. #define CSTRUCT_ENTITY_Count 18
  1066. static int OOMethod_OOEntity_C_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1067. static int OOMethod_OOEntity_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1068. static int OOMethod_OOEntity_attach_to(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1069. static int OOMethod_OOEntity_compartment(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1070. static int OOMethod_OOEntity_comptid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1071. static int OOMethod_OOEntity_count(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1072. static int OOMethod_OOEntity_deckid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1073. static int OOMethod_OOEntity_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1074. static int OOMethod_OOEntity_drawn_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1075. static int OOMethod_OOEntity_exists(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1076. static int OOMethod_OOEntity_for(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1077. static int OOMethod_OOEntity_foreach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1078. static int OOMethod_OOEntity_groupid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1079. static int OOMethod_OOEntity_groups_recalculate(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1080. static int OOMethod_OOEntity_hidden_inherit(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1081. static int OOMethod_OOEntity_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1082. static int OOMethod_OOEntity_location(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1083. static int OOMethod_OOEntity_midpoint(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1084. static int OOMethod_OOEntity_nodeget(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1085. static int OOMethod_OOEntity_nodeput(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1086. static int OOMethod_OOEntity_nodewith(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1087. static int OOMethod_OOEntity_normalize(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1088. static int OOMethod_OOEntity_orientation(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1089. static int OOMethod_OOEntity_redraw(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1090. static int OOMethod_OOEntity_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1091. static int OOMethod_OOEntity_setting(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1092. static int OOMethod_OOEntity_spec_get(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1093. static int OOMethod_OOEntity_spec_put(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1094. static int OOMethod_OOEntity_spec_replace(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1095. static int OOMethod_OOEntity_struct_get(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1096. static int OOMethod_OOEntity_struct_put(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1097. static int OOMethod_OOEntity_type(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1098. static int OOMethod_OOEntity_typeid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1099. static int OOMethod_OOEntity_visible(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1100. static int OOMethod_OOEntity_visible_filter(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1101. static int OOMethod_OOEntity_visible_hidden_subtract(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1102. static int OOMethod_OOEntity_visible_inherit(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1103. static int OOMethod_OOEntity_visible_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1104. static int OOMethod_OOEntity_visible_tree(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1105. static int OOMethod_OOEntity_witheach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1106. static int OOEntity_OO_Init(Tcl_Interp *interp);
  1107. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/entity.tcl generate-cfile-header */
  1108. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simtype.tcl generate-cfile-header */
  1109. static int OOMethod_SimType_C_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1110. static int OOMethod_SimType_children(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1111. static int OOMethod_SimType_count(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1112. static int OOMethod_SimType_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1113. static int OOMethod_SimType_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1114. static int OOMethod_SimType_exists(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1115. static int OOMethod_SimType_for(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1116. static int OOMethod_SimType_foreach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1117. static int OOMethod_SimType_groupid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1118. static int OOMethod_SimType_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1119. static int OOMethod_SimType_nodeget(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1120. static int OOMethod_SimType_nodeput(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1121. static int OOMethod_SimType_nodewith(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1122. static int OOMethod_SimType_normalize(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1123. static int OOMethod_SimType_parent(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1124. static int OOMethod_SimType_setting(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1125. static int OOMethod_SimType_spec_get(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1126. static int OOMethod_SimType_spec_put(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1127. static int OOMethod_SimType_spec_replace(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1128. static int OOMethod_SimType_struct_get(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1129. static int OOMethod_SimType_struct_put(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1130. static int OOMethod_SimType_type(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1131. static int OOMethod_SimType_typeid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1132. static int OOMethod_SimType_visible_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1133. static int OOMethod_SimType_witheach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv);
  1134. static int SimType_OO_Init(Tcl_Interp *interp);
  1135. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simtype.tcl generate-cfile-header */
  1136. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/module.ini generate-cfile-header */
  1137. /* END generate-cfile-header */
  1138. /* BEGIN generate-cfile-constant */
  1139. const static Tcl_ObjectMetadataType LinkDataType = {
  1140. TCL_OO_METADATA_VERSION_CURRENT,
  1141. "Link",
  1142. NULL,
  1143. NULL
  1144. };
  1145. #define GETLINK(OBJCONTEXT) (Link *) Tcl_ObjectGetMetadata(OBJCONTEXT,&LinkDataType)
  1146. const static Tcl_ObjectMetadataType HashDataType = {
  1147. TCL_OO_METADATA_VERSION_CURRENT,
  1148. "Hash",
  1149. NULL,
  1150. NULL
  1151. };
  1152. #define GETHASH(OBJCONTEXT) (Hash *) Tcl_ObjectGetMetadata(OBJCONTEXT,&HashDataType)
  1153. const static Tcl_ObjectMetadataType HashElemDataType = {
  1154. TCL_OO_METADATA_VERSION_CURRENT,
  1155. "HashElem",
  1156. NULL,
  1157. NULL
  1158. };
  1159. #define GETHASHELEM(OBJCONTEXT) (HashElem *) Tcl_ObjectGetMetadata(OBJCONTEXT,&HashElemDataType)
  1160. const static Tcl_ObjectMetadataType Odie_MatrixObjDataType = {
  1161. TCL_OO_METADATA_VERSION_CURRENT,
  1162. "Odie_MatrixObj",
  1163. NULL,
  1164. NULL
  1165. };
  1166. #define GETODIE_MATRIXOBJ(OBJCONTEXT) (Odie_MatrixObj *) Tcl_ObjectGetMetadata(OBJCONTEXT,&Odie_MatrixObjDataType)
  1167. const static Tcl_ObjectMetadataType MatrixFormDataType = {
  1168. TCL_OO_METADATA_VERSION_CURRENT,
  1169. "MatrixForm",
  1170. NULL,
  1171. NULL
  1172. };
  1173. #define GETMATRIXFORM(OBJCONTEXT) (MatrixForm *) Tcl_ObjectGetMetadata(OBJCONTEXT,&MatrixFormDataType)
  1174. const Tcl_ObjType matrix_tclobjtype = {
  1175. .name="matrix",
  1176. .freeIntRepProc = &MatrixObj_freeIntRepProc,
  1177. .dupIntRepProc = &MatrixObj_dupIntRepProc,
  1178. .updateStringProc = &MatrixObj_updateStringProc,
  1179. .setFromAnyProc = &MatrixObj_setFromAnyProc
  1180. };
  1181. const static Tcl_ObjectMetadataType TriagPointDataType = {
  1182. TCL_OO_METADATA_VERSION_CURRENT,
  1183. "TriagPoint",
  1184. NULL,
  1185. NULL
  1186. };
  1187. #define GETTRIAGPOINT(OBJCONTEXT) (TriagPoint *) Tcl_ObjectGetMetadata(OBJCONTEXT,&TriagPointDataType)
  1188. const static Tcl_ObjectMetadataType TriagSegmentDataType = {
  1189. TCL_OO_METADATA_VERSION_CURRENT,
  1190. "TriagSegment",
  1191. NULL,
  1192. NULL
  1193. };
  1194. #define GETTRIAGSEGMENT(OBJCONTEXT) (TriagSegment *) Tcl_ObjectGetMetadata(OBJCONTEXT,&TriagSegmentDataType)
  1195. const static Tcl_ObjectMetadataType TriagSegSetDataType = {
  1196. TCL_OO_METADATA_VERSION_CURRENT,
  1197. "TriagSegSet",
  1198. NULL,
  1199. NULL
  1200. };
  1201. #define GETTRIAGSEGSET(OBJCONTEXT) (TriagSegSet *) Tcl_ObjectGetMetadata(OBJCONTEXT,&TriagSegSetDataType)
  1202. const static Tcl_ObjectMetadataType Odie_PolygonDataType = {
  1203. TCL_OO_METADATA_VERSION_CURRENT,
  1204. "Odie_Polygon",
  1205. NULL,
  1206. NULL
  1207. };
  1208. #define GETODIE_POLYGON(OBJCONTEXT) (Odie_Polygon *) Tcl_ObjectGetMetadata(OBJCONTEXT,&Odie_PolygonDataType)
  1209. const Tcl_ObjType polygon_tclobjtype = {
  1210. .name="polygon",
  1211. .freeIntRepProc = &PolygonObj_freeIntRepProc,
  1212. .dupIntRepProc = &PolygonObj_dupIntRepProc,
  1213. .updateStringProc = &PolygonObj_updateStringRepProc,
  1214. .setFromAnyProc = &PolygonObj_setFromAnyProc
  1215. };
  1216. const static Tcl_ObjectMetadataType Odie_FaceXYZDataType = {
  1217. TCL_OO_METADATA_VERSION_CURRENT,
  1218. "Odie_FaceXYZ",
  1219. NULL,
  1220. NULL
  1221. };
  1222. #define GETODIE_FACEXYZ(OBJCONTEXT) (Odie_FaceXYZ *) Tcl_ObjectGetMetadata(OBJCONTEXT,&Odie_FaceXYZDataType)
  1223. const Tcl_ObjType odie_polygon_tclobjtype = {
  1224. .name="odie_polygon",
  1225. .freeIntRepProc = &Odie_FaceXYZ_freeIntRepProc,
  1226. .dupIntRepProc = &Odie_FaceXYZ_dupIntRepProc,
  1227. .updateStringProc = &Odie_FaceXYZ_updateStringProc,
  1228. .setFromAnyProc = &Odie_FaceXYZ_setFromAnyProc
  1229. };
  1230. const static Tcl_ObjectMetadataType FaceBoundaryDataType = {
  1231. TCL_OO_METADATA_VERSION_CURRENT,
  1232. "FaceBoundary",
  1233. NULL,
  1234. NULL
  1235. };
  1236. #define GETFACEBOUNDARY(OBJCONTEXT) (FaceBoundary *) Tcl_ObjectGetMetadata(OBJCONTEXT,&FaceBoundaryDataType)
  1237. const static Tcl_ObjectMetadataType SegmentDataType = {
  1238. TCL_OO_METADATA_VERSION_CURRENT,
  1239. "Segment",
  1240. NULL,
  1241. NULL
  1242. };
  1243. #define GETSEGMENT(OBJCONTEXT) (Segment *) Tcl_ObjectGetMetadata(OBJCONTEXT,&SegmentDataType)
  1244. const static Tcl_ObjectMetadataType SegmentSetDataType = {
  1245. TCL_OO_METADATA_VERSION_CURRENT,
  1246. "SegmentSet",
  1247. SegmentSet_Delete,
  1248. SegmentSet_Clone
  1249. };
  1250. #define GETSEGMENTSET(OBJCONTEXT) (SegmentSet *) Tcl_ObjectGetMetadata(OBJCONTEXT,&SegmentSetDataType)
  1251. const static Tcl_MethodType OOMethodType_SegmentSet_segment_info = {
  1252. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1253. .name = "segment_info",
  1254. .callProc = OOMethod_SegmentSet_segment_info,
  1255. .deleteProc = NULL,
  1256. .cloneProc = NULL
  1257. };
  1258. const static Tcl_MethodType OOMethodType_SegmentSet_SegmentSet_Init = {
  1259. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1260. .name = "SegmentSet_Init",
  1261. .callProc = OOMethod_SegmentSet_SegmentSet_Init,
  1262. .deleteProc = NULL,
  1263. .cloneProc = NULL
  1264. };
  1265. const static Tcl_MethodType OOMethodType_SegmentSet_modified = {
  1266. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1267. .name = "modified",
  1268. .callProc = OOMethod_SegmentSet_modified,
  1269. .deleteProc = NULL,
  1270. .cloneProc = NULL
  1271. };
  1272. const static Tcl_MethodType OOMethodType_SegmentSet_segment_count = {
  1273. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1274. .name = "segment_count",
  1275. .callProc = OOMethod_SegmentSet_segment_count,
  1276. .deleteProc = NULL,
  1277. .cloneProc = NULL
  1278. };
  1279. const static Tcl_MethodType OOMethodType_SegmentSet_bbox = {
  1280. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1281. .name = "bbox",
  1282. .callProc = OOMethod_SegmentSet_bbox,
  1283. .deleteProc = NULL,
  1284. .cloneProc = NULL
  1285. };
  1286. const static Tcl_MethodType OOMethodType_SegmentSet_segment_reset = {
  1287. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1288. .name = "segment_reset",
  1289. .callProc = OOMethod_SegmentSet_segment_reset,
  1290. .deleteProc = NULL,
  1291. .cloneProc = NULL
  1292. };
  1293. const static Tcl_MethodType OOMethodType_SegmentSet_segment_add = {
  1294. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1295. .name = "segment_add",
  1296. .callProc = OOMethod_SegmentSet_segment_add,
  1297. .deleteProc = NULL,
  1298. .cloneProc = NULL
  1299. };
  1300. const static Tcl_MethodType OOMethodType_SegmentSet_segment_add_virtual = {
  1301. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1302. .name = "segment_add_virtual",
  1303. .callProc = OOMethod_SegmentSet_segment_add_virtual,
  1304. .deleteProc = NULL,
  1305. .cloneProc = NULL
  1306. };
  1307. const static Tcl_MethodType OOMethodType_SegmentSet_polygon_add = {
  1308. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1309. .name = "polygon_add",
  1310. .callProc = OOMethod_SegmentSet_polygon_add,
  1311. .deleteProc = NULL,
  1312. .cloneProc = NULL
  1313. };
  1314. const static Tcl_MethodType OOMethodType_SegmentSet_vertex_add = {
  1315. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1316. .name = "vertex_add",
  1317. .callProc = OOMethod_SegmentSet_vertex_add,
  1318. .deleteProc = NULL,
  1319. .cloneProc = NULL
  1320. };
  1321. const static Tcl_MethodType OOMethodType_SegmentSet_segment_delete = {
  1322. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1323. .name = "segment_delete",
  1324. .callProc = OOMethod_SegmentSet_segment_delete,
  1325. .deleteProc = NULL,
  1326. .cloneProc = NULL
  1327. };
  1328. const static Tcl_MethodType OOMethodType_SegmentSet_delete = {
  1329. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1330. .name = "delete",
  1331. .callProc = OOMethod_SegmentSet_delete,
  1332. .deleteProc = NULL,
  1333. .cloneProc = NULL
  1334. };
  1335. const static Tcl_MethodType OOMethodType_SegmentSet_cleanup = {
  1336. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1337. .name = "cleanup",
  1338. .callProc = OOMethod_SegmentSet_cleanup,
  1339. .deleteProc = NULL,
  1340. .cloneProc = NULL
  1341. };
  1342. const static Tcl_MethodType OOMethodType_SegmentSet_cleanup_looseend = {
  1343. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1344. .name = "cleanup_looseend",
  1345. .callProc = OOMethod_SegmentSet_cleanup_looseend,
  1346. .deleteProc = NULL,
  1347. .cloneProc = NULL
  1348. };
  1349. const static Tcl_MethodType OOMethodType_SegmentSet_edge_connection = {
  1350. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1351. .name = "edge_connection",
  1352. .callProc = OOMethod_SegmentSet_edge_connection,
  1353. .deleteProc = NULL,
  1354. .cloneProc = NULL
  1355. };
  1356. const static Tcl_MethodType OOMethodType_SegmentSet_check_intersecting = {
  1357. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1358. .name = "check_intersecting",
  1359. .callProc = OOMethod_SegmentSet_check_intersecting,
  1360. .deleteProc = NULL,
  1361. .cloneProc = NULL
  1362. };
  1363. const static Tcl_MethodType OOMethodType_SegmentSet_check_coincident = {
  1364. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1365. .name = "check_coincident",
  1366. .callProc = OOMethod_SegmentSet_check_coincident,
  1367. .deleteProc = NULL,
  1368. .cloneProc = NULL
  1369. };
  1370. const static Tcl_MethodType OOMethodType_SegmentSet_segment_linelineintersect = {
  1371. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1372. .name = "segment_linelineintersect",
  1373. .callProc = OOMethod_SegmentSet_segment_linelineintersect,
  1374. .deleteProc = NULL,
  1375. .cloneProc = NULL
  1376. };
  1377. const static Tcl_MethodType OOMethodType_SegmentSet_segment_coincident = {
  1378. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1379. .name = "segment_coincident",
  1380. .callProc = OOMethod_SegmentSet_segment_coincident,
  1381. .deleteProc = NULL,
  1382. .cloneProc = NULL
  1383. };
  1384. const static Tcl_MethodType OOMethodType_SegmentSet_segment_find = {
  1385. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1386. .name = "segment_find",
  1387. .callProc = OOMethod_SegmentSet_segment_find,
  1388. .deleteProc = NULL,
  1389. .cloneProc = NULL
  1390. };
  1391. const static Tcl_MethodType OOMethodType_SegmentSet_vertex_delete = {
  1392. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1393. .name = "vertex_delete",
  1394. .callProc = OOMethod_SegmentSet_vertex_delete,
  1395. .deleteProc = NULL,
  1396. .cloneProc = NULL
  1397. };
  1398. const static Tcl_MethodType OOMethodType_SegmentSet_segment_next = {
  1399. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1400. .name = "segment_next",
  1401. .callProc = OOMethod_SegmentSet_segment_next,
  1402. .deleteProc = NULL,
  1403. .cloneProc = NULL
  1404. };
  1405. const static Tcl_MethodType OOMethodType_SegmentSet_check_oblique = {
  1406. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1407. .name = "check_oblique",
  1408. .callProc = OOMethod_SegmentSet_check_oblique,
  1409. .deleteProc = NULL,
  1410. .cloneProc = NULL
  1411. };
  1412. const static Tcl_MethodType OOMethodType_SegmentSet_check_looseends = {
  1413. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1414. .name = "check_looseends",
  1415. .callProc = OOMethod_SegmentSet_check_looseends,
  1416. .deleteProc = NULL,
  1417. .cloneProc = NULL
  1418. };
  1419. const static Tcl_MethodType OOMethodType_SegmentSet_fix_looseends = {
  1420. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1421. .name = "fix_looseends",
  1422. .callProc = OOMethod_SegmentSet_fix_looseends,
  1423. .deleteProc = NULL,
  1424. .cloneProc = NULL
  1425. };
  1426. const static Tcl_MethodType OOMethodType_SegmentSet_grid = {
  1427. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1428. .name = "grid",
  1429. .callProc = OOMethod_SegmentSet_grid,
  1430. .deleteProc = NULL,
  1431. .cloneProc = NULL
  1432. };
  1433. const static Tcl_MethodType OOMethodType_SegmentSet_segment_list = {
  1434. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1435. .name = "segment_list",
  1436. .callProc = OOMethod_SegmentSet_segment_list,
  1437. .deleteProc = NULL,
  1438. .cloneProc = NULL
  1439. };
  1440. const static Tcl_MethodType OOMethodType_SegmentSet_segment_coords = {
  1441. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1442. .name = "segment_coords",
  1443. .callProc = OOMethod_SegmentSet_segment_coords,
  1444. .deleteProc = NULL,
  1445. .cloneProc = NULL
  1446. };
  1447. const static Tcl_MethodType OOMethodType_SegmentSet_segment_uvcoords = {
  1448. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1449. .name = "segment_uvcoords",
  1450. .callProc = OOMethod_SegmentSet_segment_uvcoords,
  1451. .deleteProc = NULL,
  1452. .cloneProc = NULL
  1453. };
  1454. const static Tcl_MethodType OOMethodType_SegmentSet_selfcheck = {
  1455. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1456. .name = "selfcheck",
  1457. .callProc = OOMethod_SegmentSet_selfcheck,
  1458. .deleteProc = NULL,
  1459. .cloneProc = NULL
  1460. };
  1461. const static Tcl_MethodType OOMethodType_SegmentSet_uv_transform = {
  1462. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1463. .name = "uv_transform",
  1464. .callProc = OOMethod_SegmentSet_uv_transform,
  1465. .deleteProc = NULL,
  1466. .cloneProc = NULL
  1467. };
  1468. const static Tcl_MethodType OOMethodType_SegmentSet_polygons_xyz = {
  1469. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1470. .name = "polygons_xyz",
  1471. .callProc = OOMethod_SegmentSet_polygons_xyz,
  1472. .deleteProc = NULL,
  1473. .cloneProc = NULL
  1474. };
  1475. const static Tcl_MethodType OOMethodType_SegmentSet_polygons = {
  1476. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1477. .name = "polygons",
  1478. .callProc = OOMethod_SegmentSet_polygons,
  1479. .deleteProc = NULL,
  1480. .cloneProc = NULL
  1481. };
  1482. const static Tcl_MethodType OOMethodType_SegmentSet_polygon_faces = {
  1483. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1484. .name = "polygon_faces",
  1485. .callProc = OOMethod_SegmentSet_polygon_faces,
  1486. .deleteProc = NULL,
  1487. .cloneProc = NULL
  1488. };
  1489. const static Tcl_MethodType OOMethodType_SegmentSet_polygon_info = {
  1490. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1491. .name = "polygon_info",
  1492. .callProc = OOMethod_SegmentSet_polygon_info,
  1493. .deleteProc = NULL,
  1494. .cloneProc = NULL
  1495. };
  1496. const static Tcl_ObjectMetadataType PlotterDataType = {
  1497. TCL_OO_METADATA_VERSION_CURRENT,
  1498. "Plotter",
  1499. Plotter_Delete,
  1500. Plotter_Clone
  1501. };
  1502. #define GETPLOTTER(OBJCONTEXT) (Plotter *) Tcl_ObjectGetMetadata(OBJCONTEXT,&PlotterDataType)
  1503. const static Tcl_MethodType OOMethodType_Plotter_actualcoords = {
  1504. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1505. .name = "actualcoords",
  1506. .callProc = OOMethod_Plotter_actualcoords,
  1507. .deleteProc = NULL,
  1508. .cloneProc = NULL
  1509. };
  1510. const static Tcl_MethodType OOMethodType_Plotter_canvascoords = {
  1511. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1512. .name = "canvascoords",
  1513. .callProc = OOMethod_Plotter_canvascoords,
  1514. .deleteProc = NULL,
  1515. .cloneProc = NULL
  1516. };
  1517. const static Tcl_MethodType OOMethodType_Plotter_centerset = {
  1518. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1519. .name = "centerset",
  1520. .callProc = OOMethod_Plotter_centerset,
  1521. .deleteProc = NULL,
  1522. .cloneProc = NULL
  1523. };
  1524. const static Tcl_MethodType OOMethodType_Plotter_xoffset = {
  1525. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1526. .name = "xoffset",
  1527. .callProc = OOMethod_Plotter_xoffset,
  1528. .deleteProc = NULL,
  1529. .cloneProc = NULL
  1530. };
  1531. const static Tcl_MethodType OOMethodType_Plotter_yoffset = {
  1532. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1533. .name = "yoffset",
  1534. .callProc = OOMethod_Plotter_yoffset,
  1535. .deleteProc = NULL,
  1536. .cloneProc = NULL
  1537. };
  1538. const static Tcl_MethodType OOMethodType_Plotter_zoom = {
  1539. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1540. .name = "zoom",
  1541. .callProc = OOMethod_Plotter_zoom,
  1542. .deleteProc = NULL,
  1543. .cloneProc = NULL
  1544. };
  1545. const static Tcl_MethodType OOMethodType_Plotter_constructor = {
  1546. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1547. .name = "constructor",
  1548. .callProc = OOMethod_Plotter_constructor,
  1549. .deleteProc = NULL,
  1550. .cloneProc = NULL
  1551. };
  1552. const static Tcl_ObjectMetadataType OneSliceDataType = {
  1553. TCL_OO_METADATA_VERSION_CURRENT,
  1554. "OneSlice",
  1555. NULL,
  1556. NULL
  1557. };
  1558. #define GETONESLICE(OBJCONTEXT) (OneSlice *) Tcl_ObjectGetMetadata(OBJCONTEXT,&OneSliceDataType)
  1559. const static Tcl_ObjectMetadataType SlicerDataType = {
  1560. TCL_OO_METADATA_VERSION_CURRENT,
  1561. "Slicer",
  1562. Slicer_Delete,
  1563. Slicer_Clone
  1564. };
  1565. #define GETSLICER(OBJCONTEXT) (Slicer *) Tcl_ObjectGetMetadata(OBJCONTEXT,&SlicerDataType)
  1566. const static Tcl_MethodType OOMethodType_Slicer_drawline = {
  1567. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1568. .name = "drawline",
  1569. .callProc = OOMethod_Slicer_drawline,
  1570. .deleteProc = NULL,
  1571. .cloneProc = NULL
  1572. };
  1573. const static Tcl_MethodType OOMethodType_Slicer_above = {
  1574. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1575. .name = "above",
  1576. .callProc = OOMethod_Slicer_above,
  1577. .deleteProc = NULL,
  1578. .cloneProc = NULL
  1579. };
  1580. const static Tcl_MethodType OOMethodType_Slicer_below = {
  1581. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1582. .name = "below",
  1583. .callProc = OOMethod_Slicer_below,
  1584. .deleteProc = NULL,
  1585. .cloneProc = NULL
  1586. };
  1587. const static Tcl_MethodType OOMethodType_Slicer_deckid_to_name = {
  1588. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1589. .name = "deckid_to_name",
  1590. .callProc = OOMethod_Slicer_deckid_to_name,
  1591. .deleteProc = NULL,
  1592. .cloneProc = NULL
  1593. };
  1594. const static Tcl_MethodType OOMethodType_Slicer_deckname_to_id = {
  1595. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1596. .name = "deckname_to_id",
  1597. .callProc = OOMethod_Slicer_deckname_to_id,
  1598. .deleteProc = NULL,
  1599. .cloneProc = NULL
  1600. };
  1601. const static Tcl_MethodType OOMethodType_Slicer_bbox_to_location = {
  1602. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1603. .name = "bbox_to_location",
  1604. .callProc = OOMethod_Slicer_bbox_to_location,
  1605. .deleteProc = NULL,
  1606. .cloneProc = NULL
  1607. };
  1608. const static Tcl_MethodType OOMethodType_Slicer_bbox_to_midpoint = {
  1609. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1610. .name = "bbox_to_midpoint",
  1611. .callProc = OOMethod_Slicer_bbox_to_midpoint,
  1612. .deleteProc = NULL,
  1613. .cloneProc = NULL
  1614. };
  1615. const static Tcl_MethodType OOMethodType_Slicer_xyz_to_location = {
  1616. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1617. .name = "xyz_to_location",
  1618. .callProc = OOMethod_Slicer_xyz_to_location,
  1619. .deleteProc = NULL,
  1620. .cloneProc = NULL
  1621. };
  1622. const static Tcl_MethodType OOMethodType_Slicer_location_to_xyz = {
  1623. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1624. .name = "location_to_xyz",
  1625. .callProc = OOMethod_Slicer_location_to_xyz,
  1626. .deleteProc = NULL,
  1627. .cloneProc = NULL
  1628. };
  1629. const static Tcl_MethodType OOMethodType_Slicer_location_z = {
  1630. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1631. .name = "location_z",
  1632. .callProc = OOMethod_Slicer_location_z,
  1633. .deleteProc = NULL,
  1634. .cloneProc = NULL
  1635. };
  1636. const static Tcl_MethodType OOMethodType_Slicer_distance = {
  1637. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1638. .name = "distance",
  1639. .callProc = OOMethod_Slicer_distance,
  1640. .deleteProc = NULL,
  1641. .cloneProc = NULL
  1642. };
  1643. const static Tcl_MethodType OOMethodType_Slicer_actualcoords = {
  1644. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1645. .name = "actualcoords",
  1646. .callProc = OOMethod_Slicer_actualcoords,
  1647. .deleteProc = NULL,
  1648. .cloneProc = NULL
  1649. };
  1650. const static Tcl_MethodType OOMethodType_Slicer_canvascoords = {
  1651. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1652. .name = "canvascoords",
  1653. .callProc = OOMethod_Slicer_canvascoords,
  1654. .deleteProc = NULL,
  1655. .cloneProc = NULL
  1656. };
  1657. const static Tcl_MethodType OOMethodType_Slicer_create = {
  1658. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1659. .name = "create",
  1660. .callProc = OOMethod_Slicer_create,
  1661. .deleteProc = NULL,
  1662. .cloneProc = NULL
  1663. };
  1664. const static Tcl_MethodType OOMethodType_Slicer_deck_at_xyz = {
  1665. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1666. .name = "deck_at_xyz",
  1667. .callProc = OOMethod_Slicer_deck_at_xyz,
  1668. .deleteProc = NULL,
  1669. .cloneProc = NULL
  1670. };
  1671. const static Tcl_MethodType OOMethodType_Slicer_deckid_at_xyx = {
  1672. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1673. .name = "deckid_at_xyx",
  1674. .callProc = OOMethod_Slicer_deckid_at_xyx,
  1675. .deleteProc = NULL,
  1676. .cloneProc = NULL
  1677. };
  1678. const static Tcl_MethodType OOMethodType_Slicer_delete = {
  1679. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1680. .name = "delete",
  1681. .callProc = OOMethod_Slicer_delete,
  1682. .deleteProc = NULL,
  1683. .cloneProc = NULL
  1684. };
  1685. const static Tcl_MethodType OOMethodType_Slicer_makedlist = {
  1686. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1687. .name = "makedlist",
  1688. .callProc = OOMethod_Slicer_makedlist,
  1689. .deleteProc = NULL,
  1690. .cloneProc = NULL
  1691. };
  1692. const static Tcl_MethodType OOMethodType_Slicer_find = {
  1693. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1694. .name = "find",
  1695. .callProc = OOMethod_Slicer_find,
  1696. .deleteProc = NULL,
  1697. .cloneProc = NULL
  1698. };
  1699. const static Tcl_MethodType OOMethodType_Slicer_finddid = {
  1700. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1701. .name = "finddid",
  1702. .callProc = OOMethod_Slicer_finddid,
  1703. .deleteProc = NULL,
  1704. .cloneProc = NULL
  1705. };
  1706. const static Tcl_MethodType OOMethodType_Slicer_flatheight = {
  1707. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1708. .name = "flatheight",
  1709. .callProc = OOMethod_Slicer_flatheight,
  1710. .deleteProc = NULL,
  1711. .cloneProc = NULL
  1712. };
  1713. const static Tcl_MethodType OOMethodType_Slicer_headroom = {
  1714. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1715. .name = "headroom",
  1716. .callProc = OOMethod_Slicer_headroom,
  1717. .deleteProc = NULL,
  1718. .cloneProc = NULL
  1719. };
  1720. const static Tcl_MethodType OOMethodType_Slicer_ceiling = {
  1721. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1722. .name = "ceiling",
  1723. .callProc = OOMethod_Slicer_ceiling,
  1724. .deleteProc = NULL,
  1725. .cloneProc = NULL
  1726. };
  1727. const static Tcl_MethodType OOMethodType_Slicer_height = {
  1728. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1729. .name = "height",
  1730. .callProc = OOMethod_Slicer_height,
  1731. .deleteProc = NULL,
  1732. .cloneProc = NULL
  1733. };
  1734. const static Tcl_MethodType OOMethodType_Slicer_deckheight = {
  1735. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1736. .name = "deckheight",
  1737. .callProc = OOMethod_Slicer_deckheight,
  1738. .deleteProc = NULL,
  1739. .cloneProc = NULL
  1740. };
  1741. const static Tcl_MethodType OOMethodType_Slicer_info = {
  1742. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1743. .name = "info",
  1744. .callProc = OOMethod_Slicer_info,
  1745. .deleteProc = NULL,
  1746. .cloneProc = NULL
  1747. };
  1748. const static Tcl_MethodType OOMethodType_Slicer_list = {
  1749. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1750. .name = "list",
  1751. .callProc = OOMethod_Slicer_list,
  1752. .deleteProc = NULL,
  1753. .cloneProc = NULL
  1754. };
  1755. const static Tcl_MethodType OOMethodType_Slicer_profile = {
  1756. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1757. .name = "profile",
  1758. .callProc = OOMethod_Slicer_profile,
  1759. .deleteProc = NULL,
  1760. .cloneProc = NULL
  1761. };
  1762. const static Tcl_MethodType OOMethodType_Slicer_xoffset = {
  1763. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1764. .name = "xoffset",
  1765. .callProc = OOMethod_Slicer_xoffset,
  1766. .deleteProc = NULL,
  1767. .cloneProc = NULL
  1768. };
  1769. const static Tcl_MethodType OOMethodType_Slicer_zoom = {
  1770. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1771. .name = "zoom",
  1772. .callProc = OOMethod_Slicer_zoom,
  1773. .deleteProc = NULL,
  1774. .cloneProc = NULL
  1775. };
  1776. const static Tcl_MethodType OOMethodType_Slicer_upper_height = {
  1777. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1778. .name = "upper_height",
  1779. .callProc = OOMethod_Slicer_upper_height,
  1780. .deleteProc = NULL,
  1781. .cloneProc = NULL
  1782. };
  1783. const static Tcl_MethodType OOMethodType_Slicer_Slicer_Init = {
  1784. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1785. .name = "Slicer_Init",
  1786. .callProc = OOMethod_Slicer_Slicer_Init,
  1787. .deleteProc = NULL,
  1788. .cloneProc = NULL
  1789. };
  1790. const static Tcl_ObjectMetadataType BoundaryDataType = {
  1791. TCL_OO_METADATA_VERSION_CURRENT,
  1792. "Boundary",
  1793. NULL,
  1794. NULL
  1795. };
  1796. #define GETBOUNDARY(OBJCONTEXT) (Boundary *) Tcl_ObjectGetMetadata(OBJCONTEXT,&BoundaryDataType)
  1797. const static Tcl_ObjectMetadataType ComptBoxDataType = {
  1798. TCL_OO_METADATA_VERSION_CURRENT,
  1799. "ComptBox",
  1800. NULL,
  1801. NULL
  1802. };
  1803. #define GETCOMPTBOX(OBJCONTEXT) (ComptBox *) Tcl_ObjectGetMetadata(OBJCONTEXT,&ComptBoxDataType)
  1804. const static Tcl_ObjectMetadataType WallsetDataType = {
  1805. TCL_OO_METADATA_VERSION_CURRENT,
  1806. "Wallset",
  1807. Wallset_Delete,
  1808. Wallset_Clone
  1809. };
  1810. #define GETWALLSET(OBJCONTEXT) (Wallset *) Tcl_ObjectGetMetadata(OBJCONTEXT,&WallsetDataType)
  1811. const static Tcl_MethodType OOMethodType_Wallset_atvertex = {
  1812. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1813. .name = "atvertex",
  1814. .callProc = OOMethod_Wallset_atvertex,
  1815. .deleteProc = NULL,
  1816. .cloneProc = NULL
  1817. };
  1818. const static Tcl_MethodType OOMethodType_Wallset_boundary = {
  1819. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1820. .name = "boundary",
  1821. .callProc = OOMethod_Wallset_boundary,
  1822. .deleteProc = NULL,
  1823. .cloneProc = NULL
  1824. };
  1825. const static Tcl_MethodType OOMethodType_Wallset_closure = {
  1826. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1827. .name = "closure",
  1828. .callProc = OOMethod_Wallset_closure,
  1829. .deleteProc = NULL,
  1830. .cloneProc = NULL
  1831. };
  1832. const static Tcl_MethodType OOMethodType_Wallset_closure_polygon = {
  1833. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1834. .name = "closure_polygon",
  1835. .callProc = OOMethod_Wallset_closure_polygon,
  1836. .deleteProc = NULL,
  1837. .cloneProc = NULL
  1838. };
  1839. const static Tcl_MethodType OOMethodType_Wallset_closure_check = {
  1840. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1841. .name = "closure_check",
  1842. .callProc = OOMethod_Wallset_closure_check,
  1843. .deleteProc = NULL,
  1844. .cloneProc = NULL
  1845. };
  1846. const static Tcl_MethodType OOMethodType_Wallset_comptlist = {
  1847. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1848. .name = "comptlist",
  1849. .callProc = OOMethod_Wallset_comptlist,
  1850. .deleteProc = NULL,
  1851. .cloneProc = NULL
  1852. };
  1853. const static Tcl_MethodType OOMethodType_Wallset_corners = {
  1854. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1855. .name = "corners",
  1856. .callProc = OOMethod_Wallset_corners,
  1857. .deleteProc = NULL,
  1858. .cloneProc = NULL
  1859. };
  1860. const static Tcl_MethodType OOMethodType_Wallset_delete = {
  1861. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1862. .name = "delete",
  1863. .callProc = OOMethod_Wallset_delete,
  1864. .deleteProc = NULL,
  1865. .cloneProc = NULL
  1866. };
  1867. const static Tcl_MethodType OOMethodType_Wallset_firstboundary = {
  1868. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1869. .name = "firstboundary",
  1870. .callProc = OOMethod_Wallset_firstboundary,
  1871. .deleteProc = NULL,
  1872. .cloneProc = NULL
  1873. };
  1874. const static Tcl_MethodType OOMethodType_Wallset_foreach = {
  1875. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1876. .name = "foreach",
  1877. .callProc = OOMethod_Wallset_foreach,
  1878. .deleteProc = NULL,
  1879. .cloneProc = NULL
  1880. };
  1881. const static Tcl_MethodType OOMethodType_Wallset_info = {
  1882. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1883. .name = "info",
  1884. .callProc = OOMethod_Wallset_info,
  1885. .deleteProc = NULL,
  1886. .cloneProc = NULL
  1887. };
  1888. const static Tcl_MethodType OOMethodType_Wallset_rawinfo = {
  1889. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1890. .name = "rawinfo",
  1891. .callProc = OOMethod_Wallset_rawinfo,
  1892. .deleteProc = NULL,
  1893. .cloneProc = NULL
  1894. };
  1895. const static Tcl_MethodType OOMethodType_Wallset_insert = {
  1896. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1897. .name = "insert",
  1898. .callProc = OOMethod_Wallset_insert,
  1899. .deleteProc = NULL,
  1900. .cloneProc = NULL
  1901. };
  1902. const static Tcl_MethodType OOMethodType_Wallset_primary = {
  1903. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1904. .name = "primary",
  1905. .callProc = OOMethod_Wallset_primary,
  1906. .deleteProc = NULL,
  1907. .cloneProc = NULL
  1908. };
  1909. const static Tcl_MethodType OOMethodType_Wallset_intersect = {
  1910. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1911. .name = "intersect",
  1912. .callProc = OOMethod_Wallset_intersect,
  1913. .deleteProc = NULL,
  1914. .cloneProc = NULL
  1915. };
  1916. const static Tcl_MethodType OOMethodType_Wallset_left = {
  1917. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1918. .name = "left",
  1919. .callProc = OOMethod_Wallset_left,
  1920. .deleteProc = NULL,
  1921. .cloneProc = NULL
  1922. };
  1923. const static Tcl_MethodType OOMethodType_Wallset_list = {
  1924. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1925. .name = "list",
  1926. .callProc = OOMethod_Wallset_list,
  1927. .deleteProc = NULL,
  1928. .cloneProc = NULL
  1929. };
  1930. const static Tcl_MethodType OOMethodType_Wallset_looseends = {
  1931. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1932. .name = "looseends",
  1933. .callProc = OOMethod_Wallset_looseends,
  1934. .deleteProc = NULL,
  1935. .cloneProc = NULL
  1936. };
  1937. const static Tcl_MethodType OOMethodType_Wallset_nearest = {
  1938. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1939. .name = "nearest",
  1940. .callProc = OOMethod_Wallset_nearest,
  1941. .deleteProc = NULL,
  1942. .cloneProc = NULL
  1943. };
  1944. const static Tcl_MethodType OOMethodType_Wallset_nextcwwall = {
  1945. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1946. .name = "nextcwwall",
  1947. .callProc = OOMethod_Wallset_nextcwwall,
  1948. .deleteProc = NULL,
  1949. .cloneProc = NULL
  1950. };
  1951. const static Tcl_MethodType OOMethodType_Wallset_right = {
  1952. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1953. .name = "right",
  1954. .callProc = OOMethod_Wallset_right,
  1955. .deleteProc = NULL,
  1956. .cloneProc = NULL
  1957. };
  1958. const static Tcl_MethodType OOMethodType_Wallset_selfcheck = {
  1959. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1960. .name = "selfcheck",
  1961. .callProc = OOMethod_Wallset_selfcheck,
  1962. .deleteProc = NULL,
  1963. .cloneProc = NULL
  1964. };
  1965. const static Tcl_MethodType OOMethodType_Wallset_zoom = {
  1966. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1967. .name = "zoom",
  1968. .callProc = OOMethod_Wallset_zoom,
  1969. .deleteProc = NULL,
  1970. .cloneProc = NULL
  1971. };
  1972. const static Tcl_MethodType OOMethodType_Wallset_constructor = {
  1973. .version = TCL_OO_METADATA_VERSION_CURRENT,
  1974. .name = "constructor",
  1975. .callProc = OOMethod_Wallset_constructor,
  1976. .deleteProc = NULL,
  1977. .cloneProc = NULL
  1978. };
  1979. const static Tcl_ObjectMetadataType PolygonHullVertexDataType = {
  1980. TCL_OO_METADATA_VERSION_CURRENT,
  1981. "PolygonHullVertex",
  1982. NULL,
  1983. NULL
  1984. };
  1985. #define GETPOLYGONHULLVERTEX(OBJCONTEXT) (PolygonHullVertex *) Tcl_ObjectGetMetadata(OBJCONTEXT,&PolygonHullVertexDataType)
  1986. const static Tcl_ObjectMetadataType PolygonHullFaceDataType = {
  1987. TCL_OO_METADATA_VERSION_CURRENT,
  1988. "PolygonHullFace",
  1989. NULL,
  1990. NULL
  1991. };
  1992. #define GETPOLYGONHULLFACE(OBJCONTEXT) (PolygonHullFace *) Tcl_ObjectGetMetadata(OBJCONTEXT,&PolygonHullFaceDataType)
  1993. const static Tcl_ObjectMetadataType PolygonHullVolumeDataType = {
  1994. TCL_OO_METADATA_VERSION_CURRENT,
  1995. "PolygonHullVolume",
  1996. NULL,
  1997. NULL
  1998. };
  1999. #define GETPOLYGONHULLVOLUME(OBJCONTEXT) (PolygonHullVolume *) Tcl_ObjectGetMetadata(OBJCONTEXT,&PolygonHullVolumeDataType)
  2000. const static Tcl_ObjectMetadataType PolygonHullDataType = {
  2001. TCL_OO_METADATA_VERSION_CURRENT,
  2002. "PolygonHull",
  2003. PolygonHull_Delete,
  2004. PolygonHull_Clone
  2005. };
  2006. #define GETPOLYGONHULL(OBJCONTEXT) (PolygonHull *) Tcl_ObjectGetMetadata(OBJCONTEXT,&PolygonHullDataType)
  2007. const static Tcl_MethodType OOMethodType_PolygonHull_vertex_create = {
  2008. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2009. .name = "vertex_create",
  2010. .callProc = OOMethod_PolygonHull_vertex_create,
  2011. .deleteProc = NULL,
  2012. .cloneProc = NULL
  2013. };
  2014. const static Tcl_MethodType OOMethodType_PolygonHull_vertex_coords = {
  2015. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2016. .name = "vertex_coords",
  2017. .callProc = OOMethod_PolygonHull_vertex_coords,
  2018. .deleteProc = NULL,
  2019. .cloneProc = NULL
  2020. };
  2021. const static Tcl_MethodType OOMethodType_PolygonHull_vertex_delete = {
  2022. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2023. .name = "vertex_delete",
  2024. .callProc = OOMethod_PolygonHull_vertex_delete,
  2025. .deleteProc = NULL,
  2026. .cloneProc = NULL
  2027. };
  2028. const static Tcl_MethodType OOMethodType_PolygonHull_vertex_idlist = {
  2029. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2030. .name = "vertex_idlist",
  2031. .callProc = OOMethod_PolygonHull_vertex_idlist,
  2032. .deleteProc = NULL,
  2033. .cloneProc = NULL
  2034. };
  2035. const static Tcl_MethodType OOMethodType_PolygonHull_vertex_inject = {
  2036. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2037. .name = "vertex_inject",
  2038. .callProc = OOMethod_PolygonHull_vertex_inject,
  2039. .deleteProc = NULL,
  2040. .cloneProc = NULL
  2041. };
  2042. const static Tcl_MethodType OOMethodType_PolygonHull_vertex_list = {
  2043. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2044. .name = "vertex_list",
  2045. .callProc = OOMethod_PolygonHull_vertex_list,
  2046. .deleteProc = NULL,
  2047. .cloneProc = NULL
  2048. };
  2049. const static Tcl_MethodType OOMethodType_PolygonHull_vertex_at = {
  2050. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2051. .name = "vertex_at",
  2052. .callProc = OOMethod_PolygonHull_vertex_at,
  2053. .deleteProc = NULL,
  2054. .cloneProc = NULL
  2055. };
  2056. const static Tcl_MethodType OOMethodType_PolygonHull_face_info = {
  2057. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2058. .name = "face_info",
  2059. .callProc = OOMethod_PolygonHull_face_info,
  2060. .deleteProc = NULL,
  2061. .cloneProc = NULL
  2062. };
  2063. const static Tcl_MethodType OOMethodType_PolygonHull_face_exists = {
  2064. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2065. .name = "face_exists",
  2066. .callProc = OOMethod_PolygonHull_face_exists,
  2067. .deleteProc = NULL,
  2068. .cloneProc = NULL
  2069. };
  2070. const static Tcl_MethodType OOMethodType_PolygonHull_face_active = {
  2071. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2072. .name = "face_active",
  2073. .callProc = OOMethod_PolygonHull_face_active,
  2074. .deleteProc = NULL,
  2075. .cloneProc = NULL
  2076. };
  2077. const static Tcl_MethodType OOMethodType_PolygonHull_face_center = {
  2078. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2079. .name = "face_center",
  2080. .callProc = OOMethod_PolygonHull_face_center,
  2081. .deleteProc = NULL,
  2082. .cloneProc = NULL
  2083. };
  2084. const static Tcl_MethodType OOMethodType_PolygonHull_face_polygon = {
  2085. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2086. .name = "face_polygon",
  2087. .callProc = OOMethod_PolygonHull_face_polygon,
  2088. .deleteProc = NULL,
  2089. .cloneProc = NULL
  2090. };
  2091. const static Tcl_MethodType OOMethodType_PolygonHull_face_vertices = {
  2092. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2093. .name = "face_vertices",
  2094. .callProc = OOMethod_PolygonHull_face_vertices,
  2095. .deleteProc = NULL,
  2096. .cloneProc = NULL
  2097. };
  2098. const static Tcl_MethodType OOMethodType_PolygonHull_face_create = {
  2099. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2100. .name = "face_create",
  2101. .callProc = OOMethod_PolygonHull_face_create,
  2102. .deleteProc = NULL,
  2103. .cloneProc = NULL
  2104. };
  2105. const static Tcl_MethodType OOMethodType_PolygonHull_face_delete = {
  2106. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2107. .name = "face_delete",
  2108. .callProc = OOMethod_PolygonHull_face_delete,
  2109. .deleteProc = NULL,
  2110. .cloneProc = NULL
  2111. };
  2112. const static Tcl_MethodType OOMethodType_PolygonHull_face_intersect = {
  2113. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2114. .name = "face_intersect",
  2115. .callProc = OOMethod_PolygonHull_face_intersect,
  2116. .deleteProc = NULL,
  2117. .cloneProc = NULL
  2118. };
  2119. const static Tcl_MethodType OOMethodType_PolygonHull_face_list = {
  2120. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2121. .name = "face_list",
  2122. .callProc = OOMethod_PolygonHull_face_list,
  2123. .deleteProc = NULL,
  2124. .cloneProc = NULL
  2125. };
  2126. const static Tcl_MethodType OOMethodType_PolygonHull_face_nearest = {
  2127. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2128. .name = "face_nearest",
  2129. .callProc = OOMethod_PolygonHull_face_nearest,
  2130. .deleteProc = NULL,
  2131. .cloneProc = NULL
  2132. };
  2133. const static Tcl_MethodType OOMethodType_PolygonHull_face_radius = {
  2134. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2135. .name = "face_radius",
  2136. .callProc = OOMethod_PolygonHull_face_radius,
  2137. .deleteProc = NULL,
  2138. .cloneProc = NULL
  2139. };
  2140. const static Tcl_MethodType OOMethodType_PolygonHull_face_normal = {
  2141. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2142. .name = "face_normal",
  2143. .callProc = OOMethod_PolygonHull_face_normal,
  2144. .deleteProc = NULL,
  2145. .cloneProc = NULL
  2146. };
  2147. const static Tcl_MethodType OOMethodType_PolygonHull_face_side = {
  2148. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2149. .name = "face_side",
  2150. .callProc = OOMethod_PolygonHull_face_side,
  2151. .deleteProc = NULL,
  2152. .cloneProc = NULL
  2153. };
  2154. const static Tcl_MethodType OOMethodType_PolygonHull_face_volume = {
  2155. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2156. .name = "face_volume",
  2157. .callProc = OOMethod_PolygonHull_face_volume,
  2158. .deleteProc = NULL,
  2159. .cloneProc = NULL
  2160. };
  2161. const static Tcl_MethodType OOMethodType_PolygonHull_faces_at = {
  2162. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2163. .name = "faces_at",
  2164. .callProc = OOMethod_PolygonHull_faces_at,
  2165. .deleteProc = NULL,
  2166. .cloneProc = NULL
  2167. };
  2168. const static Tcl_MethodType OOMethodType_PolygonHull_face_within = {
  2169. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2170. .name = "face_within",
  2171. .callProc = OOMethod_PolygonHull_face_within,
  2172. .deleteProc = NULL,
  2173. .cloneProc = NULL
  2174. };
  2175. const static Tcl_MethodType OOMethodType_PolygonHull_volume_create = {
  2176. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2177. .name = "volume_create",
  2178. .callProc = OOMethod_PolygonHull_volume_create,
  2179. .deleteProc = NULL,
  2180. .cloneProc = NULL
  2181. };
  2182. const static Tcl_MethodType OOMethodType_PolygonHull_volume_delete = {
  2183. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2184. .name = "volume_delete",
  2185. .callProc = OOMethod_PolygonHull_volume_delete,
  2186. .deleteProc = NULL,
  2187. .cloneProc = NULL
  2188. };
  2189. const static Tcl_MethodType OOMethodType_PolygonHull_volume_list = {
  2190. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2191. .name = "volume_list",
  2192. .callProc = OOMethod_PolygonHull_volume_list,
  2193. .deleteProc = NULL,
  2194. .cloneProc = NULL
  2195. };
  2196. const static Tcl_MethodType OOMethodType_PolygonHull_volume_faces = {
  2197. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2198. .name = "volume_faces",
  2199. .callProc = OOMethod_PolygonHull_volume_faces,
  2200. .deleteProc = NULL,
  2201. .cloneProc = NULL
  2202. };
  2203. const static Tcl_MethodType OOMethodType_PolygonHull_volume_group = {
  2204. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2205. .name = "volume_group",
  2206. .callProc = OOMethod_PolygonHull_volume_group,
  2207. .deleteProc = NULL,
  2208. .cloneProc = NULL
  2209. };
  2210. const static Tcl_MethodType OOMethodType_PolygonHull_volume_center = {
  2211. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2212. .name = "volume_center",
  2213. .callProc = OOMethod_PolygonHull_volume_center,
  2214. .deleteProc = NULL,
  2215. .cloneProc = NULL
  2216. };
  2217. const static Tcl_MethodType OOMethodType_PolygonHull_reset = {
  2218. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2219. .name = "reset",
  2220. .callProc = OOMethod_PolygonHull_reset,
  2221. .deleteProc = NULL,
  2222. .cloneProc = NULL
  2223. };
  2224. const static Tcl_MethodType OOMethodType_PolygonHull_PolygonHull_Init = {
  2225. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2226. .name = "PolygonHull_Init",
  2227. .callProc = OOMethod_PolygonHull_PolygonHull_Init,
  2228. .deleteProc = NULL,
  2229. .cloneProc = NULL
  2230. };
  2231. const static Tcl_ObjectMetadataType Odie_ObjDataType = {
  2232. TCL_OO_METADATA_VERSION_CURRENT,
  2233. "Odie_Obj",
  2234. NULL,
  2235. NULL
  2236. };
  2237. #define GETODIE_OBJ(OBJCONTEXT) (Odie_Obj *) Tcl_ObjectGetMetadata(OBJCONTEXT,&Odie_ObjDataType)
  2238. const static Tcl_ObjectMetadataType entityObjDataType = {
  2239. TCL_OO_METADATA_VERSION_CURRENT,
  2240. "entityObj",
  2241. NULL,
  2242. NULL
  2243. };
  2244. #define GETENTITYOBJ(OBJCONTEXT) (entityObj *) Tcl_ObjectGetMetadata(OBJCONTEXT,&entityObjDataType)
  2245. const static Tcl_ObjectMetadataType OdieParamNameMapDataType = {
  2246. TCL_OO_METADATA_VERSION_CURRENT,
  2247. "OdieParamNameMap",
  2248. NULL,
  2249. NULL
  2250. };
  2251. #define GETODIEPARAMNAMEMAP(OBJCONTEXT) (OdieParamNameMap *) Tcl_ObjectGetMetadata(OBJCONTEXT,&OdieParamNameMapDataType)
  2252. const static Tcl_ObjectMetadataType Irm_LocationDataType = {
  2253. TCL_OO_METADATA_VERSION_CURRENT,
  2254. "Irm_Location",
  2255. NULL,
  2256. NULL
  2257. };
  2258. #define GETIRM_LOCATION(OBJCONTEXT) (Irm_Location *) Tcl_ObjectGetMetadata(OBJCONTEXT,&Irm_LocationDataType)
  2259. const static Tcl_ObjectMetadataType SimulatorDataType = {
  2260. TCL_OO_METADATA_VERSION_CURRENT,
  2261. "Simulator",
  2262. NULL,
  2263. NULL
  2264. };
  2265. #define GETSIMULATOR(OBJCONTEXT) (Simulator *) Tcl_ObjectGetMetadata(OBJCONTEXT,&SimulatorDataType)
  2266. const static Tcl_MethodType OOMethodType_Simulator_C_Init = {
  2267. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2268. .name = "C_Init",
  2269. .callProc = OOMethod_Simulator_C_Init,
  2270. .deleteProc = NULL,
  2271. .cloneProc = NULL
  2272. };
  2273. const static Tcl_ObjectMetadataType EntityDataType = {
  2274. TCL_OO_METADATA_VERSION_CURRENT,
  2275. "Entity",
  2276. NULL,
  2277. NULL
  2278. };
  2279. #define GETENTITY(OBJCONTEXT) (Entity *) Tcl_ObjectGetMetadata(OBJCONTEXT,&EntityDataType)
  2280. const static Tcl_MethodType OOMethodType_OOEntity_C_Init = {
  2281. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2282. .name = "C_Init",
  2283. .callProc = OOMethod_OOEntity_C_Init,
  2284. .deleteProc = NULL,
  2285. .cloneProc = NULL
  2286. };
  2287. const static Tcl_MethodType OOMethodType_OOEntity_create = {
  2288. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2289. .name = "create",
  2290. .callProc = OOMethod_OOEntity_create,
  2291. .deleteProc = NULL,
  2292. .cloneProc = NULL
  2293. };
  2294. const static Tcl_MethodType OOMethodType_OOEntity_attach_to = {
  2295. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2296. .name = "attach_to",
  2297. .callProc = OOMethod_OOEntity_attach_to,
  2298. .deleteProc = NULL,
  2299. .cloneProc = NULL
  2300. };
  2301. const static Tcl_MethodType OOMethodType_OOEntity_compartment = {
  2302. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2303. .name = "compartment",
  2304. .callProc = OOMethod_OOEntity_compartment,
  2305. .deleteProc = NULL,
  2306. .cloneProc = NULL
  2307. };
  2308. const static Tcl_MethodType OOMethodType_OOEntity_comptid = {
  2309. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2310. .name = "comptid",
  2311. .callProc = OOMethod_OOEntity_comptid,
  2312. .deleteProc = NULL,
  2313. .cloneProc = NULL
  2314. };
  2315. const static Tcl_MethodType OOMethodType_OOEntity_count = {
  2316. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2317. .name = "count",
  2318. .callProc = OOMethod_OOEntity_count,
  2319. .deleteProc = NULL,
  2320. .cloneProc = NULL
  2321. };
  2322. const static Tcl_MethodType OOMethodType_OOEntity_deckid = {
  2323. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2324. .name = "deckid",
  2325. .callProc = OOMethod_OOEntity_deckid,
  2326. .deleteProc = NULL,
  2327. .cloneProc = NULL
  2328. };
  2329. const static Tcl_MethodType OOMethodType_OOEntity_delete = {
  2330. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2331. .name = "delete",
  2332. .callProc = OOMethod_OOEntity_delete,
  2333. .deleteProc = NULL,
  2334. .cloneProc = NULL
  2335. };
  2336. const static Tcl_MethodType OOMethodType_OOEntity_drawn_reset = {
  2337. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2338. .name = "drawn_reset",
  2339. .callProc = OOMethod_OOEntity_drawn_reset,
  2340. .deleteProc = NULL,
  2341. .cloneProc = NULL
  2342. };
  2343. const static Tcl_MethodType OOMethodType_OOEntity_exists = {
  2344. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2345. .name = "exists",
  2346. .callProc = OOMethod_OOEntity_exists,
  2347. .deleteProc = NULL,
  2348. .cloneProc = NULL
  2349. };
  2350. const static Tcl_MethodType OOMethodType_OOEntity_for = {
  2351. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2352. .name = "for",
  2353. .callProc = OOMethod_OOEntity_for,
  2354. .deleteProc = NULL,
  2355. .cloneProc = NULL
  2356. };
  2357. const static Tcl_MethodType OOMethodType_OOEntity_foreach = {
  2358. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2359. .name = "foreach",
  2360. .callProc = OOMethod_OOEntity_foreach,
  2361. .deleteProc = NULL,
  2362. .cloneProc = NULL
  2363. };
  2364. const static Tcl_MethodType OOMethodType_OOEntity_groupid = {
  2365. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2366. .name = "groupid",
  2367. .callProc = OOMethod_OOEntity_groupid,
  2368. .deleteProc = NULL,
  2369. .cloneProc = NULL
  2370. };
  2371. const static Tcl_MethodType OOMethodType_OOEntity_groups_recalculate = {
  2372. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2373. .name = "groups_recalculate",
  2374. .callProc = OOMethod_OOEntity_groups_recalculate,
  2375. .deleteProc = NULL,
  2376. .cloneProc = NULL
  2377. };
  2378. const static Tcl_MethodType OOMethodType_OOEntity_hidden_inherit = {
  2379. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2380. .name = "hidden_inherit",
  2381. .callProc = OOMethod_OOEntity_hidden_inherit,
  2382. .deleteProc = NULL,
  2383. .cloneProc = NULL
  2384. };
  2385. const static Tcl_MethodType OOMethodType_OOEntity_list = {
  2386. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2387. .name = "list",
  2388. .callProc = OOMethod_OOEntity_list,
  2389. .deleteProc = NULL,
  2390. .cloneProc = NULL
  2391. };
  2392. const static Tcl_MethodType OOMethodType_OOEntity_location = {
  2393. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2394. .name = "location",
  2395. .callProc = OOMethod_OOEntity_location,
  2396. .deleteProc = NULL,
  2397. .cloneProc = NULL
  2398. };
  2399. const static Tcl_MethodType OOMethodType_OOEntity_midpoint = {
  2400. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2401. .name = "midpoint",
  2402. .callProc = OOMethod_OOEntity_midpoint,
  2403. .deleteProc = NULL,
  2404. .cloneProc = NULL
  2405. };
  2406. const static Tcl_MethodType OOMethodType_OOEntity_nodeget = {
  2407. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2408. .name = "nodeget",
  2409. .callProc = OOMethod_OOEntity_nodeget,
  2410. .deleteProc = NULL,
  2411. .cloneProc = NULL
  2412. };
  2413. const static Tcl_MethodType OOMethodType_OOEntity_nodeput = {
  2414. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2415. .name = "nodeput",
  2416. .callProc = OOMethod_OOEntity_nodeput,
  2417. .deleteProc = NULL,
  2418. .cloneProc = NULL
  2419. };
  2420. const static Tcl_MethodType OOMethodType_OOEntity_nodewith = {
  2421. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2422. .name = "nodewith",
  2423. .callProc = OOMethod_OOEntity_nodewith,
  2424. .deleteProc = NULL,
  2425. .cloneProc = NULL
  2426. };
  2427. const static Tcl_MethodType OOMethodType_OOEntity_normalize = {
  2428. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2429. .name = "normalize",
  2430. .callProc = OOMethod_OOEntity_normalize,
  2431. .deleteProc = NULL,
  2432. .cloneProc = NULL
  2433. };
  2434. const static Tcl_MethodType OOMethodType_OOEntity_orientation = {
  2435. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2436. .name = "orientation",
  2437. .callProc = OOMethod_OOEntity_orientation,
  2438. .deleteProc = NULL,
  2439. .cloneProc = NULL
  2440. };
  2441. const static Tcl_MethodType OOMethodType_OOEntity_redraw = {
  2442. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2443. .name = "redraw",
  2444. .callProc = OOMethod_OOEntity_redraw,
  2445. .deleteProc = NULL,
  2446. .cloneProc = NULL
  2447. };
  2448. const static Tcl_MethodType OOMethodType_OOEntity_reset = {
  2449. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2450. .name = "reset",
  2451. .callProc = OOMethod_OOEntity_reset,
  2452. .deleteProc = NULL,
  2453. .cloneProc = NULL
  2454. };
  2455. const static Tcl_MethodType OOMethodType_OOEntity_setting = {
  2456. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2457. .name = "setting",
  2458. .callProc = OOMethod_OOEntity_setting,
  2459. .deleteProc = NULL,
  2460. .cloneProc = NULL
  2461. };
  2462. const static Tcl_MethodType OOMethodType_OOEntity_spec_get = {
  2463. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2464. .name = "spec_get",
  2465. .callProc = OOMethod_OOEntity_spec_get,
  2466. .deleteProc = NULL,
  2467. .cloneProc = NULL
  2468. };
  2469. const static Tcl_MethodType OOMethodType_OOEntity_spec_put = {
  2470. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2471. .name = "spec_put",
  2472. .callProc = OOMethod_OOEntity_spec_put,
  2473. .deleteProc = NULL,
  2474. .cloneProc = NULL
  2475. };
  2476. const static Tcl_MethodType OOMethodType_OOEntity_spec_replace = {
  2477. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2478. .name = "spec_replace",
  2479. .callProc = OOMethod_OOEntity_spec_replace,
  2480. .deleteProc = NULL,
  2481. .cloneProc = NULL
  2482. };
  2483. const static Tcl_MethodType OOMethodType_OOEntity_struct_get = {
  2484. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2485. .name = "struct_get",
  2486. .callProc = OOMethod_OOEntity_struct_get,
  2487. .deleteProc = NULL,
  2488. .cloneProc = NULL
  2489. };
  2490. const static Tcl_MethodType OOMethodType_OOEntity_struct_put = {
  2491. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2492. .name = "struct_put",
  2493. .callProc = OOMethod_OOEntity_struct_put,
  2494. .deleteProc = NULL,
  2495. .cloneProc = NULL
  2496. };
  2497. const static Tcl_MethodType OOMethodType_OOEntity_type = {
  2498. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2499. .name = "type",
  2500. .callProc = OOMethod_OOEntity_type,
  2501. .deleteProc = NULL,
  2502. .cloneProc = NULL
  2503. };
  2504. const static Tcl_MethodType OOMethodType_OOEntity_typeid = {
  2505. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2506. .name = "typeid",
  2507. .callProc = OOMethod_OOEntity_typeid,
  2508. .deleteProc = NULL,
  2509. .cloneProc = NULL
  2510. };
  2511. const static Tcl_MethodType OOMethodType_OOEntity_visible = {
  2512. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2513. .name = "visible",
  2514. .callProc = OOMethod_OOEntity_visible,
  2515. .deleteProc = NULL,
  2516. .cloneProc = NULL
  2517. };
  2518. const static Tcl_MethodType OOMethodType_OOEntity_visible_filter = {
  2519. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2520. .name = "visible_filter",
  2521. .callProc = OOMethod_OOEntity_visible_filter,
  2522. .deleteProc = NULL,
  2523. .cloneProc = NULL
  2524. };
  2525. const static Tcl_MethodType OOMethodType_OOEntity_visible_hidden_subtract = {
  2526. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2527. .name = "visible_hidden_subtract",
  2528. .callProc = OOMethod_OOEntity_visible_hidden_subtract,
  2529. .deleteProc = NULL,
  2530. .cloneProc = NULL
  2531. };
  2532. const static Tcl_MethodType OOMethodType_OOEntity_visible_inherit = {
  2533. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2534. .name = "visible_inherit",
  2535. .callProc = OOMethod_OOEntity_visible_inherit,
  2536. .deleteProc = NULL,
  2537. .cloneProc = NULL
  2538. };
  2539. const static Tcl_MethodType OOMethodType_OOEntity_visible_reset = {
  2540. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2541. .name = "visible_reset",
  2542. .callProc = OOMethod_OOEntity_visible_reset,
  2543. .deleteProc = NULL,
  2544. .cloneProc = NULL
  2545. };
  2546. const static Tcl_MethodType OOMethodType_OOEntity_visible_tree = {
  2547. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2548. .name = "visible_tree",
  2549. .callProc = OOMethod_OOEntity_visible_tree,
  2550. .deleteProc = NULL,
  2551. .cloneProc = NULL
  2552. };
  2553. const static Tcl_MethodType OOMethodType_OOEntity_witheach = {
  2554. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2555. .name = "witheach",
  2556. .callProc = OOMethod_OOEntity_witheach,
  2557. .deleteProc = NULL,
  2558. .cloneProc = NULL
  2559. };
  2560. const static Tcl_MethodType OOMethodType_SimType_C_Init = {
  2561. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2562. .name = "C_Init",
  2563. .callProc = OOMethod_SimType_C_Init,
  2564. .deleteProc = NULL,
  2565. .cloneProc = NULL
  2566. };
  2567. const static Tcl_MethodType OOMethodType_SimType_children = {
  2568. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2569. .name = "children",
  2570. .callProc = OOMethod_SimType_children,
  2571. .deleteProc = NULL,
  2572. .cloneProc = NULL
  2573. };
  2574. const static Tcl_MethodType OOMethodType_SimType_count = {
  2575. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2576. .name = "count",
  2577. .callProc = OOMethod_SimType_count,
  2578. .deleteProc = NULL,
  2579. .cloneProc = NULL
  2580. };
  2581. const static Tcl_MethodType OOMethodType_SimType_create = {
  2582. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2583. .name = "create",
  2584. .callProc = OOMethod_SimType_create,
  2585. .deleteProc = NULL,
  2586. .cloneProc = NULL
  2587. };
  2588. const static Tcl_MethodType OOMethodType_SimType_delete = {
  2589. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2590. .name = "delete",
  2591. .callProc = OOMethod_SimType_delete,
  2592. .deleteProc = NULL,
  2593. .cloneProc = NULL
  2594. };
  2595. const static Tcl_MethodType OOMethodType_SimType_exists = {
  2596. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2597. .name = "exists",
  2598. .callProc = OOMethod_SimType_exists,
  2599. .deleteProc = NULL,
  2600. .cloneProc = NULL
  2601. };
  2602. const static Tcl_MethodType OOMethodType_SimType_for = {
  2603. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2604. .name = "for",
  2605. .callProc = OOMethod_SimType_for,
  2606. .deleteProc = NULL,
  2607. .cloneProc = NULL
  2608. };
  2609. const static Tcl_MethodType OOMethodType_SimType_foreach = {
  2610. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2611. .name = "foreach",
  2612. .callProc = OOMethod_SimType_foreach,
  2613. .deleteProc = NULL,
  2614. .cloneProc = NULL
  2615. };
  2616. const static Tcl_MethodType OOMethodType_SimType_groupid = {
  2617. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2618. .name = "groupid",
  2619. .callProc = OOMethod_SimType_groupid,
  2620. .deleteProc = NULL,
  2621. .cloneProc = NULL
  2622. };
  2623. const static Tcl_MethodType OOMethodType_SimType_list = {
  2624. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2625. .name = "list",
  2626. .callProc = OOMethod_SimType_list,
  2627. .deleteProc = NULL,
  2628. .cloneProc = NULL
  2629. };
  2630. const static Tcl_MethodType OOMethodType_SimType_nodeget = {
  2631. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2632. .name = "nodeget",
  2633. .callProc = OOMethod_SimType_nodeget,
  2634. .deleteProc = NULL,
  2635. .cloneProc = NULL
  2636. };
  2637. const static Tcl_MethodType OOMethodType_SimType_nodeput = {
  2638. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2639. .name = "nodeput",
  2640. .callProc = OOMethod_SimType_nodeput,
  2641. .deleteProc = NULL,
  2642. .cloneProc = NULL
  2643. };
  2644. const static Tcl_MethodType OOMethodType_SimType_nodewith = {
  2645. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2646. .name = "nodewith",
  2647. .callProc = OOMethod_SimType_nodewith,
  2648. .deleteProc = NULL,
  2649. .cloneProc = NULL
  2650. };
  2651. const static Tcl_MethodType OOMethodType_SimType_normalize = {
  2652. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2653. .name = "normalize",
  2654. .callProc = OOMethod_SimType_normalize,
  2655. .deleteProc = NULL,
  2656. .cloneProc = NULL
  2657. };
  2658. const static Tcl_MethodType OOMethodType_SimType_parent = {
  2659. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2660. .name = "parent",
  2661. .callProc = OOMethod_SimType_parent,
  2662. .deleteProc = NULL,
  2663. .cloneProc = NULL
  2664. };
  2665. const static Tcl_MethodType OOMethodType_SimType_setting = {
  2666. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2667. .name = "setting",
  2668. .callProc = OOMethod_SimType_setting,
  2669. .deleteProc = NULL,
  2670. .cloneProc = NULL
  2671. };
  2672. const static Tcl_MethodType OOMethodType_SimType_spec_get = {
  2673. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2674. .name = "spec_get",
  2675. .callProc = OOMethod_SimType_spec_get,
  2676. .deleteProc = NULL,
  2677. .cloneProc = NULL
  2678. };
  2679. const static Tcl_MethodType OOMethodType_SimType_spec_put = {
  2680. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2681. .name = "spec_put",
  2682. .callProc = OOMethod_SimType_spec_put,
  2683. .deleteProc = NULL,
  2684. .cloneProc = NULL
  2685. };
  2686. const static Tcl_MethodType OOMethodType_SimType_spec_replace = {
  2687. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2688. .name = "spec_replace",
  2689. .callProc = OOMethod_SimType_spec_replace,
  2690. .deleteProc = NULL,
  2691. .cloneProc = NULL
  2692. };
  2693. const static Tcl_MethodType OOMethodType_SimType_struct_get = {
  2694. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2695. .name = "struct_get",
  2696. .callProc = OOMethod_SimType_struct_get,
  2697. .deleteProc = NULL,
  2698. .cloneProc = NULL
  2699. };
  2700. const static Tcl_MethodType OOMethodType_SimType_struct_put = {
  2701. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2702. .name = "struct_put",
  2703. .callProc = OOMethod_SimType_struct_put,
  2704. .deleteProc = NULL,
  2705. .cloneProc = NULL
  2706. };
  2707. const static Tcl_MethodType OOMethodType_SimType_type = {
  2708. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2709. .name = "type",
  2710. .callProc = OOMethod_SimType_type,
  2711. .deleteProc = NULL,
  2712. .cloneProc = NULL
  2713. };
  2714. const static Tcl_MethodType OOMethodType_SimType_typeid = {
  2715. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2716. .name = "typeid",
  2717. .callProc = OOMethod_SimType_typeid,
  2718. .deleteProc = NULL,
  2719. .cloneProc = NULL
  2720. };
  2721. const static Tcl_MethodType OOMethodType_SimType_visible_reset = {
  2722. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2723. .name = "visible_reset",
  2724. .callProc = OOMethod_SimType_visible_reset,
  2725. .deleteProc = NULL,
  2726. .cloneProc = NULL
  2727. };
  2728. const static Tcl_MethodType OOMethodType_SimType_witheach = {
  2729. .version = TCL_OO_METADATA_VERSION_CURRENT,
  2730. .name = "witheach",
  2731. .callProc = OOMethod_SimType_witheach,
  2732. .deleteProc = NULL,
  2733. .cloneProc = NULL
  2734. };
  2735. /* END generate-cfile-constant */
  2736. /* BEGIN generate-cfile-functions */
  2737. /* *Odie_Alloc */
  2738. void *Odie_Alloc(unsigned int size){
  2739. /*
  2740. ** Provide wrappers around malloc and free
  2741. */
  2742. void *p;
  2743. p=(void *)ckalloc(size);
  2744. memset(p,0,size);
  2745. return p;
  2746. }
  2747. /*
  2748. ** Hash and comparison functions when the mode is READI_HASH_INT
  2749. */
  2750. static int intHash(const void *pKey, int nKey){
  2751. return nKey ^ (nKey<<8) ^ (nKey>>8);
  2752. }
  2753. static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  2754. return n2 - n1;
  2755. }
  2756.  
  2757. /*
  2758. ** Hash and comparison functions when the mode is READI_HASH_POINTER
  2759. */
  2760. static int ptrHash(const void *pKey, int nKey){
  2761. uptr x = Addr(pKey);
  2762. return x ^ (x<<8) ^ (x>>8);
  2763. }
  2764. static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  2765. if( pKey1==pKey2 ) return 0;
  2766. if( pKey1<pKey2 ) return -1;
  2767. return 1;
  2768. }
  2769.  
  2770. /*
  2771. ** Hash and comparison functions when the mode is READI_HASH_BINARY
  2772. */
  2773. static int binHash(const void *pKey, int nKey){
  2774. int h = 0;
  2775. const char *z = (const char *)pKey;
  2776. while( nKey-- > 0 ){
  2777. h = (h<<3) ^ h ^ *(z++);
  2778. }
  2779. return h & 0x7fffffff;
  2780. }
  2781. static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  2782. if( n1!=n2 ) return n2-n1;
  2783. return memcmp(pKey1,pKey2,n1);
  2784. }
  2785.  
  2786. /*
  2787. ** Return a pointer to the appropriate hash function given the key class.
  2788. **
  2789. ** The C syntax in this function definition may be unfamilar to some
  2790. ** programmers, so we provide the following additional explanation:
  2791. **
  2792. ** The name of the function is "hashFunction". The function takes a
  2793. ** single parameter "keyClass". The return value of hashFunction()
  2794. ** is a pointer to another function. Specifically, the return value
  2795. ** of hashFunction() is a pointer to a function that takes two parameters
  2796. ** with types "const void*" and "int" and returns an "int".
  2797. */
  2798. static int (*hashFunction(int keyClass))(const void*,int){
  2799. switch( keyClass ){
  2800. case READI_HASH_INT: return &intHash;
  2801. case READI_HASH_POINTER: return &ptrHash;
  2802. case READI_HASH_BINARY: return &binHash;;
  2803. default: break;
  2804. }
  2805. return 0;
  2806. }
  2807.  
  2808. /*
  2809. ** Return a pointer to the appropriate hash function given the key class.
  2810. **
  2811. ** For help in interpreted the obscure C code in the function definition,
  2812. ** see the header comment on the previous function.
  2813. */
  2814. static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
  2815. switch( keyClass ){
  2816. case READI_HASH_INT: return &intCompare;
  2817. case READI_HASH_POINTER: return &ptrCompare;
  2818. case READI_HASH_BINARY: return &binCompare;
  2819. default: break;
  2820. }
  2821. return 0;
  2822. }
  2823.  
  2824.  
  2825. /* Resize the hash table so that it cantains "new_size" buckets.
  2826. ** "new_size" must be a power of 2. The hash table might fail
  2827. ** to resize if Odie_Alloc() fails.
  2828. */
  2829. static void rehash(Hash *pH, int new_size){
  2830. struct _ht *new_ht; /* The new hash table */
  2831. HashElem *elem, *next_elem; /* For looping over existing elements */
  2832. HashElem *x; /* Element being copied to new hash table */
  2833. int (*xHash)(const void*,int); /* The hash function */
  2834.  
  2835. assert( (new_size & (new_size-1))==0 );
  2836. new_ht = (struct _ht *)Odie_Alloc( new_size*sizeof(struct _ht) );
  2837. if( new_ht==0 ) return;
  2838. memset(new_ht, 0, new_size*sizeof(struct _ht));
  2839. if( pH->ht ) Odie_Free((char *)pH->ht);
  2840. pH->ht = new_ht;
  2841. pH->htsize = new_size;
  2842. xHash = hashFunction(pH->keyClass);
  2843. for(elem=pH->first, pH->first=0; elem; elem = next_elem){
  2844. int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
  2845. next_elem = elem->next;
  2846. x = new_ht[h].chain;
  2847. if( x ){
  2848. elem->next = x;
  2849. elem->prev = x->prev;
  2850. if( x->prev ) x->prev->next = elem;
  2851. else pH->first = elem;
  2852. x->prev = elem;
  2853. }else{
  2854. elem->next = pH->first;
  2855. if( pH->first ) pH->first->prev = elem;
  2856. elem->prev = 0;
  2857. pH->first = elem;
  2858. }
  2859. new_ht[h].chain = elem;
  2860. new_ht[h].count++;
  2861. }
  2862. }
  2863.  
  2864. /* This function (for internal use only) locates an element in an
  2865. ** hash table that matches the given key. The hash for this key has
  2866. ** already been computed and is passed as the 4th parameter.
  2867. */
  2868. static HashElem *findElementGivenHash(
  2869. const Hash *pH, /* The pH to be searched */
  2870. const void *pKey, /* The key we are searching for */
  2871. int nKey,
  2872. int h /* The hash for this key. */
  2873. ){
  2874. HashElem *elem; /* Used to loop thru the element list */
  2875. int count; /* Number of elements left to test */
  2876. int (*xCompare)(const void*,int,const void*,int); /* comparison function */
  2877.  
  2878. if( pH->ht ){
  2879. elem = pH->ht[h].chain;
  2880. count = pH->ht[h].count;
  2881. xCompare = compareFunction(pH->keyClass);
  2882. while( count-- && elem ){
  2883. if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
  2884. return elem;
  2885. }
  2886. elem = elem->next;
  2887. }
  2888. }
  2889. return 0;
  2890. }
  2891.  
  2892. /* Remove a single entry from the hash table given a pointer to that
  2893. ** element and a hash on the element's key.
  2894. */
  2895. static void removeElementGivenHash(
  2896. Hash *pH, /* The pH containing "elem" */
  2897. HashElem* elem, /* The element to be removed from the pH */
  2898. int h /* Hash value for the element */
  2899. ){
  2900. if( elem->prev ){
  2901. elem->prev->next = elem->next;
  2902. }else{
  2903. pH->first = elem->next;
  2904. }
  2905. if( elem->next ){
  2906. elem->next->prev = elem->prev;
  2907. }
  2908. if( pH->ht[h].chain==elem ){
  2909. pH->ht[h].chain = elem->next;
  2910. }
  2911. pH->ht[h].count--;
  2912. if( pH->ht[h].count<=0 ){
  2913. pH->ht[h].chain = 0;
  2914. }
  2915. if( pH->copyKey && elem->pKey ){
  2916. Odie_Free((char *)elem->pKey);
  2917. }
  2918. Odie_Free((char *) elem );
  2919. pH->count--;
  2920. }
  2921. /* readiHashNoCase */
  2922. int readiHashNoCase(const void *pKey, int nKey){
  2923. const char *z = (const char *)pKey;
  2924. int h = 0;
  2925. if( nKey<=0 ) nKey = strlen(z);
  2926. while( nKey > 0 ){
  2927. h = (h<<3) ^ h ^ tolower(*z++);
  2928. nKey--;
  2929. }
  2930. return h & 0x7fffffff;
  2931. }
  2932. /* readiHashInit */
  2933. void readiHashInit(Hash *new, int keyClass, int copyKey){
  2934.  
  2935. assert( new!=0 );
  2936. assert( keyClass>=READI_HASH_INT && keyClass<=READI_HASH_BINARY );
  2937. new->keyClass = keyClass;
  2938. new->copyKey = copyKey && keyClass==READI_HASH_BINARY;
  2939. new->first = 0;
  2940. new->count = 0;
  2941. new->htsize = 0;
  2942. new->ht = 0;
  2943. }
  2944. /* readiHashClear */
  2945. void readiHashClear(Hash *pH){
  2946. HashElem *elem; /* For looping over all elements of the table */
  2947.  
  2948. assert( pH!=0 );
  2949. elem = pH->first;
  2950. pH->first = 0;
  2951. if( pH->ht ) Odie_Free((char *)pH->ht);
  2952. pH->ht = 0;
  2953. pH->htsize = 0;
  2954. while( elem ){
  2955. HashElem *next_elem = elem->next;
  2956. if( pH->copyKey && elem->pKey ){
  2957. Odie_Free((char *)elem->pKey);
  2958. }
  2959. Odie_Free((char *)elem);
  2960. elem = next_elem;
  2961. }
  2962. pH->count = 0;
  2963. }
  2964. /* *readiHashFind */
  2965. void *readiHashFind(const Hash *pH, const void *pKey, int nKey){
  2966. int h; /* A hash on key */
  2967. HashElem *elem; /* The element that matches key */
  2968. int (*xHash)(const void*,int); /* The hash function */
  2969.  
  2970. if( pH==0 || pH->ht==0 ) return 0;
  2971. xHash = hashFunction(pH->keyClass);
  2972. assert( xHash!=0 );
  2973. h = (*xHash)(pKey,nKey);
  2974. assert( (pH->htsize & (pH->htsize-1))==0 );
  2975. elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
  2976. return elem ? elem->data : 0;
  2977. }
  2978. /* *readiHashInsert */
  2979. void *readiHashInsert(Hash *pH, const void *pKey, int nKey, void *data){
  2980. int hraw; /* Raw hash value of the key */
  2981. int h; /* the hash of the key modulo hash table size */
  2982. HashElem *elem; /* Used to loop thru the element list */
  2983. HashElem *new_elem; /* New element added to the pH */
  2984. int (*xHash)(const void*,int); /* The hash function */
  2985.  
  2986. assert( pH!=0 );
  2987. xHash = hashFunction(pH->keyClass);
  2988. assert( xHash!=0 );
  2989. hraw = (*xHash)(pKey, nKey);
  2990. assert( (pH->htsize & (pH->htsize-1))==0 );
  2991. h = hraw & (pH->htsize-1);
  2992. elem = findElementGivenHash(pH,pKey,nKey,h);
  2993. if( elem ){
  2994. void *old_data = elem->data;
  2995. if( data==0 ){
  2996. removeElementGivenHash(pH,elem,h);
  2997. }else{
  2998. elem->data = data;
  2999. }
  3000. return old_data;
  3001. }
  3002. if( data==0 ) return 0;
  3003. new_elem = (HashElem*)Odie_Alloc( sizeof(HashElem) );
  3004. if( new_elem==0 ) return data;
  3005.  
  3006. if( pH->copyKey && pKey!=0 ){
  3007. new_elem->pKey = Odie_Alloc( nKey );
  3008. if( new_elem->pKey==0 ){
  3009. Odie_Free((char *)new_elem);
  3010. return data;
  3011. }
  3012. memcpy((void*)new_elem->pKey, pKey, nKey);
  3013. }else{
  3014. new_elem->pKey = (void*)pKey;
  3015. }
  3016. new_elem->nKey = nKey;
  3017. pH->count++;
  3018. if( pH->htsize==0 ) rehash(pH,8);
  3019. if( pH->htsize==0 ){
  3020. pH->count = 0;
  3021. Odie_Free((char *)new_elem);
  3022. return data;
  3023. }
  3024. if( pH->count > pH->htsize ){
  3025. rehash(pH,pH->htsize*2);
  3026. }
  3027. assert( (pH->htsize & (pH->htsize-1))==0 );
  3028. h = hraw & (pH->htsize-1);
  3029. elem = pH->ht[h].chain;
  3030. if( elem ){
  3031. new_elem->next = elem;
  3032. new_elem->prev = elem->prev;
  3033. if( elem->prev ){ elem->prev->next = new_elem; }
  3034. else { pH->first = new_elem; }
  3035. elem->prev = new_elem;
  3036. }else{
  3037. new_elem->next = pH->first;
  3038. new_elem->prev = 0;
  3039. if( pH->first ){ pH->first->prev = new_elem; }
  3040. pH->first = new_elem;
  3041. }
  3042. pH->ht[h].count++;
  3043. pH->ht[h].chain = new_elem;
  3044. new_elem->data = data;
  3045. return 0;
  3046. }
  3047. /* int */
  3048. void TreeInit(Tree *tree, int (*xCompare)(const void*, const void*),void *(*xCopy)(const void*),void (*xFree)(void*)){
  3049. /* Turn bulk memory into a Tree structure
  3050. Tree *tree, Tree object to initialize
  3051. int (*xCompare)(const void*, const void*), Comparison function
  3052. void *(*xCopy)(const void*), Key copy function or NULL
  3053. void (*xFree)(void*) Key delete function or NULL
  3054. */
  3055. tree->xCompare = xCompare;
  3056. tree->xCopy = xCopy;
  3057. tree->xFree = xFree;
  3058. tree->top = 0;
  3059. }
  3060. /* TreeCount */
  3061. int TreeCount(Tree *pTree){
  3062. /* Return the number of elements in the tree. */
  3063. if( pTree && pTree->top ){
  3064. return pTree->top->weight;
  3065. }else{
  3066. return 0;
  3067. }
  3068. }
  3069. /* void */
  3070. static void TreeClearNode(TreeElem *p, void (*xFree)(void*)){
  3071. /* Delete a single node of the binary tree and all of its children */
  3072. if( p==0 ) return;
  3073. if( p->left ) TreeClearNode(p->left, xFree);
  3074. if( p->right ) TreeClearNode(p->right, xFree);
  3075. if( xFree ){
  3076. xFree(p->key);
  3077. }
  3078. Tcl_Free((char *)p);
  3079. }
  3080. /* TreeClear */
  3081. void TreeClear(Tree *tree){
  3082. /* Remove all nodes from a tree */
  3083. if( tree->top ){
  3084. TreeClearNode(tree->top, tree->xFree);
  3085. }
  3086. tree->top = 0;
  3087. }
  3088. /* *TreeFind */
  3089. void *TreeFind(Tree *tree, const void *key){
  3090. /* Find the element of the tree (if any) whose key matches "key".
  3091. ** Return a pointer to the data for that element. If no match
  3092. ** is found, return NULL.
  3093. */
  3094. TreeElem *p;
  3095.  
  3096. p = tree->top;
  3097. while( p ){
  3098. int c = tree->xCompare(p->key, key);
  3099. if( c==0 ){
  3100. return p->data;
  3101. }else if( c<0 ){
  3102. p = p->right;
  3103. }else{
  3104. p = p->left;
  3105. }
  3106. }
  3107. return 0;
  3108. }
  3109. /* TreeRank */
  3110. int TreeRank(Tree *tree, const void *key){
  3111. /* If the node with key "key" is the left-most element of the tree,
  3112. ** return 0. If it is the second to the left, return 1. And so
  3113. ** forth.
  3114. **
  3115. ** If there is no node in the tree with the key "key", then return
  3116. ** the number that would have been returned if such a node were
  3117. ** inserted.
  3118. */
  3119. TreeElem *p;
  3120. int rank = 0;
  3121.  
  3122. p = tree->top;
  3123. while( p ){
  3124. int c = tree->xCompare(p->key, key);
  3125. if( c==0 ){
  3126. rank += p->left ? p->left->weight: 0;
  3127. break;
  3128. }else if( c<0 ){
  3129. rank += (p->left ? p->left->weight: 0) + 1;
  3130. p = p->right;
  3131. }else{
  3132. p = p->left;
  3133. }
  3134. }
  3135. return rank;
  3136. }
  3137. /* *TreeFindNthElem */
  3138. static TreeElem *TreeFindNthElem(Tree *tree, int n){
  3139. /* Return a pointer to the N-th element of a tree. (The left-most
  3140. ** element is number 0, the next is number 1 and so forth.)
  3141. */
  3142. TreeElem *p;
  3143.  
  3144. p = tree->top;
  3145. while( p ){
  3146. int c = p->left ? p->left->weight : 0;
  3147. if( n==c ){
  3148. return p;
  3149. }else if( n>c ){
  3150. n -= c+1;
  3151. p = p->right;
  3152. }else{
  3153. p = p->left;
  3154. }
  3155. }
  3156. return 0;
  3157. }
  3158. /* *TreeData */
  3159. void *TreeData(Tree *tree, int n){
  3160. /* Return the data associated with the N-th element of the tree. Return
  3161. ** NULL if there is no N-th element.
  3162. */
  3163. TreeElem *p = TreeFindNthElem(tree,n);
  3164. return p ? p->data : 0;
  3165. }
  3166. /* *TreeKey */
  3167. const void *TreeKey(Tree *tree, int n){
  3168. /* Return the key associated with the N-th element of the tree. Return
  3169. ** NULL if there is no N-th element.
  3170. */
  3171. TreeElem *p = TreeFindNthElem(tree,n);
  3172. if( p ){
  3173. return p->key;
  3174. }else{
  3175. return 0;
  3176. }
  3177. }
  3178. /* TreeBalance */
  3179. static void TreeBalance(TreeElem **ppElem){
  3180. /*
  3181. ** Definitions:
  3182. ** WEIGHT
  3183. ** The weight of a node is the total number of children for the node
  3184. ** plus 1. Leaf nodes have a weight of 1. The root node has a weight
  3185. ** which equals the number of nodes in the tree.
  3186. **
  3187. ** BALANCE
  3188. ** A node is balanced if the weight of the one child is not more than
  3189. ** twice the weight of the other child.
  3190. */
  3191.  
  3192. /* The following routine rebalances the tree rooted at *ppElem after
  3193. ** the insertion or deletion of a single ancestor.
  3194. */
  3195. TreeElem *n; /* Pointer to self */
  3196. int l,r; /* Weight of left and right daughters */
  3197. int a,b; /* Weights of various nodes */
  3198.  
  3199. if( ppElem==0 || (n=*ppElem)==0 ) return;
  3200. l = n->left ? n->left->weight: 0;
  3201. r = n->right ? n->right->weight: 0;
  3202. if( l>r*2 ){ /* Too heavy on the left side */
  3203. TreeElem *nl; /* Pointer to left daughter */
  3204. TreeElem *nr; /* Pointer to right daughter */
  3205. int ll, lr; /* Weight of left daughter's left and right daughter */
  3206. nl = n->left;
  3207. ll = nl->left ? nl->left->weight: 0;
  3208. lr = nl->right ? nl->right->weight: 0;
  3209. if( ll>lr || nl->right==0 ){
  3210. /*
  3211. ** Convert from: n to: nl
  3212. ** / \ / ** nl c a n
  3213. ** / \ / ** a b b c
  3214. */
  3215. n->left = nl->right;
  3216. nl->right = n;
  3217. n->weight = a = r + lr + 1;
  3218. nl->weight = a + ll + 1;
  3219. *ppElem = nl;
  3220. }else{
  3221. /*
  3222. ** Convert from: n to: nr
  3223. ** / \ / ** nl d nl n
  3224. ** / \ / \ / ** a nr a b c d
  3225. ** / ** b c
  3226. */
  3227. int lrl, lrr; /* Weight of Great-granddaughter nodes */
  3228. nr = nl->right;
  3229. lrl = nr->left ? nr->left->weight: 0;
  3230. lrr = nr->right ? nr->right->weight: 0;
  3231. nl->right = nr->left;
  3232. nr->left = nl;
  3233. n->left = nr->right;
  3234. nr->right = n;
  3235. n->weight = a = lrr + r + 1;
  3236. nl->weight = b = ll + lrl + 1;
  3237. nr->weight = a + b + 1;
  3238. *ppElem = nr;
  3239. }
  3240. }else if( r>l*2 ){/* Too deep on the right side */
  3241. TreeElem *nl; /* Pointer to left daughter */
  3242. TreeElem *nr; /* Pointer to right daughter */
  3243. int rl, rr; /* Weight of right daughter's left and right daughter */
  3244. nr = n->right;
  3245. rl = nr->left ? nr->left->weight: 0;
  3246. rr = nr->right ? nr->right->weight: 0;
  3247. if( rr>rl || nr->left==0 ){
  3248. /*
  3249. ** Convert from: n to: nr
  3250. ** / \ / ** a nr n c
  3251. ** / \ / ** b c a b
  3252. */
  3253. n->right = nr->left;
  3254. nr->left = n;
  3255. n->weight = a = l + rl + 1;
  3256. nr->weight = a + rr + 1;
  3257. *ppElem = nr;
  3258. }else{
  3259. /*
  3260. ** Convert from: n to: nl
  3261. ** / \ / ** a nr n nr
  3262. ** / \ / \ / ** nl d a b c d
  3263. ** / ** b c
  3264. */
  3265. int rll,rlr; /* Weights of great-granddaughter nodes */
  3266. nl = nr->left;
  3267. rll = nl->left ? nl->left->weight: 0;
  3268. rlr = nl->right ? nl->right->weight: 0;
  3269. nr->left = nl->right;
  3270. nl->right = nr;
  3271. n->right = nl->left;
  3272. nl->left = n;
  3273. n->weight = a = l + rll + 1;
  3274. nr->weight = b = rr + rlr + 1;
  3275. nl->weight = a + b + 1;
  3276. *ppElem = nl;
  3277. }
  3278. }else{ /* Node is already balanced. Just recompute its weight. */
  3279. n->weight = l + r + 1;
  3280. }
  3281. }
  3282. /* *TreeInsertElement */
  3283. static void *TreeInsertElement(Tree *pTree, void *key, void *data){
  3284. /*
  3285. Tree *pTree, The root of the tree
  3286. void *key, Insert data at this key
  3287. void *data Data to be inserted
  3288. */
  3289. /* This routine either changes the data on an existing node in the tree,
  3290. ** or inserts a new node. "key" identifies the node. If the data on
  3291. ** an existing node is changed, then the function returns the old data.
  3292. ** If a new node is created, NULL is returned.
  3293. */
  3294. TreeElem *n;
  3295. void *old = 0;
  3296. TreeElem **h[100]; /* Sufficient for a tree with up to 4.0E+17 nodes */
  3297. int level = 0;
  3298.  
  3299.  
  3300. h[0] = &pTree->top;
  3301. level = 1;
  3302. n = pTree->top;
  3303. while( n ){
  3304. int c;
  3305. c = pTree->xCompare(key, n->key);
  3306. if( c<0 ){
  3307. h[level++] = &(n->left);
  3308. n = n->left;
  3309. }else if( c>0 ){
  3310. h[level++] = &(n->right);
  3311. n = n->right;
  3312. }else{
  3313. old = n->data;
  3314. n->data = data; /* Replace data in an existing node */
  3315. break;
  3316. }
  3317. }
  3318. if( n==0 ){ /* Insert a leaf node */
  3319. level--;
  3320. n = *h[level] = (TreeElem *)Tcl_Alloc( sizeof(TreeElem) );
  3321. if( n==0 ){
  3322. return data;
  3323. }
  3324. n->data = data;
  3325. if( pTree->xCopy ){
  3326. n->key = pTree->xCopy(key);
  3327. }else{
  3328. n->key = key;
  3329. }
  3330. n->left = n->right = 0;
  3331. while( level>=0 ) TreeBalance(h[level--]);
  3332. }
  3333. return old;
  3334. }
  3335. /* *TreeDeleteNthElem */
  3336. static TreeElem *TreeDeleteNthElem(TreeElem **ppTop, int N){
  3337. /* Unlink the N-th node of the tree and return a pointer to that
  3338. ** node. (The left-most node is 0, the next node to the right is
  3339. ** 1 and so forth.)
  3340. */
  3341. TreeElem *p; /* For walking the tree */
  3342. int level = 0; /* Depth of the blancing stack */
  3343. TreeElem **h[100]; /* Balance stack. 100 is sufficient for balancing
  3344. ** a tree with up to 4.0E+17 nodes */
  3345.  
  3346. h[0] = ppTop;
  3347. level = 1;
  3348. p = *ppTop;
  3349. while( p ){
  3350. int w;
  3351. w = (p->left ? p->left->weight: 0);
  3352. if( N>w ){
  3353. h[level++] = &(p->right);
  3354. p = p->right;
  3355. N -= w+1;
  3356. }else if( N<w ){
  3357. h[level++] = &(p->left);
  3358. p = p->left;
  3359. }else{
  3360. break;
  3361. }
  3362. }
  3363. if( p ){
  3364. level--;
  3365. if( p->left==0 ){
  3366. *h[level] = p->right;
  3367. level--;
  3368. }else if( p->right==0 ){
  3369. *h[level] = p->left;
  3370. level--;
  3371. }else{
  3372. TreeElem *x;
  3373. x = TreeDeleteNthElem(&(p->right),0);
  3374. x->right = p->right;
  3375. x->left = p->left;
  3376. *h[level] = x;
  3377. }
  3378. while( level>=0 ) TreeBalance(h[level--]);
  3379. }
  3380. return p;
  3381. }
  3382. /* *TreeDeleteElem */
  3383. static TreeElem *TreeDeleteElem(Tree *tree, const void *key){
  3384. /* Unlink the node of the tree corresponding to key and return a pointer
  3385. ** to that node.
  3386. */
  3387. TreeElem *p; /* For walking the tree */
  3388. int level = 0; /* Depth of the blancing stack */
  3389. TreeElem **h[100]; /* Balance stack. 100 is sufficient for balancing
  3390. ** a tree with up to 4.0E+17 nodes */
  3391.  
  3392. h[0] = &tree->top;
  3393. level = 1;
  3394. p = tree->top;
  3395. while( p ){
  3396. int w;
  3397. w = tree->xCompare(p->key, key);
  3398. if( w<0 ){
  3399. h[level++] = &(p->right);
  3400. p = p->right;
  3401. }else if( w>0 ){
  3402. h[level++] = &(p->left);
  3403. p = p->left;
  3404. }else{
  3405. break;
  3406. }
  3407. }
  3408. if( p ){
  3409. level--;
  3410. if( p->left==0 ){
  3411. *h[level] = p->right;
  3412. level--;
  3413. }else if( p->right==0 ){
  3414. *h[level] = p->left;
  3415. level--;
  3416. }else{
  3417. TreeElem *x;
  3418. x = TreeDeleteNthElem(&(p->right),0);
  3419. x->right = p->right;
  3420. x->left = p->left;
  3421. *h[level] = x;
  3422. }
  3423. while( level>=0 ) TreeBalance(h[level--]);
  3424. }
  3425. return p;
  3426. }
  3427. /* *TreeInsert */
  3428. void *TreeInsert(Tree *tree, void *key, void *data){
  3429. /* Insert new data into a node of the tree. The node is identified
  3430. ** by "key".
  3431. **
  3432. ** If the new data is NULL, then node is deleted.
  3433. **
  3434. ** If the node aready exists, the new data overwrites the old and
  3435. ** the old data is returned. If the node doesn't already exist, then
  3436. ** a new node is created and the function returns NULL.
  3437. */
  3438.  
  3439. void *old;
  3440. if( data==0 ){
  3441. TreeElem *elem = TreeDeleteElem(tree, key);
  3442. if( elem ){
  3443. if( tree->xFree ){
  3444. tree->xFree(elem->key);
  3445. }
  3446. old = elem->data;
  3447. Tcl_Free((char *)elem);
  3448. }else{
  3449. old = 0;
  3450. }
  3451. }else{
  3452. old = TreeInsertElement(tree,key,data);
  3453. }
  3454. return old;
  3455. }
  3456. /* *TreeChangeNth */
  3457. void *TreeChangeNth(Tree *tree, int n, void *data){
  3458. /* Change the data on the n-th node of the tree. The old data
  3459. ** is returned.
  3460. **
  3461. ** If data==NULL, then the n-th node of the tree is deleted. (The
  3462. ** data associated with that node is still returned.)
  3463. **
  3464. ** If the value N is out-of-bounds, then no new node is created.
  3465. ** Instead, the "data" parameter is returned.
  3466. */
  3467. void *old;
  3468. if( data==0 ){
  3469. TreeElem *elem = TreeDeleteNthElem(&tree->top,n);
  3470. if( elem ){
  3471. if( tree->xFree ){
  3472. tree->xFree(elem->key);
  3473. }
  3474. old = elem->data;
  3475. Tcl_Free((char *)elem);
  3476. }else{
  3477. old = 0;
  3478. }
  3479. }else{
  3480. TreeElem *elem = TreeFindNthElem(tree,n);
  3481. if( elem ){
  3482. old = elem->data;
  3483. elem->data = data;
  3484. }else{
  3485. old = data;
  3486. }
  3487. }
  3488. return old;
  3489. }
  3490. /* Odie_GetMatrixElementFromObj */
  3491. static inline int Odie_GetMatrixElementFromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,double *R,int idx){
  3492. double temp;
  3493. if( Tcl_GetDoubleFromObj(interp, objPtr, &temp) ) return TCL_ERROR;
  3494. R[idx]=temp;
  3495. return TCL_OK;
  3496. }
  3497. /* hashInt */
  3498. static inline unsigned int hashInt(int x){
  3499. /*
  3500. ** Compute a hash on an integer.
  3501. */
  3502. return (x & 0x7fffffff) % SZ_HASH;
  3503. }
  3504. /* intCoord */
  3505. static inline long intCoord(double x){
  3506. /*
  3507. ** Round a coordinate to its nearest grain boundary
  3508. */
  3509. long idxX = x/OdieGrain + (x>0.0 ? 0.5 : -0.5);
  3510. return idxX*OdieGrain;
  3511. }
  3512. /* hashPoint */
  3513. static inline unsigned int hashPoint(VECTORXY p){
  3514. /*
  3515. ** Compute a hash on a point.
  3516. */
  3517. long x=intCoord(p[X_IDX])*ODIE_X_HASH;
  3518. long y=intCoord(p[Y_IDX])*ODIE_Y_HASH;
  3519. return hashInt(x ^ y);
  3520. }
  3521. /* hashVectorXY */
  3522. static inline unsigned int hashVectorXY(VECTORXY p){
  3523. long x=intCoord(p[X_IDX])*ODIE_X_HASH;
  3524. long y=intCoord(p[Y_IDX])*ODIE_Y_HASH;
  3525. return hashInt(x ^ y);
  3526. }
  3527. /* hashVectorXYZ */
  3528. static inline unsigned int hashVectorXYZ(VECTORXYZ p){
  3529. long x=intCoord(p[X_IDX])*ODIE_X_HASH;
  3530. long y=intCoord(p[Y_IDX])*ODIE_Y_HASH;
  3531. long z=intCoord(p[Z_IDX])*ODIE_Z_HASH;
  3532. if(z!=0) {
  3533. return hashInt(x ^ y ^ z);
  3534. } else {
  3535. return hashInt(x ^ y);
  3536. }
  3537. }
  3538. /* roundCoord */
  3539. static inline double roundCoord(double x){
  3540. return intCoord(x);
  3541. }
  3542. /* hashCoord */
  3543. static inline int hashCoord(double x, double y){
  3544. /*
  3545. ** Compute a hash on a pair of floating point number.
  3546. */
  3547. long idxX = intCoord(x)*ODIE_X_HASH;
  3548. long idxY = intCoord(y)*ODIE_Y_HASH;
  3549. return hashInt(idxX ^ idxY);
  3550. }
  3551. /* hashCoord3d */
  3552. static inline int hashCoord3d(double x, double y,double z){
  3553. /*
  3554. ** Compute a hash on a pair of floating point number.
  3555. */
  3556. long idxX = intCoord(x)*ODIE_X_HASH;
  3557. long idxY = intCoord(y)*ODIE_Y_HASH;
  3558. long idxZ = intCoord(z)*ODIE_Z_HASH;
  3559. if(idxZ!=0) {
  3560. return hashInt(idxX ^ idxY ^ idxZ);
  3561. } else {
  3562. return hashInt(idxX ^ idxY);
  3563. }
  3564. }
  3565. /* floatCompare */
  3566. static inline int floatCompare(double x0, double x1){
  3567. /*
  3568. ** Compare to floating point values and return negative, zero, or
  3569. ** positive if the first value is less than, equal to, or greater
  3570. ** than the second.
  3571. */
  3572. double diff = x1 - x0;
  3573. if( diff>-OdieGrain && diff<OdieGrain ){
  3574. diff = 0.0;
  3575. }
  3576. return (int)diff;
  3577. }
  3578. /* GridCoord */
  3579. static inline void GridCoord(double *x, double *y){
  3580. /*
  3581. ** Round a set of coordinates by OdieGrain
  3582. */
  3583. *x=round(*x/OdieGrain)*OdieGrain;
  3584. *y=round(*y/OdieGrain)*OdieGrain;
  3585. }
  3586. /* Math_Const_Init */
  3587. int Math_Const_Init(Tcl_Interp *interp){
  3588. Tcl_Obj *varname=Tcl_NewStringObj("math_const",-1);
  3589. Tcl_IncrRefCount(varname);
  3590. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_2_x_pi",-1),Tcl_NewDoubleObj(M_2_X_PI),TCL_GLOBAL_ONLY);
  3591. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi_180",-1),Tcl_NewDoubleObj(M_PI_180),TCL_GLOBAL_ONLY);
  3592. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi_360",-1),Tcl_NewDoubleObj(M_PI_360),TCL_GLOBAL_ONLY);
  3593. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_e",-1),Tcl_NewDoubleObj(M_E),TCL_GLOBAL_ONLY);
  3594. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_log2e",-1),Tcl_NewDoubleObj(M_LOG2E),TCL_GLOBAL_ONLY);
  3595. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_log10e",-1),Tcl_NewDoubleObj(M_LOG10E),TCL_GLOBAL_ONLY);
  3596. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_ln2",-1),Tcl_NewDoubleObj(M_LN2),TCL_GLOBAL_ONLY);
  3597. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_ln10",-1),Tcl_NewDoubleObj(M_LN10),TCL_GLOBAL_ONLY);
  3598. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi",-1),Tcl_NewDoubleObj(M_PI),TCL_GLOBAL_ONLY);
  3599. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi_2",-1),Tcl_NewDoubleObj(M_PI_2),TCL_GLOBAL_ONLY);
  3600. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi_4",-1),Tcl_NewDoubleObj(M_PI_4),TCL_GLOBAL_ONLY);
  3601. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_1_pi",-1),Tcl_NewDoubleObj(M_1_PI),TCL_GLOBAL_ONLY);
  3602. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_2_pi",-1),Tcl_NewDoubleObj(M_2_PI),TCL_GLOBAL_ONLY);
  3603. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_2_sqrtpi",-1),Tcl_NewDoubleObj(M_2_SQRTPI),TCL_GLOBAL_ONLY);
  3604. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_sqrt2",-1),Tcl_NewDoubleObj(M_SQRT2),TCL_GLOBAL_ONLY);
  3605. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_sqrt1_2",-1),Tcl_NewDoubleObj(M_SQRT1_2),TCL_GLOBAL_ONLY);
  3606. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_sqrt3",-1),Tcl_NewDoubleObj(M_SQRT3),TCL_GLOBAL_ONLY);
  3607. Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_sqrt3_2",-1),Tcl_NewDoubleObj(M_SQRT3_2),TCL_GLOBAL_ONLY);
  3608. Tcl_DecrRefCount(varname);
  3609. return TCL_OK;}
  3610. /* VectorXYZ_AABB_Normalize */
  3611. static inline void VectorXYZ_AABB_Normalize(AABBXYZ R){
  3612. double temp;
  3613. if (R[X_MIN_IDX] > R[X_MAX_IDX]) {
  3614. temp=R[X_MIN_IDX];
  3615. R[X_MIN_IDX]=R[X_MAX_IDX];
  3616. R[X_MAX_IDX]=temp;
  3617. } if (R[Y_MIN_IDX] > R[Y_MAX_IDX]) {
  3618. temp=R[Y_MIN_IDX];
  3619. R[Y_MIN_IDX]=R[Y_MAX_IDX];
  3620. R[Y_MAX_IDX]=temp;
  3621. } if (R[Z_MIN_IDX] > R[Z_MAX_IDX]) {
  3622. temp=R[Z_MIN_IDX];
  3623. R[Z_MIN_IDX]=R[Z_MAX_IDX];
  3624. R[Z_MAX_IDX]=temp;
  3625. }}
  3626. /* VectorXYZ_AABB_Copy */
  3627. static void VectorXYZ_AABB_Copy(AABBXYZ dest,AABBXYZ src){
  3628. dest[X_MIN_IDX]=src[X_MIN_IDX];
  3629. dest[X_MAX_IDX]=src[X_MAX_IDX];
  3630. dest[Y_MIN_IDX]=src[Y_MIN_IDX];
  3631. dest[Y_MAX_IDX]=src[Y_MAX_IDX];
  3632. dest[Z_MIN_IDX]=src[Z_MIN_IDX];
  3633. dest[Z_MAX_IDX]=src[Z_MAX_IDX];
  3634. }
  3635. /* VectorXYZ_AABB_Within */
  3636. static inline int VectorXYZ_AABB_Within(VectorXYZ POINT,AABBXYZ R){
  3637. if (POINT[X_IDX]<R[X_MIN_IDX]) return 0;
  3638. if (POINT[X_IDX]>R[X_MAX_IDX]) return 0;
  3639. if (POINT[Y_IDX]<R[Y_MIN_IDX]) return 0;
  3640. if (POINT[Y_IDX]>R[Y_MAX_IDX]) return 0;
  3641. if (POINT[Z_IDX]<R[Z_MIN_IDX]) return 0;
  3642. if (POINT[Z_IDX]>R[Z_MAX_IDX]) return 0;
  3643. return 1;
  3644. }
  3645. /* VectorXYZ_BBOX_Overlap_TwoVectors */
  3646. static inline int VectorXYZ_BBOX_Overlap_TwoVectors(VectorXYZ A1,VectorXYZ A2,VectorXYZ B1,VectorXYZ B2){
  3647. if (A1[X_IDX]<B1[X_IDX] && A1[X_IDX]<B2[X_IDX]) {
  3648. if (A2[X_IDX]<B1[X_IDX] && A2[X_IDX]<B2[X_IDX]) return 0;
  3649. }
  3650. if (A1[X_IDX]>B1[X_IDX] && A1[X_IDX]>B2[X_IDX]) {
  3651. if (A2[X_IDX]>B1[X_IDX] && A2[X_IDX]>B2[X_IDX]) return 0;
  3652. }
  3653. if (A1[Y_IDX]<B1[Y_IDX] && A1[Y_IDX]<B2[Y_IDX]) {
  3654. if (A2[Y_IDX]<B1[Y_IDX] && A2[Y_IDX]<B2[Y_IDX]) return 0;
  3655. }
  3656. if (A1[Y_IDX]>B1[Y_IDX] && A1[Y_IDX]>B2[Y_IDX]) {
  3657. if (A2[Y_IDX]>B1[Y_IDX] && A2[Y_IDX]>B2[Y_IDX]) return 0;
  3658. }
  3659. if (A1[Z_IDX]<B1[Z_IDX] && A1[Z_IDX]<B2[Z_IDX]) {
  3660. if (A2[Z_IDX]<B1[Z_IDX] && A2[Z_IDX]<B2[Z_IDX]) return 0;
  3661. }
  3662. if (A1[Z_IDX]>B1[Z_IDX] && A1[Z_IDX]>B2[Z_IDX]) {
  3663. if (A2[Z_IDX]>B1[Z_IDX] && A2[Z_IDX]>B2[Z_IDX]) return 0;
  3664. }
  3665. return 1;
  3666. }
  3667. /* AABB_AABB_Intersect */
  3668. static inline int AABB_AABB_Intersect(AABBXYZ A,AABBXYZ B){
  3669. int a_inside_b=0;
  3670. int b_inside_a=0;
  3671. if (A[X_MIN_IDX]>=B[X_MIN_IDX] && A[X_MAX_IDX]<=B[X_MAX_IDX]) a_inside_b++;
  3672. if (B[X_MIN_IDX]>=A[X_MIN_IDX] && B[X_MAX_IDX]<=A[X_MAX_IDX]) b_inside_a++;
  3673. if (A[Y_MIN_IDX]>=B[Y_MIN_IDX] && A[Y_MAX_IDX]<=B[Y_MAX_IDX]) a_inside_b++;
  3674. if (B[Y_MIN_IDX]>=A[Y_MIN_IDX] && B[Y_MAX_IDX]<=A[Y_MAX_IDX]) b_inside_a++;
  3675. if (A[Z_MIN_IDX]>=B[Z_MIN_IDX] && A[Z_MAX_IDX]<=B[Z_MAX_IDX]) a_inside_b++;
  3676. if (B[Z_MIN_IDX]>=A[Z_MIN_IDX] && B[Z_MAX_IDX]<=A[Z_MAX_IDX]) b_inside_a++;
  3677.  
  3678. if (a_inside_b==0 && b_inside_a==0) return 0;
  3679. if (a_inside_b==3 && b_inside_a==3) return 2;
  3680. if (a_inside_b==3) return 3;
  3681. if (b_inside_a==3) return 4;
  3682. return 1;
  3683. }
  3684. /* VectorXYZ_AABB_Measure */
  3685. static inline void VectorXYZ_AABB_Measure(VectorXYZ POINT,AABBXYZ R){
  3686. if (POINT[X_IDX]<R[X_MIN_IDX]) R[X_MIN_IDX]=POINT[X_IDX];
  3687. if (POINT[X_IDX]>R[X_MAX_IDX]) R[X_MAX_IDX]=POINT[X_IDX];
  3688. if (POINT[Y_IDX]<R[Y_MIN_IDX]) R[Y_MIN_IDX]=POINT[Y_IDX];
  3689. if (POINT[Y_IDX]>R[Y_MAX_IDX]) R[Y_MAX_IDX]=POINT[Y_IDX];
  3690. if (POINT[Z_IDX]<R[Z_MIN_IDX]) R[Z_MIN_IDX]=POINT[Z_IDX];
  3691. if (POINT[Z_IDX]>R[Z_MAX_IDX]) R[Z_MAX_IDX]=POINT[Z_IDX];
  3692. }
  3693. /* AABB_AABB_Combine */
  3694. static inline void AABB_AABB_Combine(AABBXYZ B,AABBXYZ A){
  3695. if (A[X_MIN_IDX]<B[X_MIN_IDX]) B[X_MIN_IDX]=A[X_MIN_IDX];
  3696. if (A[X_MAX_IDX]>B[X_MAX_IDX]) B[X_MAX_IDX]=A[X_MAX_IDX];
  3697. if (A[Y_MIN_IDX]<B[Y_MIN_IDX]) B[Y_MIN_IDX]=A[Y_MIN_IDX];
  3698. if (A[Y_MAX_IDX]>B[Y_MAX_IDX]) B[Y_MAX_IDX]=A[Y_MAX_IDX];
  3699. if (A[Z_MIN_IDX]<B[Z_MIN_IDX]) B[Z_MIN_IDX]=A[Z_MIN_IDX];
  3700. if (A[Z_MAX_IDX]>B[Z_MAX_IDX]) B[Z_MAX_IDX]=A[Z_MAX_IDX];
  3701. }
  3702. /* VectorXYZ_AABB_Reset */
  3703. static inline void VectorXYZ_AABB_Reset(AABBXYZ R){
  3704. R[X_MIN_IDX]=R[Y_MIN_IDX]=R[Z_MIN_IDX]=1e99;
  3705. R[X_MAX_IDX]=R[Y_MAX_IDX]=R[Z_MAX_IDX]=-1e99;
  3706. }
  3707. VectorXYZ Odie_Up_Direction = {0, 0, 1.0};
  3708. /* *Matrix_To_affine */
  3709. const char *Matrix_To_affine(Odie_MatrixObj *matrix,int form){
  3710. if(matrix->form==MATFORM_affine) {
  3711. return NULL;
  3712. }
  3713. if(matrix->form==MATFORM_euler) {
  3714. VectorXYZ TEMP;
  3715. VectorXYZ_Copy(TEMP,matrix->matrix);
  3716. affine_Rotate_From_Euler(TEMP,matrix->matrix);
  3717. matrix->form=MATFORM_affine;
  3718. return NULL;
  3719. }
  3720. if(matrix->form==MATFORM_vector_xyz) {
  3721. VectorXYZ TEMP;
  3722. VectorXYZ_Copy(TEMP,matrix->matrix);
  3723. Odie_Affine4x4_Translation(TEMP,matrix->matrix);
  3724. matrix->form=MATFORM_affine;
  3725. return NULL;
  3726. }
  3727. if(matrix->rows==4 && matrix->cols==4) {
  3728. if(matrix->form==MATFORM_null) {
  3729. matrix->form=MATFORM_affine;
  3730. }
  3731. return NULL;
  3732. }
  3733. if(matrix->rows==1 && matrix->cols==16) {
  3734. if(matrix->form==MATFORM_null) {
  3735. matrix->form=MATFORM_affine;
  3736. }
  3737. return NULL;
  3738. }
  3739. if(matrix->rows==16 && matrix->cols==1) {
  3740. if(matrix->form==MATFORM_null) {
  3741. matrix->form=MATFORM_affine;
  3742. }
  3743. return NULL;
  3744. }
  3745. return "Cannot convert to affine";
  3746. }
  3747. /* affine_Compare */
  3748. static inline int affine_Compare(AFFINE A,AFFINE B){
  3749. if(fabs(B[AFFINE_IDX_0_0]-A[AFFINE_IDX_0_0])>__FLT_EPSILON__) return 0;
  3750. if(fabs(B[AFFINE_IDX_0_1]-A[AFFINE_IDX_0_1])>__FLT_EPSILON__) return 0;
  3751. if(fabs(B[AFFINE_IDX_0_2]-A[AFFINE_IDX_0_2])>__FLT_EPSILON__) return 0;
  3752. if(fabs(B[AFFINE_IDX_0_3]-A[AFFINE_IDX_0_3])>__FLT_EPSILON__) return 0;
  3753. if(fabs(B[AFFINE_IDX_1_0]-A[AFFINE_IDX_1_0])>__FLT_EPSILON__) return 0;
  3754. if(fabs(B[AFFINE_IDX_1_1]-A[AFFINE_IDX_1_1])>__FLT_EPSILON__) return 0;
  3755. if(fabs(B[AFFINE_IDX_1_2]-A[AFFINE_IDX_1_2])>__FLT_EPSILON__) return 0;
  3756. if(fabs(B[AFFINE_IDX_1_3]-A[AFFINE_IDX_1_3])>__FLT_EPSILON__) return 0;
  3757. if(fabs(B[AFFINE_IDX_2_0]-A[AFFINE_IDX_2_0])>__FLT_EPSILON__) return 0;
  3758. if(fabs(B[AFFINE_IDX_2_1]-A[AFFINE_IDX_2_1])>__FLT_EPSILON__) return 0;
  3759. if(fabs(B[AFFINE_IDX_2_2]-A[AFFINE_IDX_2_2])>__FLT_EPSILON__) return 0;
  3760. if(fabs(B[AFFINE_IDX_2_3]-A[AFFINE_IDX_2_3])>__FLT_EPSILON__) return 0;
  3761. if(fabs(B[AFFINE_IDX_3_0]-A[AFFINE_IDX_3_0])>__FLT_EPSILON__) return 0;
  3762. if(fabs(B[AFFINE_IDX_3_1]-A[AFFINE_IDX_3_1])>__FLT_EPSILON__) return 0;
  3763. if(fabs(B[AFFINE_IDX_3_2]-A[AFFINE_IDX_3_2])>__FLT_EPSILON__) return 0;
  3764. if(fabs(B[AFFINE_IDX_3_3]-A[AFFINE_IDX_3_3])>__FLT_EPSILON__) return 0;
  3765. return 1;
  3766. }
  3767. /* Odie_Affine4x4_Copy */
  3768. inline extern void Odie_Affine4x4_Copy(AFFINE RESULT,AFFINE A){
  3769. RESULT[AFFINE_IDX_0_0]=A[AFFINE_IDX_0_0];
  3770. RESULT[AFFINE_IDX_0_1]=A[AFFINE_IDX_0_1];
  3771. RESULT[AFFINE_IDX_0_2]=A[AFFINE_IDX_0_2];
  3772. RESULT[AFFINE_IDX_0_3]=A[AFFINE_IDX_0_3];
  3773. RESULT[AFFINE_IDX_1_0]=A[AFFINE_IDX_1_0];
  3774. RESULT[AFFINE_IDX_1_1]=A[AFFINE_IDX_1_1];
  3775. RESULT[AFFINE_IDX_1_2]=A[AFFINE_IDX_1_2];
  3776. RESULT[AFFINE_IDX_1_3]=A[AFFINE_IDX_1_3];
  3777. RESULT[AFFINE_IDX_2_0]=A[AFFINE_IDX_2_0];
  3778. RESULT[AFFINE_IDX_2_1]=A[AFFINE_IDX_2_1];
  3779. RESULT[AFFINE_IDX_2_2]=A[AFFINE_IDX_2_2];
  3780. RESULT[AFFINE_IDX_2_3]=A[AFFINE_IDX_2_3];
  3781. RESULT[AFFINE_IDX_3_0]=A[AFFINE_IDX_3_0];
  3782. RESULT[AFFINE_IDX_3_1]=A[AFFINE_IDX_3_1];
  3783. RESULT[AFFINE_IDX_3_2]=A[AFFINE_IDX_3_2];
  3784. RESULT[AFFINE_IDX_3_3]=A[AFFINE_IDX_3_3];
  3785. }
  3786. /* affine_ZeroMatrix */
  3787. inline extern void affine_ZeroMatrix(AFFINE A){
  3788. A[AFFINE_IDX_0_0]=0.0;
  3789. A[AFFINE_IDX_0_1]=0.0;
  3790. A[AFFINE_IDX_0_2]=0.0;
  3791. A[AFFINE_IDX_0_3]=0.0;
  3792. A[AFFINE_IDX_1_0]=0.0;
  3793. A[AFFINE_IDX_1_1]=0.0;
  3794. A[AFFINE_IDX_1_2]=0.0;
  3795. A[AFFINE_IDX_1_3]=0.0;
  3796. A[AFFINE_IDX_2_0]=0.0;
  3797. A[AFFINE_IDX_2_1]=0.0;
  3798. A[AFFINE_IDX_2_2]=0.0;
  3799. A[AFFINE_IDX_2_3]=0.0;
  3800. A[AFFINE_IDX_3_0]=0.0;
  3801. A[AFFINE_IDX_3_1]=0.0;
  3802. A[AFFINE_IDX_3_2]=0.0;
  3803. A[AFFINE_IDX_3_3]=0.0;
  3804. }
  3805. /* Odie_Affine4x4_Identity */
  3806. inline extern void Odie_Affine4x4_Identity(AFFINE A){
  3807. A[AFFINE_IDX_0_0]=1.0;
  3808. A[AFFINE_IDX_0_1]=0.0;
  3809. A[AFFINE_IDX_0_2]=0.0;
  3810. A[AFFINE_IDX_0_3]=0.0;
  3811. A[AFFINE_IDX_1_0]=0.0;
  3812. A[AFFINE_IDX_1_1]=1.0;
  3813. A[AFFINE_IDX_1_2]=0.0;
  3814. A[AFFINE_IDX_1_3]=0.0;
  3815. A[AFFINE_IDX_2_0]=0.0;
  3816. A[AFFINE_IDX_2_1]=0.0;
  3817. A[AFFINE_IDX_2_2]=1.0;
  3818. A[AFFINE_IDX_2_3]=0.0;
  3819. A[AFFINE_IDX_3_0]=0.0;
  3820. A[AFFINE_IDX_3_1]=0.0;
  3821. A[AFFINE_IDX_3_2]=0.0;
  3822. A[AFFINE_IDX_3_3]=1.0;
  3823. }
  3824. /* Odie_Affine4x4_Translation */
  3825. void Odie_Affine4x4_Translation(AFFINE RESULT,VECTOR A){
  3826. Odie_Affine4x4_Identity(RESULT);
  3827. RESULT[AFFINE_IDX_0_3]=-A[X_IDX];
  3828. RESULT[AFFINE_IDX_1_3]=-A[Y_IDX];
  3829. RESULT[AFFINE_IDX_2_3]=-A[Z_IDX];
  3830. }
  3831. /* Odie_Affine4x4_Scale */
  3832. inline extern void Odie_Affine4x4_Scale(AFFINE RESULT,VECTOR A){
  3833. Odie_Affine4x4_Identity(RESULT);
  3834. RESULT[AFFINE_IDX_0_0]=A[X_IDX];
  3835. RESULT[AFFINE_IDX_1_1]=A[Y_IDX];
  3836. RESULT[AFFINE_IDX_2_2]=A[Z_IDX];
  3837. RESULT[AFFINE_IDX_3_3]=1.0;
  3838. }
  3839. /* affine_rotate_nutation */
  3840. inline extern void affine_rotate_nutation(AFFINE RESULT,SCALER theta){
  3841. double cos_theta,sin_theta;
  3842. cos_theta=cos(theta);
  3843. sin_theta=sin(theta);
  3844.  
  3845. Odie_Affine4x4_Identity(RESULT);
  3846. RESULT[AFFINE_IDX_1_1]=cos_theta;
  3847. RESULT[AFFINE_IDX_1_2]=sin_theta;
  3848. RESULT[AFFINE_IDX_2_1]=-sin_theta;
  3849. RESULT[AFFINE_IDX_2_2]=cos_theta;
  3850. }
  3851. /* affine_rotate_precession */
  3852. inline extern void affine_rotate_precession(AFFINE RESULT,SCALER phi){
  3853. double cos_phi,sin_phi;
  3854. cos_phi=cos(phi);
  3855. sin_phi=sin(phi);
  3856.  
  3857. Odie_Affine4x4_Identity(RESULT);
  3858. RESULT[AFFINE_IDX_0_0]=cos_phi;
  3859. RESULT[AFFINE_IDX_0_1]=sin_phi;
  3860. RESULT[AFFINE_IDX_1_0]=-sin_phi;
  3861. RESULT[AFFINE_IDX_1_1]=cos_phi;
  3862. }
  3863. /* affine_rotate_spin */
  3864. static inline void affine_rotate_spin(AFFINE RESULT,SCALER psi){
  3865. double cos_psi,sin_psi;
  3866. cos_psi=cos(psi);
  3867. sin_psi=sin(psi);
  3868.  
  3869. Odie_Affine4x4_Identity(RESULT);
  3870. RESULT[AFFINE_IDX_0_0]=cos_psi;
  3871. RESULT[AFFINE_IDX_0_1]=sin_psi;
  3872. RESULT[AFFINE_IDX_1_0]=-sin_psi;
  3873. RESULT[AFFINE_IDX_1_1]=cos_psi;
  3874. }
  3875. /* affine_Rotate_From_Euler */
  3876. void affine_Rotate_From_Euler(AFFINE RESULT,VECTOR rotate){
  3877. double cos_theta,sin_theta;
  3878. double cos_phi,sin_phi;
  3879. double cos_psi,sin_psi;
  3880. cos_theta=cos(rotate[EULER_THETA]);
  3881. sin_theta=sin(rotate[EULER_THETA]);
  3882. cos_phi=cos(rotate[EULER_PHI]);
  3883. sin_phi=sin(rotate[EULER_PHI]);
  3884. cos_psi=cos(rotate[EULER_PSI]);
  3885. sin_psi=sin(rotate[EULER_PSI]);
  3886. RESULT[AFFINE_IDX_0_0]=cos_psi*cos_phi-cos_theta*sin_psi*sin_psi;
  3887. RESULT[AFFINE_IDX_0_1]=cos_psi*sin_phi+cos_theta*cos_phi*sin_psi;
  3888. RESULT[AFFINE_IDX_0_2]=sin_theta*sin_psi;
  3889. RESULT[AFFINE_IDX_0_3]=0.0;
  3890. RESULT[AFFINE_IDX_1_0]=-sin_psi*cos_phi-cos_theta*sin_phi*cos_psi;
  3891. RESULT[AFFINE_IDX_1_1]=-sin_psi*sin_phi+cos_theta*cos_phi*cos_psi;
  3892. RESULT[AFFINE_IDX_1_2]=sin_theta*cos_psi;
  3893. RESULT[AFFINE_IDX_1_3]=0.0;
  3894. RESULT[AFFINE_IDX_2_0]=sin_phi*sin_theta;
  3895. RESULT[AFFINE_IDX_2_1]=-cos_phi*sin_theta;
  3896. RESULT[AFFINE_IDX_2_2]=cos_theta;
  3897. RESULT[AFFINE_IDX_2_3]=0.0;
  3898. RESULT[AFFINE_IDX_3_0]=0.0;
  3899. RESULT[AFFINE_IDX_3_1]=0.0;
  3900. RESULT[AFFINE_IDX_3_2]=0.0;
  3901. RESULT[AFFINE_IDX_3_3]=1.0;
  3902. }
  3903. /* Odie_Affine4x4_Multiply */
  3904. inline extern void Odie_Affine4x4_Multiply(AFFINE R,AFFINE A,AFFINE B){
  3905. double cell_0_0;
  3906. double cell_0_1;
  3907. double cell_0_2;
  3908. double cell_0_3;
  3909. double cell_1_0;
  3910. double cell_1_1;
  3911. double cell_1_2;
  3912. double cell_1_3;
  3913. double cell_2_0;
  3914. double cell_2_1;
  3915. double cell_2_2;
  3916. double cell_2_3;
  3917. double cell_3_0;
  3918. double cell_3_1;
  3919. double cell_3_2;
  3920. double cell_3_3;
  3921. 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];
  3922. 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];
  3923. 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];
  3924. 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];
  3925. 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];
  3926. 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];
  3927. 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];
  3928. 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];
  3929. 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];
  3930. 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];
  3931. 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];
  3932. 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];
  3933. 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];
  3934. 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];
  3935. 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];
  3936. 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];
  3937. R[AFFINE_IDX_0_0]=cell_0_0;
  3938. R[AFFINE_IDX_0_1]=cell_0_1;
  3939. R[AFFINE_IDX_0_2]=cell_0_2;
  3940. R[AFFINE_IDX_0_3]=cell_0_3;
  3941. R[AFFINE_IDX_1_0]=cell_1_0;
  3942. R[AFFINE_IDX_1_1]=cell_1_1;
  3943. R[AFFINE_IDX_1_2]=cell_1_2;
  3944. R[AFFINE_IDX_1_3]=cell_1_3;
  3945. R[AFFINE_IDX_2_0]=cell_2_0;
  3946. R[AFFINE_IDX_2_1]=cell_2_1;
  3947. R[AFFINE_IDX_2_2]=cell_2_2;
  3948. R[AFFINE_IDX_2_3]=cell_2_3;
  3949. R[AFFINE_IDX_3_0]=cell_3_0;
  3950. R[AFFINE_IDX_3_1]=cell_3_1;
  3951. R[AFFINE_IDX_3_2]=cell_3_2;
  3952. R[AFFINE_IDX_3_3]=cell_3_3;
  3953. }
  3954. /* Odie_Affine4x4_Inverse */
  3955. int Odie_Affine4x4_Inverse(AFFINE r, AFFINE m){
  3956. double d00, d01, d02, d03;
  3957. double d10, d11, d12, d13;
  3958. double d20, d21, d22, d23;
  3959. double d30, d31, d32, d33;
  3960. double m00, m01, m02, m03;
  3961. double m10, m11, m12, m13;
  3962. double m20, m21, m22, m23;
  3963. double m30, m31, m32, m33;
  3964. double D;
  3965.  
  3966. m00 = m[AFFINE_IDX_0_0]; m01 = m[AFFINE_IDX_0_1]; m02 = m[AFFINE_IDX_0_2]; m03 = m[AFFINE_IDX_0_3];
  3967. m10 = m[AFFINE_IDX_1_0]; m11 = m[AFFINE_IDX_1_1]; m12 = m[AFFINE_IDX_1_2]; m13 = m[AFFINE_IDX_1_3];
  3968. m20 = m[AFFINE_IDX_2_0]; m21 = m[AFFINE_IDX_2_1]; m22 = m[AFFINE_IDX_2_2]; m23 = m[AFFINE_IDX_2_3];
  3969. m30 = m[AFFINE_IDX_3_0]; m31 = m[AFFINE_IDX_3_1]; m32 = m[AFFINE_IDX_3_2]; m33 = m[AFFINE_IDX_3_3];
  3970.  
  3971. d00 = m11*m22*m33 + m12*m23*m31 + m13*m21*m32 - m31*m22*m13 - m32*m23*m11 - m33*m21*m12;
  3972. d01 = m10*m22*m33 + m12*m23*m30 + m13*m20*m32 - m30*m22*m13 - m32*m23*m10 - m33*m20*m12;
  3973. d02 = m10*m21*m33 + m11*m23*m30 + m13*m20*m31 - m30*m21*m13 - m31*m23*m10 - m33*m20*m11;
  3974. d03 = m10*m21*m32 + m11*m22*m30 + m12*m20*m31 - m30*m21*m12 - m31*m22*m10 - m32*m20*m11;
  3975.  
  3976. d10 = m01*m22*m33 + m02*m23*m31 + m03*m21*m32 - m31*m22*m03 - m32*m23*m01 - m33*m21*m02;
  3977. d11 = m00*m22*m33 + m02*m23*m30 + m03*m20*m32 - m30*m22*m03 - m32*m23*m00 - m33*m20*m02;
  3978. d12 = m00*m21*m33 + m01*m23*m30 + m03*m20*m31 - m30*m21*m03 - m31*m23*m00 - m33*m20*m01;
  3979. d13 = m00*m21*m32 + m01*m22*m30 + m02*m20*m31 - m30*m21*m02 - m31*m22*m00 - m32*m20*m01;
  3980.  
  3981. d20 = m01*m12*m33 + m02*m13*m31 + m03*m11*m32 - m31*m12*m03 - m32*m13*m01 - m33*m11*m02;
  3982. d21 = m00*m12*m33 + m02*m13*m30 + m03*m10*m32 - m30*m12*m03 - m32*m13*m00 - m33*m10*m02;
  3983. d22 = m00*m11*m33 + m01*m13*m30 + m03*m10*m31 - m30*m11*m03 - m31*m13*m00 - m33*m10*m01;
  3984. d23 = m00*m11*m32 + m01*m12*m30 + m02*m10*m31 - m30*m11*m02 - m31*m12*m00 - m32*m10*m01;
  3985.  
  3986. d30 = m01*m12*m23 + m02*m13*m21 + m03*m11*m22 - m21*m12*m03 - m22*m13*m01 - m23*m11*m02;
  3987. d31 = m00*m12*m23 + m02*m13*m20 + m03*m10*m22 - m20*m12*m03 - m22*m13*m00 - m23*m10*m02;
  3988. d32 = m00*m11*m23 + m01*m13*m20 + m03*m10*m21 - m20*m11*m03 - m21*m13*m00 - m23*m10*m01;
  3989. d33 = m00*m11*m22 + m01*m12*m20 + m02*m10*m21 - m20*m11*m02 - m21*m12*m00 - m22*m10*m01;
  3990.  
  3991. D = m00*d00 - m01*d01 + m02*d02 - m03*d03;
  3992.  
  3993.  
  3994. if (D == 0.0)
  3995. {
  3996. /* MatStack_Error("Singular matrix in MInvers."); */
  3997. return TCL_ERROR;
  3998. }
  3999.  
  4000. 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;
  4001. 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;
  4002. 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;
  4003. 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;
  4004. return TCL_OK;
  4005. }
  4006. /* Odie_Affine_From_Normal */
  4007. static void Odie_Affine_From_Normal(AFFINE RESULT,VectorXYZ NORMAL){
  4008. double c,s,C;
  4009. VectorXYZ axis;
  4010.  
  4011. /* If UP and NORMAL are identical (or nearly identical) no rotation */
  4012. if (VectorXYZ_IsZero(NORMAL)) {
  4013. Odie_Affine4x4_Identity(RESULT);
  4014. return;
  4015. }
  4016.  
  4017. if (VectorXYZ_SamePoint(Odie_Up_Direction,NORMAL)) {
  4018. Odie_Affine4x4_Identity(RESULT);
  4019. return;
  4020. }
  4021. VectorXYZ_Cross_Product(axis,Odie_Up_Direction,NORMAL);
  4022. VectorXYZ_Normalize(axis);
  4023. c=VectorXYZ_Dot_Product(Odie_Up_Direction,NORMAL);
  4024. s=sqrt(1-c*c);
  4025. C=1-c;
  4026. RESULT[AFFINE_IDX_0_0]=axis[X_IDX]*axis[X_IDX]*C+c;
  4027. RESULT[AFFINE_IDX_0_1]=axis[X_IDX]*axis[Y_IDX]*C-axis[Z_IDX]*s;
  4028. RESULT[AFFINE_IDX_0_2]=axis[X_IDX]*axis[Z_IDX]*C+axis[Y_IDX]*s;
  4029. RESULT[AFFINE_IDX_0_3]=0.0;
  4030.  
  4031. RESULT[AFFINE_IDX_1_0]=axis[Y_IDX]*axis[X_IDX]*C+axis[Z_IDX]*s;
  4032. RESULT[AFFINE_IDX_1_1]=axis[Y_IDX]*axis[Y_IDX]*C+c;
  4033. RESULT[AFFINE_IDX_1_2]=axis[Y_IDX]*axis[Z_IDX]*C-axis[X_IDX]*s;
  4034. RESULT[AFFINE_IDX_1_3]=0.0;
  4035.  
  4036. RESULT[AFFINE_IDX_2_0]=axis[Z_IDX]*axis[X_IDX]*C-axis[Y_IDX]*s;
  4037. RESULT[AFFINE_IDX_2_1]=axis[Z_IDX]*axis[Y_IDX]*C+axis[X_IDX]*s;
  4038. RESULT[AFFINE_IDX_2_2]=axis[Z_IDX]*axis[Z_IDX]*C+c;
  4039. RESULT[AFFINE_IDX_2_3]=0.0;
  4040.  
  4041. RESULT[AFFINE_IDX_3_0]=0.0;
  4042. RESULT[AFFINE_IDX_3_1]=0.0;
  4043. RESULT[AFFINE_IDX_3_2]=0.0;
  4044. RESULT[AFFINE_IDX_3_3]=1.0;
  4045.  
  4046. }
  4047. /* VectorXY_BBOX_Copy */
  4048. static inline void VectorXY_BBOX_Copy(BBOXXY dest,BBOXXY src){ dest[BBOX_X0_IDX]=src[BBOX_X0_IDX];
  4049. dest[BBOX_Y1_IDX]=src[BBOX_Y1_IDX];
  4050. dest[BBOX_X1_IDX]=src[BBOX_X1_IDX];
  4051. dest[BBOX_X1_IDX]=src[BBOX_X1_IDX];
  4052. }
  4053. /* VectorXY_BBOX_Reset */
  4054. static inline void VectorXY_BBOX_Reset(BBOXXY R){
  4055. R[BBOX_X0_IDX]=R[BBOX_Y0_IDX]=1e99;
  4056. R[BBOX_Y1_IDX]=R[BBOX_X1_IDX]=-1e99;
  4057. }
  4058. /* VectorXY_IsBetween_BBOX */
  4059. static inline int VectorXY_IsBetween_BBOX(VectorXY POINT,VectorXY A,VectorXY B){
  4060. if (POINT[X_IDX]<A[X_IDX] && POINT[X_IDX]<B[X_IDX]) return 0;
  4061. if (POINT[X_IDX]>A[X_IDX] && POINT[X_IDX]>B[X_IDX]) return 0;
  4062. if (POINT[Y_IDX]<A[Y_IDX] && POINT[Y_IDX]<B[Y_IDX]) return 0;
  4063. if (POINT[Y_IDX]>A[Y_IDX] && POINT[Y_IDX]>B[Y_IDX]) return 0;
  4064. return 1;
  4065. }
  4066. /* VectorXY_Within_BBOX */
  4067. static inline int VectorXY_Within_BBOX(VectorXY POINT,BBOXXY bbox){
  4068. if(POINT[X_IDX]<bbox[BBOX_X0_IDX]) return 0;
  4069. if(POINT[Y_IDX]>bbox[BBOX_Y1_IDX]) return 0;
  4070. if(POINT[X_IDX]>bbox[BBOX_X1_IDX]) return 0;
  4071. if(POINT[Y_IDX]<bbox[BBOX_Y0_IDX]) return 0;
  4072. return 1;
  4073. }
  4074. /* XY_Within_BBOX */
  4075. static inline int XY_Within_BBOX(double x, double y,BBOXXY bbox){
  4076. if(x<bbox[BBOX_X0_IDX]) return 0;
  4077. if(y>bbox[BBOX_Y1_IDX]) return 0;
  4078. if(x>bbox[BBOX_X1_IDX]) return 0;
  4079. if(y<bbox[BBOX_Y0_IDX]) return 0;
  4080. return 1;
  4081. }
  4082. /* VectorXY_BBOX_Measure */
  4083. static inline void VectorXY_BBOX_Measure(VectorXY POINT,BBOXXY bbox){
  4084. if(POINT[X_IDX]<bbox[BBOX_X0_IDX]) bbox[BBOX_X0_IDX]=POINT[X_IDX];
  4085. if(POINT[Y_IDX]>bbox[BBOX_Y1_IDX]) bbox[BBOX_Y1_IDX]=POINT[Y_IDX];
  4086. if(POINT[X_IDX]>bbox[BBOX_X1_IDX]) bbox[BBOX_X1_IDX]=POINT[X_IDX];
  4087. if(POINT[Y_IDX]<bbox[BBOX_Y0_IDX]) bbox[BBOX_Y0_IDX]=POINT[Y_IDX];
  4088. }
  4089. /* BBOX_BBOX_Intersect */
  4090. static inline int BBOX_BBOX_Intersect(BBOXXY A,BBOXXY B){
  4091. int a_inside_b=0;
  4092. int b_inside_a=0;
  4093. int i,j;
  4094. if(A[BBOX_X0_IDX]>=B[BBOX_X0_IDX] && A[BBOX_X1_IDX]<=B[BBOX_X1_IDX]) {
  4095. if(A[BBOX_Y1_IDX]<=B[BBOX_Y1_IDX] && A[BBOX_Y0_IDX]>=B[BBOX_Y0_IDX]) {
  4096. a_inside_b=1;
  4097. }
  4098. }
  4099. if(B[BBOX_X0_IDX]>=A[BBOX_X0_IDX] && B[BBOX_X1_IDX]<=A[BBOX_X1_IDX]) {
  4100. if(B[BBOX_Y1_IDX]<=A[BBOX_Y1_IDX] && B[BBOX_Y0_IDX]>=A[BBOX_Y0_IDX]) {
  4101. b_inside_a=1;
  4102. }
  4103. }
  4104. if(a_inside_b && b_inside_a) {
  4105. return 2;
  4106. }
  4107. if(a_inside_b) {
  4108. return 3;
  4109. }
  4110. if(b_inside_a) {
  4111. return 4;
  4112. }
  4113. if(XY_Within_BBOX(B[BBOX_X0_IDX],B[BBOX_Y1_IDX],A)) return 1;
  4114. if(XY_Within_BBOX(B[BBOX_X0_IDX],B[BBOX_Y0_IDX],A)) return 1;
  4115. if(XY_Within_BBOX(B[BBOX_X1_IDX],B[BBOX_Y1_IDX],A)) return 1;
  4116. if(XY_Within_BBOX(B[BBOX_X1_IDX],B[BBOX_Y0_IDX],A)) return 1;
  4117. if(XY_Within_BBOX(A[BBOX_X0_IDX],A[BBOX_Y1_IDX],B)) return 1;
  4118. if(XY_Within_BBOX(A[BBOX_X0_IDX],A[BBOX_Y0_IDX],B)) return 1;
  4119. if(XY_Within_BBOX(A[BBOX_X1_IDX],A[BBOX_Y1_IDX],B)) return 1;
  4120. if(XY_Within_BBOX(A[BBOX_X1_IDX],A[BBOX_Y0_IDX],B)) return 1;
  4121. return 0;
  4122. }
  4123. /* *Matrix_To_quaternion */
  4124. const char *Matrix_To_quaternion(Odie_MatrixObj *matrix,int form){
  4125. if(matrix->form==form) {
  4126. return NULL;
  4127. }
  4128. if(Matrix_To_cartesian(matrix,MATFORM_cartesian)) {
  4129. return "Cannot convert to spherical";
  4130. }
  4131. if(matrix->form==MATFORM_cartesian) {
  4132. odiemath_cartesian_to_spherical(matrix->matrix,matrix->matrix);
  4133. }
  4134. matrix->form=form;
  4135. matrix->rows=4;
  4136. matrix->cols=1;
  4137. return NULL;
  4138. }
  4139. /* *Quaternion_To_TclObj */
  4140. Tcl_Obj *Quaternion_To_TclObj(QUATERNION R){
  4141. Odie_MatrixObj *RESULT;
  4142. RESULT=Odie_MatrixObj_Create(MATFORM_quaternion);
  4143. RESULT->matrix[QW_IDX]=R[QW_IDX];
  4144. RESULT->matrix[QX_IDX]=R[QX_IDX];
  4145. RESULT->matrix[QY_IDX]=R[QY_IDX];
  4146. RESULT->matrix[QZ_IDX]=R[QZ_IDX];
  4147. return Matrix_To_TclObj(RESULT);
  4148. }
  4149. /* Odie_GetQuaternionFromTclObj */
  4150. int Odie_GetQuaternionFromTclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,QUATERNION R){
  4151. Tcl_Obj **elemPtrs;
  4152. int cols,i;
  4153. if(objPtr->typePtr) {
  4154. if(objPtr->typePtr->setFromAnyProc==&MatrixObj_setFromAnyProc) {
  4155. /*
  4156. ** Object is a matrix
  4157. */
  4158. const char *err;
  4159. Odie_MatrixObj *value=objPtr->internalRep.otherValuePtr;
  4160. err=Matrix_To_cartesian(value,MATFORM_quaternion);
  4161. if(err) {
  4162. Tcl_AppendResult(interp,err,NULL);
  4163. return TCL_ERROR;
  4164. }
  4165. R[QW_IDX]=value->matrix[QW_IDX];
  4166. R[QX_IDX]=value->matrix[QX_IDX];
  4167. R[QY_IDX]=value->matrix[QY_IDX];
  4168. R[QZ_IDX]=value->matrix[QZ_IDX];
  4169. return TCL_OK;
  4170. }
  4171. }
  4172.  
  4173. /* Step one, Measure the matrix */
  4174. if(Tcl_ListObjGetElements(interp, objPtr, &cols, &elemPtrs)) return TCL_ERROR;
  4175. if(cols<4) {
  4176. Tcl_SetObjResult(interp,Tcl_NewStringObj("Needs 3 columns",-1));
  4177. return TCL_ERROR;
  4178. }
  4179. for(i=0;i<4;i++) {
  4180. double temp;
  4181. if(Tcl_GetDoubleFromObj(interp, elemPtrs[i], &temp)) return TCL_ERROR;
  4182. R[i]=temp;
  4183. }
  4184. return TCL_OK;
  4185. }
  4186. /* Quaternion_Add */
  4187. void Quaternion_Add(QUATERNION r, QUATERNION p, QUATERNION q){
  4188. r[QW_IDX]=p[QW_IDX]+q[QW_IDX];
  4189. r[QX_IDX]=p[QX_IDX]+q[QX_IDX];
  4190. r[QY_IDX]=p[QY_IDX]+q[QY_IDX];
  4191. r[QZ_IDX]=p[QZ_IDX]+q[QZ_IDX];
  4192. }
  4193. /* Quaternion_Subtract */
  4194. void Quaternion_Subtract(QUATERNION r, QUATERNION p, QUATERNION q){
  4195. r[QW_IDX]=p[QW_IDX]-q[QW_IDX];
  4196. r[QX_IDX]=p[QX_IDX]-q[QX_IDX];
  4197. r[QY_IDX]=p[QY_IDX]-q[QY_IDX];
  4198. r[QZ_IDX]=p[QZ_IDX]-q[QZ_IDX];
  4199. }
  4200. /* Quaternion_Multiply */
  4201. void Quaternion_Multiply(QUATERNION r, QUATERNION p, QUATERNION q){
  4202. double t0, t1, t2;
  4203.  
  4204. 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];
  4205. 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];
  4206. 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];
  4207. 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];
  4208. r[QW_IDX] = t0;
  4209. r[QX_IDX] = t1;
  4210. r[QY_IDX] = t2;
  4211. }
  4212. /* Quaternion_Divide */
  4213. void Quaternion_Divide(QUATERNION r, QUATERNION p, QUATERNION q){
  4214. QUATERNION Q,t,s;
  4215. double a;
  4216. Q[QW_IDX]=q[QW_IDX];
  4217. Q[QX_IDX]=-q[QX_IDX];
  4218. Q[QY_IDX]=-q[QY_IDX];
  4219. Q[QZ_IDX]=-q[QZ_IDX];
  4220. Quaternion_Multiply(t,p,Q);
  4221. Quaternion_Multiply(s,Q,Q);
  4222. a=1.0/s[QW_IDX];
  4223. r[QW_IDX]=t[QW_IDX]*a;
  4224. r[QX_IDX]=t[QX_IDX]*a;
  4225. r[QY_IDX]=t[QY_IDX]*a;
  4226. r[QZ_IDX]=t[QY_IDX]*a;
  4227. }
  4228. /* Quaternion_Square_Root */
  4229. void Quaternion_Square_Root(QUATERNION s, QUATERNION q){
  4230. double len,m;
  4231. double a,b;
  4232. QUATERNION r;
  4233.  
  4234. len=sqrt(q[QW_IDX]*q[QW_IDX]+q[QX_IDX]*q[QX_IDX]+q[QY_IDX]*q[QY_IDX]);
  4235. if(len==0) {
  4236. s[QW_IDX]=s[QX_IDX]=s[QY_IDX]=s[QZ_IDX]=0.0;
  4237. return;
  4238. }
  4239. r[QW_IDX]=q[QW_IDX]*1.0;
  4240. r[QX_IDX]=q[QX_IDX]*1.0;
  4241. r[QY_IDX]=q[QY_IDX]*1.0;
  4242. r[QZ_IDX]=0.0;
  4243. m=1.0/sqrt(r[QW_IDX]*r[QW_IDX]+r[QX_IDX]*r[QX_IDX]);
  4244. a=sqrt((1.0+r[QY_IDX])*0.5);
  4245. b=sqrt((1.0-r[QY_IDX])*0.5);
  4246. s[QW_IDX]=sqrt(len)*b*r[QW_IDX]*m;
  4247. s[QX_IDX]=sqrt(len)*b*r[QX_IDX]*m;
  4248. s[QY_IDX]=sqrt(len)*a;
  4249. s[QZ_IDX]=q[QZ_IDX];
  4250. }
  4251. /* Quaternion_Square */
  4252. void Quaternion_Square(QUATERNION r, QUATERNION q){
  4253. double a;
  4254. a=2.0*q[QW_IDX];
  4255. 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];
  4256. r[QX_IDX]=a*q[QX_IDX];
  4257. r[QY_IDX]=a*q[QY_IDX];
  4258. r[QZ_IDX]=a*q[QZ_IDX];
  4259. }
  4260. /* EulerRotation_To_Quaternion */
  4261. void EulerRotation_To_Quaternion(QUATERNION q,double heading, double attitude, double bank){
  4262. // Assuming the angles are in radians.
  4263. double c1 = cos(heading*0.5);
  4264. double s1 = sin(heading*0.5);
  4265. double c2 = cos(attitude*0.5);
  4266. double s2 = sin(attitude*0.5);
  4267. double c3 = cos(bank*0.5);
  4268. double s3 = sin(bank*0.5);
  4269. double c1c2 = c1*c2;
  4270. double s1s2 = s1*s2;
  4271. q[QW_IDX] =c1c2*c3 - s1s2*s3;
  4272. q[QX_IDX] =c1c2*s3 + s1s2*c3;
  4273. q[QY_IDX] =s1*c2*c3 + c1*s2*s3;
  4274. q[QZ_IDX] =c1*s2*c3 - s1*c2*s3;
  4275. }
  4276. /* VectorXYZ_Rotate_by_Quaternion */
  4277. void VectorXYZ_Rotate_by_Quaternion(VECTORXYZ r, QUATERNION p, VECTORXYZ A){
  4278. double w=p[QW_IDX]; // real part of quaternion
  4279. double x=p[QX_IDX]; // imaginary i part of quaternion
  4280. double y=p[QY_IDX]; // imaginary j part of quaternion
  4281. double z=p[QZ_IDX]; // imaginary k part of quaternion
  4282. double px=A[X_IDX];
  4283. double py=A[Y_IDX];
  4284. double pz=A[Z_IDX];
  4285. 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;
  4286. 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;
  4287. 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;
  4288. }
  4289. /* Quaternion_To_EulerRotation */
  4290. void Quaternion_To_EulerRotation (VECTORXYZ r, QUATERNION p){
  4291. double sqw = p[QW_IDX]*p[QW_IDX];
  4292. double sqx = p[QX_IDX]*p[QX_IDX];
  4293. double sqy = p[QY_IDX]*p[QY_IDX];
  4294. double sqz = p[QZ_IDX]*p[QZ_IDX];
  4295. double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
  4296. double test = p[QX_IDX]*p[QY_IDX] + p[QZ_IDX]*p[QW_IDX];
  4297.  
  4298. if (test > 0.499*unit) { // singularity at north pole
  4299. r[EULER_HEADING] = 2 * atan2(p[QX_IDX],p[QW_IDX]);
  4300. r[EULER_ATTITUDE] = M_PI*0.5;
  4301. r[EULER_BANK] = 0;
  4302. return;
  4303. }
  4304. if (test < -0.499*unit) { // singularity at south pole
  4305. r[EULER_HEADING] = -2 * atan2(p[QX_IDX],p[QW_IDX]);
  4306. r[EULER_ATTITUDE] = M_PI*-0.5;
  4307. r[EULER_BANK] = 0;
  4308. return;
  4309. }
  4310. r[EULER_HEADING] = atan2(2*p[QY_IDX]*p[QW_IDX]-2*p[QX_IDX]*p[QZ_IDX] , sqx - sqy - sqz + sqw);
  4311. r[EULER_ATTITUDE] = asin(2*test/unit);
  4312. r[EULER_BANK] = atan2(2*p[QX_IDX]*p[QW_IDX]-2*p[QY_IDX]*p[QZ_IDX] , -sqx + sqy - sqz + sqw);
  4313. }
  4314. /* Quaternion_From_Normal */
  4315. static inline void Quaternion_From_Normal(QUATERNION RESULT,VectorXYZ from,VectorXYZ to){
  4316. VectorXYZ H;
  4317. VectorXYZ_Add(H,from,to);
  4318. /* Special case?
  4319. if(VectorXYZ_IsZero(H)) {
  4320. RESULT[QW_IDX]=0.0;
  4321. RESULT[QX_IDX]=1.0;
  4322. RESULT[QY_IDX]=0.0;
  4323. RESULT[QZ_IDX]=0.0;
  4324. }
  4325. */
  4326. VectorXYZ_Normalize(H);
  4327. RESULT[QW_IDX]=VectorXYZ_Dot_Product(from,H);
  4328. RESULT[QX_IDX]=from[Y_IDX]*H[Z_IDX] - from[Z_IDX]*H[Y_IDX];
  4329. RESULT[QY_IDX]=from[Z_IDX]*H[X_IDX] - from[X_IDX]*H[Z_IDX];
  4330. RESULT[QZ_IDX]=from[X_IDX]*H[Y_IDX] - from[Y_IDX]*H[X_IDX];
  4331. }
  4332. /* *Odie_Matrix_To_Fit */
  4333. static Odie_MatrixObj *Odie_Matrix_To_Fit(Odie_MatrixObj *A,Odie_MatrixObj *B){
  4334. Odie_MatrixObj *C;
  4335. int size_a;
  4336. int size_b;
  4337. if(A->rows==B->rows && A->cols==B->cols) {
  4338. if(A->form && A->form==B->form) {
  4339. C=Odie_MatrixObj_Create(A->form);
  4340. } else {
  4341. C=Odie_MatrixObj_Create_NXN(A->rows,A->cols);
  4342. }
  4343. return C;
  4344. }
  4345. size_a=A->rows*A->cols;
  4346. size_b=B->rows*B->cols;
  4347. if(size_a<size_b) {
  4348. C=Odie_MatrixObj_Create_NXN(size_b,1);
  4349. } else {
  4350. C=Odie_MatrixObj_Create_NXN(size_a,1);
  4351. }
  4352. return C;
  4353. }
  4354. /* Vector_GridScaler */
  4355. static inline double Vector_GridScaler(double x,double grid,double grain){
  4356. double q;
  4357. q=grid*round(x/grid);
  4358. if((x-q)>grain) {
  4359. q+=grain;
  4360. }
  4361. return q;
  4362. }
  4363. /* Vector2d_SamePoint */
  4364. inline extern int Vector2d_SamePoint(double x0, double y0, double x1, double y1){
  4365. /*
  4366. ** Return TRUE if x0,y0 is the same point as x1,y1
  4367. */
  4368. return floatCompare(x0,x1)==0 && floatCompare(y0,y1)==0;
  4369. }
  4370. /* Vector2d_IsColinear */
  4371. inline extern int Vector2d_IsColinear(double x1,double y1,double x2,double y2,double x3,double y3){
  4372. /* Detect of two lines are colinear */
  4373. double c=(x3-x1)*(y2-y1)-(y3-y1)*(x2-x1);
  4374. if(fabs(c) < __FLT_EPSILON__) return 1;
  4375. return 0;
  4376. }
  4377. /* Vector2d_LineLineCoincident */
  4378. inline extern int Vector2d_LineLineCoincident(
  4379. double ax1, double ay1,
  4380. double ax2, double ay2,
  4381. double bx1, double by1,
  4382. double bx2, double by2){
  4383. double x,y;
  4384. int c=0;
  4385. /* Check if wall completely wraps other wall */
  4386. if(Vector2d_SamePoint(ax1,ay1,bx1,by1)) {
  4387. if(Vector2d_SamePoint(ax2,ay2,bx2,by2)) return 6;
  4388. if(Vector2d_PointIsOnSegment(ax2,ay2,bx1,by1,bx2,by2)) return 2;
  4389. return 0;
  4390. }
  4391. if(Vector2d_SamePoint(ax2,ay2,bx1,by1)) {
  4392. if(Vector2d_SamePoint(ax1,ay1,bx2,by2)) return 6;
  4393. if(Vector2d_PointIsOnSegment(ax1,ay1,bx1,by1,bx2,by2)) return 4;
  4394. return 0;
  4395. }
  4396. if(Vector2d_SamePoint(ax1,ay1,bx2,by2)) {
  4397. if(Vector2d_PointIsOnSegment(ax2,ay2,bx1,by1,bx2,by2)) return 2;
  4398. return 0;
  4399. }
  4400. if(Vector2d_SamePoint(ax2,ay2,bx2,by2)) {
  4401. if(Vector2d_PointIsOnSegment(ax1,ay1,bx1,by1,bx2,by2)) return 4;
  4402. return 0;
  4403. }
  4404. c=ODIE_Math_LineLineIntersect(ax1,ay1,ax2,ay2,bx1,by1,bx2,by2,&x,&y);
  4405. if(c) {
  4406. if(Vector2d_SamePoint(ax1,ay1,x,y)) {
  4407. return 0;
  4408. }
  4409. if(Vector2d_SamePoint(ax2,ay2,x,y)) {
  4410. return 0;
  4411. }
  4412. }
  4413. return c;
  4414. }
  4415. /* ODIE_Math_LineLineIntersect */
  4416. int ODIE_Math_LineLineIntersect(
  4417. double ax1, double ay1,
  4418. double ax2, double ay2,
  4419. double bx1, double by1,
  4420. double bx2, double by2,
  4421. double *x, double *y){
  4422. /*
  4423. ** Detect the intersection of two lines
  4424. ** Adapted from: http://paulbourke.net/geometry/lineline2d/pdb.c
  4425. */
  4426. double mua,mub;
  4427. double denom,numera,numerb;
  4428.  
  4429.  
  4430.  
  4431. denom = (by2-by1) * (ax2-ax1) - (bx2-bx1) * (ay2-ay1);
  4432. numera = (bx2-bx1) * (ay1-by1) - (by2-by1) * (ax1-bx1);
  4433. numerb = (ax2-ax1) * (ay1-by1) - (ay2-ay1) * (ax1-bx1);
  4434.  
  4435. /* Are the line parallel */
  4436. if (ODIE_Real_Is_Zero(denom)) {
  4437. if (ODIE_Real_Is_Zero(numera) && ODIE_Real_Is_Zero(numerb)) {
  4438. /* Are the line coincident? */
  4439. int within=1;
  4440. if(ax2>ax1) {
  4441. if(bx1>ax2 && bx2>ax2) {
  4442. within=0;
  4443. } else if(bx1<ax1 && bx2<ax1) {
  4444. within=0;
  4445. }
  4446. } else {
  4447. if(bx1>ax1 && bx2>ax1) {
  4448. within=0;
  4449. } else if(bx1<ax2 && bx2<ax2) {
  4450. within=0;
  4451. }
  4452. }
  4453. if(ay2>ay1) {
  4454. if(by1>ay2 && by2>ay2) {
  4455. within=0;
  4456. } else if(by1<ay1 && by2<ay1) {
  4457. within=0;
  4458. }
  4459. } else {
  4460. if(by1>ay1 && by2>ay1) {
  4461. within=0;
  4462. } else if(by1<ay2 && by2<ay2) {
  4463. within=0;
  4464. }
  4465. }
  4466. if(within) {
  4467. *x = (ax1 + ax2) / 2;
  4468. *y = (ay1 + ay2) / 2;
  4469. return(2);
  4470. }
  4471. }
  4472. *x = 0;
  4473. *y = 0;
  4474. return(0);
  4475. }
  4476.  
  4477. /* Is the intersection along the the segments */
  4478. mua = numera / denom;
  4479. mub = numerb / denom;
  4480. if (mua < 0 || mua > 1 || mub < 0 || mub > 1) {
  4481. *x = 0;
  4482. *y = 0;
  4483. return(0);
  4484. }
  4485. *x = ax1 + mua * (ax2 - ax1);
  4486. *y = ay1 + mua * (ay2 - ay1);
  4487. return(1);
  4488. }
  4489. /* Vector2d_PointIsOnSegment */
  4490. static inline int Vector2d_PointIsOnSegment(double x,double y,double x1,double y1,double x2,double y2){
  4491. /* Returns:
  4492. ** 0 - not on segment
  4493. ** 1 - along segment
  4494. ** 2 - endpoint of segment
  4495. */
  4496. /* Bounding box check */
  4497. if(x1>x2) {
  4498. if(x>(x1+OdieGrain)) return 0;
  4499. if(x<(x2-OdieGrain)) return 0;
  4500. } else {
  4501. if(x>(x2+OdieGrain)) return 0;
  4502. if(x<(x1-OdieGrain)) return 0;
  4503. }
  4504. if(y1>y2) {
  4505. if(y>(y1+OdieGrain)) return 0;
  4506. if(y<(y2-OdieGrain)) return 0;
  4507. } else {
  4508. if(y>(y2+OdieGrain)) return 0;
  4509. if(y<(y1-OdieGrain)) return 0;
  4510. }
  4511. if(Vector2d_SamePoint(x,y,x1,y1)) return 2;
  4512. if(Vector2d_SamePoint(x,y,x2,y2)) return 2;
  4513.  
  4514. /* Detect of two lines are colinear */
  4515. if (Vector2d_IsColinear(x,y,x1,y1,x2,y2)) {
  4516. return 1;
  4517. }
  4518. return 0;
  4519. }
  4520. /* ODIE_Math_LineCircleIntersect */
  4521. int ODIE_Math_LineCircleIntersect(
  4522. double p1_x, double p1_y,
  4523. double p2_x, double p2_y,
  4524. double sc_x, double sc_y,
  4525. double r,
  4526. double *mu1, double *mu2){
  4527. /*
  4528. ** Detect the intersection of a line and a circle
  4529. ** Adapted from: http://http://paulbourke.net/geometry/circlesphere/raysphere.c
  4530. */
  4531. double a,b,c;
  4532. double bb4ac;
  4533. double dp_x,dp_y;
  4534. *mu1 = 0;
  4535. *mu2 = 0;
  4536.  
  4537. dp_x = p2_x - p1_x;
  4538. dp_y = p2_y - p1_y;
  4539. a = dp_x * dp_x + dp_y * dp_y;
  4540. b = 2 * (dp_x * (p1_x - sc_x) + dp_y * (p1_y - sc_y));
  4541. c = sc_x * sc_x + sc_y * sc_y;
  4542. c += p1_x * p1_x + p1_y * p1_y;
  4543. c -= 2 * (sc_x * p1_x + sc_y * p1_y);
  4544. c -= r * r;
  4545. bb4ac = b * b - 4 * a * c;
  4546. if (ODIE_Real_Is_Zero(a) || bb4ac < 0) {
  4547. return(0);
  4548. }
  4549.  
  4550. *mu1 = (-b + sqrt(bb4ac)) / (2 * a);
  4551. *mu2 = (-b - sqrt(bb4ac)) / (2 * a);
  4552.  
  4553. return(1);
  4554. }
  4555. /* Vector3d_SamePoint */
  4556. inline extern int Vector3d_SamePoint(double x0, double y0, double z0, double x1, double y1, double z1){
  4557. /*
  4558. ** Return TRUE if x0,y0 is the same point as x1,y1
  4559. */
  4560. return floatCompare(x0,x1)==0 && floatCompare(y0,y1)==0 && floatCompare(z0,z1)==0;
  4561. }
  4562. /* odiemath_polar_to_vec2 */
  4563. void odiemath_polar_to_vec2(VECTORXY A,VECTORXY R){
  4564. /*
  4565. ** Make a copy of the input matrix in case we are outputing back
  4566. ** to the same pointer
  4567. */
  4568. double radius,theta;
  4569. radius=A[RADIUS];
  4570. theta=A[THETA];
  4571. R[X_IDX]=radius*cos(theta);
  4572. R[Y_IDX]=radius*sin(theta);
  4573. }
  4574. /* odiemath_vec2_to_polar */
  4575. void odiemath_vec2_to_polar(VECTORXY A,VECTORXY R){
  4576. double x,y;
  4577. x=A[X_IDX];
  4578. y=A[Y_IDX];
  4579. R[RADIUS]=sqrt(x*x + y*y);
  4580. R[THETA] =atan2(y,x);
  4581. }
  4582. /* *Matrix_To_vector_xy */
  4583. const char *Matrix_To_vector_xy(Odie_MatrixObj *matrix,int form){
  4584. if(matrix->form==form) {
  4585. return NULL;
  4586. }
  4587. switch(matrix->form) {
  4588. case MATFORM_vector_xy:
  4589. return TCL_OK;
  4590. case MATFORM_vector_xyz: {
  4591. return NULL;
  4592. }
  4593. case MATFORM_cylindrical: {
  4594. odiemath_vec2_to_polar(matrix->matrix,matrix->matrix);
  4595. matrix->form=MATFORM_cartesian;
  4596. return NULL;
  4597. }
  4598. }
  4599. return Matrix_To_cartesian(matrix,MATFORM_vector_xy);
  4600. }
  4601. /* *VectorXY_To_TclObj */
  4602. Tcl_Obj *VectorXY_To_TclObj(VectorXY R){
  4603. Odie_MatrixObj *RESULT;
  4604. RESULT=Odie_MatrixObj_Create(MATFORM_vector_xy);
  4605. RESULT->matrix[X_IDX]=R[X_IDX];
  4606. RESULT->matrix[Y_IDX]=R[Y_IDX];
  4607. return Matrix_To_TclObj(RESULT);
  4608. }
  4609. /* Odie_GetVectorXYFromTclObj */
  4610. int Odie_GetVectorXYFromTclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,VectorXY R){
  4611. Tcl_Obj **elemPtrs;
  4612. int cols,i;
  4613. if(objPtr->typePtr) {
  4614. if(objPtr->typePtr->setFromAnyProc==&MatrixObj_setFromAnyProc) {
  4615. /*
  4616. ** Object is a matrix
  4617. */
  4618. const char *err;
  4619. Odie_MatrixObj *value=objPtr->internalRep.otherValuePtr;
  4620. err=Matrix_To_cartesian(value,MATFORM_vector_xy);
  4621. if(err) {
  4622. Tcl_AppendResult(interp,err,NULL);
  4623. return TCL_ERROR;
  4624. }
  4625. R[X_IDX]=value->matrix[X_IDX];
  4626. R[Y_IDX]=value->matrix[Y_IDX];
  4627. return TCL_OK;
  4628. }
  4629. }
  4630.  
  4631. /* Step one, Measure the matrix */
  4632. if(Tcl_ListObjGetElements(interp, objPtr, &cols, &elemPtrs)) return TCL_ERROR;
  4633. for(i=0;i<2;i++) {
  4634. double temp;
  4635. if(cols<=i) {
  4636. R[i]=0.0;
  4637. } else {
  4638. if(Tcl_GetDoubleFromObj(interp, elemPtrs[i], &temp)) return TCL_ERROR;
  4639. R[i]=temp;
  4640. }
  4641. }
  4642. return TCL_OK;
  4643. }
  4644. /* VectorXY_GridAlign */
  4645. static inline void VectorXY_GridAlign(VECTORXYZ A,double grid){
  4646. double x,q,grain;
  4647. grain=grid*0.5;
  4648. if(grid<=0) return;
  4649. A[X_IDX]=Vector_GridScaler(A[X_IDX],grid,grain);
  4650. A[Y_IDX]=Vector_GridScaler(A[Y_IDX],grid,grain);
  4651. }
  4652. /* VectorXY_SamePoint */
  4653. inline extern int VectorXY_SamePoint(VectorXY A, VectorXY B){
  4654. if(fabs(B[X_IDX]-A[X_IDX])>Vector_Tolerance) return 0;
  4655. if(fabs(B[Y_IDX]-A[Y_IDX])>Vector_Tolerance) return 0;
  4656. return 1;
  4657. }
  4658. /* VectorXY_SameGridPoint */
  4659. inline extern int VectorXY_SameGridPoint(VectorXY A, VectorXY B,double grid){
  4660. if(fabs(B[X_IDX]-A[X_IDX])>grid) return 0;
  4661. if(fabs(B[Y_IDX]-A[Y_IDX])>grid) return 0;
  4662. return 1;
  4663. }
  4664. /* VectorXY_Add */
  4665. inline extern void VectorXY_Add(VECTORXY C,VECTORXY A,VECTORXY B){
  4666. C[X_IDX]=B[X_IDX]+A[X_IDX];
  4667. C[Y_IDX]=B[Y_IDX]+A[Y_IDX];
  4668. }
  4669. /* VectorXY_Subtract */
  4670. inline extern void VectorXY_Subtract(VECTORXY C,VECTORXY A,VECTORXY B){
  4671. C[X_IDX]=A[X_IDX]-B[X_IDX];
  4672. C[Y_IDX]=A[Y_IDX]-B[Y_IDX];
  4673. }
  4674. /* VectorXY_Midpoint */
  4675. static inline void VectorXY_Midpoint(VECTORXY C,VECTORXY A,VECTORXY B){
  4676. C[X_IDX]=(B[X_IDX]-A[X_IDX])*0.5+A[X_IDX];
  4677. C[Y_IDX]=(B[Y_IDX]-A[Y_IDX])*0.5+A[Y_IDX];
  4678. }
  4679. /* VectorXY_Normalize */
  4680. inline extern void VectorXY_Normalize(VECTORXY A){
  4681. double length=sqrt(A[X_IDX]*A[X_IDX]+A[Y_IDX]*A[Y_IDX]);
  4682. if(length < __FLT_EPSILON__ ) {
  4683. return;
  4684. }
  4685. A[X_IDX]/=length;
  4686. A[Y_IDX]/=length;
  4687. }
  4688. /* VectorXY_Round */
  4689. inline extern void VectorXY_Round(VECTORXY A){
  4690. A[X_IDX]=round(A[X_IDX]);
  4691. A[Y_IDX]=round(A[Y_IDX]);
  4692. }
  4693. /* VectorXY_Set */
  4694. inline extern void VectorXY_Set(VECTORXY A,VECTORXY B){
  4695. A[X_IDX]=B[X_IDX];
  4696. A[Y_IDX]=B[Y_IDX];
  4697. }
  4698. /* VectorXY_crossProduct */
  4699. inline extern double VectorXY_crossProduct(VectorXY A, VectorXY B, VectorXY P){
  4700. 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]);
  4701. if(fabs(r) < __FLT_EPSILON__ ) {
  4702. return 0.0;
  4703. }
  4704. return r;
  4705. }
  4706. /* VectorXY_Dot_Product */
  4707. inline extern double VectorXY_Dot_Product(VectorXY A, VectorXY B,VectorXY C){
  4708. 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]);
  4709. if(fabs(r) < __FLT_EPSILON__ ) {
  4710. return 0.0;
  4711. }
  4712. return r;
  4713. }
  4714. /* VectorXY_BendDirection */
  4715. inline extern int VectorXY_BendDirection(VectorXY A, VectorXY B, VectorXY C){
  4716. /*
  4717. ** Consider traveling from VectorXY A to B to C. If you have to make
  4718. ** a left-turn at B, then this routine returns -1. If C is on the
  4719. ** same line as A and B then return 0. If you make a right turn
  4720. ** at B in order to reach C then return +1.
  4721. */
  4722.  
  4723. /* Algorithm: Rotate AB 90 degrees counter-clockwise. Take
  4724. ** the dot product with BP. The dot produce will be the product
  4725. ** of two (non-negative) magnitudes and the cosine of the angle. So if
  4726. ** the dot product is positive, the bend is to the left, or to the right if
  4727. ** the dot product is negative.
  4728. */
  4729. 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]);
  4730. if(fabs(r) < __FLT_EPSILON__ ) return 0;
  4731. if(r>0.0) return -1;
  4732. return 1;
  4733. }
  4734. /* VectorXY_strictlyRightOf */
  4735. inline extern int VectorXY_strictlyRightOf(VectorXY A, VectorXY B, VectorXY P){
  4736. /*
  4737. ** This is a variation on rightOf(). Return 0 only if BP is a continuation
  4738. ** of the line AB. If BP doubles back on AB then return -1.
  4739. */
  4740. int c = VectorXY_BendDirection(A,B,P);
  4741. if( c==0 ){
  4742. 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]);
  4743. c = r<0.0 ? +1 : -1;
  4744. }
  4745. return c;
  4746. }
  4747. /* VectorXY_intersect */
  4748. inline extern int VectorXY_intersect(VectorXY A, VectorXY B, VectorXY C, VectorXY D){
  4749. /*
  4750. ** Return TRUE if segments AB and CD intersect
  4751. */
  4752. return VectorXY_BendDirection(A,B,C)*VectorXY_BendDirection(A,B,D)<0 && VectorXY_BendDirection(C,D,A)*VectorXY_BendDirection(C,D,B)<0;
  4753. }
  4754. /* VectorXY_angleOf */
  4755. inline extern double VectorXY_angleOf(VectorXY A, VectorXY B, VectorXY C){
  4756. /*
  4757. ** Compute angle ABC measured counter-clockwise from AB. Return the
  4758. ** result.
  4759. **
  4760. ** This does not need to be a true angular measure as long as it is
  4761. ** monotonically increasing.
  4762. */
  4763. double a1, a2, a3;
  4764. if( VectorXY_SamePoint(A,C) ){
  4765. return M_PI;
  4766. }
  4767. a1 = atan2(B[Y_IDX] - A[Y_IDX], B[X_IDX] - A[X_IDX]);
  4768. a2 = atan2(C[Y_IDX] - B[Y_IDX], C[X_IDX] - B[X_IDX]);
  4769. a3 = a2-a1;
  4770. if( a3>M_PI ) a3 -= 2.0*M_PI;
  4771. if( a3<=-M_PI ) a3 += 2.0*M_PI;
  4772. return a3;
  4773. }
  4774. /* VectorXY_Angle_Three_Point */
  4775. inline extern double VectorXY_Angle_Three_Point(VectorXY A, VectorXY B, VectorXY C){
  4776. /*
  4777. ** Compute angle ABC measured counter-clockwise from AB. Return the
  4778. ** result.
  4779. **
  4780. ** This does not need to be a true angular measure as long as it is
  4781. ** monotonically increasing.
  4782. */
  4783. double a1, a2, a3;
  4784. if( VectorXY_SamePoint(A,C) ){
  4785. return M_PI;
  4786. }
  4787. a1 = atan2(B[Y_IDX] - A[Y_IDX], B[X_IDX] - A[X_IDX]);
  4788. a2 = atan2(C[Y_IDX] - B[Y_IDX], C[X_IDX] - B[X_IDX]);
  4789. a3 = a2-a1;
  4790. if( a3>M_PI ) a3 -= 2.0*M_PI;
  4791. if( a3<=-M_PI ) a3 += 2.0*M_PI;
  4792. return a3;
  4793. }
  4794. /* VectorXY_distance_squared */
  4795. inline extern double VectorXY_distance_squared(VectorXY A, VectorXY B){
  4796. /*
  4797. ** Return the squared distance between two VectorXYs.
  4798. */
  4799. double dx = B[X_IDX] - A[X_IDX];
  4800. double dy = B[Y_IDX] - A[Y_IDX];
  4801. return dx*dx + dy*dy;
  4802. }
  4803. /* VectorXY_distance */
  4804. inline extern double VectorXY_distance(VectorXY A, VectorXY B){
  4805. /*
  4806. ** Return the distance between two VectorXYs.
  4807. */
  4808. double dx = B[X_IDX] - A[X_IDX];
  4809. double dy = B[Y_IDX] - A[Y_IDX];
  4810. return sqrt(dx*dx + dy*dy);
  4811. }
  4812. /* odiemath_cartesian_to_spherical */
  4813. void odiemath_cartesian_to_spherical(VECTOR A,VECTOR R){
  4814. double S;
  4815. /* Work with a copy in case we are writing back to the same pointer */
  4816. double radius,theta,phi;
  4817. radius=VectorXYZ_Magnitude(A);
  4818. S=sqrt(A[X_IDX]*A[X_IDX]+A[Y_IDX]*A[Y_IDX]);
  4819. if (A[X_IDX] > 0.0) {
  4820. theta =asin(A[Y_IDX]/S);
  4821. } else {
  4822. theta =M_PI - asin(A[Y_IDX]/S);
  4823. }
  4824. phi =asin(A[Z_IDX]/R[RADIUS]);
  4825.  
  4826. R[RADIUS]=radius;
  4827. R[THETA]=theta;
  4828. R[PHI]=phi;
  4829. }
  4830. /* odiemath_spherical_to_cartesian */
  4831. void odiemath_spherical_to_cartesian(VECTOR A,VECTOR R){
  4832. /*
  4833. ** Make a copy of the input matrix in case we are outputing back
  4834. ** to the same pointer
  4835. */
  4836. double radius,theta,phi;
  4837. radius=A[RADIUS];
  4838. theta=A[THETA];
  4839. phi=A[PHI];
  4840. R[X_IDX]=radius*cos(theta)*cos(phi);
  4841. R[Y_IDX]=radius*sin(theta)*cos(phi);
  4842. R[Z_IDX]=radius*sin(phi);
  4843. }
  4844. /* odiemath_cylindrical_to_cartesian */
  4845. void odiemath_cylindrical_to_cartesian(VECTOR A,VECTOR R){
  4846. /*
  4847. ** Make a copy of the input matrix in case we are outputing back
  4848. ** to the same pointer
  4849. */
  4850. double radius,theta,z;
  4851. radius=A[RADIUS];
  4852. theta=A[THETA];
  4853. z=A[Z_IDX];
  4854. R[X_IDX]=radius*cos(theta);
  4855. R[Y_IDX]=radius*sin(theta);
  4856. R[Z_IDX]=z;
  4857. }
  4858. /* odiemath_cartesian_to_cylindrical */
  4859. void odiemath_cartesian_to_cylindrical(VECTOR A,VECTOR R){
  4860. /*
  4861. ** Make a copy of the input matrix in case we are outputing back
  4862. ** to the same pointer
  4863. */
  4864. double x,y,z;
  4865. x=A[X_IDX];
  4866. y=A[Y_IDX];
  4867. z=A[Z_IDX];
  4868. R[RADIUS]=sqrt(x*x + y*y);
  4869. R[THETA] =atan2(y,x);
  4870. R[Z_IDX] =z;
  4871. }
  4872. /* *Matrix_To_cartesian */
  4873. const char *Matrix_To_cartesian(MATOBJ *matrix,int form){
  4874. if(matrix->form==form) {
  4875. return NULL;
  4876. }
  4877. switch(matrix->form) {
  4878. case MATFORM_vector_xy:
  4879. case MATFORM_vector_xyz:
  4880. case MATFORM_vector_xyzw:
  4881. break;
  4882. case MATFORM_spherical:
  4883. {
  4884. odiemath_spherical_to_cartesian(matrix->matrix,matrix->matrix);
  4885. matrix->form=form;
  4886. break;
  4887. }
  4888. case MATFORM_polar:
  4889. case MATFORM_cylindrical: {
  4890. odiemath_cylindrical_to_cartesian(matrix->matrix,matrix->matrix);
  4891. matrix->form=form;
  4892. break;
  4893. }
  4894. default: {
  4895. if(matrix->rows==1) {
  4896. int temp=matrix->cols;
  4897. matrix->cols=matrix->rows;
  4898. matrix->rows=temp;
  4899. }
  4900. if(matrix->cols != 1) {
  4901. return "Cannot convert to cartesian";
  4902. }
  4903. }
  4904. }
  4905. switch(form) {
  4906. case MATFORM_vector_xyz:
  4907. matrix->form=form;
  4908. matrix->rows=3;
  4909. matrix->cols=1;
  4910. return NULL;
  4911. case MATFORM_vector_xy:
  4912. matrix->form=form;
  4913. matrix->rows=2;
  4914. matrix->cols=1;
  4915. return NULL;
  4916. }
  4917. return NULL;
  4918. }
  4919. /* *Matrix_To_cylindrical */
  4920. const char *Matrix_To_cylindrical(MATOBJ *matrix,int form){
  4921. if(matrix->form==form) {
  4922. return NULL;
  4923. }
  4924. switch(matrix->form) {
  4925. case MATFORM_polar:
  4926. case MATFORM_cylindrical:
  4927. case MATFORM_vector_xy:
  4928. case MATFORM_vector_xyz:
  4929. case MATFORM_vector_xyzw:
  4930. break;
  4931. default:
  4932. if(Matrix_To_cartesian(matrix,MATFORM_cartesian)) {
  4933. return "Cannot convert to polar";
  4934. }
  4935. }
  4936. if(matrix->form==MATFORM_cartesian) {
  4937. odiemath_cartesian_to_cylindrical(matrix->matrix,matrix->matrix);
  4938. }
  4939. switch(form) {
  4940. case MATFORM_cylindrical:
  4941. matrix->form=form;
  4942. matrix->rows=3;
  4943. matrix->cols=1;
  4944. return NULL;
  4945. case MATFORM_polar:
  4946. matrix->form=form;
  4947. matrix->rows=2;
  4948. matrix->cols=1;
  4949. return NULL;
  4950. }
  4951. return NULL;
  4952. }
  4953. /* *Matrix_To_spherical */
  4954. const char *Matrix_To_spherical(MATOBJ *matrix,int form){
  4955. if(matrix->form==form) {
  4956. return NULL;
  4957. }
  4958. if(Matrix_To_cartesian(matrix,MATFORM_cartesian)) {
  4959. return "Cannot convert to spherical";
  4960. }
  4961. if(matrix->form==MATFORM_cartesian) {
  4962. odiemath_cartesian_to_spherical(matrix->matrix,matrix->matrix);
  4963. }
  4964. matrix->form=form;
  4965. matrix->rows=3;
  4966. matrix->cols=1;
  4967. return NULL;
  4968. }
  4969. /* *VectorXYZ_To_TclObj */
  4970. Tcl_Obj *VectorXYZ_To_TclObj(VectorXYZ R){
  4971. MATOBJ *RESULT;
  4972. RESULT=Odie_MatrixObj_Create(MATFORM_vector_xyz);
  4973. RESULT->matrix[X_IDX]=R[X_IDX];
  4974. RESULT->matrix[Y_IDX]=R[Y_IDX];
  4975. RESULT->matrix[Z_IDX]=R[Z_IDX];
  4976. return Matrix_To_TclObj(RESULT);
  4977. }
  4978. /* Odie_GetVectorXYZFromTclObj */
  4979. int Odie_GetVectorXYZFromTclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,VectorXYZ R){
  4980. Tcl_Obj **elemPtrs;
  4981. int cols,i;
  4982. if(objPtr->typePtr) {
  4983. if(objPtr->typePtr->setFromAnyProc==&MatrixObj_setFromAnyProc) {
  4984. /*
  4985. ** Object is a matrix
  4986. */
  4987. const char *err;
  4988. MATOBJ *value=objPtr->internalRep.otherValuePtr;
  4989. err=Matrix_To_cartesian(value,MATFORM_vector_xyz);
  4990. if(err) {
  4991. Tcl_AppendResult(interp,err,NULL);
  4992. return TCL_ERROR;
  4993. }
  4994. R[X_IDX]=value->matrix[X_IDX];
  4995. R[Y_IDX]=value->matrix[Y_IDX];
  4996. R[Z_IDX]=value->matrix[Z_IDX];
  4997. return TCL_OK;
  4998. }
  4999. }
  5000. /* Step one, Measure the matrix */
  5001. if(Tcl_ListObjGetElements(interp, objPtr, &cols, &elemPtrs)) return TCL_ERROR;
  5002. for(i=0;i<3;i++) {
  5003. double temp;
  5004. if(cols<=i) {
  5005. R[i]=0.0;
  5006. } else {
  5007. if(Tcl_GetDoubleFromObj(interp, elemPtrs[i], &temp)) return TCL_ERROR;
  5008. R[i]=temp;
  5009. }
  5010. }
  5011. return TCL_OK;
  5012. }
  5013. /* VectorXYZ_Scale */
  5014. static inline void VectorXYZ_Scale(VECTOR A,SCALER S){
  5015. A[X_IDX]*=S;
  5016. A[Y_IDX]*=S;
  5017. A[Z_IDX]*=S;
  5018. }
  5019. /* VectorXYZ_Zero */
  5020. static inline void VectorXYZ_Zero(VECTORXYZ A){
  5021. A[X_IDX]=0.0;
  5022. A[Y_IDX]=0.0;
  5023. A[Z_IDX]=0.0;
  5024. }
  5025. /* VectorXYZ_GridAlign */
  5026. static inline void VectorXYZ_GridAlign(VECTORXYZ A,double grid){
  5027. double x,q,grain;
  5028. grain=grid*0.5;
  5029. if(grid<=0) return;
  5030. A[X_IDX]=Vector_GridScaler(A[X_IDX],grid,grain);
  5031. A[Y_IDX]=Vector_GridScaler(A[Y_IDX],grid,grain);
  5032. A[Z_IDX]=Vector_GridScaler(A[Z_IDX],grid,grain);
  5033. }
  5034. /* VectorXYZ_Copy */
  5035. static inline void VectorXYZ_Copy(VECTORXYZ B,VECTORXYZ A){
  5036. B[X_IDX]=A[X_IDX];
  5037. B[Y_IDX]=A[Y_IDX];
  5038. B[Z_IDX]=A[Z_IDX];
  5039. }
  5040. /* VectorXYZ_SamePoint */
  5041. static inline int VectorXYZ_SamePoint(VECTORXYZ A,VECTORXYZ B){
  5042. if(A==B) {
  5043. return 1;
  5044. }
  5045. if(fabs(B[X_IDX]-A[X_IDX])>Vector_Tolerance) return 0;
  5046. if(fabs(B[Y_IDX]-A[Y_IDX])>Vector_Tolerance) return 0;
  5047. if(fabs(B[Z_IDX]-A[Z_IDX])>Vector_Tolerance) return 0;
  5048. return 1;
  5049. }
  5050. /* VectorXYZ_IsZero */
  5051. static inline int VectorXYZ_IsZero(VECTORXYZ A){
  5052. if(!A) return 1;
  5053. if(fabs(A[X_IDX])>Vector_Tolerance) return 0;
  5054. if(fabs(A[Y_IDX])>Vector_Tolerance) return 0;
  5055. if(fabs(A[Z_IDX])>Vector_Tolerance) return 0;
  5056. return 1;
  5057. }
  5058. /* VectorXYZ_Cross_Product */
  5059. static inline void VectorXYZ_Cross_Product(VectorXYZ C,VectorXYZ A,VectorXYZ B){
  5060. C[X_IDX] = A[Y_IDX] * B[Z_IDX] - A[Z_IDX] * B[Y_IDX];
  5061. C[Y_IDX] = A[Z_IDX] * B[X_IDX] - A[X_IDX] * B[Z_IDX];
  5062. C[Z_IDX] = A[X_IDX] * B[Y_IDX] - A[Y_IDX] * B[X_IDX];
  5063. }
  5064. /* VectorXYZ_Add */
  5065. static inline void VectorXYZ_Add(VECTORXYZ C,VECTORXYZ A,VECTORXYZ B){
  5066. C[X_IDX]=B[X_IDX]+A[X_IDX];
  5067. C[Y_IDX]=B[Y_IDX]+A[Y_IDX];
  5068. C[Z_IDX]=B[Z_IDX]+A[Z_IDX];
  5069. }
  5070. /* VectorXYZ_Subtract */
  5071. static inline void VectorXYZ_Subtract(VECTORXYZ C,VECTORXYZ A,VECTORXYZ B){
  5072. C[X_IDX]=A[X_IDX]-B[X_IDX];
  5073. C[Y_IDX]=A[Y_IDX]-B[Y_IDX];
  5074. C[Z_IDX]=A[Z_IDX]-B[Z_IDX];
  5075. }
  5076. /* VectorXYZ_IsOrthagonal */
  5077. static inline int VectorXYZ_IsOrthagonal(VECTORXYZ A,VECTORXYZ B){
  5078. int result=0;
  5079. if((A[X_IDX]-B[X_IDX])>Vector_Tolerance) result++;
  5080. if((A[Y_IDX]-B[Y_IDX])>Vector_Tolerance) result++;
  5081. if((A[Z_IDX]-B[Z_IDX])>Vector_Tolerance) result++;
  5082. return result>1 ? 0 : 1;
  5083. }
  5084. /* VectorXYZ_Midpoint */
  5085. static inline void VectorXYZ_Midpoint(VECTORXYZ C,VECTORXYZ A,VECTORXYZ B){
  5086. C[X_IDX]=(B[X_IDX]-A[X_IDX])*0.5+A[X_IDX];
  5087. C[Y_IDX]=(B[Y_IDX]-A[Y_IDX])*0.5+A[Y_IDX];
  5088. C[Z_IDX]=(B[Z_IDX]-A[Z_IDX])*0.5+A[Z_IDX];
  5089. }
  5090. /* VectorXYZ_Distance */
  5091. static inline double VectorXYZ_Distance(VECTORXYZ A,VECTORXYZ B){
  5092. double dx,dy,dz;
  5093. dx=B[X_IDX]-A[X_IDX];
  5094. dy=B[Y_IDX]-A[Y_IDX];
  5095. dz=B[Z_IDX]-A[Z_IDX];
  5096. return sqrt(dx*dx+dy*dy+dz*dz);
  5097. }
  5098. /* VectorXYZ_DistanceSq */
  5099. static inline double VectorXYZ_DistanceSq(VECTORXYZ A,VECTORXYZ B){
  5100. double dx,dy,dz;
  5101. dx=A[X_IDX]-B[X_IDX];
  5102. dy=A[Y_IDX]-B[Y_IDX];
  5103. dz=A[Z_IDX]-B[Z_IDX];
  5104. return (dx*dx+dy*dy+dz*dz);
  5105. }
  5106. /* VectorXYZ_Dot_Product */
  5107. static inline double VectorXYZ_Dot_Product(VectorXYZ A,VectorXYZ B){
  5108. double r;
  5109. r=A[X_IDX] * B[X_IDX] + A[Y_IDX] * B[Y_IDX] + A[Z_IDX] * B[Z_IDX];
  5110. if(fabs(r)<__FLT_EPSILON__) {
  5111. return 0.0;
  5112. }
  5113. return r;
  5114. }
  5115. /* VectorXYZ_MatrixMultiply */
  5116. static inline void VectorXYZ_MatrixMultiply(VECTORXYZ R,VECTORXYZ A,AFFINE M){
  5117. double temp[4];
  5118. 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];
  5119. 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];
  5120. 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];
  5121. R[0]=temp[0];
  5122. R[1]=temp[1];
  5123. R[2]=temp[2];
  5124. }
  5125. /* VectorXYZ_MagnitudeSq */
  5126. static inline double VectorXYZ_MagnitudeSq(VECTOR A){
  5127. double length=A[0]*A[0]+A[1]*A[1]+A[2]*A[2];
  5128. if(length<Vector_Tolerance) {
  5129. return 0.0;
  5130. }
  5131. return length;
  5132. }
  5133. /* VectorXYZ_Magnitude */
  5134. static inline double VectorXYZ_Magnitude(VECTOR A){
  5135. double length=sqrt(A[0]*A[0]+A[1]*A[1]+A[2]*A[2]);
  5136. if(length<Vector_Tolerance) {
  5137. return 0.0;
  5138. }
  5139. return length;
  5140. }
  5141. /* VectorXYZ_MagnitudeInvSqr */
  5142. static inline double VectorXYZ_MagnitudeInvSqr(VECTOR A){
  5143. double r=A[0]+A[1]+A[2];
  5144. if(fabs(r)<Vector_Tolerance) {
  5145. return NAN;
  5146. }
  5147. return (1.0/(A[0]*A[0]+A[1]*A[1]+A[2]*A[2]));
  5148. }
  5149. /* VectorXYZ_Normalize */
  5150. static inline int VectorXYZ_Normalize(VectorXYZ A){
  5151. double d;
  5152. double r=VectorXYZ_Magnitude(A);
  5153. if(fabs(r) < __FLT_EPSILON__) {
  5154. A[0]=0.0;
  5155. A[1]=0.0;
  5156. A[3]=0.0;
  5157. return 1;
  5158. } else {
  5159. d=1.0 / r;
  5160. A[0]*=d;
  5161. A[1]*=d;
  5162. A[2]*=d;
  5163. return 0;
  5164. }
  5165. }
  5166. /* VectorXYZ_PointIsOnSegment */
  5167. static inline int VectorXYZ_PointIsOnSegment(VectorXYZ POINT,VectorXYZ A,VectorXYZ B){
  5168. VectorXYZ INTERSECT;
  5169. double t;
  5170. t=VectorXYZ_ClosestPointOnSegment(A,B,POINT,INTERSECT);
  5171. if (t<0.0 && t>1.0) return 0;
  5172. if(VectorXYZ_DistanceSq(POINT,INTERSECT)>Vector_Tolerance_Sq) return 0;
  5173. return 1;
  5174. }
  5175. /* VectorXYZ_AxisOfNormal */
  5176. static inline int VectorXYZ_AxisOfNormal(VectorXYZ NORMAL){
  5177. if(fabs(NORMAL[Z_IDX])>fabs(NORMAL[X_IDX])) {
  5178. if (fabs(NORMAL[Z_IDX])>fabs(NORMAL[Y_IDX])) {
  5179. return Z_IDX;
  5180. } else {
  5181. return Y_IDX;
  5182. }
  5183. }
  5184. if (fabs(NORMAL[X_IDX])>fabs(NORMAL[Y_IDX])) {
  5185. return X_IDX;
  5186. } else {
  5187. return Y_IDX;
  5188. }
  5189. }
  5190. /* VectorXYZ_NormalStrictAxisAligned */
  5191. static inline int VectorXYZ_NormalStrictAxisAligned(VectorXYZ NORMAL){
  5192. int i;
  5193. for(i=2;i>=0;i--) {
  5194. if(1.0-fabs(NORMAL[i]) < Vector_Tolerance) return i;
  5195. }
  5196. return -1;
  5197. }
  5198. /* VectorXYZ_AxisAligned */
  5199. static inline int VectorXYZ_AxisAligned(VectorXYZ A,VectorXYZ B,VectorXYZ C){
  5200. int i;
  5201. for(i=2;i>=0;i--) {
  5202. if(fabs((C[i]-B[i])+(B[i]-A[i])) < Vector_Tolerance) return i;
  5203. }
  5204. return -1;
  5205. }
  5206. /* VectorXYZ_BendDirection */
  5207. static inline int VectorXYZ_BendDirection(VectorXYZ A,VectorXYZ B,VectorXYZ C){
  5208. int axis;
  5209. VectorXYZ D1,D2;
  5210. if(VectorXYZ_SamePoint(A,C)) {
  5211. return -1;
  5212. }
  5213. /* If all points are axis aligned. We can treat as a 2d problem */
  5214. axis=VectorXYZ_AxisAligned(A,B,C);
  5215. if(axis==Z_IDX) {
  5216. 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]);
  5217. if(fabs(r) < __FLT_EPSILON__) return 0;
  5218. return r<0.0 ? +1 : (r>0.0 ? -1 : 0);
  5219. }
  5220. if(axis==Y_IDX) {
  5221. 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]);
  5222. if(fabs(r) < __FLT_EPSILON__) return 0;
  5223. return r<0.0 ? +1 : (r>0.0 ? -1 : 0);
  5224. }
  5225. if(axis==X_IDX) {
  5226. /* All points are axis aligned on Z. We can treat as a 2d problem */
  5227. 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]);
  5228. if(fabs(r) < __FLT_EPSILON__) return 0;
  5229. return r<0.0 ? +1 : (r>0.0 ? -1 : 0);
  5230. }
  5231. VectorXYZ_Cross_Product(D1,B,A);
  5232. VectorXYZ_Cross_Product(D2,C,B);
  5233. if(VectorXYZ_IsZero(D1) && VectorXYZ_IsZero(D2)) {
  5234. /* We must be colinear */
  5235. 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]);
  5236. if(r<0) {
  5237. return 0;
  5238. }
  5239. return -1;
  5240. }
  5241. /* Gauge the direction of the cross products. If all axis agree, we are pointed the right way */
  5242. if(D1[X_IDX]>=0 && D2[X_IDX]<0) {
  5243. return -1;
  5244. }
  5245. if(D1[Y_IDX]>=0 && D2[Y_IDX]<0) {
  5246. return -1;
  5247. }
  5248. if(D1[Z_IDX]>=0 && D2[Z_IDX]<0) {
  5249. return -1;
  5250. }
  5251. return 1;
  5252. }
  5253. /* VectorXYZ_Angle_Three_Point */
  5254. static inline double VectorXYZ_Angle_Three_Point(VectorXYZ A,VectorXYZ B,VectorXYZ C,VectorXYZ normal){
  5255. double dotprod,num;
  5256. VectorXYZ D1,D2;
  5257. int axis;
  5258. if(VectorXYZ_SamePoint(A,C)) {
  5259. return M_PI;
  5260. }
  5261. axis=VectorXYZ_AxisAligned(A,B,C);
  5262. if(axis==Z_IDX) {
  5263. /* All points are axis aligned on Z. We can treat as a 2d problem */
  5264. return VectorXY_Angle_Three_Point(A,B,C);
  5265. }
  5266. VectorXYZ_Subtract(D1,B,A);
  5267. VectorXYZ_Subtract(D2,C,B);
  5268. num=VectorXYZ_Magnitude(D1)*VectorXYZ_Magnitude(D2);
  5269. if(fabs(num)<Vector_Tolerance) {
  5270. /* At least one of the vectors is zero magnetude
  5271. ** Assume any angle is good */
  5272. return 0.0;
  5273. }
  5274. dotprod=VectorXYZ_Dot_Product(D1,D2);
  5275. return acos(dotprod/num);
  5276. }
  5277. /* VectorXYZ_IsColinear */
  5278. static inline int VectorXYZ_IsColinear(VectorXYZ A,VectorXYZ B,VectorXYZ C){
  5279. double c;
  5280. if(VectorXYZ_SamePoint(A,C)) {
  5281. return 1;
  5282. }
  5283. 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] );
  5284. if(fabs(c)>Vector_Tolerance) return 0;
  5285. 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] );
  5286. if(fabs(c)>Vector_Tolerance) return 0;
  5287. 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] );
  5288. if(fabs(c)>Vector_Tolerance) return 0;
  5289. return 1;
  5290. }
  5291. /* VectorXYZ_IsCoplaner */
  5292. static inline int VectorXYZ_IsCoplaner(VectorXYZ x1,VectorXYZ x2,VectorXYZ x3,VectorXYZ x4){
  5293. double c;
  5294. VectorXYZ d12,d14,d13,cross;
  5295. VectorXYZ_Subtract(d12,x2,x1);
  5296. VectorXYZ_Subtract(d14,x4,x1);
  5297. VectorXYZ_Cross_Product(cross,d12,d14);
  5298. VectorXYZ_Subtract(d13,x3,x1);
  5299. c=VectorXYZ_Dot_Product(cross,d13);
  5300. if(fabs(c)>Vector_Tolerance) return 0;
  5301. return 1;
  5302. }
  5303. /* VectorXYZ_LineLineCoincident */
  5304. static inline int VectorXYZ_LineLineCoincident(
  5305. VectorXYZ A1, VectorXYZ A2, VectorXYZ B1, VectorXYZ B2,
  5306. VectorXYZ ICEPT1, VectorXYZ ICEPT2
  5307. ){
  5308. int a,b,result=0;
  5309. /*
  5310. ** Optimization - two lines can't be coincident if they don't
  5311. ** occupy the same region of space
  5312. */
  5313. if(!VectorXYZ_BBOX_Overlap_TwoVectors(A1,A2,B1,B2)) {
  5314. return 0;
  5315. }
  5316. if(VectorXYZ_SamePoint(A1,B1)) {
  5317. if(VectorXYZ_SamePoint(A2,B2)) {
  5318. VectorXYZ_Copy(ICEPT1,A1);
  5319. VectorXYZ_Copy(ICEPT2,A2);
  5320. return 30;
  5321. }
  5322. }
  5323. if(VectorXYZ_SamePoint(A2,B1)) {
  5324. if(VectorXYZ_SamePoint(A1,B2)) {
  5325. VectorXYZ_Copy(ICEPT1,A1);
  5326. VectorXYZ_Copy(ICEPT2,A2);
  5327. return 30;
  5328. }
  5329. }
  5330. a=VectorXYZ_IsColinear(A1,B1,B2);
  5331. b=VectorXYZ_IsColinear(A2,B1,B2);
  5332. if(a==0 || b==0) {
  5333. /* The two lines are not colinear */
  5334. int c;
  5335. double x,y;
  5336. c=VectorXYZ_LineLineIntersect(A1,A2,B1,B2,ICEPT1,ICEPT2,&x,&y);
  5337. if(c>0) {
  5338. if(x<=0 || y<=0) return 0;
  5339. if(x>=1 || y>=1) return 0;
  5340. /* True if both intercepts happen on a single point */
  5341. return 1;
  5342. }
  5343. }
  5344. if(VectorXYZ_PointIsOnSegment(A1,B1,B2)) {
  5345. result |= 2;
  5346. }
  5347. if(VectorXYZ_PointIsOnSegment(A2,B1,B2)) {
  5348. result |= 4;
  5349. }
  5350. if(VectorXYZ_PointIsOnSegment(B1,A1,A2)) {
  5351. result |= 8;
  5352. }
  5353. if(VectorXYZ_PointIsOnSegment(B2,A1,A2)) {
  5354. result |= 16;
  5355. }
  5356. /* If the segments touch ends we don't count it as coincident */
  5357. if(result==0 || result==10 || result== 18 || result == 12 || result== 20) {
  5358. return 0;
  5359. }
  5360.  
  5361. if((result & 6)==6) {
  5362. VectorXYZ_Copy(ICEPT1,A1);
  5363. VectorXYZ_Copy(ICEPT2,A2);
  5364. } else if((result & 24)==24) {
  5365. /* Both B on A */
  5366. VectorXYZ_Copy(ICEPT1,B1);
  5367. VectorXYZ_Copy(ICEPT2,B2);
  5368. } else {
  5369. if(result & 2) {
  5370. VectorXYZ_Copy(ICEPT1,A1);
  5371. if(result&8) {
  5372. VectorXYZ_Copy(ICEPT2,B1);
  5373. } else if(result&16) {
  5374. VectorXYZ_Copy(ICEPT2,B2);
  5375. } else {
  5376. VectorXYZ_Copy(ICEPT2,A1);
  5377. }
  5378. } else if(result & 4) {
  5379. VectorXYZ_Copy(ICEPT1,A2);
  5380. if(result&8) {
  5381. VectorXYZ_Copy(ICEPT2,B1);
  5382. } else if(result&16) {
  5383. VectorXYZ_Copy(ICEPT2,B2);
  5384. } else {
  5385. VectorXYZ_Copy(ICEPT2,A2);
  5386. }
  5387. } else if(result & 8) {
  5388. VectorXYZ_Copy(ICEPT1,B1);
  5389. VectorXYZ_Copy(ICEPT1,B2);
  5390. } else {
  5391. VectorXYZ_Copy(ICEPT1,B2);
  5392. VectorXYZ_Copy(ICEPT2,B2);
  5393. }
  5394. }
  5395. return result;
  5396. }
  5397. /* VectorXYZ_LineLineIntersect */
  5398. static inline int VectorXYZ_LineLineIntersect(
  5399. VectorXYZ p1, VectorXYZ p2, VectorXYZ p3, VectorXYZ p4,
  5400. VectorXYZ pA, VectorXYZ pB, double *mua, double *mub
  5401. ){
  5402. VectorXYZ p13,p43,p21;
  5403. double d1343,d4321,d1321,d4343,d2121;
  5404. double numer,denom;
  5405.  
  5406. p13[X_IDX] = p1[X_IDX] - p3[X_IDX];
  5407. p13[Y_IDX] = p1[Y_IDX] - p3[Y_IDX];
  5408. p13[Z_IDX] = p1[Z_IDX] - p3[Z_IDX];
  5409. p43[X_IDX] = p4[X_IDX] - p3[X_IDX];
  5410. p43[Y_IDX] = p4[Y_IDX] - p3[Y_IDX];
  5411. p43[Z_IDX] = p4[Z_IDX] - p3[Z_IDX];
  5412. if (fabs(p43[X_IDX]) < Vector_Tolerance && fabs(p43[Y_IDX]) < Vector_Tolerance && fabs(p43[Z_IDX]) < Vector_Tolerance)
  5413. return(0);
  5414. p21[X_IDX] = p2[X_IDX] - p1[X_IDX];
  5415. p21[Y_IDX] = p2[Y_IDX] - p1[Y_IDX];
  5416. p21[Z_IDX] = p2[Z_IDX] - p1[Z_IDX];
  5417. if (fabs(p21[X_IDX]) < Vector_Tolerance && fabs(p21[Y_IDX]) < Vector_Tolerance && fabs(p21[Z_IDX]) < Vector_Tolerance)
  5418. return(0);
  5419.  
  5420. d1343 = p13[X_IDX] * p43[X_IDX] + p13[Y_IDX] * p43[Y_IDX] + p13[Z_IDX] * p43[Z_IDX];
  5421. d4321 = p43[X_IDX] * p21[X_IDX] + p43[Y_IDX] * p21[Y_IDX] + p43[Z_IDX] * p21[Z_IDX];
  5422. d1321 = p13[X_IDX] * p21[X_IDX] + p13[Y_IDX] * p21[Y_IDX] + p13[Z_IDX] * p21[Z_IDX];
  5423. d4343 = p43[X_IDX] * p43[X_IDX] + p43[Y_IDX] * p43[Y_IDX] + p43[Z_IDX] * p43[Z_IDX];
  5424. d2121 = p21[X_IDX] * p21[X_IDX] + p21[Y_IDX] * p21[Y_IDX] + p21[Z_IDX] * p21[Z_IDX];
  5425.  
  5426. denom = d2121 * d4343 - d4321 * d4321;
  5427. if (fabs(denom) < __FLT_EPSILON__)
  5428. return(0);
  5429. numer = d1343 * d4321 - d1321 * d4343;
  5430.  
  5431. *mua = numer / denom;
  5432. *mub = (d1343 + d4321 * (*mua)) / d4343;
  5433.  
  5434. pA[X_IDX] = p1[X_IDX] + *mua * p21[X_IDX];
  5435. pA[Y_IDX] = p1[Y_IDX] + *mua * p21[Y_IDX];
  5436. pA[Z_IDX] = p1[Z_IDX] + *mua * p21[Z_IDX];
  5437. pB[X_IDX] = p3[X_IDX] + *mub * p43[X_IDX];
  5438. pB[Y_IDX] = p3[Y_IDX] + *mub * p43[Y_IDX];
  5439. pB[Z_IDX] = p3[Z_IDX] + *mub * p43[Z_IDX];
  5440. return(1);
  5441. }
  5442. /* VectorXYZ_ClosestPointOnSegment */
  5443. static double VectorXYZ_ClosestPointOnSegment (
  5444. VectorXYZ A, VectorXYZ B, /* End points of the line segment */
  5445. VectorXYZ X, /* The point outside the line */
  5446. VectorXYZ R /* Write closest point on line segment here */
  5447. ){
  5448. VectorXYZ v1, v2;
  5449. double t, s,mag;
  5450.  
  5451. VectorXYZ_Subtract(v1, X, A);
  5452. VectorXYZ_Subtract(v2, B, A);
  5453. mag=VectorXYZ_MagnitudeSq(v2);
  5454. if(mag<Vector_Tolerance_Sq) {
  5455. /* A, B and X are on the same point */
  5456. R[X_IDX] = A[X_IDX];
  5457. R[Y_IDX] = A[Y_IDX];
  5458. R[Z_IDX] = A[Z_IDX];
  5459. return 0.5;
  5460. }
  5461. t = VectorXYZ_Dot_Product(v1, v2)/VectorXYZ_MagnitudeSq(v2);
  5462. if( t<0.0 ){
  5463. VectorXYZ_Copy(R,A);
  5464. } else if( t>1.0 ){
  5465. VectorXYZ_Copy(R,B);
  5466. } else {
  5467. s = 1.0 - t;
  5468. R[X_IDX] = A[X_IDX]*s + B[X_IDX]*t;
  5469. R[Y_IDX] = A[Y_IDX]*s + B[Y_IDX]*t;
  5470. R[Z_IDX] = A[Z_IDX]*s + B[Z_IDX]*t;
  5471. }
  5472. return t;
  5473. }
  5474. /* VectorXYX_solve3by3 */
  5475. static int VectorXYX_solve3by3(double *m){
  5476. int i, j, k;
  5477. double x, y, scale;
  5478. /* Process three rows from top to bottom */
  5479. for(i=0; i<3; i++){
  5480. /* Find the pivot for the i-th row */
  5481. x = fabs(m[i*5]);
  5482. k = i;
  5483. for(j=i+1; j<3; j++){
  5484. y = fabs(m[j*4+i]);
  5485. if( y>x ){
  5486. x = y;
  5487. k = j;
  5488. }
  5489. }
  5490.  
  5491. /* Swap in the pivot */
  5492. if( k>i ){
  5493. double t;
  5494. int n, p, q;
  5495. p = i*5;
  5496. q = k*4+i;
  5497. for(n=i; n<4; n++, p++, q++){
  5498. t = m[p];
  5499. m[p] = m[q];
  5500. m[q] = t;
  5501. }
  5502. }
  5503.  
  5504. /* No solution if the pivot is 0.0 */
  5505. if( m[i*5]==0.0 ) {
  5506. return 1;
  5507. }
  5508.  
  5509. /* Divide the i-th row by the pivot */
  5510. scale = m[i*5];
  5511. for(j=i; j<4; j++){
  5512. m[i*4+j] /= scale;
  5513. }
  5514.  
  5515. /* Add the i-th row to other rows to eliminate the i-th term. */
  5516. for(j=i+1; j<3; j++){
  5517. double scale = -m[j*4+i];
  5518. for(k=i; k<4; k++){
  5519. m[j*4+k] += m[i*4+k]*scale;
  5520. }
  5521. }
  5522. }
  5523.  
  5524. /* Now we have an upper triangular matrix with a diagonal of 1.
  5525. ** Finishing the solution is easy */
  5526. for(i=1; i>=0; i--){
  5527. for(j=2; j>i; j--){
  5528. m[i*4+3] -= m[j*4+3]*m[i*4+j];
  5529. }
  5530. }
  5531. return 0;
  5532. }
  5533. /* VectorXYZ_TriangleLineIntersect */
  5534. static double VectorXYZ_TriangleLineIntersect(
  5535. VectorXYZ A, VectorXYZ B, VectorXYZ C, /* The triangle we are trying to intersect */
  5536. VectorXYZ pStart, /* Start of the line segment */
  5537. VectorXYZ pEnd, /* End of the line segment */
  5538. VectorXYZ pIntersect /* Point of intersection written here if not NULL */
  5539. ){
  5540. double s, t;
  5541. double m[12];
  5542. m[0] = pStart[X_IDX] - pEnd[X_IDX];
  5543. m[1] = B[X_IDX] - A[X_IDX];
  5544. m[2] = C[X_IDX] - A[X_IDX];
  5545. m[3] = pStart[X_IDX] - A[X_IDX];
  5546. m[4] = pStart[Y_IDX] - pEnd[Y_IDX];
  5547. m[5] = B[Y_IDX] - A[Y_IDX];
  5548. m[6] = C[Y_IDX] - A[Y_IDX];
  5549. m[7] = pStart[Y_IDX] - A[Y_IDX];
  5550. m[8] = pStart[Z_IDX] - pEnd[Z_IDX];
  5551. m[9] = B[Z_IDX] - A[Z_IDX];
  5552. m[10] = C[Z_IDX] - A[Z_IDX];
  5553. m[11] = pStart[Z_IDX] - A[Z_IDX];
  5554. if( VectorXYX_solve3by3(m) ){
  5555. /* The line is parallel or coplanar with the triangle */
  5556. return -1.0;
  5557. }
  5558. t = m[3];
  5559. if( t<0.0 || t>1.0 ){
  5560. /* The point of intersection is off the ends of the line segment */
  5561. return -1.0;
  5562. }
  5563. if( m[7]<0.0 || m[7]>1.0 || m[11]<0.0 || m[11]>1.0 || (m[7]+m[11])>1.0 ){
  5564. /* The point of intersection is outside of the triangle boundary */
  5565. return -1.0;
  5566. }
  5567. s = 1.0 - t;
  5568. pIntersect[X_IDX] = pStart[X_IDX]*s + pEnd[X_IDX]*t;
  5569. pIntersect[Y_IDX] = pStart[Y_IDX]*s + pEnd[Y_IDX]*t;
  5570. pIntersect[Z_IDX] = pStart[Z_IDX]*s + pEnd[Z_IDX]*t;
  5571. return t;
  5572. }
  5573. /* VectorXYZ_Normal_of_Three_Points */
  5574. static inline void VectorXYZ_Normal_of_Three_Points(VectorXYZ normal,VectorXYZ A,VectorXYZ B,VectorXYZ C){
  5575. VectorXYZ one,two;
  5576. VectorXYZ_Subtract(one, B, A);
  5577. VectorXYZ_Subtract(two, C, A);
  5578. normal[X_IDX] = one[Y_IDX]*two[Z_IDX] - one[Z_IDX]*two[Y_IDX];
  5579. normal[Y_IDX] = one[Z_IDX]*two[X_IDX] - one[X_IDX]*two[Z_IDX];
  5580. normal[Z_IDX] = one[X_IDX]*two[Y_IDX] - one[Y_IDX]*two[X_IDX];
  5581. }
  5582. /* VectorXYZ_LineSphereIntersect */
  5583. int VectorXYZ_LineSphereIntersect(
  5584. double p1_x, double p1_y, double p1_z,
  5585. double p2_x, double p2_y, double p2_z,
  5586. double sc_x, double sc_y, double sc_z,
  5587. double r,
  5588. double *mu1, double *mu2){
  5589. /*
  5590. ** Detect the intersection of a line and a sphere
  5591. ** Adapted from: http://http://paulbourke.net/geometry/circlesphere/raysphere.c
  5592. */
  5593. double a,b,c;
  5594. double bb4ac;
  5595. double dp_x,dp_y,dp_z;
  5596. *mu1 = 0;
  5597. *mu2 = 0;
  5598. dp_x = p2_x - p1_x;
  5599. dp_y = p2_y - p1_y;
  5600. dp_z = p2_z - p1_z;
  5601. a = dp_x * dp_x + dp_y * dp_y + dp_z * dp_z;
  5602. b = 2 * (dp_x * (p1_x - sc_x) + dp_y * (p1_y - sc_y) + dp_z * (p1_z - sc_z));
  5603. c = sc_x * sc_x + sc_y * sc_y + sc_z * sc_z;
  5604. c += p1_x * p1_x + p1_y * p1_y + p1_z * p1_z;
  5605. c -= 2 * (sc_x * p1_x + sc_y * p1_y + sc_z * p1_z);
  5606. c -= r * r;
  5607. bb4ac = b * b - 4 * a * c;
  5608. if (ODIE_Real_Is_Zero(a) || bb4ac < 0) {
  5609. return(0);
  5610. }
  5611.  
  5612. *mu1 = (-b + sqrt(bb4ac)) / (2 * a);
  5613. *mu2 = (-b - sqrt(bb4ac)) / (2 * a);
  5614. return(1);
  5615. }
  5616. /* *VectorXYZ_ToString */
  5617. char *VectorXYZ_ToString(VectorXYZ VECTOR){
  5618. char *out=Tcl_Alloc(128);
  5619. sprintf(out,"<%g %g %g>",(float)VECTOR[X_IDX],(float)VECTOR[Y_IDX],(float)VECTOR[Z_IDX]);
  5620. return out;
  5621. }
  5622. /* Vector_Set_Tolerance */
  5623. void Vector_Set_Tolerance(double newvalue){
  5624. Vector_Tolerance=newvalue;
  5625. Vector_Tolerance_Sq=newvalue*newvalue;
  5626. }
  5627. /* *Vector_Alloc */
  5628. double *Vector_Alloc(size_t size){
  5629. double *ptr;
  5630. if(size<128) {
  5631. size=128;
  5632. }
  5633. ptr=(double*)ckalloc(size);
  5634. memset(ptr,0,size);
  5635. return ptr;
  5636. }
  5637. /* Odie_Matrix_AABBXYZ_From_TclObj */
  5638. STUB_EXPORT int Odie_Matrix_AABBXYZ_From_TclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,AABBXYZ ptr){
  5639. Odie_MatrixObj *T;
  5640. if(Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_aabb_xyz,&T)) return TCL_ERROR;
  5641. memcpy(ptr,T->matrix,sizeof(AABBXYZ));
  5642. return TCL_OK;
  5643. }
  5644. /* *Odie_Matrix_AABBXYZ_To_TclObj */
  5645. STUB_EXPORT Tcl_Obj *Odie_Matrix_AABBXYZ_To_TclObj(AABBXYZ ptr){
  5646. Odie_MatrixObj *C;
  5647. Tcl_Obj *result;
  5648. C=Odie_MatrixObj_Create(MATFORM_aabb_xyz);
  5649. memcpy(C->matrix,ptr,sizeof(AABBXYZ));
  5650. result=Matrix_To_TclObj(C);
  5651. return result;
  5652. }
  5653. /* Odie_Matrix_AFFINE_From_TclObj */
  5654. STUB_EXPORT int Odie_Matrix_AFFINE_From_TclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,AFFINE ptr){
  5655. Odie_MatrixObj *T;
  5656. if(Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_affine,&T)) return TCL_ERROR;
  5657. memcpy(ptr,T->matrix,sizeof(AFFINE));
  5658. return TCL_OK;
  5659. }
  5660. /* *Odie_Matrix_AFFINE_To_TclObj */
  5661. STUB_EXPORT Tcl_Obj *Odie_Matrix_AFFINE_To_TclObj(AFFINE ptr){
  5662. Odie_MatrixObj *C;
  5663. Tcl_Obj *result;
  5664. C=Odie_MatrixObj_Create(MATFORM_affine);
  5665. memcpy(C->matrix,ptr,sizeof(AFFINE));
  5666. result=Matrix_To_TclObj(C);
  5667. return result;
  5668. }
  5669. /* Odie_Matrix_BBOXXY_From_TclObj */
  5670. STUB_EXPORT int Odie_Matrix_BBOXXY_From_TclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,BBOXXY ptr){
  5671. Odie_MatrixObj *T;
  5672. if(Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_bbox_xy,&T)) return TCL_ERROR;
  5673. memcpy(ptr,T->matrix,sizeof(BBOXXY));
  5674. return TCL_OK;
  5675. }
  5676. /* *Odie_Matrix_BBOXXY_To_TclObj */
  5677. STUB_EXPORT Tcl_Obj *Odie_Matrix_BBOXXY_To_TclObj(BBOXXY ptr){
  5678. Odie_MatrixObj *C;
  5679. Tcl_Obj *result;
  5680. C=Odie_MatrixObj_Create(MATFORM_bbox_xy);
  5681. memcpy(C->matrix,ptr,sizeof(BBOXXY));
  5682. result=Matrix_To_TclObj(C);
  5683. return result;
  5684. }
  5685. /* Odie_Matrix_AFFINE3X3_From_TclObj */
  5686. STUB_EXPORT int Odie_Matrix_AFFINE3X3_From_TclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,AFFINE3X3 ptr){
  5687. Odie_MatrixObj *T;
  5688. if(Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_mat3,&T)) return TCL_ERROR;
  5689. memcpy(ptr,T->matrix,sizeof(AFFINE3X3));
  5690. return TCL_OK;
  5691. }
  5692. /* *Odie_Matrix_AFFINE3X3_To_TclObj */
  5693. STUB_EXPORT Tcl_Obj *Odie_Matrix_AFFINE3X3_To_TclObj(AFFINE3X3 ptr){
  5694. Odie_MatrixObj *C;
  5695. Tcl_Obj *result;
  5696. C=Odie_MatrixObj_Create(MATFORM_mat3);
  5697. memcpy(C->matrix,ptr,sizeof(AFFINE3X3));
  5698. result=Matrix_To_TclObj(C);
  5699. return result;
  5700. }
  5701. /* Odie_Matrix_QUATERNION_From_TclObj */
  5702. STUB_EXPORT int Odie_Matrix_QUATERNION_From_TclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,QUATERNION ptr){
  5703. Odie_MatrixObj *T;
  5704. if(Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_quaternion,&T)) return TCL_ERROR;
  5705. memcpy(ptr,T->matrix,sizeof(QUATERNION));
  5706. return TCL_OK;
  5707. }
  5708. /* *Odie_Matrix_QUATERNION_To_TclObj */
  5709. STUB_EXPORT Tcl_Obj *Odie_Matrix_QUATERNION_To_TclObj(QUATERNION ptr){
  5710. Odie_MatrixObj *C;
  5711. Tcl_Obj *result;
  5712. C=Odie_MatrixObj_Create(MATFORM_quaternion);
  5713. memcpy(C->matrix,ptr,sizeof(QUATERNION));
  5714. result=Matrix_To_TclObj(C);
  5715. return result;
  5716. }
  5717. /* Odie_Matrix_VECTORXY_From_TclObj */
  5718. STUB_EXPORT int Odie_Matrix_VECTORXY_From_TclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,VECTORXY ptr){
  5719. Odie_MatrixObj *T;
  5720. if(Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_vector_xy,&T)) return TCL_ERROR;
  5721. memcpy(ptr,T->matrix,sizeof(VECTORXY));
  5722. return TCL_OK;
  5723. }
  5724. /* *Odie_Matrix_VECTORXY_To_TclObj */
  5725. STUB_EXPORT Tcl_Obj *Odie_Matrix_VECTORXY_To_TclObj(VECTORXY ptr){
  5726. Odie_MatrixObj *C;
  5727. Tcl_Obj *result;
  5728. C=Odie_MatrixObj_Create(MATFORM_vector_xy);
  5729. memcpy(C->matrix,ptr,sizeof(VECTORXY));
  5730. result=Matrix_To_TclObj(C);
  5731. return result;
  5732. }
  5733. /* Odie_Matrix_VectorXYZ_From_TclObj */
  5734. STUB_EXPORT int Odie_Matrix_VectorXYZ_From_TclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,VectorXYZ ptr){
  5735. Odie_MatrixObj *T;
  5736. if(Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_vector_xyz,&T)) return TCL_ERROR;
  5737. memcpy(ptr,T->matrix,sizeof(VectorXYZ));
  5738. return TCL_OK;
  5739. }
  5740. /* *Odie_Matrix_VectorXYZ_To_TclObj */
  5741. STUB_EXPORT Tcl_Obj *Odie_Matrix_VectorXYZ_To_TclObj(VectorXYZ ptr){
  5742. Odie_MatrixObj *C;
  5743. Tcl_Obj *result;
  5744. C=Odie_MatrixObj_Create(MATFORM_vector_xyz);
  5745. memcpy(C->matrix,ptr,sizeof(VectorXYZ));
  5746. result=Matrix_To_TclObj(C);
  5747. return result;
  5748. }
  5749. /* Odie_GetIntFromObj */
  5750. int Odie_GetIntFromObj(Tcl_Interp *interp,Tcl_Obj *tclObj,int *result){
  5751. if(!Tcl_GetIntFromObj(NULL,tclObj,result)) {
  5752. return TCL_OK;
  5753. }
  5754. double s;
  5755. if(Tcl_GetDoubleFromObj(interp,tclObj,&s)) return TCL_ERROR;
  5756. *result=(int)round(s);
  5757. return TCL_OK;
  5758. }
  5759. /* Odie_GetMatrixFromTclObj */
  5760. int Odie_GetMatrixFromTclObj(Tcl_Interp *interp,Tcl_Obj *tclObj,int form,Odie_MatrixObj **result){
  5761. const char *(*xConvertToForm)(MATOBJ*,int)=MatrixForms[form].xConvertToForm;
  5762. const char *error;
  5763. *result=NULL;
  5764. if(MatrixObj_setFromAnyProc(interp,tclObj)) {
  5765. return TCL_ERROR;
  5766. }
  5767. *result=tclObj->internalRep.otherValuePtr;
  5768. if(!xConvertToForm) {
  5769. return TCL_OK;
  5770. }
  5771. error=xConvertToForm(*result,form);
  5772. if(error) {
  5773. Tcl_SetObjResult(interp,Tcl_NewStringObj(error,-1));
  5774. return TCL_ERROR;
  5775. }
  5776. return TCL_OK;
  5777. }
  5778. /* *Odie_Matrix_Duplicate */
  5779. Odie_MatrixObj *Odie_Matrix_Duplicate(Odie_MatrixObj *src){
  5780. Odie_MatrixObj *dest;
  5781. size_t matsize,size;
  5782. matsize=sizeof(double)*src->rows*src->cols;
  5783. if(matsize<128) {
  5784. matsize=128;
  5785. }
  5786. size=matsize+sizeof(Odie_MatrixObj);
  5787. dest=(Odie_MatrixObj *)Odie_Alloc(size);
  5788. memcpy(dest,src,size);
  5789. return dest;
  5790. }
  5791. /* *Odie_MatrixObj_Create_NXN */
  5792. Odie_MatrixObj *Odie_MatrixObj_Create_NXN(int rows,int cols){
  5793. Odie_MatrixObj *new;
  5794. void *p;
  5795. int size_t;
  5796. size_t=rows*cols*sizeof(double);
  5797. if(size_t<128) {
  5798. size_t=128;
  5799. }
  5800. p=Odie_Alloc(sizeof(Odie_MatrixObj)+size_t);
  5801. new=p;
  5802. new->form=MATFORM_null;
  5803. new->cols=cols;
  5804. new->rows=rows;
  5805. return new;
  5806. }
  5807. /* *Odie_MatrixObj_Create */
  5808. Odie_MatrixObj *Odie_MatrixObj_Create(int form){
  5809. Odie_MatrixObj *new;
  5810. int rows,cols;
  5811. void *p;
  5812. int size_t;
  5813. rows=MatrixForms[form].rows;
  5814. cols=MatrixForms[form].cols;
  5815. size_t=rows*cols*sizeof(double);
  5816. if(size_t<128) {
  5817. size_t=128;
  5818. }
  5819. p=Odie_Alloc(sizeof(Odie_MatrixObj)+size_t);
  5820. new=p;
  5821. new->form=form;
  5822. new->cols=cols;
  5823. new->rows=rows;
  5824. return new;
  5825. }
  5826. /* Matrix_Free */
  5827. void Matrix_Free(Odie_MatrixObj *matrix){
  5828. if(!matrix) return;
  5829. matrix->refCount--;
  5830. /*
  5831. ** Seems counter intuitive, but freeing when refCount==0 causes
  5832. ** Tcl to Crash
  5833. */
  5834. if(matrix->refCount<0) {
  5835. Odie_Free(matrix);
  5836. }
  5837. }
  5838. /* *Matrix_ToAny */
  5839. const char *Matrix_ToAny(Odie_MatrixObj *matrix,int form){
  5840. /* Accept any input */
  5841. matrix->form=form;
  5842. return NULL;
  5843. }
  5844. /* Odie_TclObj_To_MatrixObj */
  5845. int Odie_TclObj_To_MatrixObj(Tcl_Interp *interp,Tcl_Obj *listPtr,Odie_MatrixObj **matrix){
  5846. Odie_MatrixObj *pNew;
  5847. Tcl_Obj **rowPtrs;
  5848. Tcl_Obj **elemPtrs;
  5849. int result;
  5850. int rows,cols;
  5851. int idx,i,j;
  5852. int len;
  5853. /* Step one, Measure the matrix */
  5854. result = Tcl_ListObjGetElements(interp, listPtr, &rows, &rowPtrs);
  5855. if (result != TCL_OK) {
  5856. return result;
  5857. }
  5858. if(rows<1) {
  5859. Tcl_AppendResult(interp, "Could not interpret matrix", 0);
  5860. return TCL_ERROR;
  5861. }
  5862. result = Tcl_ListObjGetElements(interp, rowPtrs[0], &cols, &elemPtrs);
  5863. if (result != TCL_OK) {
  5864. return result;
  5865. }
  5866. /*
  5867. ** For NULL form, we pass the rows and cols
  5868. ** via the data structure
  5869. */
  5870. pNew=Odie_MatrixObj_Create_NXN(rows,cols);
  5871.  
  5872. idx=-1;
  5873. for(i=0;i<rows;i++) {
  5874. result = Tcl_ListObjGetElements(interp, rowPtrs[i], &len, &elemPtrs);
  5875. if (result != TCL_OK) {
  5876. return result;
  5877. }
  5878. if(len != cols) {
  5879. Tcl_SetObjResult(interp,Tcl_NewStringObj("Columns are not uniform",-1));
  5880. Matrix_Free(pNew);
  5881. return TCL_ERROR;
  5882. }
  5883. for(j=0;j<len;j++) {
  5884. double temp;
  5885. idx++;
  5886. result = Tcl_GetDoubleFromObj(interp, elemPtrs[j], &temp);
  5887. if (result != TCL_OK) {
  5888. return result;
  5889. }
  5890. *(pNew->matrix+idx)=(SCALER)temp;
  5891. }
  5892. }
  5893. *matrix=pNew;
  5894. return TCL_OK;
  5895. }
  5896. /* *Matrix_To_TclObj */
  5897. Tcl_Obj *Matrix_To_TclObj(Odie_MatrixObj *matrix){
  5898. Tcl_Obj *dest=Tcl_NewObj();
  5899. dest->typePtr=&matrix_tclobjtype;
  5900. dest->internalRep.otherValuePtr=matrix;
  5901. matrix->refCount++;
  5902. Tcl_InvalidateStringRep(dest);
  5903. return dest;
  5904. }
  5905. /* MatrixObj_setFromAnyProc */
  5906. int MatrixObj_setFromAnyProc(Tcl_Interp *interp,Tcl_Obj *objPtr){
  5907. if(objPtr->typePtr) {
  5908. if(objPtr->typePtr->setFromAnyProc==&MatrixObj_setFromAnyProc) {
  5909. /*
  5910. ** Object is already of the type requested
  5911. */
  5912. return TCL_OK;
  5913. }
  5914. }
  5915. Odie_MatrixObj *matrix;
  5916. if(Odie_TclObj_To_MatrixObj(interp,objPtr,&matrix)) {
  5917. return TCL_ERROR;
  5918. }
  5919. objPtr->internalRep.otherValuePtr=matrix;
  5920. objPtr->typePtr=&matrix_tclobjtype;
  5921. return TCL_OK;
  5922. }
  5923. /* MatrixObj_updateStringProc */
  5924. void MatrixObj_updateStringProc(Tcl_Obj *objPtr){
  5925. float value;
  5926. char outbuffer[128];
  5927. Tcl_DString result;
  5928. Odie_MatrixObj *matrix=objPtr->internalRep.otherValuePtr;
  5929. int rows,cols;
  5930. register int j;
  5931. /* Step 1, dimension matrix */
  5932. rows = matrix->rows;
  5933. cols = matrix->cols;
  5934. Tcl_DStringInit(&result);
  5935. if(cols==1) {
  5936. /*
  5937. * Output single-row matrices (i.e. vectors)
  5938. * as a single tcl list (rather than nest them
  5939. * as a list within a list)
  5940. */
  5941. for(j=0;j<rows;j++) {
  5942. value=(float)*(matrix->matrix+j);
  5943. //Tcl_PrintDouble(NULL,value,outbuffer);
  5944. sprintf(outbuffer,"%g",value);
  5945. Tcl_DStringAppendElement(&result,outbuffer);
  5946. }
  5947. } else if(rows==1) {
  5948. /*
  5949. * Output single-row matrices (i.e. vectors)
  5950. * as a single tcl list (rather than nest them
  5951. * as a list within a list)
  5952. */
  5953. for(j=0;j<cols;j++) {
  5954. value=(float)*(matrix->matrix+j);
  5955. //Tcl_PrintDouble(NULL,value,outbuffer);
  5956. sprintf(outbuffer,"%g",value);
  5957. Tcl_DStringAppendElement(&result,outbuffer);
  5958. }
  5959. } else {
  5960. register int i,idx=0;
  5961. for(i=0;i<rows;i++) {
  5962. Tcl_DStringStartSublist(&result);
  5963. for(j=0;j<cols;j++) {
  5964. idx=(i*cols)+j;
  5965. value=(float)*(matrix->matrix+idx);
  5966. sprintf(outbuffer,"%g",value);
  5967. Tcl_DStringAppendElement(&result,outbuffer);
  5968. }
  5969. Tcl_DStringEndSublist(&result);
  5970. }
  5971. }
  5972. objPtr->length=Tcl_DStringLength(&result);
  5973. objPtr->bytes=Odie_Alloc(objPtr->length+1);
  5974. memcpy(objPtr->bytes,Tcl_DStringValue(&result),objPtr->length);
  5975. objPtr->bytes[objPtr->length]='\0';
  5976. Tcl_DStringFree(&result);
  5977. }
  5978. /* MatrixObj_dupIntRepProc */
  5979. void MatrixObj_dupIntRepProc(Tcl_Obj *srcPtr,Tcl_Obj *dupPtr){
  5980. Odie_MatrixObj *srcmatrix=srcPtr->internalRep.otherValuePtr;
  5981. Odie_MatrixObj *dupmatrix=Odie_Matrix_Duplicate(srcmatrix);
  5982. dupPtr->typePtr=srcPtr->typePtr;
  5983. dupPtr->internalRep.otherValuePtr=dupmatrix;
  5984. Tcl_InvalidateStringRep(dupPtr);
  5985. }
  5986. /* MatrixObj_freeIntRepProc */
  5987. void MatrixObj_freeIntRepProc(Tcl_Obj *objPtr){
  5988. if(!objPtr->internalRep.otherValuePtr) return;
  5989. Odie_MatrixObj *matrix=objPtr->internalRep.otherValuePtr;
  5990. Matrix_Free(matrix);
  5991. objPtr->typePtr=NULL;
  5992. objPtr->internalRep.otherValuePtr=NULL;
  5993. }
  5994. /* MatrixObjType_Init */
  5995. int MatrixObjType_Init(Tcl_Interp *interp){
  5996. Tcl_RegisterObjType(&matrix_tclobjtype);
  5997. return TCL_OK;
  5998. }
  5999. /* ODIE_Real_Is_Zero */
  6000. inline extern int ODIE_Real_Is_Zero(double x){
  6001. if(fabs(x) < __FLT_EPSILON__) {
  6002. return 1;
  6003. }
  6004. return 0;
  6005. }
  6006. /* ODIE_Fuzzy_Compare_TclObj */
  6007. int ODIE_Fuzzy_Compare_TclObj(Tcl_Obj *avalue,Tcl_Obj *bvalue,double epsilon){
  6008. int result;
  6009. char *a,*b;
  6010. double ax,bx;
  6011. int ai,bi;
  6012. int atype,btype,stringcmp=0;
  6013. ClientData internalPtrA,internalPtrB;
  6014.  
  6015. if(Tcl_GetIntFromObj(NULL,avalue,&ai)) goto doublecmp;
  6016. if(Tcl_GetIntFromObj(NULL,bvalue,&bi)) goto doublecmp;
  6017. if(ai==bi) {
  6018. return 0;
  6019. } else {
  6020. result=ai>bi ? 1 : -1;
  6021. }
  6022.  
  6023. doublecmp:
  6024. if(Tcl_GetDoubleFromObj(NULL,avalue,&ax)) goto stringcmp;
  6025. if(Tcl_GetDoubleFromObj(NULL,bvalue,&bx)) goto stringcmp;
  6026. result=ODIE_Fuzzy_Compare(ax,bx,epsilon);
  6027. return result;
  6028.  
  6029. stringcmp:
  6030. a=Tcl_GetString(avalue);
  6031. b=Tcl_GetString(bvalue);
  6032. return strcmp(a,b);
  6033. }
  6034. /* ODIE_FuzzyNumber */
  6035. double ODIE_FuzzyNumber(double ax){
  6036. char newstring[128];
  6037. int expa;
  6038. double siga,ipart,fpart,result;
  6039. if (Odie_IsNaN(ax)) {
  6040. return ax;
  6041. }
  6042. if(Odie_IsInfinite(ax)) {
  6043. return ax;
  6044. }
  6045. if(ODIE_Real_Is_Zero(ax)) {
  6046. return 0;
  6047. }
  6048. siga=frexp(ax,&expa);
  6049. fpart=modf(ldexp(siga,10),&ipart);
  6050. return ldexp(ipart,expa-10);
  6051. }
  6052. /* *ODIE_NewFuzzyObj */
  6053. Tcl_Obj *ODIE_NewFuzzyObj(float ax){
  6054. double bx;
  6055. const char *use_format="%g";
  6056. char newstring[128];
  6057. if (Odie_IsNaN(ax)) {
  6058. return Tcl_NewDoubleObj(ax);
  6059. }
  6060. if(Odie_IsInfinite(ax)) {
  6061. return Tcl_NewDoubleObj(ax);
  6062. }
  6063. if(ODIE_Real_Is_Zero(ax)) {
  6064. return ODIE_REAL_ZERO();
  6065. }
  6066. bx=fabs(ax);
  6067. if(bx>1000000.0) {
  6068. use_format="%g";
  6069. } else if(bx>1000.0) {
  6070. use_format="%.0f";
  6071. } else if(bx>10.0) {
  6072. use_format="%.1f";
  6073. } else if (bx>1.0) {
  6074. use_format="%.2f";
  6075. } else if (bx>0.1) {
  6076. use_format="%.3f";
  6077. } else if (bx>0.01) {
  6078. use_format="%.4f";
  6079. } else if (bx>0.001) {
  6080. use_format="%.5f";
  6081. } else if (bx>0.0001) {
  6082. use_format="%.6f";
  6083. } else {
  6084. use_format="%g";
  6085. }
  6086. sprintf(newstring,use_format,ax);
  6087. return Tcl_NewStringObj(newstring,-1);
  6088. }
  6089. /* ODIE_Fuzzy_Compare */
  6090. inline extern int ODIE_Fuzzy_Compare(double avalue,double bvalue,double epsilon){
  6091. /* Handle the simple cases */
  6092. int expa,expb;
  6093. double siga,sigb;
  6094. double c;
  6095. siga=frexp(avalue,&expa);
  6096. sigb=frexp(bvalue,&expb);
  6097. if(expa==expb) {
  6098. c=bvalue-avalue;
  6099. if(fabs(c)<epsilon) {
  6100. return 0;
  6101. }
  6102. }
  6103. if(avalue>bvalue) return 1;
  6104. return -1;
  6105. }
  6106. /* ODIE_Fuzzy_GTE */
  6107. inline extern int ODIE_Fuzzy_GTE(double avalue,double bvalue){
  6108. /* Handle the simple cases */
  6109. if (avalue==bvalue) return 1;
  6110. if (avalue<=ODIE_REAL_TOLERANCE && bvalue>ODIE_REAL_TOLERANCE) return 0;
  6111. if (avalue>bvalue) return 1;
  6112.  
  6113. /* Add epsilon to the send */
  6114. avalue+=ODIE_REAL_TOLERANCE;
  6115. if (avalue>=bvalue) return 2;
  6116.  
  6117. /* For large quantities, loose the decimal points
  6118. if(avalue>100.0 && bvalue>100.0) {
  6119. avalue=ceil(avalue);
  6120. bvalue=floor(bvalue);
  6121. if (avalue>=bvalue) return 2;
  6122. }
  6123. */
  6124. return 0;
  6125. }
  6126. /*
  6127. ** This file implements code for braking up compartment floorplans
  6128. ** into triangles.
  6129. **
  6130. ** A floorplan is defined by vectors (x0,y0,x1,y1) which define the
  6131. ** parameter of each compartment. The interior of the compartment
  6132. ** is always to the right of the vector. Thus the outer boundary
  6133. ** of the compartment rotates clockwise when viewed from above.
  6134. ** Compartments may contain holes which are interior voids surrounded
  6135. ** by counter-clockwise rotating boundaries.
  6136. */
  6137.  
  6138.  
  6139. /*
  6140. ** Compute a hash on a point.
  6141. */
  6142. static int hashTriagPoint(TriagPoint *p){
  6143. int iTX = p->x/OdieGrain;
  6144. int iTY = p->y/OdieGrain;
  6145. return hashInt(iTX+iTY);
  6146. }
  6147.  
  6148. /*
  6149. ** Return TRUE if A is the same point as B.
  6150. */
  6151. static int sameTriagPoint(TriagPoint *A, TriagPoint *B){
  6152. return floatCompare(A->x,B->x)==0 && floatCompare(A->y,B->y)==0;
  6153. }
  6154.  
  6155.  
  6156. #if 0
  6157. /*
  6158. ** Print all vectors in the TriagSegSet. Used for debugging purposes only.
  6159. */
  6160. static void SegPrint(TriagSegment *p, const char *zText){
  6161. printf("%s ", zText);
  6162. if( p ){
  6163. printf("%g,%g -> %g,%g\n", p->from.x, p->from.y, p->to.x, p->to.y);
  6164. }else{
  6165. printf(" (null)\n");
  6166. }
  6167. }
  6168. static void TriagSegSetPrint(TriagSegSet *pSet){
  6169. Link *pLink;
  6170. printf("%d vectors:\n", pSet->nSeg);
  6171. for(pLink=pSet->pAll; pLink; pLink=pLink->pNext){
  6172. SegPrint(pLink->pLinkNode, " ");
  6173. }
  6174. }
  6175. #endif
  6176.  
  6177. /*
  6178. ** Add a new segment to the set
  6179. */
  6180. static TriagSegment *TriagSegSetInsert(
  6181. TriagSegSet *pSet,
  6182. double x0,
  6183. double y0,
  6184. double x1,
  6185. double y1,
  6186. u8 isBoundary
  6187. ){
  6188. int h;
  6189. if(pSet==NULL) {
  6190. return NULL;
  6191. }
  6192. TriagSegment *p = (TriagSegment *)Odie_Alloc( sizeof(*p) );
  6193. memset(p,0,sizeof(*p));
  6194. x0=round(x0);
  6195. y0=round(y0);
  6196. x1=round(x1);
  6197. y1=round(y1);
  6198. if( p==0 ) {
  6199. return NULL;
  6200. }
  6201. p->from.x = x0;
  6202. p->from.y = y0;
  6203. p->to.x = x1;
  6204. p->to.y = y1;
  6205. if( sameTriagPoint(&p->from, &p->to) ){
  6206. Odie_Free((char *)p);
  6207. return NULL;
  6208. }
  6209. p->isBoundary = isBoundary;
  6210. p->notOblique = 0;
  6211.  
  6212. LinkInit(p->all, p);
  6213. LinkInit(p->tmp, p);
  6214. LinkInit(p->orig, p);
  6215. LinkInsert(&pSet->pAll, &p->all);
  6216. h = hashTriagPoint(&p->from);
  6217. LinkInsert(&pSet->aHash[h], &p->orig);
  6218. pSet->nSeg++;
  6219. pSet->pCurrent = p;
  6220. return p;
  6221. }
  6222.  
  6223. /*
  6224. ** Remove a segment from the segment set
  6225. */
  6226. static void TriagSegSetRemove(TriagSegSet *pSet, TriagSegment *p){
  6227. LinkRemove(&p->all);
  6228. LinkRemove(&p->orig);
  6229. pSet->nSeg--;
  6230. if( pSet->pCurrent==p ){
  6231. pSet->pCurrent = pSet->pAll ? pSet->pAll->pLinkNode : 0;
  6232. }
  6233. }
  6234.  
  6235. /*
  6236. ** Call this routine to relink into a segment when the
  6237. ** Seg.from vector changes.
  6238. */
  6239. static void TriagSegRelink(TriagSegSet *pSet, TriagSegment *p){
  6240. int h;
  6241. LinkRemove(&p->orig);
  6242. h = hashTriagPoint(&p->from);
  6243. LinkInsert(&pSet->aHash[h], &p->orig);
  6244. }
  6245.  
  6246. /*
  6247. ** Remove all segments from a segment set
  6248. */
  6249. static void TriagSegSetClear(TriagSegSet *pSet){
  6250. while( pSet->pAll ){
  6251. TriagSegment *p;
  6252. assert( pSet->nSeg>0 );
  6253. p=pSet->pAll->pLinkNode;
  6254. TriagSegSetRemove(pSet, p);
  6255. Odie_Free((char *)p);
  6256. }
  6257. assert( pSet->nSeg==0 );
  6258. }
  6259.  
  6260. #if 0
  6261. /*
  6262. ** Advance the pSet->pAll pointer so that it is pointing to a different
  6263. ** segment.
  6264. */
  6265. static void TriagSegSetStep(TriagSegSet *pSet){
  6266. if( pSet->pCurrent ){
  6267. Link *pNext = pSet->pCurrent->all.pNext;
  6268. pSet->pCurrent = pNext ? pNext->pSeg : 0;
  6269. }
  6270. if( pSet->pCurrent==0 ){
  6271. pSet->pCurrent = pSet->pAll ? pSet->pAll->pSeg : 0;
  6272. }
  6273. }
  6274. #endif
  6275.  
  6276.  
  6277. static inline double Dot_Product(TriagPoint *A, TriagPoint *B, TriagPoint *P){
  6278. double r = (A->y-B->y)*(P->x-B->x) + (B->x-A->x)*(P->y-B->y);
  6279. if(fabs(r) < IRM_EPSILON ) {
  6280. return 0.0;
  6281. }
  6282. return r;
  6283. }
  6284.  
  6285. /*
  6286. ** Consider traveling from point A to B to P. If you have to make
  6287. ** a left-turn at B, then this routine returns -1. If P is on the
  6288. ** same line as A and B then return 0. If you make a right turn
  6289. ** at B in order to reach P then return +1.
  6290. */
  6291. static inline int rightOf(TriagPoint *A, TriagPoint *B, TriagPoint *P){
  6292. /* Algorithm: Rotate AB 90 degrees counter-clockwise. Take
  6293. ** the dot product with BP. The dot produce will be the product
  6294. ** of two (non-negative) magnitudes and the cosine of the angle. So if
  6295. ** the dot product is positive, the bend is to the left, or to the right if
  6296. ** the dot product is negative.
  6297. */
  6298. double r = (A->y-B->y)*(P->x-B->x) + (B->x-A->x)*(P->y-B->y);
  6299. if(fabs(r) < IRM_EPSILON ) {
  6300. return 0;
  6301. }
  6302. if(r>0.0) {
  6303. return -1;
  6304. }
  6305. return 1;
  6306. //return r<0.0 ? +1 : (r>0.0 ? -1 : 0);
  6307. }
  6308.  
  6309. /*
  6310. ** This is a variation on rightOf(). Return 0 only if BP is a continuation
  6311. ** of the line AB. If BP doubles back on AB then return -1.
  6312. */
  6313. static inline int strictlyRightOf(TriagPoint *A, TriagPoint *B, TriagPoint *P){
  6314. int c = rightOf(A,B,P);
  6315. if( c==0 ){
  6316. double r = (A->x-B->x)*(P->x-B->x) + (A->y-B->y)*(P->y-B->y);
  6317. c = r<0.0 ? +1 : -1;
  6318. }
  6319. return c;
  6320. }
  6321.  
  6322. /*
  6323. ** Return TRUE if segments AB and CD intersect
  6324. */
  6325. static int intersect(TriagPoint *A, TriagPoint *B, TriagPoint *C, TriagPoint *D){
  6326. return
  6327. rightOf(A,B,C)*rightOf(A,B,D)<0 &&
  6328. rightOf(C,D,A)*rightOf(C,D,B)<0;
  6329. }
  6330.  
  6331. /*
  6332. ** Return the squared distance between two points.
  6333. */
  6334. static double dist2(TriagPoint *A, TriagPoint *B){
  6335. double dx = B->x - A->x;
  6336. double dy = B->y - A->y;
  6337. return dx*dx + dy*dy;
  6338. }
  6339.  
  6340. /*
  6341. ** Compute angle ABC measured counter-clockwise from AB. Return the
  6342. ** result.
  6343. **
  6344. ** This does not need to be a true angular measure as long as it is
  6345. ** monotonically increasing.
  6346. */
  6347. static double angleOf(TriagPoint *A, TriagPoint *B, TriagPoint *C){
  6348. double a1, a2, a3;
  6349. if( sameTriagPoint(A,C) ){
  6350. return M_PI;
  6351. }
  6352. a1 = atan2(B->y - A->y, B->x - A->x);
  6353. a2 = atan2(C->y - B->y, C->x - B->x);
  6354. a3 = a2-a1;
  6355. if( a3>M_PI ) a3 -= 2.0*M_PI;
  6356. if( a3<=-M_PI ) a3 += 2.0*M_PI;
  6357. return a3;
  6358. }
  6359.  
  6360. static inline double idealAngle(TriagPoint *A, TriagPoint *B, TriagPoint *P){
  6361. double theta = angleOf(A,B,P);
  6362. double d = M_PI*0.25 - theta;
  6363. if(ODIE_Real_Is_Zero(d)) {
  6364. return 0.0;
  6365. }
  6366. return d;
  6367. }
  6368.  
  6369. /*
  6370. ** Given line segment AB, locate segment BC and return a pointer to
  6371. ** it. If there is not BC return NULL. If there is more than one
  6372. ** BC return the one that minimizes the angle ABC.
  6373. */
  6374. static TriagSegment *TriagSegSetNext(TriagSegSet *pSet, TriagSegment *pAB){
  6375. Link *pX;
  6376. TriagSegment *pBest = 0;
  6377. double angle, bestAngle;
  6378. int cnt = 0;
  6379. int h;
  6380. h = hashTriagPoint(&pAB->to);
  6381. for(pX=pSet->aHash[h]; pX; pX=pX->pNext){
  6382. TriagSegment *pSeg = pX->pLinkNode;
  6383. if( !sameTriagPoint(&pSeg->from, &pAB->to) ) continue;
  6384. /* if(pAB->isBoundary > 1 && pSeg->isBoundary!=0 && pSeg->isBoundary!=pAB->isBoundary) continue; */
  6385. if( cnt==0 ){
  6386. pBest = pSeg;
  6387. bestAngle = angleOf(&pAB->from, &pAB->to, &pBest->to);
  6388. }else{
  6389. angle = angleOf(&pAB->from, &pAB->to, &pSeg->to);
  6390. if( angle<bestAngle ){
  6391. bestAngle = angle;
  6392. pBest = pSeg;
  6393. }
  6394. }
  6395. cnt++;
  6396. }
  6397. return pBest;
  6398. }
  6399.  
  6400. /*
  6401. ** Find and return the line segment that goes from A to B. Return NULL
  6402. ** if there is not such line segment
  6403. */
  6404. static TriagSegment *TriagSegSetFind(TriagSegSet *pSet, TriagPoint *A, TriagPoint *B){
  6405. Link *pX;
  6406. TriagSegment *p;
  6407. int h;
  6408. h = hashTriagPoint(A);
  6409. for(pX=pSet->aHash[h]; pX; pX=pX->pNext){
  6410. p = pX->pLinkNode;
  6411. if( sameTriagPoint(&p->from, A) && sameTriagPoint(&p->to, B) ){
  6412. return p;
  6413. }
  6414. }
  6415. return 0;
  6416. }
  6417.  
  6418. /*
  6419. ** Remove all segments whose length is less than minLength. For
  6420. ** each segment removed, coalesce the inputs into a single new
  6421. ** point at the center of the segment.
  6422. */
  6423. static void removeShortTriagSegments(TriagSegSet *pSet, double minLength){
  6424. Link *pLoop, *pNext;
  6425. double minLen2;
  6426.  
  6427. minLen2 = minLength*minLength;
  6428. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  6429. TriagSegment *p;
  6430. TriagPoint from, to, center;
  6431.  
  6432. p = pLoop->pLinkNode;
  6433. pNext = pLoop->pNext;
  6434. if( dist2(&p->from, &p->to)<minLen2 ){
  6435. from = p->from;
  6436. to = p->to;
  6437. center.x = rint(0.5*(from.x + to.x));
  6438. center.y = rint(0.5*(from.y + to.y));
  6439. TriagSegSetRemove(pSet, p);
  6440. Odie_Free((char *)p);
  6441. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  6442. pNext = pLoop->pNext;
  6443. p = pLoop->pLinkNode;
  6444. if( (p->to.x==from.x && p->to.y==from.y)
  6445. || (p->to.x==to.x && p->to.y==to.y)
  6446. ){
  6447. p->to = center;
  6448. }
  6449. if( (p->from.x==from.x && p->from.y==from.y)
  6450. || (p->from.x==to.x && p->from.y==to.y)
  6451. ){
  6452. p->from = center;
  6453. TriagSegRelink(pSet, p);
  6454. }
  6455. if( p->from.x==p->to.x && p->from.y==p->to.y ){
  6456. TriagSegSetRemove(pSet, p);
  6457. Odie_Free((char *)p);
  6458. }
  6459. }
  6460. pNext = pSet->pAll;
  6461. }
  6462. }
  6463. }
  6464.  
  6465. static int WalkTriagSegments(TriagSegSet *pSet) {
  6466. Link *pLoop, *pNext;
  6467. int changed=0;
  6468. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  6469. TriagSegment *pAB, *pBC;
  6470. Link *pRight, *pL2;
  6471. int c;
  6472. /* Find an oblique angle ABC */
  6473. pAB = pLoop->pLinkNode;
  6474. pNext = pLoop->pNext;
  6475.  
  6476. /*
  6477. ** If we are at an oblique for a non boundary
  6478. ** segment, continue
  6479. */
  6480. if( pAB->notOblique ) continue;
  6481. pBC = TriagSegSetNext(pSet, pAB);
  6482. if( pBC==0 ) {
  6483. /*
  6484. ** Remove an orphan wall
  6485. */
  6486. TriagSegSetRemove(pSet, pAB);
  6487. Odie_Free((char *)pAB);
  6488. changed=1;
  6489. continue;
  6490. }
  6491.  
  6492. if( (c = rightOf(&pAB->from, &pAB->to, &pBC->to))>=0 ){
  6493. if( c>0 || !sameTriagPoint(&pAB->from, &pBC->to) ){
  6494. pAB->notOblique = 1;
  6495. continue;
  6496. }
  6497. }
  6498.  
  6499. /* If we reach here, it means that ABC is an oblique angle.
  6500. ** Locate all vertices to the right of AB.
  6501. */
  6502. pRight = 0;
  6503. for(pL2=pSet->pAll; pL2; pL2=pL2->pNext){
  6504. TriagSegment *pX = pL2->pLinkNode;
  6505. if( strictlyRightOf(&pAB->from, &pAB->to, &pX->from)<0 ) continue;
  6506. if( sameTriagPoint(&pAB->to, &pX->from) ) continue;
  6507. pX->score = dist2(&pAB->to, &pX->from);
  6508. pX->isRight = rightOf(&pBC->from, &pBC->to, &pX->from);
  6509. LinkInit(pX->tmp, pX);
  6510. LinkInsert(&pRight, &pX->tmp);
  6511. }
  6512. if( pRight==0 ){
  6513. return TCL_ERROR;
  6514. }
  6515.  
  6516. /* pRight is a list of vertices to the right of AB. Find the
  6517. ** closest vertex X on this list where the line BX does not intersect
  6518. ** any other segment in the polygon. Then add segments BX and XB.
  6519. */
  6520. while( pRight ){
  6521. Link *pBest=NULL;
  6522. double bestScore;
  6523. int bestRight;
  6524. TriagSegment *pThis,*pX, *pQ;
  6525.  
  6526.  
  6527. /* Search for the "best" vertex. The best vertex is the
  6528. ** one that is closest. Though if the vertex is to the left
  6529. ** of BC (and thus would create another oblique angle) then
  6530. ** artificially reduce its score because we would prefer not
  6531. ** to use it.
  6532. */
  6533. pBest = pRight;
  6534. pThis=pBest->pLinkNode;
  6535. bestScore = pThis->score;
  6536. bestRight = pThis->isRight;
  6537. for(pL2=pBest->pNext; pL2; pL2=pL2->pNext){
  6538. int better=0;
  6539. pX = pL2->pLinkNode;
  6540. if( pX->isRight>0 && bestRight <=0 ) {
  6541. better=1;
  6542. } else if ( pX->isRight<=0 && bestRight>0 ) {
  6543. better=0;
  6544. } else if( pX->score<bestScore ){
  6545. better=1;
  6546. }
  6547. if(better) {
  6548. bestScore = pX->score;
  6549. bestRight = pX->isRight;
  6550. pBest = pL2;
  6551. }
  6552. }
  6553.  
  6554. /* The best vertex is pX */
  6555. pX = pBest->pLinkNode;
  6556. LinkRemove(pBest);
  6557.  
  6558. /* Check to see if BX intersects any segment. If it does, then
  6559. ** go back and search for a different X
  6560. */
  6561. for(pL2=pSet->pAll; pL2; pL2=pL2->pNext){
  6562. pQ = pL2->pLinkNode;
  6563. if( pQ!=pAB && pQ!=pX
  6564. && intersect(&pAB->to, &pX->from, &pQ->from, &pQ->to) ){
  6565. break;
  6566. }
  6567. }
  6568. if( pL2 ) continue;
  6569.  
  6570. /* It did not intersect. So add BX and XB to the pSet->
  6571. */
  6572. TriagSegSetInsert(pSet, pAB->to.x, pAB->to.y, pX->from.x, pX->from.y, 0);
  6573. TriagSegSetInsert(pSet, pX->from.x, pX->from.y, pAB->to.x, pAB->to.y, 0);
  6574. pRight = 0;
  6575. }
  6576. changed=1;
  6577. if(!pAB->isBoundary) {
  6578. pNext = pSet->pAll;
  6579. }
  6580. }
  6581. if(changed) {
  6582. return TCL_CONTINUE;
  6583. }
  6584. return TCL_OK;
  6585. }
  6586.  
  6587. /*
  6588. ** tclcmd: convex_subpolygons_new VECTORS ?MINLENGTH? ?HOLE? ?HOLE? ...
  6589. **
  6590. ** VECTORS is a list of floating-point values. Each group of four values
  6591. ** forms a vector X0,Y0->X1,Y1. The vectors are in no particular order,
  6592. ** but together they form one or more loops. Space to the right of each
  6593. ** vector is within the loop and space to the left is outside.
  6594. **
  6595. ** Loops can be nested. The outer boundary is formed by a clockwise loop
  6596. ** of vectors. Interior holes are formed by counter-clockwise loops.
  6597. **
  6598. ** The output is a list polygons. Each polygon is a list of 3 or more
  6599. ** X,Y coordinate pairs. All polygons are convex and disjoint and they
  6600. ** together cover the input polygon.
  6601. **
  6602. ** Optionally, the user can specify a series of polygons to be subtracted
  6603. ** from the main polygon. These are given as an XY list suitable for
  6604. ** producing a polygon on the tkcanvas
  6605. */
  6606. static int convexNewSubpolyCmd(
  6607. void *pArg,
  6608. Tcl_Interp *interp,
  6609. int objc,
  6610. Tcl_Obj *CONST objv[]
  6611. ){
  6612. Tcl_Obj *pOut; /* The output list */
  6613. Tcl_Obj *pSub; /* A sublist for a single polygon */
  6614. int i, idx, n, nb, cnt;
  6615. TriagSegSet set;
  6616. double minLen = 0.0;
  6617.  
  6618. if( objc!=2 && objc!=3 && objc<4 ){
  6619. Tcl_WrongNumArgs(interp, 1, objv, "VECTORS ?MINLENGTH? ?HOLE? ?HOLE? ...");
  6620. return TCL_ERROR;
  6621. }
  6622. if( Tcl_ListObjLength(interp, objv[1], &n) ) return TCL_ERROR;
  6623. if( objc>2 ){
  6624. if( Tcl_GetDoubleFromObj(interp, objv[2], &minLen) ) return TCL_ERROR;
  6625. }
  6626. if( n<12 || n%4!=0 ){
  6627. Tcl_AppendResult(interp, "VECTORS argument should contain at least 12 and "
  6628. " a multiple of 4 values", 0);
  6629. return TCL_ERROR;
  6630. }
  6631. memset(&set, 0, sizeof(set));
  6632.  
  6633. /*
  6634. ** Insert the polygons the user specified as
  6635. ** the shape of the holes first
  6636. */
  6637. for(idx=3;idx<objc;idx++) {
  6638. double fx,fy,px,py;
  6639.  
  6640. if( Tcl_ListObjLength(interp, objv[idx], &nb) ) return TCL_ERROR;
  6641. if( nb > 0 && (nb<6 || nb%2!=0) ){
  6642. TriagSegSetClear(&set);
  6643. Tcl_AppendResult(interp, "HOLES arguments should contain at least 6 and "
  6644. " a multiple of 2 values", 0);
  6645. return TCL_ERROR;
  6646. }
  6647. Tcl_Obj *pObj;
  6648. Tcl_ListObjIndex(0, objv[idx], 0, &pObj);
  6649. if( Tcl_GetDoubleFromObj(interp, pObj, &fx) ){
  6650. TriagSegSetClear(&set);
  6651. return TCL_ERROR;
  6652. }
  6653. Tcl_ListObjIndex(0, objv[idx], 1, &pObj);
  6654. if( Tcl_GetDoubleFromObj(interp, pObj, &fy) ){
  6655. TriagSegSetClear(&set);
  6656. return TCL_ERROR;
  6657. }
  6658. px=fx;
  6659. py=fy;
  6660. for(i=2; i<nb; i+=2){
  6661. double mx,my;
  6662. double nx,ny;
  6663. Tcl_ListObjIndex(0, objv[idx], i, &pObj);
  6664. if( Tcl_GetDoubleFromObj(interp, pObj, &nx) ){
  6665. TriagSegSetClear(&set);
  6666. return TCL_ERROR;
  6667. }
  6668. Tcl_ListObjIndex(0, objv[idx], i+1, &pObj);
  6669. if( Tcl_GetDoubleFromObj(interp, pObj, &ny) ){
  6670. TriagSegSetClear(&set);
  6671. return TCL_ERROR;
  6672. }
  6673. /*
  6674. TriagSegSetInsert(&set, px, py, nx, ny, idx);
  6675. */
  6676. mx=(nx+px)/2.0;
  6677. my=(ny+py)/2.0;
  6678.  
  6679. TriagSegSetInsert(&set, px, py, mx, my, idx);
  6680. TriagSegSetInsert(&set, mx, my, nx, ny, idx);
  6681. px=nx;
  6682. py=ny;
  6683. }
  6684. double mx,my;
  6685. mx=(fx+px)/2.0;
  6686. my=(fy+py)/2.0;
  6687. TriagSegSetInsert(&set, px, py, mx, my, idx);
  6688. TriagSegSetInsert(&set, mx, my, fx, fy, idx);
  6689. }
  6690.  
  6691. for(i=0; i<n; i+=4){
  6692. int j;
  6693. double x[4];
  6694. TriagPoint A,B,C;
  6695. for(j=0; j<4; j++){
  6696. Tcl_Obj *pObj;
  6697. Tcl_ListObjIndex(0, objv[1], i+j, &pObj);
  6698. if( Odie_GetMatrixElementFromObj(interp, pObj, x, j) ){
  6699. TriagSegSetClear(&set);
  6700. return TCL_ERROR;
  6701. }
  6702. }
  6703. A.x=x[0];
  6704. A.y=x[1];
  6705. C.x=x[2];
  6706. C.y=x[3];
  6707. B.x=(C.x+A.x)/2.0;
  6708. B.y=(C.y+A.y)/2.0;
  6709.  
  6710. /*
  6711. ** Do not insert a vector into the wallset if it
  6712. ** matches a vector already given. It's either redundent
  6713. ** or the edge of a hole
  6714. */
  6715. if(!TriagSegSetFind(&set,&A,&C)) {
  6716. TriagSegSetInsert(&set, A.x, A.y, B.x, B.y, 1);
  6717. }
  6718. if(!TriagSegSetFind(&set,&B,&C)) {
  6719. TriagSegSetInsert(&set, B.x, B.y, C.x, C.y, 1);
  6720. }
  6721. }
  6722.  
  6723. if( minLen>0.0 ){
  6724. removeShortTriagSegments(&set, minLen);
  6725. }
  6726.  
  6727. cnt=0;
  6728. i=TCL_CONTINUE;
  6729. while(i==TCL_CONTINUE) {
  6730. i=WalkTriagSegments(&set);
  6731. cnt++;
  6732. if(cnt>10) {
  6733. break;
  6734. }
  6735. }
  6736. if(i==TCL_CONTINUE) {
  6737. Tcl_AppendResult(interp, "boundary too complex", 0);
  6738. TriagSegSetClear(&set);
  6739. return TCL_ERROR;
  6740. }
  6741. if(i==TCL_ERROR) {
  6742. Tcl_AppendResult(interp, "boundary does not enclose a finite space", 0);
  6743. TriagSegSetClear(&set);
  6744. return TCL_ERROR;
  6745. }
  6746.  
  6747. /* Now all polygons should be convex. We just have to generate them. */
  6748. pOut = Tcl_NewObj();
  6749. int npoly=0;
  6750. while( set.nSeg ){
  6751. TriagPoint start;
  6752. TriagSegment *pAB, *pBC;
  6753. int valid = 0;
  6754. int cnt = 0;
  6755. npoly++;
  6756.  
  6757. pAB = set.pAll->pLinkNode;
  6758. start = pAB->from;
  6759. /*
  6760. ** Walk along the wallsets, filter out
  6761. ** any that do not include one of the
  6762. ** vectors given as an input of the first
  6763. ** argument
  6764. */
  6765. pSub = Tcl_NewObj();
  6766. while( pAB ){
  6767. Tcl_ListObjAppendElement(0, pSub, Tcl_NewDoubleObj(pAB->to.x));
  6768. Tcl_ListObjAppendElement(0, pSub, Tcl_NewDoubleObj(pAB->to.y));
  6769. if(pAB->isBoundary < 2) valid=1;
  6770. cnt++;
  6771. TriagSegSetRemove(&set, pAB);
  6772. if( sameTriagPoint(&pAB->to, &start) ) {
  6773. break;
  6774. }
  6775. pBC = TriagSegSetNext(&set, pAB);
  6776. Odie_Free((char *)pAB);
  6777. pAB = pBC;
  6778. }
  6779. if( pAB==0 || cnt<3 || !valid){
  6780. Tcl_DecrRefCount(pSub);
  6781. }else{
  6782. Tcl_ListObjAppendElement(0, pOut, pSub);
  6783. }
  6784. }
  6785. TriagSegSetClear(&set);
  6786. Tcl_SetObjResult(interp, pOut);
  6787. return TCL_OK;
  6788. }
  6789.  
  6790.  
  6791. /*
  6792. ** tclcmd: convex_subpolygons VECTORS ?MINLENGTH? ?HOLE? ?HOLE? ...
  6793. **
  6794. ** VECTORS is a list of floating-point values. Each group of four values
  6795. ** forms a vector X0,Y0->X1,Y1. The vectors are in no particular order,
  6796. ** but together they form one or more loops. Space to the right of each
  6797. ** vector is within the loop and space to the left is outside.
  6798. **
  6799. ** Loops can be nested. The outer boundary is formed by a clockwise loop
  6800. ** of vectors. Interior holes are formed by counter-clockwise loops.
  6801. **
  6802. ** The output is a list polygons. Each polygon is a list of 3 or more
  6803. ** X,Y coordinate pairs. All polygons are convex and disjoint and they
  6804. ** together cover the input polygon.
  6805. **
  6806. ** Optionally, the user can specify a series of polygons to be subtracted
  6807. ** from the main polygon. These are given as an XY list suitable for
  6808. ** producing a polygon on the tkcanvas
  6809. */
  6810. static int convexSubpolyCmd(
  6811. void *pArg,
  6812. Tcl_Interp *interp,
  6813. int objc,
  6814. Tcl_Obj *CONST objv[]
  6815. ){
  6816. Tcl_Obj *pOut; /* The output list */
  6817. Tcl_Obj *pSub; /* A sublist for a single polygon */
  6818. int i, idx, n, nb, cnt;
  6819. TriagSegSet set;
  6820. double minLen = 0.0;
  6821.  
  6822. if( objc!=2 && objc!=3 && objc<4 ){
  6823. Tcl_WrongNumArgs(interp, 1, objv, "VECTORS ?MINLENGTH? ?HOLE? ?HOLE? ...");
  6824. return TCL_ERROR;
  6825. }
  6826. if( Tcl_ListObjLength(interp, objv[1], &n) ) return TCL_ERROR;
  6827. if( objc>2 ){
  6828. if( Tcl_GetDoubleFromObj(interp, objv[2], &minLen) ) return TCL_ERROR;
  6829. }
  6830. if( n<12 || n%4!=0 ){
  6831. Tcl_AppendResult(interp, "VECTORS argument should contain at least 12 and "
  6832. " a multiple of 4 values", 0);
  6833. return TCL_ERROR;
  6834. }
  6835. memset(&set, 0, sizeof(set));
  6836.  
  6837. /*
  6838. ** Insert the polygons the user specified as
  6839. ** the shape of the holes first
  6840. */
  6841. for(idx=3;idx<objc;idx++) {
  6842. double fx,fy,px,py;
  6843.  
  6844. if( Tcl_ListObjLength(interp, objv[idx], &nb) ) return TCL_ERROR;
  6845. if( nb > 0 && (nb<6 || nb%2!=0) ){
  6846. TriagSegSetClear(&set);
  6847. Tcl_AppendResult(interp, "HOLES arguments should contain at least 6 and "
  6848. " a multiple of 2 values", 0);
  6849. return TCL_ERROR;
  6850. }
  6851. Tcl_Obj *pObj;
  6852. Tcl_ListObjIndex(0, objv[idx], 0, &pObj);
  6853. if( Tcl_GetDoubleFromObj(interp, pObj, &fx) ){
  6854. TriagSegSetClear(&set);
  6855. return TCL_ERROR;
  6856. }
  6857. Tcl_ListObjIndex(0, objv[idx], 1, &pObj);
  6858. if( Tcl_GetDoubleFromObj(interp, pObj, &fy) ){
  6859. TriagSegSetClear(&set);
  6860. return TCL_ERROR;
  6861. }
  6862. px=fx;
  6863. py=fy;
  6864. for(i=2; i<nb; i+=2){
  6865. double nx,ny;
  6866. Tcl_ListObjIndex(0, objv[idx], i, &pObj);
  6867. if( Tcl_GetDoubleFromObj(interp, pObj, &nx) ){
  6868. TriagSegSetClear(&set);
  6869. return TCL_ERROR;
  6870. }
  6871. Tcl_ListObjIndex(0, objv[idx], i+1, &pObj);
  6872. if( Tcl_GetDoubleFromObj(interp, pObj, &ny) ){
  6873. TriagSegSetClear(&set);
  6874. return TCL_ERROR;
  6875. }
  6876. TriagSegSetInsert(&set, px, py, nx, ny, idx);
  6877. px=nx;
  6878. py=ny;
  6879. }
  6880. TriagSegSetInsert(&set, px, py, fx, fy, idx);
  6881. }
  6882.  
  6883. for(i=0; i<n; i+=4){
  6884. int j;
  6885. double x[4];
  6886. TriagPoint A,B;
  6887. for(j=0; j<4; j++){
  6888. Tcl_Obj *pObj;
  6889. Tcl_ListObjIndex(0, objv[1], i+j, &pObj);
  6890. if( Odie_GetMatrixElementFromObj(interp, pObj, x, j) ){
  6891. TriagSegSetClear(&set);
  6892. return TCL_ERROR;
  6893. }
  6894. }
  6895. A.x=x[0];
  6896. A.y=x[1];
  6897. B.x=x[2];
  6898. B.y=x[3];
  6899. /*
  6900. ** Do not insert a vector into the wallset if it
  6901. ** matches a vector already given. It's either redundent
  6902. ** or the edge of a hole
  6903. */
  6904. if(TriagSegSetFind(&set,&A,&B)) continue;
  6905. TriagSegSetInsert(&set, x[0], x[1], x[2], x[3], 1);
  6906. }
  6907.  
  6908. if( minLen>0.0 ){
  6909. removeShortTriagSegments(&set, minLen);
  6910. }
  6911.  
  6912. cnt=0;
  6913. i=TCL_CONTINUE;
  6914. while(i==TCL_CONTINUE) {
  6915. i=WalkTriagSegments(&set);
  6916. cnt++;
  6917. if(cnt>10) {
  6918. break;
  6919. }
  6920. }
  6921. if(i==TCL_CONTINUE) {
  6922. Tcl_AppendResult(interp, "{boundary too complex}", 0);
  6923. TriagSegSetClear(&set);
  6924. return TCL_ERROR;
  6925. }
  6926. if(i==TCL_ERROR) {
  6927. Tcl_AppendResult(interp, "{boundary does not enclose a finite space}", 0);
  6928. TriagSegSetClear(&set);
  6929. return TCL_ERROR;
  6930. }
  6931.  
  6932. int obtuseangles=0;
  6933. /* Now all polygons should be convex. We just have to generate them. */
  6934. pOut = Tcl_NewObj();
  6935. while( set.nSeg ){
  6936. TriagPoint start;
  6937. TriagSegment *pAB, *pBC;
  6938. int valid = 0;
  6939. int cnt = 0;
  6940.  
  6941. pAB = set.pAll->pLinkNode;
  6942. start = pAB->from;
  6943. /*
  6944. ** Walk along the wallsets, filter out
  6945. ** any that do not include one of the
  6946. ** vectors given as an input of the first
  6947. ** argument
  6948. */
  6949. pSub = Tcl_NewObj();
  6950. while( pAB ){
  6951. Tcl_ListObjAppendElement(0, pSub, Tcl_NewDoubleObj(pAB->to.x));
  6952. Tcl_ListObjAppendElement(0, pSub, Tcl_NewDoubleObj(pAB->to.y));
  6953. pBC = TriagSegSetNext(&set, pAB);
  6954. if(pAB->isBoundary < 2) valid=1;
  6955. if(pAB->isRight<0) obtuseangles++;
  6956. cnt++;
  6957. TriagSegSetRemove(&set, pAB);
  6958. if( sameTriagPoint(&pAB->to, &start) ) {
  6959. break;
  6960. }
  6961. Odie_Free((char *)pAB);
  6962. pAB = pBC;
  6963. }
  6964. if( pAB==0 || cnt<3 || !valid){
  6965. Tcl_DecrRefCount(pSub);
  6966. }else{
  6967. Tcl_ListObjAppendElement(0, pOut, pSub);
  6968. }
  6969. }
  6970. TriagSegSetClear(&set);
  6971. if(obtuseangles) {
  6972. Tcl_DecrRefCount(pOut);
  6973. convexNewSubpolyCmd(NULL,interp,objc,objv);
  6974. } else {
  6975. Tcl_SetObjResult(interp, pOut);
  6976. }
  6977. return TCL_OK;
  6978. }
  6979. /*
  6980. ** This file implements a TCL object used for tracking polygons. A
  6981. ** single new TCL command named "poly" is defined. This command
  6982. ** has methods for creating, deleting, and taking the intersection
  6983. ** of 2-D polygons. There are comments on the implementation of each
  6984. ** method to describe what the method does.
  6985. **
  6986. ** This module was originally developed to aid in computing the
  6987. ** shared surface area between two compartments on separate decks.
  6988. ** The shared surface area is needed in initializing the fire model
  6989. ** since heat conduction between the two compartments is proportional
  6990. ** to their shared area.
  6991. */
  6992. /* PolygonObj_freeIntRepProc */
  6993. void PolygonObj_freeIntRepProc(Tcl_Obj *objPtr){
  6994. if(objPtr->internalRep.otherValuePtr) {
  6995. Odie_Polygon *pPoly=objPtr->internalRep.otherValuePtr;
  6996. if(pPoly->refCount) {
  6997. pPoly->refCount--;
  6998. }
  6999. if(!pPoly->refCount) {
  7000. Tcl_Free(objPtr->internalRep.otherValuePtr);
  7001. objPtr->internalRep.otherValuePtr=NULL;
  7002. objPtr->typePtr=NULL;
  7003. }
  7004. }
  7005. }
  7006. /* PolygonObj_dupIntRepProc */
  7007. void PolygonObj_dupIntRepProc(Tcl_Obj *srcPtr,Tcl_Obj *dupPtr){
  7008. Odie_Polygon *src=srcPtr->internalRep.otherValuePtr;
  7009. int size=sizeof(*src)+src->nVertex*sizeof(src->v[0]);
  7010. Odie_Polygon *copy=(Odie_Polygon *)Odie_Alloc(size);
  7011.  
  7012. memcpy(copy,src,size);
  7013. Tcl_InvalidateStringRep(dupPtr);
  7014. dupPtr->typePtr=&polygon_tclobjtype;
  7015. dupPtr->internalRep.otherValuePtr=copy;
  7016. }
  7017. /* PolygonObj_updateStringRepProc */
  7018. void PolygonObj_updateStringRepProc(Tcl_Obj *objPtr){
  7019. /* Update String Rep */
  7020. char outbuffer[128];
  7021. Tcl_DString result;
  7022. Odie_Polygon *p=objPtr->internalRep.otherValuePtr;
  7023. int i,j;
  7024. Tcl_DStringInit(&result);
  7025. j=p->nVertex-1;
  7026. if(p->v[0][X_IDX]==p->v[j][X_IDX] && p->v[0][Y_IDX]==p->v[j][Y_IDX]) {
  7027. j=p->nVertex-2;
  7028. }
  7029. for(i=0; i<=j; i++){
  7030. sprintf(outbuffer,"%g %g",(float)p->v[i][X_IDX],(float)p->v[i][Y_IDX]);
  7031. Tcl_DStringAppendElement(&result,outbuffer);
  7032. }
  7033. objPtr->length=Tcl_DStringLength(&result);
  7034. objPtr->bytes=Odie_Alloc(objPtr->length+1);
  7035. strcpy(objPtr->bytes,Tcl_DStringValue(&result));
  7036. Tcl_DStringFree(&result);
  7037. }
  7038. /* Odie_Poly_ShimmerOrFree_TclObj */
  7039. int Odie_Poly_ShimmerOrFree_TclObj(Tcl_Obj *objPtr,Odie_Polygon *p){
  7040. if(objPtr->typePtr) {
  7041. if(objPtr->typePtr->setFromAnyProc==&PolygonObj_setFromAnyProc) {
  7042. /*
  7043. ** Object is already of the type requested
  7044. */
  7045. return 1;
  7046. }
  7047. }
  7048. if(Tcl_IsShared(objPtr)) {
  7049. Odie_Free((char *)p);
  7050. return 1;
  7051. }
  7052. if(objPtr->typePtr && objPtr->typePtr->freeIntRepProc) {
  7053. Tcl_FreeInternalRepProc *freeIntRepProc=objPtr->typePtr->freeIntRepProc;
  7054. freeIntRepProc(objPtr);
  7055. }
  7056. objPtr->internalRep.otherValuePtr=p;
  7057. objPtr->typePtr=&polygon_tclobjtype;
  7058. Tcl_IncrRefCount(objPtr);
  7059. return 0;
  7060. }
  7061. /* *Odie_Poly_Create */
  7062. Odie_Polygon *Odie_Poly_Create(int nVertex){
  7063. Odie_Polygon *p;
  7064. p=(Odie_Polygon *)Odie_Alloc(sizeof(*p)+(nVertex+1)*sizeof(p->v[0]));
  7065. p->nVertex=nVertex;
  7066. return p;
  7067. }
  7068. /* PolygonObj_setFromAnyProc */
  7069. int PolygonObj_setFromAnyProc(Tcl_Interp *interp,Tcl_Obj *objPtr){
  7070. /* Set internal rep from any Tcl_Obj */
  7071. if(objPtr->typePtr) {
  7072. if(objPtr->typePtr==&polygon_tclobjtype) {
  7073. /*
  7074. ** Object is already of the type requested
  7075. */
  7076. return TCL_OK;
  7077. }
  7078. }
  7079. Odie_Polygon *p;
  7080. int created=0;
  7081. if(Odie_Polygon_GetFromTclObj(interp,objPtr,&p,&created)) {
  7082. return TCL_ERROR;
  7083. }
  7084. Tcl_InvalidateStringRep(objPtr);
  7085. objPtr->internalRep.otherValuePtr=p;
  7086. objPtr->typePtr=&polygon_tclobjtype;
  7087. return TCL_OK;
  7088. }
  7089. /* *Odie_Polygon_NewTclObj */
  7090. Tcl_Obj *Odie_Polygon_NewTclObj(Odie_Polygon *pPoly){
  7091. Tcl_Obj *pResult;
  7092. pResult=Tcl_NewObj();
  7093. Tcl_InvalidateStringRep(pResult);
  7094. pPoly->refCount++;
  7095. pResult->internalRep.otherValuePtr=pPoly;
  7096. pResult->typePtr=&polygon_tclobjtype;
  7097. return pResult;
  7098. }
  7099. /* Odie_Polygon_From_FaceXYZ */
  7100. int Odie_Polygon_From_FaceXYZ(Tcl_Interp *interp,Tcl_Obj *objPtr,Odie_Polygon **ptr){
  7101. int i,nVertex;
  7102. Tcl_Obj *pElem;
  7103. Odie_Polygon *p;
  7104. Odie_FaceXYZ *poly;
  7105. poly=objPtr->internalRep.otherValuePtr;
  7106. nVertex=poly->nVertex;
  7107. p=Odie_Poly_Create(nVertex);
  7108. for(i=0; i<nVertex; i++){
  7109. VectorXY_Copy(p->v[i],poly->vertex_xyz[i]);
  7110. }
  7111. VectorXY_Copy(p->v[nVertex],poly->vertex_xyz[0]);
  7112.  
  7113. if(Odie_Polygon_ComputeArea(interp,p)) goto createfail;
  7114. *ptr=p;
  7115. return TCL_OK;
  7116.  
  7117. createfail:
  7118. Odie_Free((char *)p);
  7119. return TCL_ERROR;
  7120. }
  7121. /* Odie_Polygon_GetFromTclObj */
  7122. int Odie_Polygon_GetFromTclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,Odie_Polygon **ptr,int *created){
  7123. Odie_Polygon *p;
  7124. *created=0;
  7125.  
  7126. if(objPtr->typePtr) {
  7127. if(objPtr->typePtr==&polygon_tclobjtype && objPtr->internalRep.otherValuePtr) {
  7128. /*
  7129. ** Object is already of the type requested
  7130. */
  7131. *ptr=objPtr->internalRep.otherValuePtr;
  7132. return TCL_OK;
  7133. }
  7134. if(objPtr->typePtr->setFromAnyProc==&Odie_FaceXYZ_setFromAnyProc && objPtr->internalRep.otherValuePtr) {
  7135. *created=1;
  7136. return Odie_Polygon_From_FaceXYZ(interp,objPtr,ptr);
  7137. }
  7138. }
  7139. int k,i;
  7140. if( Tcl_ListObjLength(interp, objPtr, &k) ) return TCL_ERROR;
  7141. if( k<6 ){
  7142. Tcl_AppendResult(interp, "need at least 3 vertices", 0);
  7143. return TCL_ERROR;
  7144. }
  7145. if( k&1 ){
  7146. Tcl_AppendResult(interp, "coordinates should come in pairs", 0);
  7147. return TCL_ERROR;
  7148. }
  7149. *created=1;
  7150. p=(Odie_Polygon *)Odie_Alloc(sizeof(*p)+(k+2)*sizeof(p->v[0]));
  7151. p->nVertex=k/2;
  7152. for(i=0; i<p->nVertex; i++){
  7153. Tcl_Obj *pElem;
  7154. double d;
  7155. Tcl_ListObjIndex(0, objPtr, i*2, &pElem);
  7156. if(Tcl_GetDoubleFromObj(interp, pElem, &d)) goto createfail;
  7157. p->v[i][X_IDX] = d;
  7158. Tcl_ListObjIndex(0, objPtr, i*2+1, &pElem);
  7159. if(Tcl_GetDoubleFromObj(interp, pElem, &d)) goto createfail;
  7160. p->v[i][Y_IDX] = d;
  7161. }
  7162. if(Odie_Polygon_ComputeArea(interp,p)==TCL_OK) {
  7163. *ptr=p;
  7164. return TCL_OK;
  7165. }
  7166.  
  7167. createfail:
  7168. Tcl_Free((char *)p);
  7169. return TCL_ERROR;
  7170. }
  7171. /* Odie_IsColinear */
  7172. static inline int Odie_IsColinear(double x1,double y1,double x2,double y2,double x3,double y3){
  7173. /* Detect of two lines are colinear */
  7174. if(floatCompare(x1,x3)==0 && floatCompare(y1,y3)==0) {
  7175. return 1;
  7176. }
  7177. double c=(x3-x1)*(y2-y1)-(y3-y1)*(x2-x1);
  7178. if(fabs(c) < __FLT_EPSILON__) return 1;
  7179. return 0;
  7180. }
  7181. /* dist */
  7182. static inline double dist(double x0, double y0, double x1, double y1){
  7183. /*
  7184. ** Return the distance between two points
  7185. */
  7186. double dx = x1 - x0;
  7187. double dy = y1 - y0;
  7188. return sqrt(dx*dx + dy*dy);
  7189. }
  7190. /* withinPolygon */
  7191. static inline int withinPolygon(Odie_Polygon *p, double x, double y){
  7192. /*
  7193. ** Return -1, 0, or 1 if the point x,y is outside, on, or within
  7194. ** the polygon p.
  7195. */
  7196. int res, i;
  7197. /* Do a bounding box check before getting more ellaborate */
  7198. if( x>p->bbox[BBOX_X1_IDX]
  7199. || x<p->bbox[BBOX_X0_IDX]
  7200. || y>p->bbox[BBOX_Y1_IDX]
  7201. || y<p->bbox[BBOX_Y0_IDX]
  7202. ) return -1;
  7203. res = -1;
  7204. for(i=0; i<p->nVertex-1; i++){
  7205. double x0, y0, x1, y1, yP;
  7206. x0 = p->v[i][X_IDX];
  7207. y0 = p->v[i][Y_IDX];
  7208. x1 = p->v[i+1][X_IDX];
  7209. y1 = p->v[i+1][Y_IDX];
  7210. if( x0==x1 ){
  7211. if( x0==x && ((y0<=y && y1>=y) || (y1<=y && y0>=y)) ){
  7212. res = 0;
  7213. break;
  7214. }
  7215. continue;
  7216. }
  7217. if( x0>x1 ){
  7218. int t = x0;
  7219. x0 = x1;
  7220. x1 = t;
  7221. t = y0;
  7222. y0 = y1;
  7223. y1 = t;
  7224. }
  7225. if( x>=x1 || x<x0 ) continue;
  7226. yP = y1 - (x1-x)*(y1-y0)/(x1-x0);
  7227. if( yP == y ){ res = 0; break; }
  7228. if( yP > y ){ res = -res; }
  7229. }
  7230. return res;
  7231. }
  7232. /* Odie_Polygon_XYWithin */
  7233. int Odie_Polygon_XYWithin(Odie_Polygon *p, double x, double y){
  7234. /*
  7235. ** Return -1, 0, or 1 if the point x,y is outside, on, or within
  7236. ** the polygon p.
  7237. */
  7238. return withinPolygon(p,x,y);
  7239. }
  7240. /* Odie_Polygon_VectorXYWithin */
  7241. int Odie_Polygon_VectorXYWithin(Odie_Polygon *p, VectorXY C){
  7242. /*
  7243. ** Return -1, 0, or +1 if the point P is outside, on the border of, or
  7244. ** fully contained within the subcompartment pSub.
  7245. */
  7246. return withinPolygon(p,C[X_IDX],C[Y_IDX]);
  7247. }
  7248. /* Odie_Polygon_ComputeArea */
  7249. int Odie_Polygon_ComputeArea(Tcl_Interp *interp,Odie_Polygon *p){
  7250. double area=0.0;
  7251. double areacomp=0.0;
  7252. int i;
  7253.  
  7254. 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] ){
  7255. p->v[p->nVertex][X_IDX] = p->v[0][X_IDX];
  7256. p->v[p->nVertex][Y_IDX] = p->v[0][Y_IDX];
  7257. p->nVertex++;
  7258. }
  7259.  
  7260. for(i=0; i<p->nVertex-1; i++){
  7261. 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]);
  7262. }
  7263. if( area<0.0 ){
  7264. int b, e;
  7265. for(b=0, e=p->nVertex-1; b<e; b++, e--){
  7266. double t;
  7267. t = p->v[b][X_IDX];
  7268. p->v[b][X_IDX] = p->v[e][X_IDX];
  7269. p->v[e][X_IDX] = t;
  7270. t = p->v[b][Y_IDX];
  7271. p->v[b][Y_IDX] = p->v[e][Y_IDX];
  7272. p->v[e][Y_IDX] = t;
  7273. }
  7274. area = -area;
  7275. }
  7276. p->area = area;
  7277. p->bbox[BBOX_X0_IDX] = p->bbox[BBOX_X1_IDX] = p->v[0][X_IDX];
  7278. p->bbox[BBOX_Y1_IDX] = p->bbox[BBOX_Y0_IDX] = p->v[0][Y_IDX];
  7279. for(i=1; i<p->nVertex-1; i++){
  7280. double x, y;
  7281. x = p->v[i][X_IDX];
  7282. if( x<p->bbox[BBOX_X0_IDX] ) p->bbox[BBOX_X0_IDX] = x;
  7283. if( x>p->bbox[BBOX_X1_IDX] ) p->bbox[BBOX_X1_IDX] = x;
  7284. y = p->v[i][Y_IDX];
  7285. if( y>p->bbox[BBOX_Y1_IDX] ) p->bbox[BBOX_Y1_IDX] = y;
  7286. if( y<p->bbox[BBOX_Y0_IDX] ) p->bbox[BBOX_Y0_IDX] = y;
  7287. }
  7288. areacomp=(p->bbox[BBOX_X1_IDX] - p->bbox[BBOX_X0_IDX])*(p->bbox[BBOX_Y1_IDX]-p->bbox[BBOX_Y0_IDX])*1.00001;
  7289.  
  7290. p->center[X_IDX]=(p->bbox[BBOX_X1_IDX]-p->bbox[BBOX_X0_IDX])*0.5+p->bbox[BBOX_X0_IDX];
  7291. p->center[Y_IDX]=(p->bbox[BBOX_Y1_IDX]-p->bbox[BBOX_Y0_IDX])*0.5+p->bbox[BBOX_Y0_IDX];
  7292. if(area<=areacomp) {
  7293. return TCL_OK;
  7294. } else {
  7295. char errstr[256];
  7296. sprintf(errstr,"Area: %g Calculated: %g\n",area,areacomp);
  7297. Tcl_AppendResult(interp, "Area of polygon wonky ", errstr, 0);
  7298. return TCL_ERROR;
  7299. }
  7300. }
  7301. /* Odie_Poly_Compare */
  7302. int Odie_Poly_Compare(Odie_Polygon *polyA,Odie_Polygon *polyB){
  7303. int i,j,N;
  7304. if(!polyA || !polyB) {
  7305. return 0;
  7306. }
  7307. if(polyA->nVertex!=polyB->nVertex) {
  7308. return 0;
  7309. }
  7310. N=polyA->nVertex;
  7311. for(i=0;i<N;i++) {
  7312. if(VectorXY_SamePoint(polyA->v[i],polyB->v[0])) {
  7313. /* Check in either direction */
  7314. for(j=1;j<N;j++) {
  7315. if(
  7316. VectorXY_SamePoint(polyA->v[(i+j)%N],polyB->v[j])==0
  7317. &&
  7318. VectorXY_SamePoint(polyA->v[(i-j)%N],polyB->v[j])==0
  7319. ) {
  7320. return 0;
  7321. }
  7322. }
  7323. /* If we got here we pass */
  7324. return 1;
  7325. }
  7326. }
  7327. return 0;
  7328.  
  7329. }
  7330. /* *Odie_FaceXYZ_ToDict */
  7331. Tcl_Obj *Odie_FaceXYZ_ToDict(Odie_FaceXYZ *pPoly){
  7332. Tcl_Obj *element=Tcl_NewObj();
  7333. {
  7334. Tcl_Obj *value;
  7335. value=Tcl_NewIntObj(pPoly->id);
  7336. Odie_DictObjPut(NULL,element,"id",value);
  7337. }
  7338. {
  7339. Tcl_Obj *value;
  7340. value=Tcl_NewDoubleObj(pPoly->area);
  7341. Odie_DictObjPut(NULL,element,"area",value);
  7342. }
  7343. {
  7344. Tcl_Obj *value;
  7345.  
  7346. Odie_MatrixObj *C;
  7347. if(pPoly->is_2d) {
  7348. C=Odie_MatrixObj_Create(MATFORM_bbox_xy);
  7349. VectorXY_BBOX_Copy(C->matrix,pPoly->bbox_uv);
  7350. value=Matrix_To_TclObj(C);
  7351. } else {
  7352. C=Odie_MatrixObj_Create(MATFORM_aabb_xyz);
  7353. VectorXYZ_AABB_Copy(C->matrix,pPoly->bbox_xyz);
  7354. value=Matrix_To_TclObj(C);
  7355. }
  7356.  
  7357. Odie_DictObjPut(NULL,element,"bbox",value);
  7358. }
  7359. {
  7360. Tcl_Obj *value;
  7361. value=Tcl_NewIntObj(pPoly->bend);
  7362. Odie_DictObjPut(NULL,element,"bend",value);
  7363. }
  7364. {
  7365. Tcl_Obj *value;
  7366. value=VectorXYZ_To_TclObj(pPoly->center);
  7367. Odie_DictObjPut(NULL,element,"center",value);
  7368. }
  7369. {
  7370. Tcl_Obj *value;
  7371. value=Tcl_NewBooleanObj(pPoly->is_convex);
  7372. Odie_DictObjPut(NULL,element,"is_2d",value);
  7373. }
  7374. {
  7375. Tcl_Obj *value;
  7376. value=Tcl_NewBooleanObj(pPoly->is_convex);
  7377. Odie_DictObjPut(NULL,element,"is_convex",value);
  7378. }
  7379. {
  7380. Tcl_Obj *value;
  7381. value=VectorXYZ_To_TclObj(pPoly->normal);
  7382. Odie_DictObjPut(NULL,element,"normal",value);
  7383. }
  7384. {
  7385. Tcl_Obj *value;
  7386. value=Tcl_NewIntObj(pPoly->nVertex);
  7387. Odie_DictObjPut(NULL,element,"nVertex",value);
  7388. }
  7389. {
  7390. Tcl_Obj *value;
  7391. value=Tcl_NewDoubleObj(pPoly->radius);
  7392. Odie_DictObjPut(NULL,element,"radius",value);
  7393. }
  7394. {
  7395. Tcl_Obj *value;
  7396.  
  7397. Odie_MatrixObj *C;
  7398. C=Odie_MatrixObj_Create(MATFORM_affine);
  7399. Odie_Affine4x4_Copy(C->matrix,pPoly->rotation);
  7400. value=Matrix_To_TclObj(C);
  7401.  
  7402. Odie_DictObjPut(NULL,element,"rotation",value);
  7403. }
  7404. {
  7405. Tcl_Obj *value;
  7406.  
  7407. Odie_MatrixObj *C;
  7408. C=Odie_MatrixObj_Create(MATFORM_affine);
  7409. Odie_Affine4x4_Copy(C->matrix,pPoly->rotation_inv);
  7410. value=Matrix_To_TclObj(C);
  7411.  
  7412. Odie_DictObjPut(NULL,element,"rotation_inv",value);
  7413. }
  7414. return element;}
  7415. /* Odie_FaceXYZ_freeIntRepProc */
  7416. void Odie_FaceXYZ_freeIntRepProc(Tcl_Obj *objPtr){
  7417. Odie_Free(objPtr->internalRep.otherValuePtr);
  7418. objPtr->internalRep.otherValuePtr=NULL;
  7419. objPtr->typePtr=NULL;
  7420. }
  7421. /* Odie_FaceXYZ_dupIntRepProc */
  7422. void Odie_FaceXYZ_dupIntRepProc(Tcl_Obj *srcPtr,Tcl_Obj *dupPtr){
  7423. Odie_FaceXYZ *src=srcPtr->internalRep.otherValuePtr;
  7424. Odie_FaceXYZ *copy=Odie_FaceXYZ_Create(src->nVertex);
  7425. memcpy(copy,src,src->alloc_bytes);
  7426. Tcl_InvalidateStringRep(dupPtr);
  7427. dupPtr->typePtr=srcPtr->typePtr;
  7428. dupPtr->internalRep.otherValuePtr=copy;
  7429. }
  7430. /* Odie_FaceXYZ_updateStringProc */
  7431. void Odie_FaceXYZ_updateStringProc(Tcl_Obj *objPtr){
  7432. /* Update String Rep */
  7433. char outbuffer[256];
  7434. Tcl_DString result;
  7435. Odie_FaceXYZ *p=objPtr->internalRep.otherValuePtr;
  7436. int i,n;
  7437. Tcl_DStringInit(&result);
  7438. n=p->nVertex;
  7439.  
  7440. /* Express as 3d */
  7441. for(i=0; i<n; i++){
  7442. 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]);
  7443. Tcl_DStringAppendElement(&result,outbuffer);
  7444. }
  7445.  
  7446. objPtr->length=Tcl_DStringLength(&result);
  7447. objPtr->bytes=Odie_Alloc(objPtr->length+1);
  7448. strcpy(objPtr->bytes,Tcl_DStringValue(&result));
  7449. Tcl_DStringFree(&result);
  7450. }
  7451. /* Odie_FaceXYZ_setFromAnyProc */
  7452. int Odie_FaceXYZ_setFromAnyProc(Tcl_Interp *interp,Tcl_Obj *objPtr){
  7453. /* Set internal rep from any Tcl_Obj */
  7454. if(objPtr->typePtr) {
  7455. if(objPtr->typePtr->setFromAnyProc==&Odie_FaceXYZ_setFromAnyProc && objPtr->internalRep.otherValuePtr) {
  7456. /*
  7457. ** Object is already of the type requested
  7458. */
  7459. return TCL_OK;
  7460. }
  7461. }
  7462. Odie_FaceXYZ *p;
  7463. int created=0;
  7464. if(Odie_FaceXYZ_GetFromTclObj(interp,objPtr,&p,&created)) {
  7465. return TCL_ERROR;
  7466. }
  7467. Tcl_InvalidateStringRep(objPtr);
  7468. objPtr->internalRep.otherValuePtr=p;
  7469. objPtr->typePtr=&odie_polygon_tclobjtype;
  7470. return TCL_OK;
  7471. }
  7472. /* *Odie_FaceXYZ_NewTclObj */
  7473. Tcl_Obj *Odie_FaceXYZ_NewTclObj(Odie_FaceXYZ *pPolygon){
  7474. Tcl_Obj *pResult;
  7475. pResult=Tcl_NewObj();
  7476. pResult->internalRep.otherValuePtr=pPolygon;
  7477. pResult->typePtr=&odie_polygon_tclobjtype;
  7478. Tcl_InvalidateStringRep(pResult);
  7479. Tcl_IncrRefCount(pResult);
  7480. return pResult;
  7481. }
  7482. /* *Odie_FaceXYZ_Create */
  7483. Odie_FaceXYZ *Odie_FaceXYZ_Create(int nVertex){
  7484. void *ptr;
  7485. Odie_FaceXYZ *p;
  7486. size_t size;
  7487. int maxVertex=nVertex+2; /* Allocate room for an additional 2 vertices */
  7488. if(nVertex<3) {
  7489. nVertex=3;
  7490. maxVertex=nVertex+2;
  7491. }
  7492. size=sizeof(*p)+maxVertex*sizeof(VectorXYZ)+maxVertex*sizeof(VectorXYZ);
  7493. ptr=Odie_Alloc(size);
  7494. p=(Odie_FaceXYZ *)ptr;
  7495. p->alloc_bytes=size;
  7496. p->maxVertex=maxVertex;
  7497. p->nVertex=nVertex;
  7498. p->vertex_uv=(ptr+sizeof(*p));
  7499. p->vertex_xyz=(ptr+sizeof(*p)+maxVertex*sizeof(VectorXYZ));
  7500. return p;
  7501. }
  7502. /* Odie_FaceXYZ_FromXYList */
  7503. int Odie_FaceXYZ_FromXYList(Tcl_Interp *interp,Tcl_Obj *objPtr,Odie_FaceXYZ **ptr){
  7504. int k,i,nVertex;
  7505. Tcl_Obj *pElem;
  7506. Odie_FaceXYZ *p;
  7507. if( Tcl_ListObjLength(interp, objPtr, &k) ) return TCL_ERROR;
  7508. /* Read in a series of doubles a X Y pairs */
  7509. if( k<6 ){
  7510. Tcl_AppendResult(interp, "need at least 3 vertices", 0);
  7511. return TCL_ERROR;
  7512. }
  7513. if( k&1 ){
  7514. Tcl_AppendResult(interp, "coordinates should come in pairs", 0);
  7515. return TCL_ERROR;
  7516. }
  7517. nVertex=k/2;
  7518. p=Odie_FaceXYZ_Create(nVertex);
  7519. for(i=0; i<nVertex; i++){
  7520. double d;
  7521. Tcl_ListObjIndex(0, objPtr, i*2, &pElem);
  7522. if(Tcl_GetDoubleFromObj(interp, pElem, &d)) goto createfail;
  7523. p->vertex_xyz[i][X_IDX] = d;
  7524.  
  7525. Tcl_ListObjIndex(0, objPtr, i*2+1, &pElem);
  7526. if(Tcl_GetDoubleFromObj(interp, pElem, &d)) goto createfail;
  7527. p->vertex_xyz[i][Y_IDX] = d;
  7528. p->vertex_xyz[i][Z_IDX] = 0.0;
  7529. }
  7530. if(Odie_FaceXYZ_Compute(interp,p)) goto createfail;
  7531. *ptr=p;
  7532. return TCL_OK;
  7533.  
  7534. createfail:
  7535. Odie_Free((char *)p);
  7536. return TCL_ERROR;
  7537. }
  7538. /* Odie_FaceXYZ_FromPoly */
  7539. int Odie_FaceXYZ_FromPoly(Tcl_Interp *interp,Tcl_Obj *objPtr,Odie_FaceXYZ **ptr){
  7540. int k,i,nVertex;
  7541. Tcl_Obj *pElem;
  7542. Odie_FaceXYZ *p;
  7543. Odie_Polygon *poly;
  7544. poly=objPtr->internalRep.otherValuePtr;
  7545. nVertex=poly->nVertex;
  7546. p=Odie_FaceXYZ_Create(nVertex);
  7547. for(i=0; i<nVertex; i++){
  7548. VectorXY_Copy(p->vertex_xyz[i],poly->v[i]);
  7549. p->vertex_xyz[i][Z_IDX] = 0.0;
  7550. }
  7551. if(Odie_FaceXYZ_Compute(interp,p)) goto createfail;
  7552. *ptr=p;
  7553. return TCL_OK;
  7554.  
  7555. createfail:
  7556. Odie_Free((char *)p);
  7557. return TCL_ERROR;
  7558. }
  7559. /* Odie_FaceXYZ_FromVectorList */
  7560. int Odie_FaceXYZ_FromVectorList(Tcl_Interp *interp,Tcl_Obj *objPtr,Odie_FaceXYZ **ptr){
  7561. int k,i,nVertex;
  7562. Tcl_Obj *pElem;
  7563. Odie_FaceXYZ *p;
  7564. if( Tcl_ListObjLength(interp, objPtr, &k) ) return TCL_ERROR;
  7565.  
  7566. if( k<3 ){
  7567. Tcl_AppendResult(interp, "need at least 3 vertices", 0);
  7568. return TCL_ERROR;
  7569. }
  7570. nVertex=k;
  7571. p=Odie_FaceXYZ_Create(nVertex);
  7572. for(i=0; i<p->nVertex; i++){
  7573. Tcl_ListObjIndex(0, objPtr, i, &pElem);
  7574. if(Odie_GetVectorXYZFromTclObj(interp,pElem,p->vertex_xyz[i])) goto createfail;
  7575. }
  7576. if(Odie_FaceXYZ_Compute(interp,p)) goto createfail;
  7577. *ptr=p;
  7578. return TCL_OK;
  7579.  
  7580. createfail:
  7581. Odie_Free((char *)p);
  7582. return TCL_ERROR;
  7583. }
  7584. /* Odie_ConvexPolygon_GetFromTclObj */
  7585. int Odie_ConvexPolygon_GetFromTclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,Odie_FaceXYZ **ptr,int *created){
  7586. int result;
  7587. result=Odie_FaceXYZ_GetFromTclObj(interp,objPtr,ptr,created);
  7588. if(result) {
  7589. return result;
  7590. }
  7591. Odie_FaceXYZ *pPoly=*ptr;
  7592. if(pPoly->is_convex) {
  7593. return TCL_OK;
  7594. }
  7595. if(interp) {
  7596. Tcl_AppendResult(interp,"Polygon is not convex",NULL);
  7597. }
  7598. if(*created) Odie_FaceXYZ_ShimmerOrFree_TclObj(objPtr,*ptr);
  7599. return TCL_ERROR;
  7600. }
  7601. /* Odie_FaceXYZ_GetFromTclObj */
  7602. int Odie_FaceXYZ_GetFromTclObj(Tcl_Interp *interp,Tcl_Obj *objPtr,Odie_FaceXYZ **ptr,int *created){
  7603. *created=1;
  7604. Tcl_Obj *pElem;
  7605. int k,first_element_length;
  7606.  
  7607. if(objPtr->typePtr) {
  7608. if(objPtr->typePtr->setFromAnyProc==&Odie_FaceXYZ_setFromAnyProc && objPtr->internalRep.otherValuePtr) {
  7609. /*
  7610. ** Object is already of the type requested
  7611. */
  7612. *ptr=objPtr->internalRep.otherValuePtr;
  7613. *created=0;
  7614. return TCL_OK;
  7615. }
  7616. if(objPtr->typePtr->setFromAnyProc==&PolygonObj_setFromAnyProc && objPtr->internalRep.otherValuePtr) {
  7617. /* Our first element is encoded as an ODIE vector */
  7618. *created=1;
  7619. return Odie_FaceXYZ_FromPoly(interp,objPtr,ptr);
  7620. }
  7621. }
  7622. *created=1;
  7623. if( Tcl_ListObjLength(interp, objPtr, &k) ) return TCL_ERROR;
  7624. if( k<3 ){
  7625. Tcl_AppendResult(interp, "need at least 3 vertices", 0);
  7626. return TCL_ERROR;
  7627. }
  7628. /* See if our first element is a valid XYZ Coordnate */
  7629. Tcl_ListObjIndex(0, objPtr, 0, &pElem);
  7630. if(pElem->typePtr) {
  7631. if(objPtr->typePtr->setFromAnyProc==&MatrixObj_setFromAnyProc && objPtr->internalRep.otherValuePtr) {
  7632. /* Our first element is encoded as an ODIE vector */
  7633. return Odie_FaceXYZ_FromVectorList(interp,objPtr,ptr);
  7634. }
  7635. }
  7636. /* Guess form by the list contents */
  7637. if( Tcl_ListObjLength(interp, pElem, &first_element_length) ) return TCL_ERROR;
  7638. if(first_element_length==1) {
  7639. /* The first element is only 1 element long, guess we have a stream of doubles */
  7640. return Odie_FaceXYZ_FromXYList(interp,objPtr,ptr);
  7641. }
  7642. if(first_element_length==2) {
  7643. /* The first element is 2 element long, guess we have a stream of vectors */
  7644. return Odie_FaceXYZ_FromVectorList(interp,objPtr,ptr);
  7645. }
  7646. if(first_element_length==3) {
  7647. /* The first element is 3 element long, guess we have a stream of vectors */
  7648. return Odie_FaceXYZ_FromVectorList(interp,objPtr,ptr);
  7649. }
  7650. /* Stop trying to quess */
  7651. Tcl_AppendResult(interp, "Cannot intepret input", 0);
  7652. return TCL_ERROR;
  7653. }
  7654. /* Odie_FaceXYZ_ShimmerOrFree_TclObj */
  7655. void Odie_FaceXYZ_ShimmerOrFree_TclObj(Tcl_Obj *objPtr,Odie_FaceXYZ *p){
  7656. if(objPtr->typePtr) {
  7657. if(objPtr->typePtr->setFromAnyProc==&Odie_FaceXYZ_setFromAnyProc) {
  7658. /*
  7659. ** Object is already of the type requested
  7660. */
  7661. return;
  7662. }
  7663. }
  7664. if(Tcl_IsShared(objPtr)) {
  7665. Odie_Free((char *)p);
  7666. return;
  7667. }
  7668. if(objPtr->typePtr && objPtr->typePtr->freeIntRepProc) {
  7669. Tcl_FreeInternalRepProc *freeIntRepProc=objPtr->typePtr->freeIntRepProc;
  7670. freeIntRepProc(objPtr);
  7671. }
  7672. objPtr->internalRep.otherValuePtr=p;
  7673. objPtr->typePtr=&odie_polygon_tclobjtype;
  7674. Tcl_IncrRefCount(objPtr);
  7675. return;
  7676. }
  7677. /* Odie_FaceXYZ_Compute */
  7678. int Odie_FaceXYZ_Compute(Tcl_Interp *interp,Odie_FaceXYZ *p){
  7679. double normal_length=0.0;
  7680. int i,j,k,rmax=0,r1;
  7681. double area=0.0;
  7682. double areacomp=0.0;
  7683. int is2d=1;
  7684. VectorXYZ SUM;
  7685. if(p->nVertex<3) {
  7686. if(interp) {
  7687. Tcl_AppendResult(interp,"Polygons need at least 3 vertices",NULL);
  7688. }
  7689. return TCL_ERROR;
  7690. }
  7691. while(VectorXYZ_SamePoint(p->vertex_xyz[p->nVertex-1],p->vertex_xyz[0])) {
  7692. p->nVertex--;
  7693. if(p->nVertex<=0) {
  7694. return TCL_ERROR;
  7695. }
  7696. }
  7697. VectorXYZ_Copy(p->vertex_xyz[p->nVertex],p->vertex_xyz[0]);
  7698. VectorXYZ_Zero(SUM);
  7699. VectorXYZ_Zero(p->normal);
  7700. VectorXYZ_Zero(p->center);
  7701. VectorXYZ_AABB_Reset(p->bbox_xyz);
  7702. for(i=0;i<p->nVertex;i++) {
  7703. VectorXYZ_AABB_Measure(p->vertex_xyz[i],p->bbox_xyz);
  7704. p->center[X_IDX]+=p->vertex_xyz[i][X_IDX];
  7705. p->center[Y_IDX]+=p->vertex_xyz[i][Y_IDX];
  7706. p->center[Y_IDX]+=p->vertex_xyz[i][Z_IDX];
  7707. }
  7708. p->center[X_IDX] /= p->nVertex;
  7709. p->center[Y_IDX] /= p->nVertex;
  7710. p->center[Z_IDX] /= p->nVertex;
  7711.  
  7712. if(fabs(p->bbox_xyz[Z_MAX_IDX])>__FLT_EPSILON__) {
  7713. is2d=0;
  7714. }
  7715. if(fabs(p->bbox_xyz[Z_MIN_IDX])>__FLT_EPSILON__) {
  7716. is2d=0;
  7717. }
  7718. p->is_2d=is2d;
  7719. if(is2d) {
  7720. p->normal[X_IDX]=0.0;
  7721. p->normal[Y_IDX]=0.0;
  7722. p->normal[Z_IDX]=1.0;
  7723. Odie_Affine4x4_Identity(p->rotation);
  7724. Odie_Affine4x4_Identity(p->rotation_inv);
  7725. for(i=0;i<=p->nVertex;i++) {
  7726. VectorXYZ_Copy(p->vertex_uv[i],p->vertex_xyz[i]);
  7727. }
  7728. } else {
  7729. for(i=0,j=1;i<p->nVertex;i++,j++) {
  7730. r1 = VectorXYZ_DistanceSq(p->center, p->vertex_xyz[i]);
  7731. if(r1>rmax) {
  7732. rmax=r1;
  7733. }
  7734. 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]);
  7735. 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]);
  7736. 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]);
  7737. }
  7738. p->radius=sqrt(rmax);
  7739. normal_length=VectorXYZ_Magnitude(p->normal);
  7740. if(normal_length>0.0) {
  7741. double inv=1.0/normal_length;
  7742. p->normal[X_IDX]*=inv;
  7743. p->normal[Y_IDX]*=inv;
  7744. p->normal[Z_IDX]*=inv;
  7745. }
  7746. AFFINE rotation,translation;
  7747. Odie_Affine_From_Normal(rotation,p->normal);
  7748. Odie_Affine4x4_Translation(translation,p->center);
  7749. Odie_Affine4x4_Multiply(p->rotation_inv,rotation,translation);
  7750. Odie_Affine4x4_Inverse(p->rotation,p->rotation_inv);
  7751. /* Map the Polygon to UV Space */
  7752. for(i=0;i<=p->nVertex;i++) {
  7753. VectorXYZ_MatrixMultiply(p->vertex_uv[i],p->vertex_xyz[i],p->rotation);
  7754. }
  7755. }
  7756. VectorXYZ_Copy(p->vertex_uv[p->nVertex],p->vertex_xyz[0]);
  7757. /* Compute 2d information from the UV coordinates */
  7758. p->is_convex=1;
  7759. for(i=0; i<p->nVertex; i++){
  7760. int bend;
  7761. j=(i+1)%p->nVertex;
  7762. k=(i+2)%p->nVertex;
  7763. bend=VectorXY_BendDirection(p->vertex_uv[i], p->vertex_uv[j], p->vertex_uv[k]);
  7764. if(bend>0 && p->bend<0) {
  7765. p->is_convex=0;
  7766. } else if(bend<0 && p->bend>0) {
  7767. p->is_convex=0;
  7768. }
  7769. p->bend+=bend;
  7770. }
  7771. if(!p->is_convex) {
  7772. /*
  7773. ** A convex polygon is legal,
  7774. ** we just can't answer questions about area and intersections
  7775. */
  7776. return TCL_OK;
  7777. }
  7778. for(i=0; i<p->nVertex; i++){
  7779. 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]);
  7780. }
  7781. if( area<0.0 ){
  7782. int b, e;
  7783. for(b=0, e=p->nVertex; b<e; b++, e--){
  7784. double t;
  7785. t = p->vertex_uv[b][X_IDX];
  7786. p->vertex_uv[b][X_IDX] = p->vertex_uv[e][X_IDX];
  7787. p->vertex_uv[e][X_IDX] = t;
  7788. t = p->vertex_uv[b][Y_IDX];
  7789. p->vertex_uv[b][Y_IDX] = p->vertex_uv[e][Y_IDX];
  7790. p->vertex_uv[e][Y_IDX] = t;
  7791. }
  7792. area = -area;
  7793. }
  7794. if(fabs(area)<__FLT_EPSILON__) {
  7795. area=0.0;
  7796. }
  7797. p->area = area;
  7798. p->bbox_uv[BBOX_X0_IDX] = p->bbox_uv[BBOX_X1_IDX] = p->vertex_uv[0][X_IDX];
  7799. p->bbox_uv[BBOX_Y1_IDX] = p->bbox_uv[BBOX_Y0_IDX] = p->vertex_uv[0][Y_IDX];
  7800. for(i=1; i<p->nVertex; i++){
  7801. double x, y;
  7802. x = p->vertex_uv[i][X_IDX];
  7803. if( x<p->bbox_uv[BBOX_X0_IDX] ) p->bbox_uv[BBOX_X0_IDX] = x;
  7804. if( x>p->bbox_uv[BBOX_X1_IDX] ) p->bbox_uv[BBOX_X1_IDX] = x;
  7805. y = p->vertex_uv[i][Y_IDX];
  7806. if( y>p->bbox_uv[BBOX_Y1_IDX] ) p->bbox_uv[BBOX_Y1_IDX] = y;
  7807. if( y<p->bbox_uv[BBOX_Y0_IDX] ) p->bbox_uv[BBOX_Y0_IDX] = y;
  7808. }
  7809. return TCL_OK;
  7810. }
  7811. /* *Odie_FaceXYZ_Simplify */
  7812. Odie_FaceXYZ *Odie_FaceXYZ_Simplify(Odie_FaceXYZ *pPolygonXYZ){
  7813. Odie_FaceXYZ *pNewPolygonXYZ;
  7814. int i,j,k,N;
  7815. pNewPolygonXYZ=Odie_FaceXYZ_Create(pPolygonXYZ->nVertex);
  7816. pNewPolygonXYZ->nVertex=0;
  7817. N=pPolygonXYZ->nVertex;
  7818.  
  7819. /* The first vertex always belongs */
  7820. VectorXYZ_Copy(pNewPolygonXYZ->vertex_xyz[0],pPolygonXYZ->vertex_xyz[0]);
  7821. pNewPolygonXYZ->nVertex++;
  7822. i=1;
  7823. j=(i-1) % N;
  7824. k=(i-2) % N;
  7825. while(i<N) {
  7826. /* Skip identical points */
  7827. while(VectorXYZ_SamePoint(pPolygonXYZ->vertex_xyz[i],pPolygonXYZ->vertex_xyz[j]) && i<N) {
  7828. i++;
  7829. }
  7830. /* Skip colinear points */
  7831. while(VectorXYZ_IsColinear(pPolygonXYZ->vertex_xyz[k],pPolygonXYZ->vertex_xyz[j],pPolygonXYZ->vertex_xyz[i]) && i<N) {
  7832. i++;
  7833. }
  7834. VectorXYZ_Copy(pNewPolygonXYZ->vertex_xyz[i],pPolygonXYZ->vertex_xyz[i]);
  7835. pNewPolygonXYZ->nVertex++;
  7836. k=j;
  7837. j=i;
  7838. i++;
  7839. }
  7840. return pNewPolygonXYZ;
  7841. }
  7842. /* Odie_FaceXYZ_Compare */
  7843. static inline int Odie_FaceXYZ_Compare(Odie_FaceXYZ *A,Odie_FaceXYZ *B){
  7844. Odie_FaceXYZ *pPolyA,*pPolyB;
  7845. int i,j=0,result=1;
  7846. if(!A || !B) return 0;
  7847. if(A==B) return 1;
  7848. pPolyA=Odie_FaceXYZ_Simplify(A);
  7849. pPolyB=Odie_FaceXYZ_Simplify(B);
  7850. if(pPolyA->nVertex!=pPolyB->nVertex) {
  7851. result=0; goto finished;
  7852. }
  7853. for(i=0;i<pPolyA->nVertex;i++) {
  7854. if(VectorXYZ_SamePoint(pPolyA->vertex_xyz[i],pPolyB->vertex_xyz[i])) continue;
  7855. /* Check the reverse */
  7856. j=pPolyA->nVertex-i-1;
  7857. if(!VectorXYZ_SamePoint(pPolyA->vertex_xyz[i],pPolyB->vertex_xyz[j])) {
  7858. result=0;
  7859. goto finished;
  7860. }
  7861. result=-1;
  7862. }
  7863. finished:
  7864. Odie_Free(pPolyA);
  7865. Odie_Free(pPolyB);
  7866. return result;
  7867. }
  7868. /* Odie_FaceXYZ_Coplaner */
  7869. static inline int Odie_FaceXYZ_Coplaner(Odie_FaceXYZ *A,Odie_FaceXYZ *B){
  7870. int i,j,ia=0,ja=0,ka=0;
  7871. if(!A || !B) return 0;
  7872. if(A==B) return 1;
  7873. for(i=0;i<A->nVertex;i++) {
  7874. int c;
  7875. ia=i;
  7876. ja=(i+1) % A->nVertex;
  7877. ka=(i+2) % A->nVertex;
  7878. for(j=0;j<B->nVertex;j++) {
  7879. c=VectorXYZ_IsCoplaner(A->vertex_xyz[ia],A->vertex_xyz[ja],A->vertex_xyz[ka],B->vertex_xyz[j]);
  7880. if(!c) {
  7881. return 0;
  7882. }
  7883. }
  7884. }
  7885. return 1;
  7886. }
  7887. /* PolygonUV_Within */
  7888. static inline int PolygonUV_Within(Odie_FaceXYZ *p, double x, double y){
  7889. /*
  7890. ** Return -1, 0, or 1 if the point x,y is outside, on, or within
  7891. ** the polygon p.
  7892. */
  7893. int res, i;
  7894. res = -1;
  7895. for(i=0; i<p->nVertex-1; i++){
  7896. double x0, y0, x1, y1, yP;
  7897. x0 = p->vertex_uv[i][X_IDX];
  7898. y0 = p->vertex_uv[i][Y_IDX];
  7899. x1 = p->vertex_uv[i+1][X_IDX];
  7900. y1 = p->vertex_uv[i+1][Y_IDX];
  7901. if( x0==x1 ){
  7902. if( x0==x && ((y0<=y && y1>=y) || (y1<=y && y0>=y)) ){
  7903. res = 0;
  7904. break;
  7905. }
  7906. continue;
  7907. }
  7908. if( x0>x1 ){
  7909. int t = x0;
  7910. x0 = x1;
  7911. x1 = t;
  7912. t = y0;
  7913. y0 = y1;
  7914. y1 = t;
  7915. }
  7916. if( x>=x1 || x<x0 ) continue;
  7917. yP = y1 - (x1-x)*(y1-y0)/(x1-x0);
  7918. if( yP == y ){ res = 0; break; }
  7919. if( yP > y ){ res = -res; }
  7920. }
  7921. return res;
  7922. }
  7923. /* Odie_FaceXYZ_Within */
  7924. static inline int Odie_FaceXYZ_Within(Odie_FaceXYZ *p, VectorXYZ POINT){
  7925. VectorXYZ a; /* Temporary variable to map coordinates during rotation */
  7926.  
  7927. /*
  7928. ** Return -1, 0, or 1 if the point x,y is outside, on, or within
  7929. ** the polygonxyz p.
  7930. */
  7931. if(!VectorXYZ_AABB_Within(POINT,p->bbox_xyz)) {
  7932. return -1;
  7933. }
  7934. /*
  7935. ** If we reach here it means that the closest point will be on the
  7936. ** permiter of the triangle. There are three line faces on the
  7937. ** permiter. Try them all.
  7938. */
  7939. int i, j;
  7940. for(i=0;i<p->nVertex;i++) {
  7941. j=(i+1)%p->nVertex;
  7942. if(VectorXYZ_PointIsOnSegment(POINT,p->vertex_xyz[i], p->vertex_xyz[j])) {
  7943. return 0;
  7944. }
  7945. }
  7946. /*
  7947. ** Translate the coordinate to the same rotation as the polygon
  7948. ** and use 2d checks
  7949. */
  7950. VectorXYZ_MatrixMultiply(a,POINT,p->rotation);
  7951. return PolygonUV_Within(p,a[X_IDX],a[Y_IDX]);
  7952. }
  7953. /* Odie_FaceXYZ_IntersectTest */
  7954. static int Odie_FaceXYZ_IntersectTest(Odie_FaceXYZ *p1,Odie_FaceXYZ *p2){
  7955. double area,x,y;
  7956. area = Odie_FaceXYZ_AreaOfIntersection(p1,p2,&x,&y);
  7957. if(area>0) {
  7958. return 1;
  7959. } else {
  7960. return 0;
  7961. }
  7962. }
  7963. /* Odie_FaceXYZ_AreaOfIntersection */
  7964. static double Odie_FaceXYZ_AreaOfIntersection(Odie_FaceXYZ *p1,Odie_FaceXYZ *p2,double *xin,double *yin){
  7965. double area=0;
  7966. double xInside = 0.0, yInside = 0.0;
  7967. double x0, y0, x1, y1, dx, dy, xP, yP, xC, yC;
  7968. int i, j, cnt;
  7969. int score, bestScore;
  7970. static const int n = 50;
  7971. char hit[50][50];
  7972.  
  7973. /* Compute the overlap of the bounding boxes of the two polygons. */
  7974. 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];
  7975. 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];
  7976. 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];
  7977. 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];
  7978.  
  7979. /* Divide the intersection of the bounding boxes into a n-by-n grid
  7980. ** and count the number of elements in this grid whose centers fall
  7981. ** within both polygons. This will be our approximation for the
  7982. ** intersection of the polygons themselves.
  7983. */
  7984. dx = (x1-x0)/n;
  7985. dy = (y1-y0)/n;
  7986. cnt = 0;
  7987. xC = yC = 0.0;
  7988. for(i=0; i<n; i++){
  7989. xP = x0 + dx*(i+0.5);
  7990. for(j=0; j<n; j++){
  7991. yP = y0 + dy*(j+0.5);
  7992. if( PolygonUV_Within(p1, xP, yP)>0 && PolygonUV_Within(p2, xP, yP)>0 ){
  7993. cnt++;
  7994. hit[i][j] = 1;
  7995. xC += xP;
  7996. yC += yP;
  7997. }else{
  7998. hit[i][j] = 0;
  7999. }
  8000. }
  8001. }
  8002.  
  8003. /* We need to find a good approximation for the center of the
  8004. ** overlap. Begin by computing the center of mass for the
  8005. ** overlapping region. Then find the point inside the intersection
  8006. ** that is nearest the center of mass.
  8007. */
  8008. if( cnt>0 ){
  8009. area = cnt*(x1-x0)*(y0-y1)/(n*n);
  8010. xC /= cnt;
  8011. yC /= cnt;
  8012. bestScore = -1.0;
  8013. for(i=0; i<n; i++){
  8014. xP = x0 + dx*(i+0.5);
  8015. for(j=0; j<n; j++){
  8016. if( !hit[i][j] ) continue;
  8017. yP = y0 + dy*(j+0.5);
  8018. score = dist(xP,yP,xC,yC);
  8019. if( score<bestScore || bestScore<0.0 ){
  8020. xInside = xP;
  8021. yInside = yP;
  8022. bestScore = score;
  8023. }
  8024. }
  8025. }
  8026. } else {
  8027. area=0.0;
  8028. }
  8029. *xin=xInside;
  8030. *yin=yInside;
  8031. return area;
  8032. }
  8033. /* SegmentSet_Delete */
  8034. static void SegmentSet_Delete(ClientData clientData){
  8035. SegmentSet *pSet=(SegmentSet *)clientData;
  8036. SegmentSetClear(pSet);
  8037. Odie_Free(pSet);
  8038. }
  8039. /* SegmentSet_Clone */
  8040. static int SegmentSet_Clone(
  8041. Tcl_Interp* interp, /* Tcl interpreter for error reporting */
  8042. ClientData metadata, /* Metadata to be cloned */
  8043. ClientData* newMetaData /* Where to put the cloned metadata */
  8044. ){
  8045. SegmentSet *src=(SegmentSet*)metadata;
  8046. SegmentSet *dest=(SegmentSet*)Odie_Alloc(sizeof(SegmentSet));
  8047. SegmentSetCopy(dest,src);
  8048. *newMetaData=(ClientData*)dest;
  8049. return TCL_OK;
  8050. }
  8051. /* *Segment_To_Dict */
  8052. Tcl_Obj *Segment_To_Dict(Segment *pSeg){
  8053. Tcl_Obj *element=Tcl_NewObj();
  8054. {
  8055. Tcl_Obj *value;
  8056. value=Tcl_NewIntObj(pSeg->id);
  8057. Odie_DictObjPut(NULL,element,"id:",value);
  8058. }
  8059. {
  8060. Tcl_Obj *value;
  8061. value=Tcl_NewBooleanObj(pSeg->isVirtual);
  8062. Odie_DictObjPut(NULL,element,"virtual:",value);
  8063. }
  8064. {
  8065. Tcl_Obj *value;
  8066. value=VectorXYZ_To_TclObj(pSeg->from);
  8067. Odie_DictObjPut(NULL,element,"from:",value);
  8068. }
  8069. {
  8070. Tcl_Obj *value;
  8071. value=VectorXYZ_To_TclObj(pSeg->to);
  8072. Odie_DictObjPut(NULL,element,"to:",value);
  8073. }
  8074. {
  8075. Tcl_Obj *value;
  8076. value=Tcl_NewBooleanObj(pSeg->isVirtual);
  8077. Odie_DictObjPut(NULL,element,"exported:",value);
  8078. }
  8079. {
  8080. Tcl_Obj *value;
  8081. value=Tcl_NewIntObj(pSeg->idLC);
  8082. Odie_DictObjPut(NULL,element,"id_left:",value);
  8083. }
  8084. {
  8085. Tcl_Obj *value;
  8086. value=Tcl_NewIntObj(pSeg->idRC);
  8087. Odie_DictObjPut(NULL,element,"id_right:",value);
  8088. }
  8089. {
  8090. Tcl_Obj *value;
  8091. value=Tcl_NewBooleanObj(pSeg->isVirtual);
  8092. Odie_DictObjPut(NULL,element,"ignore:",value);
  8093. }
  8094. {
  8095. Tcl_Obj *value;
  8096.  
  8097. if(pSeg->boundfwd) {
  8098. value=Tcl_NewIntObj(pSeg->boundfwd->faceid);
  8099. } else {
  8100. value=Tcl_NewIntObj(0);
  8101. }
  8102.  
  8103. Odie_DictObjPut(NULL,element,"facefwd:",value);
  8104. }
  8105. {
  8106. Tcl_Obj *value;
  8107.  
  8108. if(pSeg->boundback) {
  8109. value=Tcl_NewIntObj(pSeg->boundback->faceid);
  8110. } else {
  8111. value=Tcl_NewIntObj(0);
  8112. }
  8113.  
  8114. Odie_DictObjPut(NULL,element,"faceback:",value);
  8115. }
  8116. return element;}
  8117. /* *SegmentSet_Insert_XYZ */
  8118. Segment *SegmentSet_Insert_XYZ(SegmentSet *pSet,int id,VectorXYZ A,VectorXYZ B){
  8119. Segment *pSeg;
  8120. if(id>0) {
  8121. if(SegmentSet_FindById(pSet, id)) return NULL;
  8122. }
  8123. VectorXYZ_GridAlign(A,pSet->grid);
  8124. VectorXYZ_GridAlign(B,pSet->grid);
  8125. if(VectorXYZ_SamePoint(A,B)) return NULL;
  8126. SegmentSet_AddVertex(pSet,A);
  8127. SegmentSet_AddVertex(pSet,B);
  8128. pSeg=Segment_FindByLocation(pSet,A,B);
  8129. if(pSeg) return pSeg;
  8130. pSeg=Segment_Create(pSet,id);
  8131. if(pSeg) {
  8132. Segment_SetToFrom(pSet,pSeg,A,B);
  8133. }
  8134. return pSeg;
  8135. }
  8136. /* SegmentSet_Cleanup_Coincident */
  8137. static int SegmentSet_Cleanup_Coincident(SegmentSet *pSet,Segment *pAB){
  8138. Link *qLoop,*qNext;
  8139. int changes=0;
  8140. for(qLoop=pSet->pAll; qLoop; qLoop=qNext){
  8141. int c;
  8142. Segment *pCD;
  8143. pCD = qLoop->pLinkNode;
  8144. qNext = qLoop->pNext;
  8145. VectorXYZ ICEPT;
  8146.  
  8147. VectorXYZ_ClosestPointOnSegment(pAB->from,pAB->to,pCD->from,ICEPT);
  8148. VectorXYZ_GridAlign(ICEPT,pSet->grid);
  8149. if(VectorXYZ_SamePoint(ICEPT,pCD->from)) {
  8150. changes+=SegmentSet_AddVertex(pSet,ICEPT);
  8151. }
  8152. VectorXYZ_ClosestPointOnSegment(pAB->from,pAB->to,pCD->to,ICEPT);
  8153. VectorXYZ_GridAlign(ICEPT,pSet->grid);
  8154. if(VectorXYZ_SamePoint(ICEPT,pCD->to)) {
  8155. changes+=SegmentSet_AddVertex(pSet,ICEPT);
  8156. }
  8157. }
  8158. for(qLoop=pSet->pAll; qLoop; qLoop=qNext){
  8159. int c;
  8160. Segment *pCD;
  8161. pCD = qLoop->pLinkNode;
  8162. qNext = qLoop->pNext;
  8163. VectorXYZ ICEPT1,ICEPT2;
  8164. /* Evaluate lower to higher */
  8165. if(pCD->id == pAB->id) continue;
  8166. c=VectorXYZ_LineLineCoincident(pAB->from,pAB->to,pCD->from,pCD->to,ICEPT1,ICEPT2);
  8167. if(c<=0) continue;
  8168. changes+=SegmentSet_AddVertex(pSet,ICEPT1);
  8169. if(!VectorXYZ_SamePoint(ICEPT1,ICEPT2)) {
  8170. changes+=SegmentSet_AddVertex(pSet,ICEPT2);
  8171. }
  8172. }
  8173. return changes;
  8174. }
  8175. /* Segset_Insert_Polygon */
  8176. int Segset_Insert_Polygon(SegmentSet *pSet,Odie_FaceXYZ *p,int comptid){
  8177. int h,i,j,reversed=0;
  8178. int bend=0;
  8179. if(p->nVertex<3) {
  8180. return TCL_ERROR;
  8181. }
  8182. for(i=0;i<=p->nVertex;i++) {
  8183. VectorXYZ h_uv,i_uv,j_uv;
  8184. j=(i+1)%p->nVertex;
  8185. h=(i-1)%p->nVertex;
  8186. VectorXYZ_MatrixMultiply(h_uv,p->vertex_xyz[h],pSet->rotation);
  8187. VectorXYZ_MatrixMultiply(i_uv,p->vertex_xyz[i],pSet->rotation);
  8188. VectorXYZ_MatrixMultiply(j_uv,p->vertex_xyz[j],pSet->rotation);
  8189. bend+=VectorXY_BendDirection(h_uv, i_uv, j_uv);
  8190. }
  8191. for(i=0;i<=p->nVertex;i++) {
  8192. Segment *pSeg;
  8193. j=(i+1)%p->nVertex;
  8194. h=(i-1)%p->nVertex;
  8195. pSeg=SegmentSet_Insert_XYZ(pSet,-1,p->vertex_xyz[i],p->vertex_xyz[j]);
  8196. if(pSeg) {
  8197. if(VectorXYZ_SamePoint(pSeg->from,p->vertex_xyz[j])) {
  8198. reversed=1;
  8199. }
  8200. pSeg->isVirtual=0;
  8201. /*
  8202. ** Paint the inside edge of the polygon with the comptid
  8203. */
  8204. if(reversed) {
  8205. /* The line inserted into the segment set was backward from what we specified */
  8206. if(bend<=0) {
  8207. /* The polygon was given in a counter clockwise direction */
  8208. pSeg->idRC=comptid;
  8209. } else {
  8210. pSeg->idLC=comptid;
  8211. }
  8212. } else {
  8213. if(bend<=0) {
  8214. /* The polygon was given in a counter clockwise direction */
  8215. pSeg->idRC=comptid;
  8216. } else {
  8217. pSeg->idLC=comptid;
  8218. }
  8219. }
  8220. }
  8221. }
  8222. return TCL_OK;
  8223. }
  8224. /* SegmentSetCopy */
  8225. void SegmentSetCopy(SegmentSet *dest,SegmentSet *src){
  8226. SegmentSetClear(dest);
  8227. memset(dest, 0, sizeof(SegmentSet));
  8228. Link *pLoop, *pNext;
  8229. for(pLoop=src->pAll; pLoop; pLoop=pNext){
  8230. Segment *pAB,*pNewSeg;
  8231. pAB = pLoop->pLinkNode;
  8232. pNext = pLoop->pNext;
  8233. pNewSeg=SegmentSet_Insert_XYZ(dest,pAB->id,pAB->from,pAB->to);
  8234. if(pNewSeg) {
  8235. Segment_Imprint(pAB,pNewSeg);
  8236. }
  8237. }
  8238. }
  8239. /* Segment_OnList */
  8240. static int Segment_OnList(Segment *pSeg, Link *pList){
  8241. while( pList ){
  8242. if( pList->pLinkNode==pSeg ) return 1;
  8243. pList = pList->pNext;
  8244. }
  8245. return 0;
  8246. }
  8247. /* *SegmentSet_FindById */
  8248. static Segment *SegmentSet_FindById(SegmentSet *p, int id){
  8249. int h;
  8250. Link *pLink;
  8251.  
  8252. h = hashInt(id);
  8253. for(pLink = p->hashId[h]; pLink; pLink=pLink->pNext){
  8254. Segment *pSeg=pLink->pLinkNode;
  8255. if( pSeg->id==id ) return pSeg;
  8256. }
  8257. return 0;
  8258. }
  8259. /* *Segment_FindByLocation */
  8260. Segment *Segment_FindByLocation(SegmentSet *pSet, VectorXYZ A, VectorXYZ B){
  8261. /*
  8262. ** Find and return the line segment that goes from A to B. Return NULL
  8263. ** if there is not such line segment
  8264. */
  8265. Link *pX;
  8266. Segment *p;
  8267. int h;
  8268. VectorXYZ_GridAlign(A,pSet->grid);
  8269. h = hashVectorXYZ(A);
  8270. for(pX=pSet->hashFrom[h]; pX; pX=pX->pNext){
  8271. p = pX->pLinkNode;
  8272. if( VectorXYZ_SamePoint(p->from, A) && VectorXYZ_SamePoint(p->to, B) ){
  8273. return p;
  8274. }
  8275. if( VectorXYZ_SamePoint(p->to, A) && VectorXYZ_SamePoint(p->from, B) ){
  8276. return p;
  8277. }
  8278. }
  8279. for(pX=pSet->hashTo[h]; pX; pX=pX->pNext){
  8280. p = pX->pLinkNode;
  8281. if( VectorXYZ_SamePoint(p->from, A) && VectorXYZ_SamePoint(p->to, B) ){
  8282. return p;
  8283. }
  8284. if( VectorXYZ_SamePoint(p->to, A) && VectorXYZ_SamePoint(p->from, B) ){
  8285. return p;
  8286. }
  8287. }
  8288. return 0;
  8289. }
  8290. /* Segment_Imprint */
  8291. static void Segment_Imprint(Segment *pSrc,Segment *pDest){
  8292. if(pSrc==pDest) return;
  8293. pDest->isVirtual=pSrc->isVirtual;
  8294. pDest->idLC=pSrc->idLC;
  8295. pDest->idRC=pSrc->idRC;
  8296. }
  8297. /* Segment_SetToFrom */
  8298. static void Segment_SetToFrom(SegmentSet *pSet, Segment *p, VECTORXYZ from, VECTORXYZ to){
  8299. int h;
  8300. VectorXYZ_GridAlign(from,pSet->grid);
  8301. VectorXYZ_GridAlign(to,pSet->grid);
  8302. if(VectorXYZ_SamePoint(from,p->from) && VectorXYZ_SamePoint(to,p->to)) {
  8303. return;
  8304. }
  8305. LinkRemove(&p->pFrom);
  8306. LinkRemove(&p->pTo);
  8307. pSet->modified=1;
  8308. VectorXYZ_Copy(p->from,from);
  8309. VectorXYZ_Copy(p->to,to);
  8310. VectorXY_BBOX_Measure(p->from,pSet->bbox_uv);
  8311. VectorXY_BBOX_Measure(p->to,pSet->bbox_uv);
  8312. h = hashVectorXYZ(p->from);
  8313. LinkInsert(&pSet->hashFrom[h], &p->pFrom);
  8314. h = hashVectorXYZ(p->to);
  8315. LinkInsert(&pSet->hashTo[h], &p->pTo);
  8316. }
  8317. /* *Segment_Create */
  8318. static inline Segment *Segment_Create(SegmentSet *pSet,int newid){
  8319. Link *pLoop,*pNext;
  8320. Segment *p=NULL;
  8321. int id,h;
  8322. for(pLoop=pSet->pFree; pLoop; pLoop=pNext){
  8323. p=pLoop->pLinkNode;
  8324. pNext=pLoop->pNext;
  8325. if(p) {
  8326. LinkRemove(&p->pFree);
  8327. id=p->id;
  8328. memset(p,0,sizeof(*p));
  8329. if(newid<=0) {
  8330. p->id=id;
  8331. } else if(p->id>pSet->nextid) {
  8332. pSet->nextid=p->id;
  8333. }
  8334. break;
  8335. }
  8336. }
  8337. if(!p) {
  8338. p=(Segment *)Odie_Alloc( sizeof(*p) );
  8339. if(newid<=0) {
  8340. pSet->nextid++;
  8341. p->id=pSet->nextid;
  8342. } else if(p->id>pSet->nextid) {
  8343. pSet->nextid=p->id;
  8344. }
  8345. }
  8346. if(!p) {
  8347. return NULL;
  8348. }
  8349. LinkInit(p->pAll, p);
  8350. LinkInit(p->pSet, p);
  8351. LinkInit(p->pHash, p);
  8352. LinkInit(p->pFrom, p);
  8353. LinkInit(p->pTo, p);
  8354.  
  8355. LinkInit(p->pFree, p);
  8356. LinkInsert(&pSet->pAll, &p->pAll);
  8357. h = hashInt(p->id);
  8358. LinkInsert(&pSet->hashId[h], &p->pHash);
  8359. pSet->modified=1;
  8360. pSet->nSeg++;
  8361. pSet->pCurrent = p;
  8362. return p;
  8363. }
  8364. /* SegmentSetRemove */
  8365. static inline void SegmentSetRemove(SegmentSet *pSet, Segment *p){
  8366. /*
  8367. ** Remove a segment from the segment set
  8368. */
  8369. pSet->modified=1;
  8370. LinkRemove(&p->pAll);
  8371. /* We intentionally do not remove pSeg->pSet because it might not be
  8372. ** a well-formed list */
  8373. LinkRemove(&p->pHash);
  8374. LinkRemove(&p->pFrom);
  8375. LinkRemove(&p->pTo);
  8376.  
  8377. LinkInit(p->pAll, p);
  8378. //LinkInit(p->pSet, p);
  8379. LinkInit(p->pHash, p);
  8380. LinkInit(p->pFrom, p);
  8381. LinkInit(p->pTo, p);
  8382. LinkInsert(&pSet->pFree,&p->pFree);
  8383. pSet->nSeg--;
  8384. if( pSet->pCurrent==p ){
  8385. pSet->pCurrent = pSet->pAll ? pSet->pAll->pLinkNode : 0;
  8386. }
  8387. }
  8388. /* SegRelink */
  8389. static inline void SegRelink(SegmentSet *pSet, Segment *p){
  8390. /*
  8391. ** Call this routine to relink into a segment when the
  8392. ** Seg.from vector changes.
  8393. */
  8394. int h;
  8395. pSet->modified=1;
  8396. LinkRemove(&p->pHash);
  8397. LinkRemove(&p->pFrom);
  8398. LinkRemove(&p->pTo);
  8399. LinkRemove(&p->pFree);
  8400. h = hashInt(p->id);
  8401. LinkInsert(&pSet->hashId[h], &p->pHash);
  8402. h = hashVectorXY(p->from);
  8403. LinkInsert(&pSet->hashFrom[h], &p->pFrom);
  8404. h = hashVectorXY(p->to);
  8405. LinkInsert(&pSet->hashTo[h], &p->pTo);
  8406. }
  8407. /* SegmentSetClear */
  8408. static inline void SegmentSetClear(SegmentSet *pSet){
  8409. /*
  8410. ** Remove all segments from a segment set
  8411. */
  8412. Link *pLoop,*pNext;
  8413. Segment *p;
  8414. SegmentSet_ClearFaceEdgeCache(pSet);
  8415. while( pSet->pAll ){
  8416. assert( pSet->nSeg>0 );
  8417. p=pSet->pAll->pLinkNode;
  8418. SegmentSetRemove(pSet, p);
  8419. }
  8420. for(pLoop=pSet->pFree; pLoop; pLoop=pNext){
  8421. p=pLoop->pLinkNode;
  8422. pNext=pLoop->pNext;
  8423. LinkRemove(&p->pFree);
  8424. Odie_Free((char *)p);
  8425. }
  8426. assert( pSet->nSeg==0 );
  8427. }
  8428. /* SegmentSetStep */
  8429. static inline void SegmentSetStep(SegmentSet *pSet){
  8430. /*
  8431. ** Advance the pSet->pAll pointer so that it is pointing to a different
  8432. ** segment.
  8433. */
  8434. if( pSet->pCurrent ){
  8435. Link *pNext = pSet->pCurrent->pAll.pNext;
  8436. pSet->pCurrent = pNext ? pNext->pLinkNode : 0;
  8437. }
  8438. if( pSet->pCurrent==0 ){
  8439. pSet->pCurrent = pSet->pAll ? pSet->pAll->pLinkNode : 0;
  8440. }
  8441. }
  8442. /* SegmentSet_AddVertex */
  8443. static int SegmentSet_AddVertex(SegmentSet *pSet,VectorXYZ A){
  8444. Link *pLoop,*pNext;
  8445. VectorXYZ B,ICEPT;
  8446. int changes=0;
  8447. VectorXYZ_GridAlign(A,pSet->grid);
  8448. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  8449. int delete=0;
  8450. Segment *pAB,*pNew;
  8451. Segment *found;
  8452. pAB = pLoop->pLinkNode;
  8453. pNext=pLoop->pNext;
  8454. if(VectorXYZ_SamePoint(A,pAB->from)) continue;
  8455. if(VectorXYZ_SamePoint(A,pAB->to)) continue;
  8456. VectorXYZ_ClosestPointOnSegment(pAB->from,pAB->to,A,ICEPT);
  8457. if(!VectorXYZ_SamePoint(ICEPT,A)) continue;
  8458. changes++;
  8459. /* Preserve the segment's original destination */
  8460. VectorXYZ_Copy(B,pAB->to);
  8461. found=Segment_FindByLocation(pSet,pAB->from,A);
  8462. if(!found) {
  8463. /* Truncate the first part of the segment */
  8464. Segment_SetToFrom(pSet,pAB,pAB->from,A);
  8465. } else {
  8466. delete=1;
  8467. }
  8468. found=Segment_FindByLocation(pSet,A,B);
  8469. if(!found) {
  8470. if(delete) {
  8471. /*
  8472. ** A segment exists for the first part of this segment
  8473. ** but not the second. Rather than throw this link out
  8474. ** just to re-create it, recycle
  8475. */
  8476. delete=0;
  8477. Segment_SetToFrom(pSet,pAB,A,B);
  8478. } else {
  8479. pNew=SegmentSet_Insert_XYZ(pSet,-1,A,B);
  8480. if(pNew) {
  8481. Segment_Imprint(pAB,pNew);
  8482. }
  8483. }
  8484. }
  8485. if(delete) {
  8486. /* A segment already exists, delete this one */
  8487. SegmentSetRemove(pSet,pAB);
  8488. }
  8489. }
  8490. return changes;
  8491. }
  8492. /* SegmentSet_Cleanup */
  8493. int SegmentSet_Cleanup(SegmentSet *pSet,int looseend){
  8494. Link *pLoop,*pNext;
  8495. Link *qLoop,*qNext;
  8496. Segment *pAB,*pCD;
  8497. int count=0;
  8498. int loop=0;
  8499. int match=0;
  8500. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  8501. pAB = pLoop->pLinkNode;
  8502. pNext = pLoop->pNext;
  8503. pAB->test=0;
  8504. }
  8505. /* Cleanup loose ends */
  8506. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  8507. VectorXYZ A,B;
  8508. Link *pList;
  8509. int nSeg;
  8510. pAB = pLoop->pLinkNode;
  8511. pNext = pLoop->pNext;
  8512. VectorXYZ_Copy(A,pAB->from);
  8513. VectorXYZ_Copy(B,pAB->to);
  8514. VectorXYZ_GridAlign(A,pSet->grid);
  8515. VectorXYZ_GridAlign(B,pSet->grid);
  8516. Segment_SetToFrom(pSet,pAB,A,B);
  8517. }
  8518. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  8519. pAB = pLoop->pLinkNode;
  8520. pNext = pLoop->pNext;
  8521. count+=SegmentSet_Cleanup_Coincident(pSet,pAB);
  8522. }
  8523.  
  8524. if(looseend) {
  8525. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  8526. Link *pList;
  8527. int nSeg;
  8528. pAB = pLoop->pLinkNode;
  8529. pNext = pLoop->pNext;
  8530. pList = SegmentSet_Segments_AtVertex(pSet, pAB->from,&nSeg);
  8531. if( nSeg < 2 ){
  8532. pAB->test=1;
  8533. match++;
  8534. }
  8535. pList = SegmentSet_Segments_AtVertex(pSet, pAB->to,&nSeg);
  8536. if( nSeg < 2 ){
  8537. pAB->test=1;
  8538. match++;
  8539. }
  8540. }
  8541. /* Cleanup overlapping walls */
  8542. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  8543. pAB = pLoop->pLinkNode;
  8544. pNext = pLoop->pNext;
  8545. if(pAB->test) continue;
  8546. if(VectorXYZ_DistanceSq(pAB->from,pAB->to)<pSet->gridSq) {
  8547. pAB->test=1;
  8548. continue;
  8549. }
  8550. for(qLoop=pNext; qLoop; qLoop=qNext){
  8551. pCD = qLoop->pLinkNode;
  8552. qNext = qLoop->pNext;
  8553. if(pCD->test) continue;
  8554. if(VectorXYZ_SamePoint(pAB->from,pCD->from)) {
  8555. if(VectorXYZ_SamePoint(pAB->to,pCD->to)) {
  8556. if(pAB->isVirtual>pCD->isVirtual) {
  8557. pAB->test=1;
  8558. } else if(pAB->id>pCD->id) {
  8559. pAB->test=1;
  8560. } else {
  8561. pCD->test=1;
  8562. }
  8563. continue;
  8564. }
  8565. }
  8566. if(VectorXYZ_SamePoint(pAB->from,pCD->from)) {
  8567. if(VectorXYZ_SamePoint(pAB->to,pCD->to)) {
  8568. if(pAB->isVirtual>pCD->isVirtual) {
  8569. pAB->test=1;
  8570. } else if(pAB->id>pCD->id) {
  8571. pAB->test=1;
  8572. } else {
  8573. pCD->test=1;
  8574. }
  8575. }
  8576. }
  8577. }
  8578. }
  8579. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  8580. pAB = pLoop->pLinkNode;
  8581. pNext = pLoop->pNext;
  8582. if(pAB->test) {
  8583. SegmentSetRemove(pSet,pAB);
  8584. count++;
  8585. }
  8586. }
  8587. }
  8588. return count;
  8589. }
  8590. /* SegmentSet_Interference_Check */
  8591. static int SegmentSet_Interference_Check(SegmentSet *pSet,VectorXYZ A,VectorXYZ B){
  8592. Link *qLoop,*qNext;
  8593. int onsegment=0;
  8594. for(qLoop=pSet->pAll; qLoop; qLoop=qNext){
  8595. int c;
  8596. Segment *pTest;
  8597. VectorXYZ ICEPT1,ICEPT2;
  8598. qNext = qLoop->pNext;
  8599. pTest = qLoop->pLinkNode;
  8600. if((VectorXYZ_DistanceSq(A,pTest->from) < pSet->gridSq) && (VectorXYZ_DistanceSq(B,pTest->to) < pSet->gridSq)) return 3;
  8601. if((VectorXYZ_DistanceSq(A,pTest->to) < pSet->gridSq) && (VectorXYZ_DistanceSq(B,pTest->from) < pSet->gridSq)) return 3;
  8602. if(VectorXYZ_PointIsOnSegment(A,pTest->from,pTest->to)) {
  8603. onsegment++;
  8604. continue;
  8605. }
  8606. c=VectorXYZ_LineLineCoincident(A,B,pTest->from,pTest->to,ICEPT1,ICEPT2);
  8607. if(c>0) {
  8608. return c;
  8609. }
  8610. }
  8611. /* If the ray did not touch any segment return a unique error code */
  8612. if(onsegment==0) {
  8613. return 16;
  8614. }
  8615. return 0;
  8616. }
  8617. /* SegmentSet_Edge_Connection */
  8618. static int SegmentSet_Edge_Connection(SegmentSet *pSet,VectorXYZ A,int comptid,VectorXYZ RESULT){
  8619. Link *pLoop,*pNext;
  8620. Segment *pAB,*pBest=NULL;
  8621. VectorXYZ ICEPT;
  8622. double pBestDist=HUGE_VAL;
  8623. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  8624. double score;
  8625. int interference;
  8626. pAB = pLoop->pLinkNode;
  8627. pNext = pLoop->pNext;
  8628. if(comptid!=0 && pAB->idRC!=comptid && pAB->idLC!=comptid) {
  8629. continue;
  8630. }
  8631. VectorXYZ_ClosestPointOnSegment(pAB->from,pAB->to,A,ICEPT);
  8632. VectorXYZ_GridAlign(ICEPT,pSet->grid);
  8633. score=VectorXYZ_DistanceSq(A,ICEPT);
  8634. if(score<pSet->gridSq) continue;
  8635. interference=SegmentSet_Interference_Check(pSet,A,ICEPT);
  8636. if(interference>0) continue;
  8637. if(!pBest || score<pBestDist) {
  8638. pBest=pAB;
  8639. pBestDist=score;
  8640. VectorXYZ_Copy(RESULT,ICEPT);
  8641. }
  8642. }
  8643. if(pBest) {
  8644. return TCL_OK;
  8645. }
  8646. return TCL_ERROR;
  8647. }
  8648. /* Segment_Compute_UV */
  8649. inline extern void Segment_Compute_UV(SegmentSet *pSet,Segment *pSeg,VectorXYZ uvfrom,VectorXYZ uvto){
  8650. VectorXYZ_MatrixMultiply(uvfrom,pSeg->from,pSet->rotation);
  8651. VectorXYZ_MatrixMultiply(uvto,pSeg->to,pSet->rotation);
  8652. }
  8653. /* SegmentSet_Convex_Connection */
  8654. static int SegmentSet_Convex_Connection(SegmentSet *pSet,Segment *pAB,int back,VectorXYZ RESULT){
  8655. Link *pLoop;
  8656. Segment *pCD,*pBest=NULL;
  8657. VectorXYZ A,B,AB,C,ICEPT,A_UV,B_UV,C_UV;
  8658. double pBestAngle=4*M_PI;
  8659. double pBestDist=HUGE_VAL;
  8660. double angle,rangle,len;
  8661. double rightangle=M_PI*0.5;
  8662. int ortho=0,i;
  8663.  
  8664. /* Try to ray cast the vector and find an intercept continuing along the line */
  8665. if(back) {
  8666. VectorXYZ_Copy(A,pAB->to);
  8667. VectorXYZ_Copy(B,pAB->from);
  8668. } else {
  8669. VectorXYZ_Copy(A,pAB->from);
  8670. VectorXYZ_Copy(B,pAB->to);
  8671. }
  8672. VectorXYZ_MatrixMultiply(A_UV,A,pSet->rotation);
  8673. VectorXYZ_MatrixMultiply(B_UV,B,pSet->rotation);
  8674. VectorXYZ_Subtract(AB,A_UV,B_UV);
  8675. len=pSet->grid;
  8676. angle=atan2(AB[Y_IDX],AB[X_IDX]);
  8677. for(i=-1;i<1;i++) {
  8678. rangle=angle+(M_PI*0.5*i);
  8679. rangle-=fmod(rangle,M_PI*0.5);
  8680. C_UV[X_IDX]=A_UV[X_IDX]+cos(rangle)*len;
  8681. C_UV[Y_IDX]=A_UV[Y_IDX]+sin(rangle)*len;
  8682. C_UV[Z_IDX]=A_UV[Z_IDX];
  8683. VectorXYZ_MatrixMultiply(C,C_UV,pSet->rotation_inv);
  8684. for(pLoop=pSet->pAll; pLoop; pLoop=pLoop->pNext){
  8685. double x,y;
  8686. int c;
  8687. VectorXYZ ICEPT1,ICEPT2;
  8688. pCD = pLoop->pLinkNode;
  8689. if(pCD->ignore) continue;
  8690. if(pCD==pAB) continue;
  8691. if(VectorXYZ_SamePoint(pAB->from,pCD->from)) continue;
  8692. if(VectorXYZ_SamePoint(pAB->from,pCD->to)) continue;
  8693. if(VectorXYZ_SamePoint(pAB->to,pCD->from)) continue;
  8694. if(VectorXYZ_SamePoint(pAB->to,pCD->to)) continue;
  8695. c=VectorXYZ_LineLineIntersect(A,C,pCD->from,pCD->to,ICEPT1,ICEPT2,&x,&y);
  8696. if(c>0) {
  8697. int interference;
  8698. double score;
  8699. if(!VectorXYZ_PointIsOnSegment(ICEPT1,pCD->from,pCD->to)) {
  8700. interference=16;
  8701. } else {
  8702. interference=SegmentSet_Interference_Check(pSet,A,ICEPT1);
  8703. }
  8704. if(interference<=0) {
  8705. if(fabs(angle-rangle)<pBestAngle) {
  8706. score=VectorXYZ_Distance(A,ICEPT1);
  8707. if(score>(pSet->grid*10) && (!pBest || score<pBestDist)) {
  8708. pBest=pCD;
  8709. pBestDist=score;
  8710. VectorXYZ_Copy(RESULT,ICEPT1);
  8711. pBestAngle=rangle;
  8712. }
  8713. }
  8714. }
  8715. if(!VectorXYZ_PointIsOnSegment(ICEPT2,pCD->from,pCD->to)) {
  8716. interference=16;
  8717. } else {
  8718. interference=SegmentSet_Interference_Check(pSet,A,ICEPT2);
  8719. }
  8720. if(interference<=0) {
  8721. if(fabs(angle-rangle)<pBestAngle) {
  8722. score=VectorXYZ_DistanceSq(A,ICEPT2);
  8723. if(score>(pSet->grid*10) && (!pBest || score<pBestDist)) {
  8724. pBest=pCD;
  8725. pBestDist=score;
  8726. VectorXYZ_Copy(RESULT,ICEPT2);
  8727. pBestAngle=rangle;
  8728. }
  8729. }
  8730. }
  8731. }
  8732. }
  8733. }
  8734. if(pBest) {
  8735. return TCL_OK;
  8736. }
  8737. return TCL_ERROR;
  8738. }
  8739. /* SegmentSetNextBend */
  8740. static int SegmentSetNextBend(
  8741. SegmentSet *pSet,
  8742. Segment *pAB,
  8743. int backwards,
  8744. Segment **ppSeg, /* OUT: First segment clockwise from xR,yR->xV,yV */
  8745. int *pfBack, /* OUT: True if output segment goes backwards */
  8746. int *pfBend, /* OUT: Bend direction */
  8747. double *pfAngle
  8748. ){
  8749. Segment *pSegThis;
  8750. int thisBack,thisBend;
  8751. double thisAngle;
  8752. pSegThis=pAB;
  8753. thisBack=backwards;
  8754. thisBend=0;
  8755. while(thisBend==0) {
  8756. if(SegmentSetNext(pSet, pSegThis, thisBack,ppSeg,pfBack,pfBend,pfAngle)) {
  8757. return TCL_ERROR;
  8758. }
  8759. thisBack=*pfBack;
  8760. thisBend=*pfBend;
  8761. if(thisBend==0) {
  8762. pSegThis->isBoundary=1;
  8763. }
  8764. pSegThis=*ppSeg;
  8765. }
  8766. return TCL_OK;
  8767. }
  8768. /* SegmentSet_SelfCheck */
  8769. static int SegmentSet_SelfCheck(Tcl_Interp *interp, SegmentSet *p){
  8770. Link *pLink;
  8771. Segment *pSeg;
  8772. int h;
  8773. char zErr[200];
  8774.  
  8775. for(pLink=p->pAll; pLink; pLink=pLink->pNext){
  8776. pSeg = pLink->pLinkNode;
  8777. h = hashInt(pSeg->id);
  8778. if(!Segment_OnList(pSeg, p->hashId[h]) ){
  8779. sprintf(zErr, "segment %d missing from hashId[%d]", pSeg->id, h);
  8780. Tcl_SetResult(interp, zErr, TCL_VOLATILE);
  8781. return TCL_ERROR;
  8782. }
  8783. h = hashCoord(pSeg->from[X_IDX], pSeg->from[Y_IDX]);
  8784. if(!Segment_OnList(pSeg, p->hashFrom[h]) ){
  8785. sprintf(zErr, "segment %d missing from hashFrom[%d]", pSeg->id, h);
  8786. Tcl_SetResult(interp, zErr, TCL_VOLATILE);
  8787. return TCL_ERROR;
  8788. }
  8789. h = hashCoord(pSeg->to[X_IDX], pSeg->to[Y_IDX]);
  8790. if(!Segment_OnList(pSeg, p->hashTo[h]) ){
  8791. sprintf(zErr, "segment %d missing from hashTo[%d]", pSeg->id, h);
  8792. Tcl_SetResult(interp, zErr, TCL_VOLATILE);
  8793. return TCL_ERROR;
  8794. }
  8795. }
  8796. return TCL_OK;
  8797. }
  8798. /* *SegmentSet_Segments_AtVertex */
  8799. static Link *SegmentSet_Segments_AtVertex(SegmentSet *p, VectorXYZ point,int *nSeg){
  8800. Link *pList = 0;
  8801. Link *pI;
  8802. int h,count=0;
  8803. VectorXYZ_GridAlign(point,p->grid);
  8804. h = hashVectorXYZ(point);
  8805. for(pI=p->hashFrom[h]; pI; pI=pI->pNext){
  8806. Segment *pSeg = pI->pLinkNode;
  8807. if( pSeg->ignore_fwd ) continue;
  8808. if(VectorXYZ_SamePoint(point,pSeg->from)) {
  8809. //assert( !segmentOnList(pSeg, pList) );
  8810. count++;
  8811. LinkInit(pSeg->pSet, pSeg);
  8812. LinkInsert(&pList, &pSeg->pSet);
  8813. }
  8814. }
  8815. for(pI=p->hashTo[h]; pI; pI=pI->pNext){
  8816. Segment *pSeg = pI->pLinkNode;
  8817. if( pSeg->ignore_back ) continue;
  8818. if(VectorXYZ_SamePoint(point,pSeg->to)) {
  8819. //assert( !segmentOnList(pSeg, pList) );
  8820. count++;
  8821. LinkInit(pSeg->pSet, pSeg);
  8822. LinkInsert(&pList, &pSeg->pSet);
  8823. }
  8824. }
  8825. *nSeg=count;
  8826. return pList;
  8827. }
  8828. /* SegmentSetNext */
  8829. static int SegmentSetNext(
  8830. SegmentSet *pSet,
  8831. Segment *pAB,
  8832. int backwards,
  8833. Segment **ppSeg, /* OUT: First segment clockwise from xR,yR->xV,yV */
  8834. int *pfBack, /* OUT: True if output segment goes backwards */
  8835. int *pfBend, /* OUT: Bend direction */
  8836. double *pfAngle
  8837. ){
  8838. VectorXYZ remote,vertex,remote_uv,vertex_uv;
  8839. Link *pI,*vList;
  8840. int i,best=-1;
  8841. int nSeg=0;
  8842. struct {
  8843. Segment *pSeg;
  8844. int isBack;
  8845. double angle;
  8846. int bend;
  8847. int edge;
  8848. VectorXYZ uv_remote;
  8849. } *aSeg, aSegStatic[20];
  8850.  
  8851. /*
  8852. pAB->ignore_fwd=1;
  8853. pAB->ignore_back=1;
  8854. */
  8855. if(backwards) {
  8856. VectorXYZ_Copy(remote,pAB->to);
  8857. VectorXYZ_Copy(vertex,pAB->from);
  8858. } else {
  8859. VectorXYZ_Copy(remote,pAB->from);
  8860. VectorXYZ_Copy(vertex,pAB->to);
  8861. }
  8862. VectorXYZ_MatrixMultiply(remote_uv,remote,pSet->rotation);
  8863. VectorXYZ_MatrixMultiply(vertex_uv,vertex,pSet->rotation);
  8864. vList=SegmentSet_Segments_AtVertex(pSet,vertex,&nSeg);
  8865. if(nSeg==0) {
  8866. *ppSeg=NULL;
  8867. *pfBack=0;
  8868. *pfBend=2;
  8869. *pfAngle=2*M_PI;
  8870. return TCL_ERROR;
  8871. }
  8872. if( nSeg<=sizeof(aSegStatic)/sizeof(aSegStatic[0]) ){
  8873. aSeg = aSegStatic;
  8874. }else{
  8875. aSeg = (void *)Odie_Alloc( nSeg*sizeof(*aSeg) );
  8876. }
  8877. for(pI=vList, i=0; pI; i++, pI=pI->pNext){
  8878. Segment *pSeg;
  8879. aSeg[i].pSeg = pSeg = pI->pLinkNode;
  8880. if( VectorXYZ_SamePoint(pSeg->from,vertex)) {
  8881. aSeg[i].isBack = 0;
  8882. aSeg[i].edge=pSeg->isVirtual||(pSeg->idRC>0);
  8883. VectorXYZ_MatrixMultiply(aSeg[i].uv_remote,pSeg->to,pSet->rotation);
  8884. } else {
  8885. aSeg[i].isBack = 1;
  8886. aSeg[i].edge=pSeg->isVirtual||(pSeg->idLC>0);
  8887. VectorXYZ_MatrixMultiply(aSeg[i].uv_remote,pSeg->from,pSet->rotation);
  8888. }
  8889. if(VectorXYZ_SamePoint(aSeg[i].uv_remote,remote)) {
  8890. aSeg[i].angle = 2*M_PI;
  8891. aSeg[i].bend = -2;
  8892. } else {
  8893. aSeg[i].angle = VectorXY_Angle_Three_Point(remote_uv, vertex_uv, aSeg[i].uv_remote);
  8894. aSeg[i].bend = VectorXY_BendDirection(remote_uv, vertex_uv, aSeg[i].uv_remote);
  8895. }
  8896. }
  8897. best=0;
  8898. for(i=1;i<nSeg;i++) {
  8899. if(aSeg[i].angle<aSeg[best].angle) {
  8900. best=i;
  8901. }
  8902. }
  8903. *ppSeg=aSeg[best].pSeg;
  8904. *pfBack=aSeg[best].isBack;
  8905. *pfBend=aSeg[best].bend;
  8906. *pfAngle=aSeg[best].angle;
  8907. if( aSeg!=aSegStatic ){
  8908. Tcl_Free((char *) aSeg );
  8909. }
  8910. return TCL_OK;
  8911. }
  8912. /* SegmentSet_ClearFaceEdgeCache */
  8913. static void SegmentSet_ClearFaceEdgeCache(SegmentSet *pSet){
  8914. if(!pSet->aBoundary) return;
  8915. Odie_Free(pSet->aBoundary);
  8916. pSet->aBoundary=NULL;
  8917. pSet->modified=0;
  8918. }
  8919. /* FaceBoundary_Mark_Degenerate */
  8920. static void FaceBoundary_Mark_Degenerate(FaceBoundary *pFace,int code){
  8921. FaceBoundary *qFace,*pFaceNext;
  8922. for(qFace=pFace;qFace;qFace=pFaceNext) {
  8923. pFaceNext=qFace->pNext;
  8924. qFace->pNext=NULL;
  8925. qFace->isloop=0;
  8926. qFace->faceid=qFace->id;
  8927. }
  8928. pFace->faceid=pFace->id;
  8929. pFace->nSeg=1;
  8930. pFace->isloop=code;
  8931. pFace->pNext=NULL;
  8932. }
  8933. /* SegmentSet_BuildFaceEdgeCache_ExpandRight */
  8934. static int SegmentSet_BuildFaceEdgeCache_ExpandRight(SegmentSet *pSet,int faceid,int stage){
  8935. FaceBoundary *sFace;
  8936. FaceBoundary *pFace;
  8937. FaceBoundary *oFace=NULL;
  8938. Link *pLoop;
  8939. VectorXYZ start;
  8940. Segment *pSeg,*pAB,*pBC;
  8941. int pbcback,pbcbend,idx;
  8942. double pbcangle;
  8943.  
  8944. sFace=pFace=&pSet->aBoundary[faceid];
  8945. /*
  8946. ** If this boundary is part of a loop, or the end of a loop continue
  8947. */
  8948. if(sFace->pNext || sFace->isloop>0) {
  8949. return 0;
  8950. }
  8951. /*
  8952. ** Don't expand the backface of real walls until stage 2
  8953. */
  8954. if(stage<1 && !sFace->pSeg->isVirtual) {
  8955. if(sFace->outside_edge) return 0;
  8956. }
  8957.  
  8958. /*
  8959. ** Detect degenerate loops if they wrap back to a different point
  8960. ** than our starting point. Reset the flag we use to detect that.
  8961. */
  8962. for(idx=0;idx<(pSet->nSeg*2);idx++) {
  8963. pSet->aBoundary[idx].parsed=0;
  8964. pSet->aBoundary[idx].pSeg->ignore=0;
  8965. pSet->aBoundary[idx].pSeg->ignore_fwd=0;
  8966. pSet->aBoundary[idx].pSeg->ignore_back=0;
  8967. pSet->aBoundary[idx].angle=0;
  8968. }
  8969. sFace->nSeg=1;
  8970. sFace->facebend=0;
  8971.  
  8972. pSeg=pAB=sFace->pSeg;
  8973. if(pFace->backwards) {
  8974. VectorXYZ_Copy(start,pSeg->to);
  8975. } else {
  8976. VectorXYZ_Copy(start,pSeg->from);
  8977. }
  8978. while(pAB) {
  8979. int atstart=0;
  8980. if(SegmentSetNext(pSet,pAB,pFace->backwards,&pBC,&pbcback,&pbcbend,&pbcangle)) {
  8981. /*
  8982. ** If this case occurs, we reached the end of the line without
  8983. ** returning to the start. Mark this section as degenerate
  8984. */
  8985. FaceBoundary_Mark_Degenerate(sFace,3);
  8986. return 1;
  8987. }
  8988. if(!pBC) {
  8989. FaceBoundary_Mark_Degenerate(sFace,4);
  8990. return 1;
  8991. }
  8992. /*
  8993. ** If we have returned to the start mark the beginning and end
  8994. ** of the loop
  8995. */
  8996. if(pbcback) {
  8997. oFace=pBC->boundback;
  8998. atstart=VectorXYZ_SamePoint(start,pBC->to);
  8999. } else {
  9000. oFace=pBC->boundfwd;
  9001. atstart=VectorXYZ_SamePoint(start,pBC->from);
  9002. }
  9003. if(oFace==sFace || atstart) {
  9004. sFace->isloop=1;
  9005. sFace->nSeg++;
  9006. if(sFace->nSeg<3) {
  9007. FaceBoundary_Mark_Degenerate(sFace,0);
  9008. } else {
  9009. pFace->faceid=faceid;
  9010. pFace->pNext=oFace;
  9011. pFace->isloop=2;
  9012. }
  9013. return 1;
  9014. }
  9015. if(oFace->parsed) {
  9016. /*
  9017. ** This loop has encountered a knot
  9018. */
  9019. FaceBoundary_Mark_Degenerate(sFace,0);
  9020. return 1;
  9021. }
  9022. if(oFace->faceid!=oFace->id) {
  9023. /*
  9024. ** This loop has bumped up against a different loop
  9025. ** Try to find another vertex
  9026. */
  9027. if(stage<2) {
  9028. FaceBoundary_Mark_Degenerate(sFace,0);
  9029. return 1;
  9030. } else {
  9031. if(oFace->backwards) {
  9032. oFace->pSeg->ignore_back=1;
  9033. } else {
  9034. oFace->pSeg->ignore_fwd=1;
  9035. }
  9036. continue;
  9037. }
  9038. }
  9039. if(VectorXYZ_SamePoint(pAB->from,pBC->to)) {
  9040. if(VectorXYZ_SamePoint(pBC->from,pAB->to)) {
  9041. if(oFace->backwards) {
  9042. oFace->pSeg->ignore_back=1;
  9043. } else {
  9044. oFace->pSeg->ignore_fwd=1;
  9045. }
  9046. continue;
  9047. }
  9048. }
  9049. sFace->facebend+=pbcbend;
  9050. oFace->parsed=1;
  9051.  
  9052. /*
  9053. ** Add this segment to the end of the list and
  9054. ** mark the segment as part of the same face
  9055. */
  9056. pFace->faceid=faceid;
  9057. pFace->pNext=oFace;
  9058. oFace->faceid=faceid;
  9059. oFace->bend=pbcbend;
  9060. oFace->angle=pbcangle;
  9061. sFace->nSeg++;
  9062. pAB=pBC;
  9063. pFace=oFace;
  9064. }
  9065. return 1;
  9066. }
  9067. /* SegmentSet_BuildFaceEdgeCache */
  9068. static void SegmentSet_BuildFaceEdgeCache(SegmentSet *pSet){
  9069. Link *pLoop;
  9070. int nBound=0;
  9071. int i,changes=0,count=0;
  9072. size_t asize;
  9073. if(pSet->modified) {
  9074. SegmentSet_ClearFaceEdgeCache(pSet);
  9075. SegmentSet_Cleanup(pSet,0);
  9076. } else {
  9077. /* Return immediately if the cache already exists */
  9078. if(pSet->aBoundary) {
  9079. return;
  9080. }
  9081. }
  9082. nBound=(pSet->nSeg*2);
  9083. asize=sizeof(FaceBoundary)*nBound;
  9084. pSet->aBoundary=(FaceBoundary *)Odie_Alloc(asize);
  9085. i=nBound=0;
  9086. for(pLoop=pSet->pAll; pLoop; pLoop=pLoop->pNext){
  9087. Segment *pSeg=pLoop->pLinkNode;
  9088. if(!pSeg->idRC && !pSeg->idLC) {
  9089. pSeg->isVirtual=1;
  9090. }
  9091. pSeg->ignore_fwd=0;
  9092. pSeg->ignore_back=0;
  9093.  
  9094.  
  9095. pSeg->boundfwd=&pSet->aBoundary[i];
  9096. pSet->aBoundary[i].id=i;
  9097. pSet->aBoundary[i].pSeg=pSeg;
  9098. pSet->aBoundary[i].nSeg=0;
  9099. pSet->aBoundary[i].backwards=0;
  9100. pSet->aBoundary[i].isloop=0;
  9101. pSet->aBoundary[i].facebend=0;
  9102. pSet->aBoundary[i].pNext=NULL;
  9103. pSet->aBoundary[i].bend=2;
  9104. if(pSeg->idLC<0) {
  9105. pSet->aBoundary[i].inside_edge=0;
  9106. pSet->aBoundary[i].outside_edge=1;
  9107. } else {
  9108. if(pSeg->idLC>0) {
  9109. pSet->aBoundary[i].inside_edge=1;
  9110. pSet->aBoundary[i].outside_edge=0;
  9111. } else if(pSeg->idRC>0) {
  9112. pSet->aBoundary[i].inside_edge=0;
  9113. pSet->aBoundary[i].outside_edge=1;
  9114. }
  9115. }
  9116. i++;
  9117. pSeg->boundback=&pSet->aBoundary[i];
  9118. pSet->aBoundary[i].id=i;
  9119. pSet->aBoundary[i].pSeg=pSeg;
  9120. pSet->aBoundary[i].nSeg=0;
  9121. pSet->aBoundary[i].backwards=1;
  9122. pSet->aBoundary[i].isloop=0;
  9123. pSet->aBoundary[i].facebend=0;
  9124. pSet->aBoundary[i].pNext=NULL;
  9125. pSet->aBoundary[i].bend=2;
  9126. if(pSeg->idRC<0) {
  9127. pSet->aBoundary[i].inside_edge=0;
  9128. pSet->aBoundary[i].outside_edge=1;
  9129. } else {
  9130. if(pSeg->idRC>0) {
  9131. pSet->aBoundary[i].inside_edge=1;
  9132. pSet->aBoundary[i].outside_edge=0;
  9133. } else if(pSeg->idLC>0) {
  9134. pSet->aBoundary[i].inside_edge=0;
  9135. pSet->aBoundary[i].outside_edge=1;
  9136. }
  9137. }
  9138. i++;
  9139. }
  9140.  
  9141. nBound=i;
  9142. /* Incubation stage. Let the clear cut winners take shape */
  9143. changes=0;
  9144. /* On the first pass ignore backfaces for "real" panels */
  9145. for(count=0;count<nBound;count++) {
  9146. if(count>0 && changes==0) {
  9147. break;
  9148. }
  9149. changes=0;
  9150. for(i=0;i<nBound;i++) {
  9151. changes+=SegmentSet_BuildFaceEdgeCache_ExpandRight(pSet,i,0);
  9152. }
  9153. }
  9154. /* On the second pass include backfaces for real panels */
  9155. for(count=0;count<nBound;count++) {
  9156. if(count>0 && changes==0) {
  9157. break;
  9158. }
  9159. changes=0;
  9160. for(i=0;i<nBound;i++) {
  9161. changes+=SegmentSet_BuildFaceEdgeCache_ExpandRight(pSet,i,1);
  9162. }
  9163. }
  9164. /* On the second pass include backfaces for real panels */
  9165. for(count=0;count<nBound;count++) {
  9166. if(count>0 && changes==0) {
  9167. break;
  9168. }
  9169. changes=0;
  9170. for(i=0;i<nBound;i++) {
  9171. changes+=SegmentSet_BuildFaceEdgeCache_ExpandRight(pSet,i,2);
  9172. }
  9173. }
  9174. }
  9175. /*
  9176. ** This widget translates 3-D coordinates onto a flat canvas by splitting
  9177. ** the 3-D space into layers and stacking the layers on the canvas.
  9178. **
  9179. ** The layers are decks of the ship. The highest layer (or deck) is drawn
  9180. ** at the top of the page. The next layer down is drawn below the top layer.
  9181. ** and so forth down the canvas. In other words, the 3D object is drawn
  9182. ** by showing a set of 2D slices where each slice is viewed from above.
  9183. **
  9184. ** The original 3D coordinates are called "actual" coordinates. When
  9185. ** translated into the 2D canvas they are called "canvas" coordinates.
  9186. **
  9187. ** The actual coordinate system is right-handed. The X axis increases to
  9188. ** the right. The Y axis increases going up. The Z axis comes out of the
  9189. ** page at the viewer. The canvas coordinate system is left-handed. The
  9190. ** X axis increase to the right but the Y axis increases going down.
  9191. **
  9192. ** A plotter is a object with methods. The details of the available
  9193. ** methods and what each does are described in comments before the
  9194. ** implementation of each method.
  9195. */
  9196. /* Plotter_Delete */
  9197. static void Plotter_Delete(ClientData clientData){
  9198. /*
  9199. ** This routine is called when a plotter is deleted. All the memory and
  9200. ** other resources allocated by this plotter is recovered.
  9201. */
  9202. Plotter *p = (Plotter*)clientData;
  9203. Odie_Free((char *)p);
  9204. }
  9205. /* Plotter_Clone */
  9206. static int Plotter_Clone(
  9207. Tcl_Interp* interp, /* Tcl interpreter for error reporting */
  9208. ClientData metadata, /* Metadata to be cloned */
  9209. ClientData* newMetaData /* Where to put the cloned metadata */
  9210. ){
  9211. Tcl_SetObjResult(interp,
  9212. Tcl_NewStringObj("PLOTTERs are not clonable", -1));
  9213. /* For now... */
  9214. return TCL_ERROR;
  9215. }
  9216. /* Plotter_xCanvasToActual */
  9217. static inline double Plotter_xCanvasToActual(Plotter *p,double cx){
  9218. return (cx+p->rXOffset)*p->rZoom;
  9219. }
  9220. /* Plotter_yCanvasToActual */
  9221. static inline double Plotter_yCanvasToActual(Plotter *p,double cy){
  9222. return -1.0*(cy+p->rYOffset)*p->rZoom;
  9223. }
  9224. /* Plotter_xActualToCanvas */
  9225. static inline double Plotter_xActualToCanvas(Plotter *p,double ax){
  9226. /*
  9227. ** Convert a Y coordinate from actual to canvas coordinates for a
  9228. ** given deck.
  9229. */
  9230. return (ax/p->rZoom)-p->rXOffset;
  9231. }
  9232. /* Plotter_yActualToCanvas */
  9233. static inline double Plotter_yActualToCanvas(Plotter *p,double ay){
  9234. /*
  9235. ** Convert a Y coordinate from actual to canvas coordinates for a
  9236. ** given deck.
  9237. */
  9238. return -1.0*(ay/p->rZoom)-p->rYOffset;
  9239. }
  9240. /*
  9241. ** This widget translates 3-D coordinates onto a flat canvas by splitting
  9242. ** the 3-D space into layers and stacking the layers on the canvas.
  9243. **
  9244. ** The layers are decks of the ship. The highest layer (or deck) is drawn
  9245. ** at the top of the page. The next layer down is drawn below the top layer.
  9246. ** and so forth down the canvas. In other words, the 3D object is drawn
  9247. ** by showing a set of 2D slices where each slice is viewed from above.
  9248. **
  9249. ** The original 3D coordinates are called "actual" coordinates. When
  9250. ** translated into the 2D canvas they are called "canvas" coordinates.
  9251. **
  9252. ** The actual coordinate system is right-handed. The X axis increases to
  9253. ** the right. The Y axis increases going up. The Z axis comes out of the
  9254. ** page at the viewer. The canvas coordinate system is left-handed. The
  9255. ** X axis increase to the right but the Y axis increases going down.
  9256. **
  9257. ** A slicer is a object with methods. The details of the available
  9258. ** methods and what each does are described in comments before the
  9259. ** implementation of each method.
  9260. */
  9261. /* Slicer_Delete */
  9262. static void Slicer_Delete(ClientData clientData){
  9263. /*
  9264. ** This routine is called when a slicer is deleted. All the memory and
  9265. ** other resources allocated by this slicer is recovered.
  9266. */
  9267. Slicer *p = (Slicer*)clientData;
  9268. int i;
  9269. for(i=0; i<p->nSlice; i++){
  9270. Odie_Free((char *)p->a[i].zName);
  9271. Odie_Free((char *)p->a[i].xz);
  9272. }
  9273. Odie_Free((char *)p->a);
  9274. Odie_Free((char *)p);
  9275. }
  9276. /* Slicer_Clone */
  9277. static int Slicer_Clone(
  9278. Tcl_Interp* interp, /* Tcl interpreter for error reporting */
  9279. ClientData metadata, /* Metadata to be cloned */
  9280. ClientData* newMetaData /* Where to put the cloned metadata */
  9281. ){
  9282. Tcl_SetObjResult(interp,
  9283. Tcl_NewStringObj("SLICERs are not clonable", -1));
  9284. /* For now... */
  9285. return TCL_ERROR;
  9286. }
  9287. /* Slicer_xCanvasToActual */
  9288. static double Slicer_xCanvasToActual(Slicer *p,struct OneSlice *pS, double cx){
  9289. double ax;
  9290. if(p->nSlice==1) {
  9291. ax = cx*p->rZoom;
  9292. } else {
  9293. ax = cx*p->rZoom - pS->rXShift;
  9294. }
  9295. return ax;
  9296. }
  9297. /* Slicer_yCanvasToActual */
  9298. static double Slicer_yCanvasToActual(Slicer *p,struct OneSlice *pS, double cy){
  9299. double ay;
  9300. if(p->nSlice==1) {
  9301. ay=-cy*p->rZoom;
  9302. } else {
  9303. ay = pS->mxY + (pS->mnY-pS->mxY)*(cy-pS->top)/(pS->btm-pS->top);
  9304. }
  9305. return ay;
  9306. }
  9307. /* Slicer_xActualToCanvas */
  9308. static double Slicer_xActualToCanvas(Slicer *p,struct OneSlice *pS, double ax){
  9309. /*
  9310. ** Convert a X coordinate from actual to canvas coordinates for a
  9311. ** given deck.
  9312. */
  9313. double cx;
  9314. if(p->nSlice==1) {
  9315. cx = ax/p->rZoom;
  9316. } else {
  9317. cx = (ax+pS->rXShift)/p->rZoom;
  9318. }
  9319. return cx;
  9320. }
  9321. /* Slicer_yActualToCanvas */
  9322. static double Slicer_yActualToCanvas(Slicer *p,struct OneSlice *pS, double ay){
  9323. /*
  9324. ** Convert a Y coordinate from actual to canvas coordinates for a
  9325. ** given deck.
  9326. */
  9327. double cy;
  9328. if(p->nSlice==1) {
  9329. cy=-ay/p->rZoom;
  9330. } else {
  9331. cy = pS->top + (pS->btm-pS->top)*(ay-pS->mxY)/(pS->mnY-pS->mxY);
  9332. }
  9333. return cy;
  9334. }
  9335. /* Slicer_deckHeight */
  9336. static double Slicer_deckHeight(struct OneSlice *p, double rX){
  9337. /*
  9338. ** Return the height above baseline for the deck location rX.
  9339. */
  9340. int i;
  9341. double *xz;
  9342. if(!p) {
  9343. return 0.0;
  9344. }
  9345. if( p->nXZ<4 ){
  9346. return p->z;
  9347. }
  9348. xz = p->xz;
  9349. if( rX<=xz[0] ){
  9350. return xz[1];
  9351. }
  9352. for(i=2; i<p->nXZ; i+=2){
  9353. if( rX<=xz[i] ){
  9354. assert( xz[i]>xz[i-2] );
  9355. return xz[i-1] + (xz[i+1]-xz[i-1])*(rX-xz[i-2])/(xz[i]-xz[i-2]);
  9356. }
  9357. }
  9358. return xz[p->nXZ-1];
  9359. }
  9360. /* *Slicer_deckAt */
  9361. static struct OneSlice *Slicer_deckAt(Slicer *p, double rX, double rZ){
  9362. /*
  9363. ** Return a pointer to the particular deck at actual coordinates
  9364. ** X, Z
  9365. */
  9366. int i;
  9367. struct OneSlice *pBest;
  9368. double bestHeight;
  9369. if( p->nSlice==0 ) return 0;
  9370. pBest = &p->a[0];
  9371. bestHeight = Slicer_deckHeight(pBest, rX);
  9372. for(i=1; i<p->nSlice; i++){
  9373. double dh = Slicer_deckHeight(&p->a[i],rX);
  9374. if( dh>bestHeight && dh<=rZ ){
  9375. pBest = &p->a[i];
  9376. bestHeight = dh;
  9377. }
  9378. }
  9379. return pBest;
  9380. }
  9381. /* *Slicer_deckAbove */
  9382. static struct OneSlice *Slicer_deckAbove(Slicer *p, struct OneSlice *pRef){
  9383. /*
  9384. ** Return a pointer to the deck immediately above the given deck.
  9385. ** Return NULL if the given deck is topmost.
  9386. */
  9387. int i;
  9388. struct OneSlice *pBest = 0;
  9389. if( p->nSlice==0 ) return 0;
  9390. for(i=0; i<p->nSlice; i++){
  9391. struct OneSlice *pTest = &p->a[i];
  9392. if( pTest->z<=pRef->z ) continue;
  9393. if( pBest==0 || pBest->z>pTest->z ){
  9394. pBest = pTest;
  9395. }
  9396. }
  9397. return pBest;
  9398. }
  9399. /* *Slicer_deckBelow */
  9400. static struct OneSlice *Slicer_deckBelow(Slicer *p, struct OneSlice *pRef){
  9401. /*
  9402. ** Return a pointer to the deck immediately above the given deck.
  9403. ** Return NULL if the given deck is topmost.
  9404. */
  9405. int i;
  9406. struct OneSlice *pBest = 0;
  9407. if( p->nSlice==0 ) return 0;
  9408. for(i=0; i<p->nSlice; i++){
  9409. struct OneSlice *pTest = &p->a[i];
  9410. if( pTest->z>=pRef->z ) continue;
  9411. if( pBest==0 || pBest->z<pTest->z ){
  9412. pBest = pTest;
  9413. }
  9414. }
  9415. return pBest;
  9416. }
  9417. /* Slicer_computeTopAndBottom */
  9418. static void Slicer_computeTopAndBottom(Slicer *p){
  9419. /*
  9420. ** Recompute the values of p->a[].top and p->a[].btm for all slices in
  9421. ** the given slicer.
  9422. */
  9423. int i;
  9424. double rY = 0.0;
  9425. double rBound = -9.9e99;
  9426. for(i=p->nSlice-1; i>=0; i--){
  9427. double h = (p->a[i].mxY - p->a[i].mnY)/p->rZoom;
  9428. p->a[i].upperbound = rBound;
  9429. p->a[i].top = rY;
  9430. p->a[i].btm = rY + h;
  9431. rY = p->a[i].btm + 0.3*h;
  9432. rBound = p->a[i].btm + 0.15*h;
  9433. }
  9434.  
  9435. if( p->nSlice==0 ) return;
  9436.  
  9437. /* Calculate the above and below for each deck */
  9438.  
  9439. for(i=0; i<p->nSlice; i++){
  9440. struct OneSlice *pThis = &p->a[i];
  9441. struct OneSlice *pBest = 0;
  9442.  
  9443. pBest=Slicer_deckAbove(p,pThis);
  9444. if(pBest) {
  9445. pThis->above=pBest->did;
  9446. } else {
  9447. pThis->above=0;
  9448. }
  9449. pBest=Slicer_deckBelow(p,pThis);
  9450. if(pBest) {
  9451. pThis->below=pBest->did;
  9452. } else {
  9453. pThis->below=0;
  9454. }
  9455. }
  9456. }
  9457. /* Slicer_getDeck */
  9458. static int Slicer_getDeck(
  9459. Tcl_Interp *interp, /* Put error messages here */
  9460. Slicer *p, /* The slicer */
  9461. double rX, /* X coord used to find deck if pObj is a Z coord */
  9462. Tcl_Obj *pObj, /* Either a deck name or a Z coordinate */
  9463. struct OneSlice **ppS /* Write the slice pointer here */
  9464. ){
  9465. /*
  9466. ** pObj is either the name of a deck or a Z coordinate. If it is a
  9467. ** deck name, find the deck and write a pointer to it in *ppS. If
  9468. ** it is a Z coordinate, use that coordinate together with rX to
  9469. ** find the deck and write it into *ppS. If an error occurs, put
  9470. ** an error message on the TCL interpreter and return TCL_ERROR.
  9471. ** Return TCL_OK on success.
  9472. */
  9473. double rZ;
  9474. const char *zName;
  9475. int i;
  9476. if(p->nSlice==1) {
  9477. *ppS=&p->a[0];
  9478. return TCL_OK;
  9479. }
  9480. if( Tcl_GetDoubleFromObj(0, pObj, &rZ)==TCL_OK ){
  9481. *ppS = Slicer_deckAt(p, rX, rZ);
  9482. return TCL_OK;
  9483. }
  9484. zName = Tcl_GetStringFromObj(pObj, 0);
  9485. for(i=0; i<p->nSlice; i++){
  9486. if( strcmp(zName, p->a[i].zName)==0 ){
  9487. *ppS = &p->a[i];
  9488. return TCL_OK;
  9489. }
  9490. }
  9491. Tcl_AppendResult(interp, "no such deck: ", zName, 0);
  9492. return TCL_ERROR;
  9493. }
  9494. /* Slicer_getDeckId */
  9495. static int Slicer_getDeckId(
  9496. Tcl_Interp *interp, /* Put error messages here */
  9497. Slicer *p, /* The slicer */
  9498. Tcl_Obj *pObj, /* Either a deck name or a Z coordinate */
  9499. struct OneSlice **ppS /* Write the slice pointer here */
  9500. ){
  9501. /*
  9502. ** pObj is either the name of a deck or a Z coordinate. If it is a
  9503. ** deck name, find the deck and write a pointer to it in *ppS. If
  9504. ** it is a Z coordinate, use that coordinate together with rX to
  9505. ** find the deck and write it into *ppS. If an error occurs, put
  9506. ** an error message on the TCL interpreter and return TCL_ERROR.
  9507. ** Return TCL_OK on success.
  9508. */
  9509. int did;
  9510. const char *zName;
  9511. int i;
  9512. if(p->nSlice==1) {
  9513. *ppS=&p->a[0];
  9514. return TCL_OK;
  9515. }
  9516. if( Tcl_GetIntFromObj(interp, pObj, &did)==TCL_OK ){
  9517. for(i=0; i<p->nSlice; i++){
  9518. if( did == p->a[i].did ){
  9519. *ppS = &p->a[i];
  9520. return TCL_OK;
  9521. }
  9522. }
  9523. Tcl_AppendResult(interp, "no such deckid: ", 0);
  9524. return TCL_ERROR;
  9525. }
  9526. zName = Tcl_GetStringFromObj(pObj, 0);
  9527. for(i=0; i<p->nSlice; i++){
  9528. if( strcmp(zName, p->a[i].zName)==0 ){
  9529. *ppS = &p->a[i];
  9530. return TCL_OK;
  9531. }
  9532. }
  9533. Tcl_AppendResult(interp, "no such deck: ", zName, 0);
  9534. return TCL_ERROR;
  9535. }
  9536. /* *Slicer_GetSlicerFromObj */
  9537. Slicer *Slicer_GetSlicerFromObj(Tcl_Interp *interp,Tcl_Obj *tclobj){
  9538. Tcl_Object pObj;
  9539. Slicer *pSlicer=NULL;
  9540. pObj=Tcl_GetObjectFromObj(interp,tclobj);
  9541. if(!pObj) {
  9542. return NULL;
  9543. }
  9544. pSlicer=(Slicer *)Tcl_ObjectGetMetadata(pObj,&SlicerDataType);
  9545. return pSlicer;
  9546. }
  9547. /* *Slicer_getDeck_FromInt */
  9548. static inline struct OneSlice *Slicer_getDeck_FromInt(
  9549. Slicer *p,
  9550. int did
  9551. ){
  9552. int i;
  9553. if(p->nSlice==1) {
  9554. return &p->a[0];
  9555. }
  9556. for(i=0; i<p->nSlice; i++){
  9557. if( did == p->a[i].did ){
  9558. return &p->a[i];
  9559. }
  9560. }
  9561. return NULL;
  9562. }
  9563. /* slicer_drawline_do */
  9564. static int slicer_drawline_do(
  9565. Tcl_Interp *interp,
  9566. Slicer *p,
  9567. int coord_count,
  9568. int *deckCoord,double *xCoord,double *yCoord,
  9569. struct OneSlice **apDeck,
  9570. Tcl_Obj *canvas,
  9571. const char *zKTag,
  9572. const char *zXTag,
  9573. const char *zBTag
  9574. ){
  9575. int i;
  9576.  
  9577. Tcl_Obj *pVTag; /* The "sNNN" tag added to all line segments */
  9578.  
  9579. Tcl_Obj *aLineArg[20]; /* Element of "create line" TCL command */
  9580. int nLineArg; /* Number of used entries in aLineArg[] */
  9581. Tcl_Obj *aBendArg[20]; /* Cmd to bends penetractions */
  9582. int nBendArg;
  9583.  
  9584. nBendArg = 0;
  9585. if(zBTag) {
  9586. aBendArg[0] = canvas;
  9587. aBendArg[1] = ODIE_CONSTANT_STRING("create");
  9588. aBendArg[2] = ODIE_CONSTANT_STRING("oval");
  9589. for(i=3; i<=6; i++){
  9590. aBendArg[i] = Tcl_NewObj();
  9591. }
  9592. aBendArg[7] = ODIE_CONSTANT_STRING("-tags");
  9593. for(i=0; i<=7; i++){
  9594. Tcl_IncrRefCount(aBendArg[i]);
  9595. }
  9596. nBendArg = 9;
  9597. }
  9598. aLineArg[0] = canvas;
  9599. aLineArg[1] = ODIE_CONSTANT_STRING("create");
  9600. aLineArg[2] = ODIE_CONSTANT_STRING("line");
  9601. for(i=3; i<=6; i++){
  9602. aLineArg[i] = Tcl_NewObj();
  9603. }
  9604. aLineArg[7] = ODIE_CONSTANT_STRING("-tags");
  9605. for(i=0; i<=7; i++){
  9606. Tcl_IncrRefCount(aLineArg[i]);
  9607. }
  9608. nLineArg = 9;
  9609.  
  9610.  
  9611.  
  9612. for(i=1; i<coord_count; i++){
  9613. char zBuf[30];
  9614. double x0, y0, x1, y1;
  9615.  
  9616. x0 = Slicer_xActualToCanvas(p,apDeck[i-1],xCoord[i-1]);
  9617. x1 = Slicer_xActualToCanvas(p,apDeck[i],xCoord[i]);
  9618. y0 = Slicer_yActualToCanvas(p,apDeck[i-1],yCoord[i-1]);
  9619. y1 = Slicer_yActualToCanvas(p,apDeck[i], yCoord[i]);
  9620. Tcl_SetDoubleObj(aLineArg[3], x0);
  9621. Tcl_SetDoubleObj(aLineArg[4], y0);
  9622. Tcl_SetDoubleObj(aLineArg[5], x1);
  9623. Tcl_SetDoubleObj(aLineArg[6], y1);
  9624. if( apDeck[i]!=apDeck[i-1] && zXTag ){
  9625. sprintf(zBuf, "%s s%d", zXTag, i);
  9626. } else {
  9627. sprintf(zBuf, "%s s%d", zKTag, i);
  9628. }
  9629. pVTag = Tcl_NewStringObj(zBuf, -1);
  9630. Tcl_IncrRefCount(pVTag);
  9631. aLineArg[8]=pVTag;
  9632.  
  9633. if(i<(coord_count-1) && nBendArg) {
  9634. char bBuf[30];
  9635. Tcl_Obj *pBTag; /* The "nNNN" tag added to all line bend points */
  9636. sprintf(bBuf, "%s b%d", zBTag, i);
  9637. pBTag = Tcl_NewStringObj(bBuf, -1);
  9638. Tcl_IncrRefCount(pVTag);
  9639. Tcl_SetDoubleObj(aBendArg[3], x1-4);
  9640. Tcl_SetDoubleObj(aBendArg[4], y1-4);
  9641. Tcl_SetDoubleObj(aBendArg[5], x1+4);
  9642. Tcl_SetDoubleObj(aBendArg[6], y1+4);
  9643. aBendArg[8] = pBTag;
  9644. Tcl_EvalObjv(interp, nBendArg, aBendArg, 0);
  9645. }
  9646. Tcl_EvalObjv(interp, nLineArg, aLineArg, 0);
  9647. }
  9648. for(i=0; i<=7; i++){
  9649. Tcl_DecrRefCount(aLineArg[i]);
  9650. if( i<nBendArg ) Tcl_DecrRefCount(aBendArg[i]);
  9651. }
  9652. for(i=9; i<nLineArg; i++){
  9653. Tcl_DecrRefCount(aLineArg[i]);
  9654. }
  9655. for(i=9; i<nBendArg; i++){
  9656. Tcl_DecrRefCount(aBendArg[i]);
  9657. }
  9658. return TCL_OK;
  9659. }
  9660. /* Slicer_Location_zabs */
  9661. static inline double Slicer_Location_zabs(Slicer *p,struct OneSlice *pS,double x0,double dheight){
  9662. struct OneSlice *pAbove;
  9663. if(dheight >= 0) {
  9664. return dheight+Slicer_deckHeight(pS,x0);
  9665. }
  9666. pAbove=Slicer_deckAbove(p,pS);
  9667. if(pAbove) {
  9668. return Slicer_deckHeight(pAbove,x0)+dheight;
  9669. }
  9670. return Slicer_deckHeight(pS,x0)+p->upper_height+dheight;
  9671. }
  9672. /* Location_zdeck */
  9673. static inline double Location_zdeck(Slicer *p,struct OneSlice *pS,double x0,double dheight){
  9674. struct OneSlice *pAbove;
  9675. if(dheight >= 0) {
  9676. return dheight;
  9677. }
  9678. pAbove=Slicer_deckAbove(p,pS);
  9679. if(pAbove) {
  9680. return Slicer_deckHeight(pAbove,x0)-Slicer_deckHeight(pS,x0)+dheight;
  9681. }
  9682. return p->upper_height+dheight;
  9683. }
  9684. /* Slicer_Find_Deckid_And_Offset */
  9685. int Slicer_Find_Deckid_And_Offset(Slicer *pSlicer,double x0,double y0,double z0,int *deckid,double *zoff){
  9686. struct OneSlice *ppS,*pAbove;
  9687. double zdeck;
  9688. *zoff=0.0;
  9689. *deckid=0;
  9690. if(!pSlicer) {
  9691. return TCL_ERROR;
  9692. }
  9693. ppS=Slicer_deckAt(pSlicer,x0,z0);
  9694. if(!ppS) {
  9695. return TCL_ERROR;
  9696. }
  9697. *deckid=ppS->did;
  9698. zdeck=Slicer_deckHeight(ppS,x0);
  9699. *zoff=z0-zdeck;
  9700. return TCL_OK;
  9701. }
  9702. /* Slicer_Absolute_Z */
  9703. double Slicer_Absolute_Z(Slicer *pSlicer,int deckid,double x0,double y0,double zoff){
  9704. struct OneSlice *ppS,*pAbove;
  9705. double zresult=0.0;
  9706. if(!pSlicer) {
  9707. return 0;
  9708. }
  9709. ppS=Slicer_getDeck_FromInt(pSlicer,deckid);
  9710. if(!ppS) {
  9711. return 0;
  9712. }
  9713. if(zoff < 0.0) {
  9714. pAbove = Slicer_deckAbove(pSlicer, ppS);
  9715. if(pAbove) {
  9716. zresult=Slicer_deckHeight(pAbove,x0)+zoff;
  9717. } else {
  9718. zresult=Slicer_deckHeight(ppS,x0)+2000+zoff;
  9719. }
  9720. } else {
  9721. zresult=Slicer_deckHeight(ppS,x0)+zoff;
  9722. }
  9723. return zresult;
  9724. }
  9725. /*
  9726. ** This file implements a TCL object that keeps track of the walls and
  9727. ** bulkheads on a single deck of a ship.
  9728. **
  9729. ** This widget assumes a right-handed coordinate system if zoom is positive
  9730. ** and a left-handed coordinate system is zoom is negative. The Tk canvas
  9731. ** widget uses a left-handed coordinate system all the time. The READI
  9732. ** database uses a right-handed coordinate system all the time. This module
  9733. ** can be used to translate by setting zoom to +1.0 for database I/O and
  9734. ** to -$g(zoom) for canvas I/O.
  9735. **
  9736. ** This module uses a purely 2-D model. It can only handle a single
  9737. ** deck at a time. If a multi-deck model needs to be displayed then
  9738. ** that multi-deck model should first be flattened into a stack of
  9739. ** individual decks in the same plane using the separate "slicer" object.
  9740. **
  9741. ** This file implements a single new constructor tcl command named "wallset".
  9742. ** The wallset command creates a new wallset object. Methods on this
  9743. ** wallset object are used to manage the object.
  9744. **
  9745. ** The details of the various methods and what they do are provided in
  9746. ** header comments above the implementation of each method.
  9747. */
  9748. #ifndef M_PI
  9749. # define M_PI 3.1415926535898
  9750. #endif
  9751.  
  9752. /*
  9753. ** Remove all of the ComptBox entries from the wallset.
  9754. */
  9755. static void clearComptBoxCache(Wallset *pWS){
  9756. ComptBox *p = pWS->pComptBox;
  9757. while( p ){
  9758. ComptBox *pNext = p->pNext;
  9759. Tcl_Free((char *)p);
  9760. p = pNext;
  9761. }
  9762. pWS->pComptBox = 0;
  9763. }
  9764.  
  9765. /*
  9766. ** This routine is invoked when the TCL command that implements a
  9767. ** wallset is deleted. Free all memory associated with that
  9768. ** wallset.
  9769. */
  9770. static void destroyWallset(void *pArg){
  9771. Wallset *p = (Wallset*)pArg;
  9772. Link *pLink = p->pAll;
  9773. clearComptBoxCache(p);
  9774. while( pLink ){
  9775. Segment *pSeg = pLink->pLinkNode;
  9776. pLink = pSeg->pAll.pNext;
  9777. Tcl_Free((char *) pSeg );
  9778. }
  9779. Tcl_Free((char *) p );
  9780. }
  9781.  
  9782. /*
  9783. ** Clear the Segment.ignore flag on all segments within a wallset.
  9784. */
  9785. static void ignoreNone(Wallset *p){
  9786. #if 0
  9787. Link *pLink;
  9788. for(pLink=p->pAll; pLink; pLink=pLink->pNext){
  9789. pLink->pSeg->ignore = 0;
  9790. }
  9791. #endif
  9792. }
  9793.  
  9794. /*
  9795. ** Return a pointer to the segment with the given ID. Return NULL
  9796. ** if there is no such segment.
  9797. */
  9798. static Segment *findSegment(Wallset *p, int id){
  9799. int h;
  9800. Link *pLink;
  9801.  
  9802. h = hashInt(id);
  9803. for(pLink = p->hashId[h]; pLink; pLink=pLink->pNext){
  9804. Segment *pSeg=pLink->pLinkNode;
  9805. if( pSeg->id==id ) return pSeg;
  9806. }
  9807. return 0;
  9808. }
  9809.  
  9810. /*
  9811. ** Scan all segments looking for the vertex or vertices that are nearest
  9812. ** to x,y. Return a pointer to a Segment.set that is the list of matching
  9813. ** segments. Also write the nearest point into *pX,*pY.
  9814. **
  9815. ** The returned list uses the Segment.set link.
  9816. */
  9817. static Link *nearestVertex(
  9818. Wallset *p, /* The wallset to be scanned */
  9819. double x, double y, /* Search for points near to this point */
  9820. double *pX, double *pY /* Write nearest vertex here */
  9821. ){
  9822. double nx, ny;
  9823. double min = -1.0;
  9824. Link *pList = 0;
  9825. Link *pI;
  9826.  
  9827. nx = x = roundCoord(x);
  9828. ny = y = roundCoord(y);
  9829. for(pI=p->pAll; pI; pI=pI->pNext){
  9830. double dx, dy, dist;
  9831. Segment *pSeg = pI->pLinkNode;
  9832. dx = x - pSeg->from[X_IDX];
  9833. dy = y - pSeg->from[Y_IDX];
  9834. dist = dx*dx + dy*dy;
  9835. if( min<0.0 || dist<=min ){
  9836. if( min<0.0 || nx!=pSeg->from[X_IDX] || ny!=pSeg->from[Y_IDX] ){
  9837. pList = 0;
  9838. nx = pSeg->from[X_IDX];
  9839. ny = pSeg->from[Y_IDX];
  9840. min = dist;
  9841. }
  9842. LinkInit(pSeg->pSet, pSeg);
  9843. LinkInsert(&pList, &pSeg->pSet);
  9844. }
  9845. dx = x - pSeg->to[X_IDX];
  9846. dy = y - pSeg->to[Y_IDX];
  9847. dist = dx*dx + dy*dy;
  9848. if( dist<=min ){
  9849. if( nx!=pSeg->to[X_IDX] || ny!=pSeg->to[Y_IDX] ){
  9850. pList = 0;
  9851. nx = pSeg->to[X_IDX];
  9852. ny = pSeg->to[Y_IDX];
  9853. min = dist;
  9854. }
  9855. LinkInit(pSeg->pSet, pSeg);
  9856. LinkInsert(&pList, &pSeg->pSet);
  9857. }
  9858. }
  9859. *pX = nx;
  9860. *pY = ny;
  9861. return pList;
  9862. }
  9863.  
  9864. /*
  9865. ** Scan all segments looking for the point on a segment that is nearest
  9866. ** to x,y. Return a pointer to a Segment.set that is the list of matching
  9867. ** segments. This set might contain multiple members if the nearest point
  9868. ** is actually a vertex shared by two or more segments. Write the nearest
  9869. ** point into *pX, *pY.
  9870. **
  9871. ** /// Ignore any segment that has its Segment.ignore flag set. -- removed
  9872. **
  9873. ** The returned list uses the Segment.set list.
  9874. */
  9875. static Link *nearestPoint(
  9876. Wallset *p, /* The wallset to be scanned */
  9877. double x, double y, /* Search for points near to this point */
  9878. double *pX, double *pY /* Write nearest vertex here */
  9879. ){
  9880. double nx, ny;
  9881. double min = -1.0;
  9882. Link *pList = 0;
  9883. Link *pI;
  9884.  
  9885. nx = x = roundCoord(x);
  9886. ny = y = roundCoord(y);
  9887. for(pI=p->pAll; pI; pI=pI->pNext){
  9888. double dx, dy, dist;
  9889. Segment *pSeg;
  9890. double acx, acy; /* Vector from x0,y0 to x,y */
  9891. double abx, aby; /* Vector from x0,y0 to x1,y1 */
  9892. double rx, ry; /* Nearest point on x0,y0->to[X_IDX],y1 to x,y */
  9893. double r;
  9894.  
  9895. pSeg = pI->pLinkNode;
  9896. /* if( pSeg->ignore ) continue; */
  9897. acx = x - pSeg->from[X_IDX];
  9898. acy = y - pSeg->from[Y_IDX];
  9899. abx = pSeg->to[X_IDX] - pSeg->from[X_IDX];
  9900. aby = pSeg->to[Y_IDX] - pSeg->from[Y_IDX];
  9901. r = (acx*abx + acy*aby)/(abx*abx + aby*aby);
  9902. if( r<=0 ){
  9903. rx = pSeg->from[X_IDX];
  9904. ry = pSeg->from[Y_IDX];
  9905. }else if( r>=1 ){
  9906. rx = pSeg->to[X_IDX];
  9907. ry = pSeg->to[Y_IDX];
  9908. }else{
  9909. rx = pSeg->from[X_IDX] + abx*r;
  9910. ry = pSeg->from[Y_IDX] + aby*r;
  9911. }
  9912. rx = roundCoord(rx);
  9913. ry = roundCoord(ry);
  9914. dx = x - rx;
  9915. dy = y - ry;
  9916. dist = dx*dx + dy*dy;
  9917. if( min<0.0 || dist<=min ){
  9918. if( min<0.0 || nx!=rx || ny!=ry ){
  9919. pList = 0;
  9920. nx = rx;
  9921. ny = ry;
  9922. min = dist;
  9923. }
  9924. LinkInit(pSeg->pSet, pSeg);
  9925. LinkInsert(&pList, &pSeg->pSet);
  9926. }
  9927. }
  9928. *pX = nx;
  9929. *pY = ny;
  9930. return pList;
  9931. }
  9932.  
  9933. /*
  9934. ** Return TRUE if the value x is in between x1 and x2.
  9935. */
  9936. static int between(double x, double x1, double x2){
  9937. if( x1<x2 ){
  9938. return x>=x1 && x<=x2;
  9939. }else{
  9940. return x>=x2 && x<=x1;
  9941. }
  9942. }
  9943.  
  9944. /*
  9945. ** Return TRUE if the given segment is on the given list
  9946. */
  9947. static int segmentOnList(Segment *pSeg, Link *pList){
  9948. while( pList ){
  9949. if( pList->pLinkNode==pSeg ) return 1;
  9950. pList = pList->pNext;
  9951. }
  9952. return 0;
  9953. }
  9954.  
  9955. /*
  9956. ** Return a list of all segments which have an end at the given vertex.
  9957. ** The returned list uses Segment.set
  9958. */
  9959. static Link *segmentsAtVertex(Wallset *p, double x, double y){
  9960. Link *pList = 0;
  9961. Link *pI;
  9962. int h;
  9963.  
  9964. x = roundCoord(x);
  9965. y = roundCoord(y);
  9966. h = hashCoord(x, y);
  9967. for(pI=p->hashFrom[h]; pI; pI=pI->pNext){
  9968. Segment *pSeg = pI->pLinkNode;
  9969. /* if( pSeg->ignore ) continue; */
  9970. if( floatCompare(x, pSeg->from[X_IDX])==0 && floatCompare(y, pSeg->from[Y_IDX])==0 ){
  9971. assert( !segmentOnList(pSeg, pList) );
  9972. LinkInit(pSeg->pSet, pSeg);
  9973. LinkInsert(&pList, &pSeg->pSet);
  9974. }
  9975. }
  9976. for(pI=p->hashTo[h]; pI; pI=pI->pNext){
  9977. Segment *pSeg = pI->pLinkNode;
  9978. /* if( pSeg->ignore ) continue; */
  9979. if( floatCompare(x, pSeg->to[X_IDX])==0 && floatCompare(y, pSeg->to[Y_IDX])==0 ){
  9980. assert( !segmentOnList(pSeg, pList) );
  9981. LinkInit(pSeg->pSet, pSeg);
  9982. LinkInsert(&pList, &pSeg->pSet);
  9983. }
  9984. }
  9985. return pList;
  9986. }
  9987.  
  9988. /*
  9989. ** The point xV,yV is a vertex in the wallset. This routine locates
  9990. ** a segment connected to that vertex which is the first segment in
  9991. ** a clockwise direction from xR,yR->xV,yV. A pointer to the segment
  9992. ** is written into *ppSeg. If the output segment moves backwards
  9993. ** (in other words if x1,y1 of the segment is connected at xV,yV)
  9994. ** then *pfBack is true.
  9995. **
  9996. ** If a suitable segment is found, 0 is returned. Non-zero is returned
  9997. ** if no suitable segment could be found.
  9998. **
  9999. ** This routine uses the Segment.set list internally.
  10000. */
  10001. static int nextCwSegment(
  10002. Wallset *p, /* The wallset */
  10003. double xR, double yR, /* Remote end of input segment */
  10004. double xV, double yV, /* Vertex (near end of input segment) */
  10005. Segment **ppSeg, /* OUT: First segment clockwise from xR,yR->xV,yV */
  10006. int *pfBack /* OUT: True if output segment goes backwards */
  10007. ){
  10008. Link *pList, *pI;
  10009. double rRef, rBest;
  10010. int i, nSeg, iBest;
  10011. Segment *pSeg;
  10012. struct {
  10013. Segment *pSeg;
  10014. int isBack;
  10015. double rAngle;
  10016. } *aSeg, aSegStatic[20];
  10017.  
  10018. /* Find all segments at xV,yV */
  10019. pList = segmentsAtVertex(p, xV, yV);
  10020. for(pI=pList, nSeg=0; pI; nSeg++, pI=pI->pNext){}
  10021. if( nSeg==0 ) return 1;
  10022. if( nSeg<=sizeof(aSegStatic)/sizeof(aSegStatic[0]) ){
  10023. aSeg = aSegStatic;
  10024. }else{
  10025. aSeg = (void *)Odie_Alloc( nSeg*sizeof(*aSeg) );
  10026. }
  10027. for(pI=pList, i=0; pI; i++, pI=pI->pNext){
  10028. aSeg[i].pSeg = pSeg = pI->pLinkNode;
  10029. aSeg[i].isBack = floatCompare(xV, pSeg->to[X_IDX])==0
  10030. && floatCompare(yV, pSeg->to[Y_IDX])==0;
  10031. }
  10032.  
  10033. /* Find the reference angle */
  10034. rRef = atan2(yR-yV, xR-xV)*180.0/M_PI;
  10035.  
  10036. /* Find angles on all segments */
  10037. for(i=0; i<nSeg; i++){
  10038. pSeg = aSeg[i].pSeg;
  10039. if( aSeg[i].isBack ){
  10040. aSeg[i].rAngle = atan2(pSeg->from[Y_IDX]-pSeg->to[Y_IDX], pSeg->from[X_IDX]-pSeg->to[X_IDX])*180.0/M_PI;
  10041. }else{
  10042. aSeg[i].rAngle = atan2(pSeg->to[Y_IDX]-pSeg->from[Y_IDX], pSeg->to[X_IDX]-pSeg->from[X_IDX])*180.0/M_PI;
  10043. }
  10044. }
  10045.  
  10046. /* Subtract 360 to any segment angle that is less than the reference angle */
  10047. for(i=0; i<nSeg; i++){
  10048. if( aSeg[i].rAngle<rRef ) aSeg[i].rAngle += 360;
  10049. }
  10050.  
  10051. /* Choose the segment with the largest angle */
  10052. rBest = aSeg[0].rAngle;
  10053. iBest = 0;
  10054. for(i=1; i<nSeg; i++){
  10055. if( aSeg[i].rAngle>rBest ){
  10056. iBest = i;
  10057. rBest = aSeg[i].rAngle;
  10058. }
  10059. }
  10060. *ppSeg = aSeg[iBest].pSeg;
  10061. *pfBack = aSeg[iBest].isBack;
  10062. if( aSeg!=aSegStatic ){
  10063. Tcl_Free((char *) aSeg );
  10064. }
  10065.  
  10066. return 0;
  10067. }
  10068.  
  10069. /*
  10070. ** Consider a line beginning at x0,y0 then going from x1,y1 to x2,y2.
  10071. ** x1,y1 is an elbow in the line. This routine returns -1 if the
  10072. ** elbow bends to the right, and +1 if it bends to the left. zero is
  10073. ** returned if the elbow does not bend at all.
  10074. */
  10075. static int bendDirection(
  10076. double x0, double y0,
  10077. double x1, double y1,
  10078. double x2, double y2
  10079. ){
  10080. /* Algorithm: Rotate x0,y0->to[X_IDX],y1 90 degrees counter-clockwise. Take
  10081. ** the dot product with x1,y1->x2,y2. The dot produce will be the product
  10082. ** of two (non-negative) magnitudes and the cosine of the angle. So if
  10083. ** the dot product is positive, the bend is to the left, or to the right if
  10084. ** the dot product is negative.
  10085. */
  10086. double r = (y0-y1)*(x2-x1) + (x1-x0)*(y2-y1);
  10087. return r<0.0 ? +1 : (r>0.0 ? -1 : 0);
  10088. }
  10089.  
  10090. /*
  10091. ** Given an interior point xI,yI, this routine finds a segment on the
  10092. ** boundary that contains the interior point. That segment is returned
  10093. ** in *ppSeg. *pfLeft is set to true if the interior point is to the left
  10094. ** of the segment and false if it is to the right.
  10095. **
  10096. ** Zero is returned on success. Non-zero is returned if no suitable
  10097. ** boundary could be located. Non-zero might be returned, for example,
  10098. ** if xI,yI is positioned directly on top of a wall or if there are no
  10099. ** walls in the wallset.
  10100. **
  10101. ** // Any segment marked with Segment.ignore is ignored for purposes of
  10102. ** // this routine. -- removed
  10103. **
  10104. ** This routine uses the Segment.set list internally.
  10105. */
  10106. static int firstBoundarySegment(
  10107. Wallset *p, /* The wallset */
  10108. double xI, double yI, /* An interior point */
  10109. Segment **ppSeg, /* OUT: A segment on the boundary containing xI,yI */
  10110. int *pfLeft /* OUT: True if xI,yI is to the left side *ppSeg */
  10111. ){
  10112. Link *pList;
  10113. double xN, yN;
  10114.  
  10115. /* Find nearest point, xN,yN */
  10116. pList = nearestPoint(p, xI, yI, &xN, &yN);
  10117. if( pList==0 ) return 1;
  10118. if( pList->pNext ){
  10119. /* xN,yN is a vertex...
  10120. ** Locate the first segment clockwise from xI,yI->xN,yN and return
  10121. */
  10122. return nextCwSegment(p, xI, yI, xN, yN, ppSeg, pfLeft);
  10123. }else{
  10124. /* xN,yN is a point on single line segment...
  10125. */
  10126. Segment *pSeg;
  10127. pSeg = *ppSeg = pList->pLinkNode;
  10128. *pfLeft = bendDirection(pSeg->from[X_IDX], pSeg->from[Y_IDX], xN, yN, xI, yI)>0;
  10129. }
  10130. return 0;
  10131. }
  10132.  
  10133. /*
  10134. ** Fill the given Boundary array with a list of segments (with
  10135. ** Segment.ignore set to false) that form a closed circuit. The
  10136. ** first entry in aBound[] has already been filled in by the
  10137. ** calling function and is used to seed the search.
  10138. **
  10139. ** At most nBound slots in aBound[] will be used. The return value
  10140. ** is the number of slots in aBound[] that would have been used if those
  10141. ** slots had been available. A return of 0 indicates that no boundary
  10142. ** is available.
  10143. **
  10144. ** If the checkIsPrimary flag is true and the aBound[0] entry is not
  10145. ** the primary segment for the compartment, then the aBound[] is not
  10146. ** completely filled in and the routine returns 0;
  10147. */
  10148. static int completeBoundary(
  10149. Wallset *p, /* The wallset */
  10150. int checkIsPrimary, /* Abort if aBound[0] is not the primary segment */
  10151. int nBound, /* Number of slots available in aBound[] */
  10152. Boundary *aBound /* IN-OUT: Write results into aBound[1...] */
  10153. ){
  10154. int cnt = 1;
  10155. Segment *pSeg, *pS;
  10156. int isLeft;
  10157. int isBack;
  10158. double xR, yR, xV, yV;
  10159.  
  10160. pS = pSeg = aBound[0].pSeg;
  10161. isLeft = aBound[0].backwards;
  10162. if( !isLeft ){
  10163. xR = pSeg->from[X_IDX];
  10164. yR = pSeg->from[Y_IDX];
  10165. xV = pSeg->to[X_IDX];
  10166. yV = pSeg->to[Y_IDX];
  10167. }else{
  10168. xV = pSeg->from[X_IDX];
  10169. yV = pSeg->from[Y_IDX];
  10170. xR = pSeg->to[X_IDX];
  10171. yR = pSeg->to[Y_IDX];
  10172. }
  10173. while( nextCwSegment(p,xR,yR,xV,yV,&pS,&isBack)==0 &&
  10174. (isBack!=isLeft || pS!=pSeg) ){
  10175. if( checkIsPrimary ){
  10176. if( pS->id<pSeg->id ) return 0;
  10177. if( pS->id==pSeg->id && !isLeft ) return 0;
  10178. }
  10179. if( isBack ){
  10180. xV = pS->from[X_IDX];
  10181. yV = pS->from[Y_IDX];
  10182. xR = pS->to[X_IDX];
  10183. yR = pS->to[Y_IDX];
  10184. }else{
  10185. xR = pS->from[X_IDX];
  10186. yR = pS->from[Y_IDX];
  10187. xV = pS->to[X_IDX];
  10188. yV = pS->to[Y_IDX];
  10189. }
  10190. if( nBound>cnt ){
  10191. aBound[cnt].pSeg = pS;
  10192. aBound[cnt].backwards = isBack;
  10193. }
  10194. cnt++;
  10195. if( cnt>1000 /* 00 */ ) return -cnt; /* Avoid an infinite loop */
  10196. }
  10197. return cnt;
  10198. }
  10199.  
  10200. /*
  10201. ** Compute the "spin" on a boundary. A positive value means the
  10202. ** circulation is to counter-clockwise and a negative value means the
  10203. ** circulation is clockwise. For boundaries, a positive
  10204. ** value means the region is internal and a negative value means
  10205. ** the region is external.
  10206. */
  10207. static double spin(Boundary *aBound, int nBound){
  10208. double sum = 0;
  10209. int i;
  10210. for(i=0; i<nBound; i++){
  10211. double x0, y0, x1, y1;
  10212. double dx, dy;
  10213. Segment *pSeg = aBound->pSeg;
  10214. if( aBound->backwards ){
  10215. x0 = pSeg->to[X_IDX];
  10216. y0 = pSeg->to[Y_IDX];
  10217. x1 = pSeg->from[X_IDX];
  10218. y1 = pSeg->from[Y_IDX];
  10219. }else{
  10220. x0 = pSeg->from[X_IDX];
  10221. y0 = pSeg->from[Y_IDX];
  10222. x1 = pSeg->to[X_IDX];
  10223. y1 = pSeg->to[Y_IDX];
  10224. }
  10225. aBound++;
  10226. dx = x1-x0;
  10227. dy = y1-y0;
  10228. sum += x0*dy - y0*dx;
  10229. }
  10230. return sum;
  10231. }
  10232.  
  10233. /*
  10234. ** The input is two linked lists of ComptBox structures where each
  10235. ** list is sorted by increasing area. Combine these two lists into
  10236. ** a single sorted linked list.
  10237. */
  10238. static ComptBox *mergeComptBox(ComptBox *p1, ComptBox *p2){
  10239. ComptBox head;
  10240. ComptBox *pTail = &head;
  10241. ComptBox *p;
  10242. while( p1 && p2 ){
  10243. if( p1->area<=p2->area ){
  10244. p = p1->pNext;
  10245. pTail->pNext = p1;
  10246. pTail = p1;
  10247. p1 = p;
  10248. }else{
  10249. p = p2->pNext;
  10250. pTail->pNext = p2;
  10251. pTail = p2;
  10252. p2 = p;
  10253. }
  10254. }
  10255. if( p1 ){
  10256. pTail->pNext = p1;
  10257. }else{
  10258. pTail->pNext = p2;
  10259. }
  10260. return head.pNext;
  10261. }
  10262.  
  10263. /*
  10264. ** Construct the ComptBox cache. For each compartment (where a compartment
  10265. ** is a closed circuit of Segments) make an entry on the Wallset.pComptBox
  10266. ** list.
  10267. **
  10268. ** If the ComptBox cache already exists, this routine is a no-op.
  10269. */
  10270. static void buildComptBoxCache(Wallset *p){
  10271. Link *pI;
  10272. int i;
  10273. ComptBox *aSort[30];
  10274.  
  10275. /* Return immediately if the cache already exists */
  10276. if( p->pComptBox ) return;
  10277.  
  10278. /* Compute a linked list of all compartment boxes */
  10279. for(pI=p->pAll; pI; pI=pI->pNext){
  10280. int i, j, n;
  10281. Boundary aBound[1000];
  10282.  
  10283. aBound[0].pSeg = pI->pLinkNode;
  10284. for(j=0; j<2; j++){
  10285. aBound[0].backwards = j;
  10286. n = completeBoundary(p, 1, sizeof(aBound)/sizeof(aBound[0]), aBound);
  10287. if( n>0 && spin(aBound,n)>0.0 ){
  10288. double dx, dy;
  10289. Segment *pSeg = pI->pLinkNode;
  10290. ComptBox *pNew = (ComptBox *)Odie_Alloc( sizeof(*pNew) );
  10291. pNew->pNext = p->pComptBox;
  10292. pNew->bbox[BBOX_X0_IDX] = pNew->bbox[BBOX_X1_IDX] = pSeg->from[X_IDX];
  10293. pNew->bbox[BBOX_Y1_IDX] = pNew->bbox[BBOX_Y0_IDX] = pSeg->from[Y_IDX];
  10294. pNew->prim = aBound[0];
  10295. for(i=1; i<n; i++){
  10296. Segment *pSeg = aBound[i].pSeg;
  10297. if( pSeg->from[X_IDX]<pNew->bbox[BBOX_X0_IDX] ) pNew->bbox[BBOX_X0_IDX] = pSeg->from[X_IDX];
  10298. if( pSeg->from[X_IDX]>pNew->bbox[BBOX_X1_IDX] ) pNew->bbox[BBOX_X1_IDX] = pSeg->from[X_IDX];
  10299. if( pSeg->from[Y_IDX]<pNew->bbox[BBOX_Y0_IDX] ) pNew->bbox[BBOX_Y0_IDX] = pSeg->from[Y_IDX];
  10300. if( pSeg->from[Y_IDX]>pNew->bbox[BBOX_Y1_IDX] ) pNew->bbox[BBOX_Y1_IDX] = pSeg->from[Y_IDX];
  10301. if( pSeg->to[X_IDX]<pNew->bbox[BBOX_X0_IDX] ) pNew->bbox[BBOX_X0_IDX] = pSeg->to[X_IDX];
  10302. if( pSeg->to[X_IDX]>pNew->bbox[BBOX_X1_IDX] ) pNew->bbox[BBOX_X1_IDX] = pSeg->to[X_IDX];
  10303. if( pSeg->to[Y_IDX]<pNew->bbox[BBOX_Y0_IDX] ) pNew->bbox[BBOX_Y0_IDX] = pSeg->to[Y_IDX];
  10304. if( pSeg->to[Y_IDX]>pNew->bbox[BBOX_Y1_IDX] ) pNew->bbox[BBOX_Y1_IDX] = pSeg->to[Y_IDX];
  10305. }
  10306. dx = pNew->bbox[BBOX_X1_IDX] - pNew->bbox[BBOX_X0_IDX];
  10307. dy = pNew->bbox[BBOX_Y1_IDX] - pNew->bbox[BBOX_Y0_IDX];
  10308. pNew->area = sqrt(dx*dx+dy*dy);
  10309. p->pComptBox = pNew;
  10310. }
  10311. }
  10312. }
  10313.  
  10314. /* Sort the list into order of increasing area */
  10315. for(i=0; i<sizeof(aSort)/sizeof(aSort[0]); i++) aSort[i] = 0;
  10316. while( p->pComptBox ){
  10317. ComptBox *pBox = p->pComptBox;
  10318. p->pComptBox = pBox->pNext;
  10319. pBox->pNext = 0;
  10320. for(i=0; i<sizeof(aSort)/sizeof(aSort[0])-1 && aSort[i]!=0; i++){
  10321. pBox = mergeComptBox(aSort[i], pBox);
  10322. aSort[i] = 0;
  10323. }
  10324. aSort[i] = mergeComptBox(aSort[i], pBox);
  10325. }
  10326. for(i=0; i<sizeof(aSort)/sizeof(aSort[0]); i++){
  10327. p->pComptBox = mergeComptBox(aSort[i], p->pComptBox);
  10328. }
  10329. }
  10330.  
  10331. /*
  10332. ** Test to see if the point x,y is contained within the given
  10333. ** boundary or is on the outside of the boundary.
  10334. */
  10335. static int pointWithinBoundary(
  10336. Boundary *aBound, /* The boundary */
  10337. int nBound, /* Number of segments in the boundary */
  10338. double x, double y /* The point to test */
  10339. ){
  10340. int inside = 0;
  10341. int i;
  10342. for(i=0; i<nBound; i++){
  10343. double x0, y0, x1, y1;
  10344. Segment *p = aBound[i].pSeg;
  10345. x0 = p->from[X_IDX];
  10346. y0 = p->from[Y_IDX];
  10347. x1 = p->to[X_IDX];
  10348. y1 = p->to[Y_IDX];
  10349. if( x0==x1 ) continue;
  10350. if( (x0>x && x1>x) || (x0<x && x1<x) ) continue;
  10351. if( y1 - (x1-x)*(y1-y0)/(x1-x0) >= y ) inside = !inside;
  10352. }
  10353. return inside;
  10354. }
  10355.  
  10356. /*
  10357. ** Find a boundary which contains xI, yI. If the size of the boundary
  10358. ** is set to 0, that means no such boundary exists.
  10359. */
  10360. static int findBoundary(
  10361. Wallset *p, /* The wallset */
  10362. double xI, double yI, /* A point that the boundary should be near */
  10363. int nBound, /* Number of slots available in aBound[] */
  10364. Boundary *aBound /* OUT: Write results here */
  10365. ){
  10366. int n = 0;
  10367. ComptBox *pBox;
  10368.  
  10369. buildComptBoxCache(p);
  10370. for(pBox=p->pComptBox; pBox; pBox=pBox->pNext){
  10371. 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;
  10372. aBound[0] = pBox->prim;
  10373. n = completeBoundary(p, 0, nBound, aBound);
  10374. if( n>0 && pointWithinBoundary(aBound, n, xI, yI) ) break;
  10375. n = 0;
  10376. }
  10377. return n;
  10378. }
  10379.  
  10380.  
  10381. /*
  10382. ** Do an check of the integrity of the internal data structures. If
  10383. ** a problem is found, leave an error message in interp->result and
  10384. ** return TCL_ERROR. Return TCL_OK if everything is OK.
  10385. */
  10386. static int selfCheck(Tcl_Interp *interp, Wallset *p){
  10387. Link *pLink;
  10388. Segment *pSeg;
  10389. int h;
  10390. char zErr[200];
  10391.  
  10392. for(pLink=p->pAll; pLink; pLink=pLink->pNext){
  10393. pSeg = pLink->pLinkNode;
  10394. h = hashInt(pSeg->id);
  10395. if(!segmentOnList(pSeg, p->hashId[h]) ){
  10396. sprintf(zErr, "segment %d missing from hashId[%d]", pSeg->id, h);
  10397. Tcl_SetResult(interp, zErr, TCL_VOLATILE);
  10398. return TCL_ERROR;
  10399. }
  10400. h = hashCoord(pSeg->from[X_IDX], pSeg->from[Y_IDX]);
  10401. if(!segmentOnList(pSeg, p->hashFrom[h]) ){
  10402. sprintf(zErr, "segment %d missing from hashFrom[%d]", pSeg->id, h);
  10403. Tcl_SetResult(interp, zErr, TCL_VOLATILE);
  10404. return TCL_ERROR;
  10405. }
  10406. h = hashCoord(pSeg->to[X_IDX], pSeg->to[Y_IDX]);
  10407. if(!segmentOnList(pSeg, p->hashTo[h]) ){
  10408. sprintf(zErr, "segment %d missing from hashTo[%d]", pSeg->id, h);
  10409. Tcl_SetResult(interp, zErr, TCL_VOLATILE);
  10410. return TCL_ERROR;
  10411. }
  10412. }
  10413. return TCL_OK;
  10414. }
  10415.  
  10416. /*
  10417. ** The maximum number of segments in a boundary
  10418. */
  10419. #define MX_BOUND 1000
  10420.  
  10421. /* Wallset_Delete */
  10422. static void Wallset_Delete(ClientData clientData){
  10423. Wallset *p = (Wallset *)clientData;
  10424. Link *pLink = p->pAll;
  10425. clearComptBoxCache(p);
  10426. while( pLink ){
  10427. Segment *pSeg = pLink->pLinkNode;
  10428. pLink = pSeg->pAll.pNext;
  10429. Tcl_Free((char *) pSeg );
  10430. }
  10431. Tcl_Free((char *) p );
  10432. }
  10433. /* Wallset_Clone */
  10434. static int Wallset_Clone(
  10435. Tcl_Interp* interp, /* Tcl interpreter for error reporting */
  10436. ClientData metadata, /* Metadata to be cloned */
  10437. ClientData* newMetaData /* Where to put the cloned metadata */
  10438. ){
  10439. Tcl_SetObjResult(interp,
  10440. Tcl_NewStringObj("WALLSETs are not clonable", -1));
  10441. /* For now... */
  10442. return TCL_ERROR;
  10443. }
  10444. /* *PolygonHullVertex_ById */
  10445. static PolygonHullVertex *PolygonHullVertex_ById(PolygonHull *pHull, int id){
  10446. PolygonHullVertex *pVertex;
  10447. pVertex = (PolygonHullVertex*)readiHashFind(&pHull->VertexHash, 0, id);
  10448. return pVertex;
  10449. }
  10450. /* *PolygonHullVertex_ByCoords */
  10451. static PolygonHullVertex *PolygonHullVertex_ByCoords(PolygonHull *pHull, VectorXYZ A){
  10452. int h;
  10453. Link *pLink;
  10454. HashElem *i;
  10455. PolygonHullVertex *pVertex;
  10456. h = hashCoord3d(A[X_IDX],A[Y_IDX],A[X_IDX]);
  10457. for(pLink = pHull->VertexHashCoords[h]; pLink; pLink=pLink->pNext){
  10458. pVertex=pLink->pLinkNode;
  10459. if(VectorXYZ_SamePoint(pVertex->center,A)) {
  10460. return pVertex;
  10461. }
  10462. }
  10463. /* The hash checks sometimes miss. Search all */
  10464. for(i=readiHashFirst(&pHull->VertexHash); i; i=readiHashNext(i)) {
  10465. PolygonHullVertex *pVertex=(PolygonHullVertex *)readiHashData(i);
  10466. if(VectorXYZ_SamePoint(pVertex->center,A)) {
  10467. return pVertex;
  10468. }
  10469. }
  10470. return NULL;
  10471. }
  10472. /* *PolygonHullVertex_Create */
  10473. static PolygonHullVertex *PolygonHullVertex_Create(
  10474. PolygonHull *pHull,
  10475. int id,
  10476. VectorXYZ point
  10477. ){
  10478. int hx;
  10479. PolygonHullVertex *pVertex;
  10480. pVertex = (PolygonHullVertex *)Odie_Alloc( sizeof(PolygonHullVertex) );
  10481. if( pVertex==NULL ) return NULL;
  10482. if(id<0) {
  10483. pHull->VertexNextId++;
  10484. id=pHull->VertexNextId;
  10485. } else if (id>=pHull->VertexNextId) {
  10486. pHull->VertexNextId=id;
  10487. }
  10488. pVertex->id=id;
  10489. LinkInit(pVertex->pHashVertexCoords, pVertex);
  10490. readiHashInsert(&pHull->VertexHash, 0, id, pVertex);
  10491.  
  10492. pVertex->center[X_IDX]=point[X_IDX];
  10493. pVertex->center[Y_IDX]=point[Y_IDX];
  10494. pVertex->center[Z_IDX]=point[Z_IDX];
  10495. hx=hashCoord3d(point[X_IDX],point[Y_IDX],point[Z_IDX]);
  10496. LinkInsert(&pHull->VertexHashCoords[hx], &pVertex->pHashVertexCoords);
  10497. return pVertex;
  10498. }
  10499. /* PolygonHullVertex_Remove */
  10500. static void PolygonHullVertex_Remove(PolygonHullVertex *pVertex){
  10501. Link *pLink;
  10502. for(pLink=pVertex->pHashFace;pLink;pLink=pLink->pNext) {
  10503. PolygonHullFace *pFace=pLink->pLinkNode;
  10504. if(pFace) {
  10505. PolygonHullFace_Remove(pFace);
  10506. }
  10507. }
  10508. LinkRemove(&pVertex->pHashVertexCoords);
  10509. }
  10510. /* *PolygonHullFace_VertexInject */
  10511. static const char *PolygonHullFace_VertexInject(PolygonHullFace *pFace,PolygonHullVertex *pThisVertex){
  10512. PolygonHullVertex *pVertex,*pPrior=NULL,*pFirst;
  10513. PolygonHullFace_SerializeEdges(pFace);
  10514. pFirst=pFace->pNextVertex;
  10515. for(pVertex=pFirst;pVertex;pVertex=pVertex->pNextVertex) {
  10516. if(VectorXYZ_SamePoint(pVertex->center,pThisVertex->center)) {
  10517. /* Vertex already exists in polygon noop */
  10518. return NULL;
  10519. }
  10520. pPrior=pVertex;
  10521. }
  10522. for(pVertex=pFirst;pVertex;pVertex=pVertex->pNextVertex) {
  10523. if(VectorXYZ_PointIsOnSegment(pThisVertex->center,pPrior->center,pVertex->center)) {
  10524. pThisVertex->pNextVertex=pVertex;
  10525. if(pVertex==pFirst) {
  10526. /* Head Insert */
  10527. pFace->pNextVertex=pThisVertex;
  10528. return NULL;
  10529. } else {
  10530. /* Mid segment insert */
  10531. pPrior->pNextVertex=pThisVertex;
  10532. return NULL;
  10533. }
  10534. }
  10535. pPrior=pVertex;
  10536. }
  10537. /* Oh brother... */
  10538. return "Could not break edge";
  10539. }
  10540. /* *PolygonHullFace_To_Dict */
  10541. Tcl_Obj *PolygonHullFace_To_Dict(PolygonHullFace *pFace){
  10542. Tcl_Obj *element=Tcl_NewObj();
  10543. {
  10544. Tcl_Obj *value;
  10545. value=Tcl_NewIntObj(pFace->id);
  10546. Odie_DictObjPut(NULL,element,"id:",value);
  10547. }
  10548. {
  10549. Tcl_Obj *value;
  10550. value=Tcl_NewIntObj(pFace->nVertex);
  10551. Odie_DictObjPut(NULL,element,"nVertex:",value);
  10552. }
  10553. {
  10554. Tcl_Obj *value;
  10555. value=Tcl_NewIntObj(pFace->wallid);
  10556. Odie_DictObjPut(NULL,element,"wallid:",value);
  10557. }
  10558. {
  10559. Tcl_Obj *value;
  10560. value=Tcl_NewIntObj(pFace->deckid);
  10561. Odie_DictObjPut(NULL,element,"deckid:",value);
  10562. }
  10563. {
  10564. Tcl_Obj *value;
  10565. value=Tcl_NewIntObj(pFace->typeid);
  10566. Odie_DictObjPut(NULL,element,"typeid:",value);
  10567. }
  10568. {
  10569. Tcl_Obj *value;
  10570. value=Tcl_NewBooleanObj(pFace->is_wall);
  10571. Odie_DictObjPut(NULL,element,"is_wall:",value);
  10572. }
  10573. {
  10574. Tcl_Obj *value;
  10575. value=Tcl_NewBooleanObj(pFace->is_exterior);
  10576. Odie_DictObjPut(NULL,element,"is_exterior:",value);
  10577. }
  10578. {
  10579. Tcl_Obj *value;
  10580. value=Tcl_NewIntObj(pFace->is_virtual);
  10581. Odie_DictObjPut(NULL,element,"is_virtual:",value);
  10582. }
  10583. {
  10584. Tcl_Obj *value;
  10585. value=Tcl_NewIntObj(pFace->idLC);
  10586. Odie_DictObjPut(NULL,element,"idLC:",value);
  10587. }
  10588. {
  10589. Tcl_Obj *value;
  10590. value=Tcl_NewIntObj(pFace->idRC);
  10591. Odie_DictObjPut(NULL,element,"idRC:",value);
  10592. }
  10593. {
  10594. Tcl_Obj *value;
  10595. value=VectorXYZ_To_TclObj(pFace->center);
  10596. Odie_DictObjPut(NULL,element,"center:",value);
  10597. }
  10598. {
  10599. Tcl_Obj *value;
  10600. value=VectorXYZ_To_TclObj(pFace->normal);
  10601. Odie_DictObjPut(NULL,element,"normal:",value);
  10602. }
  10603. {
  10604. Tcl_Obj *value;
  10605. value=Tcl_NewDoubleObj(pFace->radius);
  10606. Odie_DictObjPut(NULL,element,"radius:",value);
  10607. }
  10608. {
  10609. Tcl_Obj *value;
  10610.  
  10611. char outbuf[64];
  10612. int i;
  10613. value=Tcl_NewObj();
  10614. for(i=0;i<6;i++) {
  10615. sprintf(outbuf,"%.3f",(float)pFace->bbox[i]);
  10616. Tcl_ListObjAppendElement(NULL,value,Tcl_NewStringObj(outbuf,-1));
  10617. }
  10618.  
  10619. Odie_DictObjPut(NULL,element,"bbox:",value);
  10620. }
  10621. return element;}
  10622. /* *PolygonHullFace_Create */
  10623. static PolygonHullFace *PolygonHullFace_Create(
  10624. PolygonHull *pHull,
  10625. int id
  10626. ){
  10627. PolygonHullFace *pFace;
  10628. pFace = (PolygonHullFace *)Odie_Alloc( sizeof(PolygonHullFace) );
  10629. if( pFace==NULL ) return NULL;
  10630. if(id<0) {
  10631. pHull->FaceNextId++;
  10632. id=pHull->FaceNextId;
  10633. } else if (id>=pHull->FaceNextId) {
  10634. pHull->FaceNextId=id;
  10635. }
  10636. pFace->id=id;
  10637. readiHashInsert(&pHull->FaceHash, 0, id, pFace);
  10638.  
  10639. pFace->id = id;
  10640. pFace->pActive = pHull->pActive;
  10641. pHull->pActive = pFace;
  10642.  
  10643. LinkInit(pFace->pSet, pFace);
  10644. return pFace;
  10645. }
  10646. /* *PolygonHull_mergeFaceList */
  10647. static PolygonHullFace *PolygonHull_mergeFaceList(PolygonHullFace *a, PolygonHullFace *b){
  10648. PolygonHullFace head, *pTail;
  10649. pTail = &head;
  10650. while( a && b ){
  10651. if( a->dist <= b->dist ){
  10652. pTail->pNext = a;
  10653. pTail = a;
  10654. a = a->pNext;
  10655. }else{
  10656. pTail->pNext = b;
  10657. pTail = b;
  10658. b = b->pNext;
  10659. }
  10660. }
  10661. if( a ){
  10662. pTail->pNext = a;
  10663. }else if( b ){
  10664. pTail->pNext = b;
  10665. }else{
  10666. pTail->pNext = 0;
  10667. }
  10668. return head.pNext;
  10669. }
  10670. /* *PolygonHull_sortFaceList */
  10671. static PolygonHullFace *PolygonHull_sortFaceList(PolygonHullFace *pList){
  10672. int i;
  10673. PolygonHullFace *p;
  10674. PolygonHullFace *ap[NBUCKET];
  10675. for(i=0; i<NBUCKET; i++){ ap[i] = 0; }
  10676. while( pList ){
  10677. p = pList;
  10678. pList = p->pNext;
  10679. p->pNext = 0;
  10680. for(i=0; i<NBUCKET-1; i++){
  10681. if( ap[i] ){
  10682. p = PolygonHull_mergeFaceList(ap[i], p);
  10683. ap[i] = 0;
  10684. }else{
  10685. ap[i] = p;
  10686. break;
  10687. }
  10688. }
  10689. if( i==NBUCKET ){
  10690. ap[i] = PolygonHull_mergeFaceList(ap[i],p);
  10691. }
  10692. }
  10693. p = 0;
  10694. for(i=0; i<NBUCKET; i++){
  10695. p = PolygonHull_mergeFaceList(ap[i], p);
  10696. }
  10697. return p;
  10698. }
  10699. /* *PolygonHullFace_ById */
  10700. static PolygonHullFace *PolygonHullFace_ById(PolygonHull *pHull, int id){
  10701. PolygonHullFace *pFace;
  10702. pFace = (PolygonHullFace*)readiHashFind(&pHull->FaceHash, 0, id);
  10703. return pFace;
  10704. }
  10705. /* PolygonHull_findFace */
  10706. static int PolygonHull_findFace(
  10707. Tcl_Interp *interp, /* Leave any error message here */
  10708. PolygonHull *pHull,
  10709. Tcl_Obj *pObj, /* The PolygonHullFace ID */
  10710. PolygonHullFace **ppHullFace /* Write PolygonHullFace pointer here */
  10711. ){
  10712. int id;
  10713. if( Tcl_GetIntFromObj(interp, pObj, &id) ) return TCL_ERROR;
  10714. *ppHullFace = PolygonHullFace_ById(pHull,id);
  10715. if( *ppHullFace==0 ){
  10716. Tcl_AppendResult(interp, "no such PolygonHullFace", 0);
  10717. return TCL_ERROR;
  10718. }
  10719. PolygonHullFace_Compute(*ppHullFace);
  10720. return TCL_OK;
  10721. }
  10722. /* PolygonHullFace_Remove */
  10723. static void PolygonHullFace_Remove(PolygonHullFace *pFace){
  10724. int i;
  10725. if(!pFace) return;
  10726. LinkRemove(&pFace->pSet);
  10727.  
  10728. if(pFace->aVertex) {
  10729. for(i=0;i<pFace->nVertex;i++) {
  10730. if(pFace->aVertex[i]==0) continue;
  10731. LinkRemove(&pFace->pVertex[i]);
  10732. }
  10733. Odie_Free((char *)pFace->aVertex);
  10734. }
  10735. if(pFace->pVertex) {
  10736. Odie_Free((char *)pFace->pVertex);
  10737. }
  10738. }
  10739. /* PolygonHullFace_SerializeEdges */
  10740. static void PolygonHullFace_SerializeEdges(PolygonHullFace *p){
  10741. int i;
  10742. PolygonHullVertex *pPrior=NULL,*pVertex;
  10743. if(p->pNextVertex) {
  10744. return;
  10745. }
  10746. //printf("PolygonHullFace_SerializeEdges %d %p\n",p->id,p->aVertex);
  10747. for(i=0;i<p->nVertex;i++) {
  10748. pVertex=p->aVertex[i];
  10749. assert(pVertex);
  10750. LinkRemove(&p->pVertex[i]);
  10751. //printf("PolygonHullFace_SerializeEdges %d #%d %p %p\n",p->id,i,pPrior,pVertex);
  10752. pVertex->pNextVertex=NULL;
  10753. if(!pPrior) {
  10754. p->pNextVertex=pVertex;
  10755. } else {
  10756. pPrior->pNextVertex=pVertex;
  10757. }
  10758. pPrior=pVertex;
  10759. }
  10760. //printf("PolygonHullFace_SerializeEdges %d LAST %d %p\n",p->id,i,pPrior);
  10761. if(pPrior) {
  10762. pPrior->pNextVertex=NULL;
  10763. }
  10764. Odie_Free(p->aVertex);
  10765. Odie_Free(p->pVertex);
  10766. p->nVertex=0;
  10767. p->aVertex=NULL;
  10768. p->pVertex=NULL;
  10769.  
  10770. }
  10771. /* PolygonHullFace_Compute */
  10772. static void PolygonHullFace_Compute(PolygonHullFace *pFace){
  10773. VectorXYZ one,two;
  10774. int i;
  10775. double r1,rmax;
  10776. int nVertex;
  10777. PolygonHullVertex *pVertex,*pFirst;
  10778. //printf("PolygonHullFace_Compute %d %p %p\n",pFace->id,pFace,pFace->pNextVertex);
  10779. if(!pFace->pNextVertex) {
  10780. return;
  10781. }
  10782. VectorXYZ_AABB_Reset(pFace->bbox);
  10783. nVertex=0;
  10784. /* Count the number of vertices */
  10785. pFirst=pFace->pNextVertex;
  10786. for(pVertex=pFirst;pVertex;pVertex=pVertex->pNextVertex) {
  10787. nVertex++;
  10788. if(nVertex>32) break;
  10789. }
  10790. pFace->nVertex=nVertex;
  10791. /* Allocate the arrays to store the vertices */
  10792. pFace->aVertex=(PolygonHullVertex **)Odie_Alloc(sizeof(PolygonHullVertex *)*pFace->nVertex);
  10793. pFace->pVertex=(Link *)Odie_Alloc(sizeof(Link)*pFace->nVertex);
  10794. pVertex=pFirst;
  10795. for(i=0;i<nVertex;i++) {
  10796. VectorXYZ_AABB_Measure(pVertex->center,pFace->bbox);
  10797. pFace->pNextVertex=pVertex->pNextVertex;
  10798. pFace->aVertex[i]=pVertex;
  10799. LinkInit(pFace->pVertex[i],pFace);
  10800. LinkInsert(&pVertex->pHashFace, &pFace->pVertex[i]);
  10801. pVertex=pVertex->pNextVertex;
  10802. }
  10803. for(i=0;i<nVertex;i++) {
  10804. pVertex=pFace->aVertex[i];
  10805. pVertex->pNextVertex=NULL;
  10806. }
  10807. if(pFace->nVertex==3) {
  10808. VectorXYZ_Subtract(one, pFace->aVertex[1]->center, pFace->aVertex[0]->center);
  10809. VectorXYZ_Subtract(two, pFace->aVertex[2]->center, pFace->aVertex[0]->center);
  10810. pFace->normal[X_IDX] = one[Y_IDX]*two[Z_IDX] - one[Z_IDX]*two[Y_IDX];
  10811. pFace->normal[Y_IDX] = one[Z_IDX]*two[X_IDX] - one[X_IDX]*two[Z_IDX];
  10812. pFace->normal[Z_IDX] = one[X_IDX]*two[Y_IDX] - one[Y_IDX]*two[X_IDX];
  10813. } else {
  10814. int i,j;
  10815. VectorXYZ_Zero(pFace->normal);
  10816. for(i=0,j=1;i<pFace->nVertex;i++,j++) {
  10817. if(j==pFace->nVertex) j=0;
  10818. 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]);
  10819. 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]);
  10820. 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]);
  10821. }
  10822. }
  10823. VectorXYZ_Normalize(pFace->normal);
  10824. /* Compute the center and radius of the face. */
  10825. VectorXYZ_Zero(pFace->center);
  10826. for(i=0; i<pFace->nVertex; i++){
  10827. pFace->center[X_IDX] += pFace->aVertex[i]->center[X_IDX];
  10828. pFace->center[Y_IDX] += pFace->aVertex[i]->center[Y_IDX];
  10829. pFace->center[Z_IDX] += pFace->aVertex[i]->center[Z_IDX];
  10830. }
  10831. pFace->center[X_IDX] /= pFace->nVertex;
  10832. pFace->center[Y_IDX] /= pFace->nVertex;
  10833. pFace->center[Z_IDX] /= pFace->nVertex;
  10834. rmax=0.0;
  10835. for(i=0; i<pFace->nVertex; i++){
  10836. r1 = VectorXYZ_DistanceSq(pFace->center, pFace->aVertex[i]->center);
  10837. if(r1>rmax) {
  10838. rmax=r1;
  10839. }
  10840. }
  10841. pFace->radiusSq = rmax;
  10842. pFace->radius = sqrt(rmax);
  10843. }
  10844. /* PolygonHull_sqrDistPointToEdge */
  10845. static double PolygonHull_sqrDistPointToEdge(
  10846. VectorXYZ A, VectorXYZ B, /* End points of the line segment */
  10847. VectorXYZ X /* The point to measure distance to */
  10848. ){
  10849. VectorXYZ closest; /* Point on line segment closest to X */
  10850. VectorXYZ_ClosestPointOnSegment(A,B,X,closest);
  10851. return VectorXYZ_DistanceSq(X, closest);
  10852. }
  10853. /* PolygonHull_intersectLineSegFace */
  10854. static double PolygonHull_intersectLineSegFace(
  10855. PolygonHullFace *pFace, /* The triangle we are trying to intersect */
  10856. VectorXYZ pStart, /* Start of the line segment */
  10857. VectorXYZ pEnd, /* End of the line segment */
  10858. VectorXYZ pIntersect /* Point of intersection written here if not NULL */
  10859. ){
  10860. double d;
  10861. int i;
  10862. for(i=2;i<pFace->nVertex;i++) {
  10863. /*
  10864. ** Assuming we are fed convex polygons,
  10865. ** break the surface into triangles
  10866. ** and evaluate each triangle
  10867. */
  10868. d = VectorXYZ_TriangleLineIntersect(pFace->aVertex[0]->center,pFace->aVertex[i-1]->center,pFace->aVertex[i]->center,pStart,pEnd,pIntersect);
  10869. if(d>=0.0) {
  10870. return d;
  10871. }
  10872. }
  10873. return -1.0;
  10874. }
  10875. /* *PolygonHullFace_findHits */
  10876. static PolygonHullFace *PolygonHullFace_findHits(PolygonHull *pHull, VectorXYZ A, VectorXYZ B){
  10877. PolygonHullFace *p, *pList;
  10878. double d1, d2;
  10879. pList = 0;
  10880. for(p=pHull->pActive; p; p=p->pActive){
  10881. d1 = PolygonHull_sqrDistPointToEdge(A, B, p->center);
  10882. d2 = p->radiusSq;
  10883. if( d2<d1 ){
  10884. continue;
  10885. }
  10886. d1 = PolygonHull_intersectLineSegFace(p, A, B,p->intersect);
  10887. if( d1>=0.0 ){
  10888. p->pNext = pList;
  10889. pList = p;
  10890. p->dist = d1;
  10891. }
  10892. }
  10893. return PolygonHull_sortFaceList(pList);
  10894. }
  10895. /* PolygonHull_closestPointOnFace */
  10896. static double PolygonHull_closestPointOnFace(PolygonHullFace *p, VectorXYZ X, VectorXYZ R){
  10897. double d1, d2, distBest=1e99;
  10898. VectorXYZ testPt;
  10899. VectorXYZ a, b; /* End points of line seg parallel to p->normal */
  10900. int i,j;
  10901.  
  10902. /* Construct a line segment a->b that is parallel to p->normal and which
  10903. ** passes through X. Make sure the line segment is plenty long
  10904. ** enough so that it will intersect the plane of p.
  10905. */
  10906. d1 = VectorXYZ_Distance(X, p->center)*2;
  10907. d2 = p->normal[X_IDX]*d1;
  10908. a[X_IDX] = X[X_IDX] + d2;
  10909. b[X_IDX] = X[X_IDX] - d2;
  10910. d2 = p->normal[Y_IDX]*d1;
  10911. a[Y_IDX] = X[Y_IDX] + d2;
  10912. b[Y_IDX] = X[Y_IDX] - d2;
  10913. d2 = p->normal[Z_IDX]*d1;
  10914. a[Z_IDX] = X[Z_IDX] + d2;
  10915. b[Z_IDX] = X[Z_IDX] - d2;
  10916.  
  10917. /* Figure out if a->b intersects the triangle, and if so where. If
  10918. ** there is an intersection, then this is the closest point.
  10919. */
  10920. if( PolygonHull_intersectLineSegFace(p, a, b, R)>=0.0 ){
  10921. return VectorXYZ_Distance(X,R);
  10922. }
  10923.  
  10924. /*
  10925. ** If we reach here it means that the closest point will be on the
  10926. ** permiter of the triangle. There are three line faces on the
  10927. ** permiter. Try them all.
  10928. */
  10929. for(i=0,j=1;i<p->nVertex;i++,j++) {
  10930. if(j==p->nVertex) j=0;
  10931. VectorXYZ_ClosestPointOnSegment(p->aVertex[i]->center, p->aVertex[j]->center, X, testPt);
  10932. d1 = VectorXYZ_Distance(X, testPt);
  10933. if(i==0 || d1<distBest) {
  10934. distBest = d1;
  10935. R[X_IDX]=testPt[X_IDX];
  10936. R[Y_IDX]=testPt[Y_IDX];
  10937. R[Z_IDX]=testPt[Z_IDX];
  10938. }
  10939. }
  10940. return distBest;
  10941. }
  10942. /* *PolygonHullFace_findClosest */
  10943. static PolygonHullFace *PolygonHullFace_findClosest(PolygonHull *pHull,VectorXYZ X, VectorXYZ R, double *pDist){
  10944. double d1;
  10945. double distBest=1e99;
  10946. PolygonHullFace *pBest=NULL;
  10947. VectorXYZ testPt;
  10948. PolygonHullFace *p;
  10949. HashElem *i;
  10950. /* First pass: Locate the triangle whose center is closest to X.
  10951. ** This will be our first guess of what the closest triangle is.
  10952. ** And because it is probably pretty close to the best, it will make
  10953. ** it easy to eliminate other triangles from contention.
  10954. */
  10955. for(i=readiHashFirst(&pHull->FaceHash); i; i=readiHashNext(i)) {
  10956. p = readiHashData(i);
  10957. d1 = VectorXYZ_DistanceSq(p->center, X);
  10958. if( pBest==0 || d1<distBest ){
  10959. pBest = p;
  10960. distBest = d1;
  10961. }
  10962. }
  10963. if( pBest==0 ){
  10964. return 0;
  10965. }
  10966.  
  10967. /* Compute the exact distance from X to our first guess at the closest
  10968. ** triangle.
  10969. */
  10970. d1=PolygonHull_closestPointOnFace(pBest, X, R);
  10971. distBest = d1*d1;
  10972.  
  10973. /* Do a second pass over the data to see if we can find another
  10974. ** triangle that is closer than pBest. We only need to check
  10975. ** triangle whose center is not further away from X than distBest
  10976. ** plus the triangle radius.
  10977. */
  10978. for(i=readiHashFirst(&pHull->FaceHash); i; i=readiHashNext(i)) {
  10979. p = readiHashData(i);
  10980. if( p==pBest ){
  10981. continue;
  10982. }
  10983. d1 = VectorXYZ_DistanceSq(p->center, X);
  10984. if( d1 - p->radiusSq > distBest ){
  10985. continue;
  10986. }
  10987. d1 = PolygonHull_closestPointOnFace(p, X, testPt);
  10988. if( (d1*d1)<distBest ){
  10989. pBest = p;
  10990. distBest = d1*d1;
  10991. R[X_IDX] = testPt[X_IDX];
  10992. R[Y_IDX] = testPt[Y_IDX];
  10993. R[Z_IDX] = testPt[Z_IDX];
  10994. }
  10995. }
  10996. *pDist = sqrt(distBest);
  10997. return pBest;
  10998. }
  10999. /* *PolygonHullVolume_ById */
  11000. static PolygonHullVolume *PolygonHullVolume_ById(PolygonHull *pHull, int id){
  11001. PolygonHullVolume *pVolume;
  11002. pVolume = readiHashFind(&pHull->VolumeHash, 0, id);
  11003. return pVolume;
  11004. }
  11005. /* *PolygonHullVolume_Create */
  11006. static PolygonHullVolume *PolygonHullVolume_Create(
  11007. PolygonHull *pHull,
  11008. int id
  11009. ){
  11010. PolygonHullVolume *pVolume;
  11011. pVolume = (PolygonHullVolume *)Odie_Alloc( sizeof(PolygonHullVolume) );
  11012. if( pVolume==NULL ) return NULL;
  11013. if(id<0) {
  11014. pHull->VolumeNextId++;
  11015. id=pHull->VolumeNextId;
  11016. } else if (id>=pHull->VolumeNextId) {
  11017. pHull->VolumeNextId=id;
  11018. }
  11019. pVolume->id=id;
  11020. readiHashInsert(&pHull->VolumeHash, 0, id, pVolume);
  11021. return pVolume;
  11022. }
  11023. /* PolygonHullVolume_Unlink */
  11024. static void PolygonHullVolume_Unlink(PolygonHullVolume *pVolume){
  11025. }
  11026. /* PolygonHull_clearSurfaces */
  11027. static void PolygonHull_clearSurfaces(PolygonHull *pHull){
  11028. }
  11029. /* PolygonHull_Reset */
  11030. static void PolygonHull_Reset(PolygonHull *pHull){
  11031. PolygonHull_clearSurfaces(pHull);
  11032. pHull->FaceNextId=0;
  11033. pHull->VertexNextId=0;
  11034. pHull->VolumeNextId=0;
  11035. HashElem *i;
  11036. for(i=readiHashFirst(&pHull->VolumeHash); i; i=readiHashNext(i)) {
  11037. char *ptr=(char *)readiHashData(i);
  11038. Odie_Free((char *)ptr);
  11039. }
  11040. readiHashClear(&pHull->VolumeHash);
  11041. for(i=readiHashFirst(&pHull->FaceHash); i; i=readiHashNext(i)) {
  11042. char *ptr=(char *)readiHashData(i);
  11043. Odie_Free((char *)ptr);
  11044. }
  11045. readiHashClear(&pHull->FaceHash);
  11046. for(i=readiHashFirst(&pHull->VertexHash); i; i=readiHashNext(i)) {
  11047. char *ptr=(char *)readiHashData(i);
  11048. Odie_Free((char *)ptr);
  11049. }
  11050. readiHashClear(&pHull->VertexHash);
  11051. }
  11052. /* PolygonHull_Delete */
  11053. static void PolygonHull_Delete(ClientData clientData){
  11054. PolygonHull *pHull = (PolygonHull *)clientData;
  11055. PolygonHull_Reset(pHull);
  11056. Odie_Free((char *) pHull);
  11057. }
  11058. /* PolygonHull_Clone */
  11059. static int PolygonHull_Clone(
  11060. Tcl_Interp* interp, /* Tcl interpreter for error reporting */
  11061. ClientData metadata, /* Metadata to be cloned */
  11062. ClientData* newMetaData /* Where to put the cloned metadata */
  11063. ){
  11064. Tcl_SetObjResult(interp,
  11065. Tcl_NewStringObj("POLYGONHULLs are not clonable", -1));
  11066. /* For now... */
  11067. return TCL_ERROR;
  11068. }
  11069. /* *Odie_Obj_To_Int */
  11070. Tcl_Obj *Odie_Obj_To_Int(Tcl_Obj *tclObj){
  11071. int sint;
  11072. double s;
  11073. if (Tcl_GetIntFromObj(NULL,tclObj,&sint)==TCL_OK) {
  11074. return tclObj;
  11075. }
  11076. if (Tcl_GetDoubleFromObj(NULL,tclObj,&s)) {
  11077. return tclObj;
  11078. }
  11079. return Tcl_NewIntObj((int)round(s));
  11080. }
  11081. /* Odie_trace_printf */
  11082. void Odie_trace_printf(Tcl_Interp *interp,const char *zFormat, ...){
  11083. /*
  11084. ** Print a trace message
  11085. */
  11086. int n;
  11087. va_list ap;
  11088. char zBuf[4000];
  11089.  
  11090. va_start(ap, zFormat);
  11091. strcpy(zBuf, "puts -nonewline \x7b");
  11092. n = strlen(zBuf);
  11093. vsnprintf(&zBuf[n], sizeof(zBuf)-5-n, zFormat, ap);
  11094. strcat(zBuf, "\x7d\n");
  11095. Tcl_Eval(interp, zBuf);
  11096. }
  11097. /*
  11098. *----------------------------------------------------------------------
  11099. *
  11100. * MergeLists -
  11101. *
  11102. * This procedure combines two sorted lists of SortElement structures
  11103. * into a single sorted list.
  11104. *
  11105. * Results:
  11106. * The unified list of SortElement structures.
  11107. *
  11108. * Side effects:
  11109. * If infoPtr->unique is set then infoPtr->numElements may be updated.
  11110. * Possibly others, if a user-defined comparison command does something
  11111. * weird.
  11112. *
  11113. * Note:
  11114. * If infoPtr->unique is set, the merge assumes that there are no
  11115. * "repeated" elements in each of the left and right lists. In that case,
  11116. * if any element of the left list is equivalent to one in the right list
  11117. * it is omitted from the merged list.
  11118. * This simplified mechanism works because of the special way
  11119. * our MergeSort creates the sublists to be merged and will fail to
  11120. * eliminate all repeats in the general case where they are already
  11121. * present in either the left or right list. A general code would need to
  11122. * skip adjacent initial repeats in the left and right lists before
  11123. * comparing their initial elements, at each step.
  11124. *----------------------------------------------------------------------
  11125. */
  11126.  
  11127. static SortElement *
  11128. MergeLists(
  11129. SortElement *leftPtr, /* First list to be merged; may be NULL. */
  11130. SortElement *rightPtr, /* Second list to be merged; may be NULL. */
  11131. SortInfo *infoPtr) /* Information needed by the comparison
  11132. * operator. */
  11133. {
  11134. SortElement *headPtr, *tailPtr;
  11135. int cmp;
  11136.  
  11137. if (leftPtr == NULL) {
  11138. return rightPtr;
  11139. }
  11140. if (rightPtr == NULL) {
  11141. return leftPtr;
  11142. }
  11143. cmp = SortCompare(leftPtr, rightPtr, infoPtr);
  11144. if (cmp > 0 || (cmp == 0 && infoPtr->unique)) {
  11145. if (cmp == 0) {
  11146. infoPtr->numElements--;
  11147. leftPtr = leftPtr->nextPtr;
  11148. }
  11149. tailPtr = rightPtr;
  11150. rightPtr = rightPtr->nextPtr;
  11151. } else {
  11152. tailPtr = leftPtr;
  11153. leftPtr = leftPtr->nextPtr;
  11154. }
  11155. headPtr = tailPtr;
  11156. if (!infoPtr->unique) {
  11157. while ((leftPtr != NULL) && (rightPtr != NULL)) {
  11158. cmp = SortCompare(leftPtr, rightPtr, infoPtr);
  11159. if (cmp > 0) {
  11160. tailPtr->nextPtr = rightPtr;
  11161. tailPtr = rightPtr;
  11162. rightPtr = rightPtr->nextPtr;
  11163. } else {
  11164. tailPtr->nextPtr = leftPtr;
  11165. tailPtr = leftPtr;
  11166. leftPtr = leftPtr->nextPtr;
  11167. }
  11168. }
  11169. } else {
  11170. while ((leftPtr != NULL) && (rightPtr != NULL)) {
  11171. cmp = SortCompare(leftPtr, rightPtr, infoPtr);
  11172. if (cmp >= 0) {
  11173. if (cmp == 0) {
  11174. infoPtr->numElements--;
  11175. leftPtr = leftPtr->nextPtr;
  11176. }
  11177. tailPtr->nextPtr = rightPtr;
  11178. tailPtr = rightPtr;
  11179. rightPtr = rightPtr->nextPtr;
  11180. } else {
  11181. tailPtr->nextPtr = leftPtr;
  11182. tailPtr = leftPtr;
  11183. leftPtr = leftPtr->nextPtr;
  11184. }
  11185. }
  11186. }
  11187. if (leftPtr != NULL) {
  11188. tailPtr->nextPtr = leftPtr;
  11189. } else {
  11190. tailPtr->nextPtr = rightPtr;
  11191. }
  11192. return headPtr;
  11193. }
  11194.  
  11195. /*
  11196. *----------------------------------------------------------------------
  11197. *
  11198. * SortCompare --
  11199. *
  11200. * This procedure is invoked by MergeLists to determine the proper
  11201. * ordering between two elements.
  11202. *
  11203. * Results:
  11204. * A negative results means the the first element comes before the
  11205. * second, and a positive results means that the second element should
  11206. * come first. A result of zero means the two elements are equal and it
  11207. * doesn't matter which comes first.
  11208. *
  11209. * Side effects:
  11210. * None, unless a user-defined comparison command does something weird.
  11211. *
  11212. *----------------------------------------------------------------------
  11213. */
  11214.  
  11215. static int
  11216. SortCompare(
  11217. SortElement *elemPtr1, SortElement *elemPtr2,
  11218. /* Values to be compared. */
  11219. SortInfo *infoPtr) /* Information passed from the top-level
  11220. * "lsort" command. */
  11221. {
  11222. int order = 0;
  11223.  
  11224. if (infoPtr->sortMode == SORTMODE_ASCII) {
  11225. order = strcmp(elemPtr1->index.strValuePtr,
  11226. elemPtr2->index.strValuePtr);
  11227. } else if (infoPtr->sortMode == SORTMODE_ASCII_NC) {
  11228. order = strcasecmp(elemPtr1->index.strValuePtr,
  11229. elemPtr2->index.strValuePtr);
  11230. } else if (infoPtr->sortMode == SORTMODE_DICTIONARY) {
  11231. order = DictionaryCompare(elemPtr1->index.strValuePtr,
  11232. elemPtr2->index.strValuePtr);
  11233. } else if (infoPtr->sortMode == SORTMODE_INTEGER) {
  11234. long a, b;
  11235.  
  11236. a = elemPtr1->index.intValue;
  11237. b = elemPtr2->index.intValue;
  11238. order = ((a >= b) - (a <= b));
  11239. } else if (infoPtr->sortMode == SORTMODE_REAL) {
  11240. double a, b;
  11241.  
  11242. a = elemPtr1->index.doubleValue;
  11243. b = elemPtr2->index.doubleValue;
  11244. order = ((a >= b) - (a <= b));
  11245. } else {
  11246. Tcl_Obj **objv, *paramObjv[2];
  11247. int objc;
  11248. Tcl_Obj *objPtr1, *objPtr2;
  11249.  
  11250. if (infoPtr->resultCode != TCL_OK) {
  11251. /*
  11252. * Once an error has occurred, skip any future comparisons so as
  11253. * to preserve the error message in sortInterp->result.
  11254. */
  11255.  
  11256. return 0;
  11257. }
  11258.  
  11259.  
  11260. objPtr1 = elemPtr1->index.objValuePtr;
  11261. objPtr2 = elemPtr2->index.objValuePtr;
  11262.  
  11263. paramObjv[0] = objPtr1;
  11264. paramObjv[1] = objPtr2;
  11265.  
  11266. /*
  11267. * We made space in the command list for the two things to compare.
  11268. * Replace them and evaluate the result.
  11269. */
  11270.  
  11271. Tcl_ListObjLength(infoPtr->interp, infoPtr->compareCmdPtr, &objc);
  11272. Tcl_ListObjReplace(infoPtr->interp, infoPtr->compareCmdPtr, objc - 2,
  11273. 2, 2, paramObjv);
  11274. Tcl_ListObjGetElements(infoPtr->interp, infoPtr->compareCmdPtr,
  11275. &objc, &objv);
  11276.  
  11277. infoPtr->resultCode = Tcl_EvalObjv(infoPtr->interp, objc, objv, 0);
  11278.  
  11279. if (infoPtr->resultCode != TCL_OK) {
  11280. Tcl_AddErrorInfo(infoPtr->interp,
  11281. "\n (-compare command)");
  11282. return 0;
  11283. }
  11284.  
  11285. /*
  11286. * Parse the result of the command.
  11287. */
  11288.  
  11289. if (Tcl_GetIntFromObj(infoPtr->interp,
  11290. Tcl_GetObjResult(infoPtr->interp), &order) != TCL_OK) {
  11291. Tcl_ResetResult(infoPtr->interp);
  11292. Tcl_AppendResult(infoPtr->interp,
  11293. "-compare command returned non-integer result", NULL);
  11294. infoPtr->resultCode = TCL_ERROR;
  11295. return 0;
  11296. }
  11297. }
  11298. if (!infoPtr->isIncreasing) {
  11299. order = -order;
  11300. }
  11301. return order;
  11302. }
  11303.  
  11304. /*
  11305. *----------------------------------------------------------------------
  11306. *
  11307. * DictionaryCompare
  11308. *
  11309. * This function compares two strings as if they were being used in an
  11310. * index or card catalog. The case of alphabetic characters is ignored,
  11311. * except to break ties. Thus "B" comes before "b" but after "a". Also,
  11312. * integers embedded in the strings compare in numerical order. In other
  11313. * words, "x10y" comes after "x9y", not * before it as it would when
  11314. * using strcmp().
  11315. *
  11316. * Results:
  11317. * A negative result means that the first element comes before the
  11318. * second, and a positive result means that the second element should
  11319. * come first. A result of zero means the two elements are equal and it
  11320. * doesn't matter which comes first.
  11321. *
  11322. * Side effects:
  11323. * None.
  11324. *
  11325. *----------------------------------------------------------------------
  11326. */
  11327.  
  11328. static int
  11329. DictionaryCompare(
  11330. char *left, char *right) /* The strings to compare. */
  11331. {
  11332. Tcl_UniChar uniLeft, uniRight, uniLeftLower, uniRightLower;
  11333. int diff, zeros;
  11334. int secondaryDiff = 0;
  11335.  
  11336. while (1) {
  11337. if (isdigit(UCHAR(*right)) /* INTL: digit */
  11338. && isdigit(UCHAR(*left))) { /* INTL: digit */
  11339. /*
  11340. * There are decimal numbers embedded in the two strings. Compare
  11341. * them as numbers, rather than strings. If one number has more
  11342. * leading zeros than the other, the number with more leading
  11343. * zeros sorts later, but only as a secondary choice.
  11344. */
  11345.  
  11346. zeros = 0;
  11347. while ((*right == '0') && (isdigit(UCHAR(right[1])))) {
  11348. right++;
  11349. zeros--;
  11350. }
  11351. while ((*left == '0') && (isdigit(UCHAR(left[1])))) {
  11352. left++;
  11353. zeros++;
  11354. }
  11355. if (secondaryDiff == 0) {
  11356. secondaryDiff = zeros;
  11357. }
  11358.  
  11359. /*
  11360. * The code below compares the numbers in the two strings without
  11361. * ever converting them to integers. It does this by first
  11362. * comparing the lengths of the numbers and then comparing the
  11363. * digit values.
  11364. */
  11365.  
  11366. diff = 0;
  11367. while (1) {
  11368. if (diff == 0) {
  11369. diff = UCHAR(*left) - UCHAR(*right);
  11370. }
  11371. right++;
  11372. left++;
  11373. if (!isdigit(UCHAR(*right))) { /* INTL: digit */
  11374. if (isdigit(UCHAR(*left))) { /* INTL: digit */
  11375. return 1;
  11376. } else {
  11377. /*
  11378. * The two numbers have the same length. See if their
  11379. * values are different.
  11380. */
  11381.  
  11382. if (diff != 0) {
  11383. return diff;
  11384. }
  11385. break;
  11386. }
  11387. } else if (!isdigit(UCHAR(*left))) { /* INTL: digit */
  11388. return -1;
  11389. }
  11390. }
  11391. continue;
  11392. }
  11393.  
  11394. /*
  11395. * Convert character to Unicode for comparison purposes. If either
  11396. * string is at the terminating null, do a byte-wise comparison and
  11397. * bail out immediately.
  11398. */
  11399.  
  11400. if ((*left != '\0') && (*right != '\0')) {
  11401. left += Tcl_UtfToUniChar(left, &uniLeft);
  11402. right += Tcl_UtfToUniChar(right, &uniRight);
  11403.  
  11404. /*
  11405. * Convert both chars to lower for the comparison, because
  11406. * dictionary sorts are case insensitve. Covert to lower, not
  11407. * upper, so chars between Z and a will sort before A (where most
  11408. * other interesting punctuations occur).
  11409. */
  11410.  
  11411. uniLeftLower = Tcl_UniCharToLower(uniLeft);
  11412. uniRightLower = Tcl_UniCharToLower(uniRight);
  11413. } else {
  11414. diff = UCHAR(*left) - UCHAR(*right);
  11415. break;
  11416. }
  11417.  
  11418. diff = uniLeftLower - uniRightLower;
  11419. if (diff) {
  11420. return diff;
  11421. }
  11422. if (secondaryDiff == 0) {
  11423. if (Tcl_UniCharIsUpper(uniLeft) && Tcl_UniCharIsLower(uniRight)) {
  11424. secondaryDiff = -1;
  11425. } else if (Tcl_UniCharIsUpper(uniRight)
  11426. && Tcl_UniCharIsLower(uniLeft)) {
  11427. secondaryDiff = 1;
  11428. }
  11429. }
  11430. }
  11431. if (diff == 0) {
  11432. diff = secondaryDiff;
  11433. }
  11434. return diff;
  11435. }
  11436.  
  11437.  
  11438. static int Odie_SortElement_FromObj(
  11439. Tcl_Interp *interp,
  11440. int sortMode,
  11441. Tcl_Obj *valuePtr,
  11442. SortElement *elementPtr
  11443. ) {
  11444. /*
  11445. * Determine the "value" of this object for sorting purposes
  11446. */
  11447. if (sortMode == SORTMODE_ASCII) {
  11448. elementPtr->index.strValuePtr = Tcl_GetString(valuePtr);
  11449. } else if (sortMode == SORTMODE_INTEGER) {
  11450. long a;
  11451.  
  11452. if (Tcl_GetLongFromObj(interp, valuePtr, &a) != TCL_OK) {
  11453. return TCL_ERROR;
  11454. }
  11455. elementPtr->index.intValue = a;
  11456. } else if (sortMode == SORTMODE_REAL) {
  11457. double a;
  11458.  
  11459. if (Tcl_GetDoubleFromObj(interp, valuePtr, &a) != TCL_OK) {
  11460. return TCL_ERROR;
  11461. }
  11462. elementPtr->index.doubleValue = a;
  11463. } else {
  11464. elementPtr->index.objValuePtr = valuePtr;
  11465. }
  11466. elementPtr->objPtr = valuePtr;
  11467. return TCL_OK;
  11468. }
  11469. /* *Odie_MergeList_ToObj */
  11470. static Tcl_Obj *Odie_MergeList_ToObj(SortElement *elementPtr){
  11471. /*
  11472. ** Converts a linked list of structures into
  11473. ** a Tcl list object
  11474. */
  11475. SortElement *loopPtr;
  11476. Tcl_Obj **newArray;
  11477. int i,len=0;
  11478. loopPtr=elementPtr;
  11479. for (len=0; loopPtr != NULL ; loopPtr = loopPtr->nextPtr) {
  11480. len++;
  11481. }
  11482. newArray = (Tcl_Obj **)Odie_Alloc(sizeof(Tcl_Obj *)*len);
  11483. loopPtr=elementPtr;
  11484. for (i=0; loopPtr != NULL ; loopPtr = loopPtr->nextPtr) {
  11485. Tcl_Obj *objPtr = loopPtr->objPtr;
  11486. newArray[i] = objPtr;
  11487. i++;
  11488. //Tcl_IncrRefCount(objPtr);
  11489. }
  11490. return Tcl_NewListObj(len,newArray);
  11491. }
  11492. /* Odie_Lsearch */
  11493. STUB_EXPORT int Odie_Lsearch(int listLength,Tcl_Obj **listObjPtrs,Tcl_Obj *element){
  11494. int i;
  11495. Tcl_Obj *o;
  11496. if(element==NULL) {
  11497. return -1;
  11498. }
  11499.  
  11500. int matchLen;
  11501. char *match=Tcl_GetStringFromObj(element,&matchLen);
  11502.  
  11503. int s2len,found;
  11504. const char *s2;
  11505.  
  11506. if(matchLen < 0) {
  11507. return -1;
  11508. }
  11509.  
  11510. found = 0;
  11511. for(i=0;i<listLength && !found;i++) {
  11512. o=listObjPtrs[i];
  11513. if (o != NULL) {
  11514. s2 = Tcl_GetStringFromObj(o, &s2len);
  11515. } else {
  11516. s2 = "";
  11517. }
  11518. if (matchLen == s2len) {
  11519. found = (strcmp(match, s2) == 0);
  11520. if(found) {
  11521. return i;
  11522. }
  11523. }
  11524. }
  11525. return -1;
  11526. }
  11527. /* *Logicset_To_TclObj */
  11528. STUB_EXPORT Tcl_Obj *Logicset_To_TclObj(Tcl_Obj *set){
  11529. if(set) {
  11530. return Tcl_DuplicateObj(set);
  11531. } else {
  11532. return Tcl_NewObj();
  11533. }
  11534. }
  11535. /* Logicset_LIST_RESET */
  11536. STUB_EXPORT void Logicset_LIST_RESET(Tcl_Obj **set){
  11537. if(*set) {
  11538. Tcl_DecrRefCount(*set);
  11539. }
  11540. *set=Tcl_NewObj();
  11541. }
  11542. /* Logicset_LIST_CONTAINS */
  11543. STUB_EXPORT int Logicset_LIST_CONTAINS(Tcl_Obj **aPtrs,int aLength,Tcl_Obj *element){
  11544. if(element==NULL) return 0;
  11545. if(aLength<1) return 0;
  11546.  
  11547. int matchIdx=Odie_Lsearch(aLength,aPtrs,element);
  11548. if(matchIdx>=0) {
  11549. return 1;
  11550. }
  11551. return 0;
  11552. }
  11553. /* Logicset_Sanitize_List */
  11554. STUB_EXPORT void Logicset_Sanitize_List(char *value,int len){
  11555. int i,skipped=0;
  11556. for(i=0;i<len;i++) {
  11557. unsigned char x=value[i];
  11558. skipped++;
  11559. /* Anything outside this range in non-printable, whitespace, or a delimeter */
  11560. if(x<0x30 || x>0x80 || x==0x7D || x==0x7B) {
  11561. value[i]=0x20;
  11562. continue;
  11563. }
  11564. skipped--;
  11565. }
  11566. }
  11567. /* *Logicset_FromObj */
  11568. STUB_EXPORT Tcl_Obj *Logicset_FromObj(Tcl_Obj *rawlist){
  11569. if(!rawlist) {
  11570. return NULL;
  11571. }
  11572. int len;
  11573. char *rawvalue=Tcl_GetStringFromObj(rawlist,&len);
  11574. if(len==0) {
  11575. return NULL;
  11576. }
  11577. Logicset_Sanitize_List(rawvalue,len);
  11578. Tcl_Obj *tempString=Tcl_NewStringObj(rawvalue,len);
  11579.  
  11580. int listLength,i;
  11581. Tcl_Obj **listObjPtrs;
  11582. if(Tcl_ListObjGetElements(NULL, tempString, &listLength, &listObjPtrs)) {
  11583. Tcl_DecrRefCount(tempString);
  11584. return NULL;
  11585. }
  11586. if(listLength <= 0) {
  11587. Tcl_DecrRefCount(tempString);
  11588. return NULL;
  11589. }
  11590. Tcl_Obj *listObj=Tcl_NewObj();
  11591. for(i=0;i<listLength;i++) {
  11592. Logicset_Add(listObj,listObjPtrs[i]);
  11593. }
  11594. Tcl_DecrRefCount(tempString);
  11595. return listObj;
  11596. }
  11597. /* Logicset_Add */
  11598. STUB_EXPORT int Logicset_Add(Tcl_Obj *aset,Tcl_Obj *element){
  11599. int listLength;
  11600. int i;
  11601. Tcl_Obj **listObjPtrs;
  11602.  
  11603. if(element==NULL) {
  11604. return TCL_OK;
  11605. }
  11606. int matchLen;
  11607. char *match=Tcl_GetStringFromObj(element,&matchLen);
  11608.  
  11609. int s2len;
  11610. const char *s2;
  11611.  
  11612. if(matchLen < 0) {
  11613. return TCL_ERROR;
  11614. }
  11615. if(Tcl_ListObjGetElements(NULL, aset, &listLength, &listObjPtrs)) {
  11616. return TCL_ERROR;
  11617. }
  11618. /* Check that item isn't in list already */
  11619. int found = 0;
  11620. for(i=0;i<listLength && !found;i++) {
  11621. Tcl_Obj *o=listObjPtrs[i];
  11622. if (o != NULL) {
  11623. s2 = Tcl_GetStringFromObj(o, &s2len);
  11624. } else {
  11625. s2 = "";
  11626. }
  11627. if (matchLen == s2len) {
  11628. found = (strcmp(match, s2) == 0);
  11629. if(found) {
  11630. return TCL_OK;
  11631. }
  11632. }
  11633. }
  11634. for(i=0;i<listLength;i++) {
  11635. int cmp = 0;
  11636. Tcl_Obj *o=listObjPtrs[i];
  11637. if (o != NULL) {
  11638. s2 = Tcl_GetStringFromObj(o, &s2len);
  11639. } else {
  11640. s2 = "";
  11641. }
  11642. cmp = strcmp(match, s2);
  11643. if(cmp==0) {
  11644. return TCL_OK;
  11645. } else if (cmp<0) {
  11646. Tcl_Obj *NewVals[1];
  11647. NewVals[0]=element;
  11648. /* Add the new element here */
  11649. return Tcl_ListObjReplace(NULL,aset,i,0,1,NewVals);
  11650. }
  11651. }
  11652. Tcl_ListObjAppendElement(NULL,aset,element);
  11653. return TCL_OK;
  11654. }
  11655. /* Logicset_Include */
  11656. STUB_EXPORT void Logicset_Include(Tcl_Obj *aset,Tcl_Obj *bset){
  11657. /*
  11658. ** Add all elements of A and B together into a new set
  11659. */
  11660. if(!aset || !bset) {
  11661. return;
  11662. }
  11663. int bLength;
  11664. Tcl_Obj **bPtrs;
  11665. if(Tcl_ListObjGetElements(0, bset, &bLength, &bPtrs)) {
  11666. return;
  11667. }
  11668. if(bLength==0) {
  11669. return;
  11670. }
  11671. if(bLength>1) {
  11672. int i;
  11673. for(i=0;i<bLength;i++) {
  11674. Logicset_Include(aset,bPtrs[i]);
  11675. }
  11676. } else {
  11677. if(Logicset_Add(aset,bPtrs[0])) {
  11678. return;
  11679. }
  11680. }
  11681. return;
  11682. }
  11683. /* Logicset_EXPR_AND */
  11684. STUB_EXPORT int Logicset_EXPR_AND(Tcl_Obj *aset,Tcl_Obj *bset){
  11685. /*
  11686. ** Returns 1 if all elements in B are contained in A
  11687. */
  11688. int aLength;
  11689. Tcl_Obj **aPtrs;
  11690. if(!aset || !bset) return 0;
  11691. if(Tcl_ListObjGetElements(0, aset, &aLength, &aPtrs)) {
  11692. return 0;
  11693. }
  11694. int bLength;
  11695. Tcl_Obj **bPtrs;
  11696. if(Tcl_ListObjGetElements(0, bset, &bLength, &bPtrs)) {
  11697. return 0;
  11698. }
  11699. int i;
  11700. for(i=0;i<bLength;i++) {
  11701. int found=Logicset_LIST_CONTAINS(aPtrs,aLength,bPtrs[i]);
  11702. if(!found) {
  11703. return 0;
  11704. }
  11705. }
  11706. return 1;
  11707. }
  11708. /* Logicset_EXPR_OR */
  11709. STUB_EXPORT int Logicset_EXPR_OR(Tcl_Obj *aset,Tcl_Obj *bset){
  11710. int aLength;
  11711. Tcl_Obj **aPtrs;
  11712. if(!aset || !bset) return 0;
  11713. if(Tcl_ListObjGetElements(0, aset, &aLength, &aPtrs)) {
  11714. return 0;
  11715. }
  11716. int bLength;
  11717. Tcl_Obj **bPtrs;
  11718. if(Tcl_ListObjGetElements(0, bset, &bLength, &bPtrs)) {
  11719. return 0;
  11720. }
  11721. int i;
  11722. for(i=0;i<bLength;i++) {
  11723. int found=Logicset_LIST_CONTAINS(aPtrs,aLength,bPtrs[i]);
  11724. if(found) {
  11725. return 1;
  11726. }
  11727. }
  11728. return 0;
  11729. }
  11730. /* *Logicset_PRODUCT_INTERSECT */
  11731. STUB_EXPORT Tcl_Obj *Logicset_PRODUCT_INTERSECT(Tcl_Obj *aset,Tcl_Obj *bset){
  11732. int aLength;
  11733. Tcl_Obj **aPtrs;
  11734. if(!aset) {
  11735. return bset;
  11736. }
  11737. if(!bset) {
  11738. return aset;
  11739. }
  11740. if(Tcl_ListObjGetElements(0, aset, &aLength, &aPtrs)) return bset;
  11741. int bLength;
  11742. Tcl_Obj **bPtrs;
  11743. if(Tcl_ListObjGetElements(0, bset, &bLength, &bPtrs)) return aset;
  11744. int i,resultlen=0;
  11745. Tcl_Obj *result=Tcl_NewObj();
  11746. for(i=0;i<bLength;i++) {
  11747. int found=Logicset_LIST_CONTAINS(aPtrs,aLength,bPtrs[i]);
  11748. if(found) {
  11749. resultlen++;
  11750. Logicset_Add(result,bPtrs[i]);
  11751. }
  11752. }
  11753. if(!resultlen) {
  11754. Tcl_DecrRefCount(result);
  11755. return NULL;
  11756. }
  11757. return result;
  11758. }
  11759. /* *Logicset_PRODUCT_UNION */
  11760. STUB_EXPORT Tcl_Obj *Logicset_PRODUCT_UNION(Tcl_Obj *aset,Tcl_Obj *bset){
  11761. if(!aset) {
  11762. return bset;
  11763. }
  11764. if(!bset) {
  11765. return aset;
  11766. }
  11767. Tcl_Obj *listObj=Tcl_NewObj();
  11768. Logicset_Include(listObj,aset);
  11769. Logicset_Include(listObj,bset);
  11770. return listObj;
  11771. }
  11772. /* *Logicset_PRODUCT_XOR */
  11773. STUB_EXPORT Tcl_Obj *Logicset_PRODUCT_XOR(Tcl_Obj *aset,Tcl_Obj *bset){
  11774. int aLength;
  11775. Tcl_Obj **aPtrs;
  11776. if(!aset) {
  11777. return bset;
  11778. }
  11779. if(!bset) {
  11780. return aset;
  11781. }
  11782. if(Tcl_ListObjGetElements(0, aset, &aLength, &aPtrs)) return bset;
  11783. int bLength;
  11784. Tcl_Obj **bPtrs;
  11785. if(Tcl_ListObjGetElements(0, bset, &bLength, &bPtrs)) return aset;
  11786. int i,resultlen=0;
  11787. Tcl_Obj *result=Tcl_NewObj();
  11788. for(i=0;i<bLength;i++) {
  11789. int found=Logicset_LIST_CONTAINS(aPtrs,aLength,bPtrs[i]);
  11790. if(!found) {
  11791. resultlen++;
  11792. Logicset_Add(result,bPtrs[i]);
  11793. }
  11794. }
  11795. for(i=0;i<aLength;i++) {
  11796. int found=Logicset_LIST_CONTAINS(bPtrs,bLength,aPtrs[i]);
  11797. if(!found) {
  11798. resultlen++;
  11799. Logicset_Add(result,aPtrs[i]);
  11800. }
  11801. }
  11802. if(!resultlen) {
  11803. Tcl_DecrRefCount(result);
  11804. return NULL;
  11805. }
  11806. Tcl_Obj *resultPtr=Odie_ListObj_Sort(result);
  11807. if(resultPtr!=result) {
  11808. Tcl_DecrRefCount(result);
  11809. }
  11810. return resultPtr;
  11811. }
  11812. /* *Logicset_PRODUCT_MISSING */
  11813. STUB_EXPORT Tcl_Obj *Logicset_PRODUCT_MISSING(Tcl_Obj *aset,Tcl_Obj *bset){
  11814. int aLength;
  11815. Tcl_Obj **aPtrs;
  11816. if(!aset) {
  11817. return NULL;
  11818. }
  11819. if(!bset) {
  11820. return aset;
  11821. }
  11822. if(Tcl_ListObjGetElements(0, aset, &aLength, &aPtrs)) return bset;
  11823. int bLength;
  11824. Tcl_Obj **bPtrs;
  11825. if(Tcl_ListObjGetElements(0, bset, &bLength, &bPtrs)) return aset;
  11826. int i,resultlen=0;
  11827. Tcl_Obj *result=Tcl_NewObj();
  11828. for(i=0;i<aLength;i++) {
  11829. int found=Logicset_LIST_CONTAINS(bPtrs,bLength,aPtrs[i]);
  11830. if(!found) {
  11831. resultlen++;
  11832. Logicset_Add(result,aPtrs[i]);
  11833. }
  11834. }
  11835. if(!resultlen) {
  11836. Tcl_DecrRefCount(result);
  11837. return NULL;
  11838. }
  11839. return result;
  11840. }
  11841. /* *Odie_ListObj_Sort */
  11842. STUB_EXPORT Tcl_Obj *Odie_ListObj_Sort(Tcl_Obj *listObj){
  11843. Tcl_Obj *resultPtr=NULL;
  11844. int i, j, length, sortMode;
  11845. int idx;
  11846. Tcl_Obj **listObjPtrs, *indexPtr;
  11847. SortElement *elementArray, *elementPtr;
  11848. SortInfo sortInfo;
  11849.  
  11850. sortInfo.isIncreasing = 1;
  11851. sortInfo.sortMode = SORTMODE_DICTIONARY;
  11852. sortInfo.indexv = NULL;
  11853. sortInfo.unique = 1;
  11854. sortInfo.interp = NULL;
  11855. sortInfo.resultCode = TCL_OK;
  11856.  
  11857. /*
  11858. * The subList array below holds pointers to temporary lists built during
  11859. * the merge sort. Element i of the array holds a list of length 2**i.
  11860. */
  11861. # define NUM_LISTS 30
  11862. SortElement *subList[NUM_LISTS+1];
  11863.  
  11864.  
  11865. sortInfo.resultCode = Tcl_ListObjGetElements(sortInfo.interp, listObj,
  11866. &length, &listObjPtrs);
  11867.  
  11868. if(length<2) {
  11869. /*
  11870. ** If the list is zero length, just return
  11871. ** the original pointer
  11872. */
  11873. return listObj;
  11874. }
  11875.  
  11876. if (sortInfo.resultCode != TCL_OK || length <= 0) {
  11877. goto done;
  11878. }
  11879.  
  11880. sortInfo.numElements = length;
  11881.  
  11882. sortMode = sortInfo.sortMode;
  11883. if ((sortMode == SORTMODE_ASCII_NC)
  11884. || (sortMode == SORTMODE_DICTIONARY)) {
  11885. /*
  11886. * For this function's purpose all string-based modes are equivalent
  11887. */
  11888. sortMode = SORTMODE_ASCII;
  11889. }
  11890.  
  11891. /*
  11892. * Initialize the sublists. After the following loop, subList[i] will
  11893. * contain a sorted sublist of length 2**i. Use one extra subList at the
  11894. * end, always at NULL, to indicate the end of the lists.
  11895. */
  11896.  
  11897. for (j=0 ; j<=NUM_LISTS ; j++) {
  11898. subList[j] = NULL;
  11899. }
  11900.  
  11901. /*
  11902. * The following loop creates a SortElement for each list element and
  11903. * begins sorting it into the sublists as it appears.
  11904. */
  11905.  
  11906. elementArray = (SortElement *) Odie_Alloc( length * sizeof(SortElement));
  11907.  
  11908. for (i=0; i < length; i++){
  11909. idx = i;
  11910. indexPtr = listObjPtrs[idx];
  11911. sortInfo.resultCode=Odie_SortElement_FromObj(sortInfo.interp,sortMode,indexPtr,&elementArray[i]);
  11912. if(sortInfo.resultCode!=TCL_OK) {
  11913. goto done1;
  11914. }
  11915. }
  11916.  
  11917. for (i=0; i < length; i++){
  11918. /*
  11919. * Merge this element in the pre-existing sublists (and merge together
  11920. * sublists when we have two of the same size).
  11921. */
  11922.  
  11923. elementArray[i].nextPtr = NULL;
  11924. elementPtr = &elementArray[i];
  11925. for (j=0 ; subList[j] ; j++) {
  11926. elementPtr = MergeLists(subList[j], elementPtr, &sortInfo);
  11927. subList[j] = NULL;
  11928. }
  11929. if (j >= NUM_LISTS) {
  11930. j = NUM_LISTS-1;
  11931. }
  11932. subList[j] = elementPtr;
  11933. }
  11934.  
  11935. /*
  11936. * Merge all sublists
  11937. */
  11938.  
  11939. elementPtr = subList[0];
  11940. for (j=1 ; j<NUM_LISTS ; j++) {
  11941. elementPtr = MergeLists(subList[j], elementPtr, &sortInfo);
  11942. }
  11943.  
  11944. /*
  11945. * Now store the sorted elements in the result list.
  11946. */
  11947.  
  11948. if (sortInfo.resultCode == TCL_OK) {
  11949. resultPtr=Odie_MergeList_ToObj(elementPtr);
  11950.  
  11951. }
  11952.  
  11953. done1:
  11954. Odie_Free((char *) elementArray);
  11955.  
  11956. done:
  11957. if (sortInfo.sortMode == SORTMODE_COMMAND) {
  11958. Tcl_DecrRefCount(sortInfo.compareCmdPtr);
  11959. Tcl_DecrRefCount(listObj);
  11960. sortInfo.compareCmdPtr = NULL;
  11961. }
  11962. if (sortInfo.resultCode != TCL_OK) {
  11963. return NULL;
  11964. }
  11965. return resultPtr;
  11966. }
  11967. /* Odie_Trace */
  11968. int Odie_Trace(int newvalue){
  11969. OdieTrace=newvalue;
  11970. return OdieTrace;
  11971. }
  11972. /* *Odie_LiteralConstantObj */
  11973. Tcl_Obj *Odie_LiteralConstantObj(int which){
  11974. if(which > ODIE_STATIC_MAX || which < 0) {
  11975. Tcl_IncrRefCount(OdieStatic[ODIE_STATIC_NULL]);
  11976. return OdieStatic[ODIE_STATIC_NULL];
  11977. }
  11978. Tcl_IncrRefCount(OdieStatic[which]);
  11979. return OdieStatic[which];
  11980. }
  11981. /* *Odie_StoreObj */
  11982. Tcl_Obj *Odie_StoreObj(Tcl_Obj *value){
  11983. Tcl_Obj *storedVal;
  11984. double floatVal;
  11985. int intVal,strLen;
  11986. char *stringVal,*strtmp;
  11987. if(!value) {
  11988. storedVal=OdieStatic[ODIE_STATIC_NULL];
  11989. Tcl_IncrRefCount(storedVal);
  11990. nOdieDictSpecNull++;
  11991. return storedVal;
  11992. }
  11993. /* If this value is already shared, just store it and bump the refcount */
  11994. if(Tcl_IsShared(value)) {
  11995. Tcl_IncrRefCount(value);
  11996. nOdieDictSpecRecycled++;
  11997. return value;
  11998. }
  11999. /* Try to map this string to an existing literal */
  12000. stringVal=Tcl_GetString(value);
  12001. storedVal=Odie_constant(stringVal,0);
  12002. if(storedVal) {
  12003. Tcl_IncrRefCount(storedVal);
  12004. nOdieDictSpecShared++;
  12005. return storedVal;
  12006. }
  12007. /* Avoid storing a list or other volitile data */
  12008. strtmp=strchr(stringVal,' ');
  12009. if(!strtmp) {
  12010. strtmp=strchr(stringVal,'/');
  12011. if(!strtmp) {
  12012. storedVal=Odie_constant(stringVal,1);
  12013. Tcl_IncrRefCount(storedVal);
  12014. return storedVal;
  12015. }
  12016. }
  12017. Tcl_IncrRefCount(value);
  12018. return value;
  12019. }
  12020. /* *Odie_constant */
  12021. static Tcl_Obj *Odie_constant(const char *zName,int create){
  12022. int len,isNew=0;
  12023. Tcl_HashEntry *pEntry;
  12024. Tcl_Obj *p;
  12025. if(zName==NULL) {
  12026. return NULL;
  12027. }
  12028. if(create) {
  12029. pEntry=Tcl_CreateHashEntry(&OdieLiteralStringTable,zName,&isNew);
  12030. } else {
  12031. pEntry=Tcl_FindHashEntry(&OdieLiteralStringTable,zName);
  12032. }
  12033. if(isNew) {
  12034. nOdieObjString++;
  12035. len = strlen(zName);
  12036. p=Tcl_NewStringObj(zName,len);
  12037. Tcl_IncrRefCount(p);
  12038. Tcl_SetHashValue(pEntry,(ClientData)p);
  12039. return p;
  12040. }
  12041. if(pEntry) {
  12042. p=(Tcl_Obj*)Tcl_GetHashValue(pEntry);
  12043. return p;
  12044. }
  12045. return NULL;
  12046. }
  12047. /* Odie_SameString */
  12048. int Odie_SameString(char *aPtr,char *bPtr){
  12049. if(aPtr==bPtr) {
  12050. return 1;
  12051. }
  12052. if(!bPtr || !aPtr) {
  12053. return 0;
  12054. }
  12055. if(strcmp(aPtr,bPtr)==0) {
  12056. return 1;
  12057. }
  12058. return 0;
  12059. }
  12060. /* *Odie_LiteralString */
  12061. char *Odie_LiteralString(const char *zName){
  12062. Tcl_Obj *p;
  12063. p=Odie_constant(zName,1);
  12064. return Tcl_GetString(p);
  12065. }
  12066. /* *Odie_LiteralStringObj */
  12067. Tcl_Obj *Odie_LiteralStringObj(const char *zName){
  12068. Tcl_Obj *p;
  12069. p=Odie_constant(zName,1);
  12070. Tcl_IncrRefCount(p);
  12071. return p;
  12072. }
  12073. /* Odie_DictObjPut */
  12074. inline extern int Odie_DictObjPut(Tcl_Interp *interp,Tcl_Obj *pDictObj,const char *pField,Tcl_Obj *pValue){
  12075. int result=TCL_OK;
  12076. if(!pValue) {
  12077. return TCL_OK;
  12078. }
  12079. result=Tcl_DictObjPut(interp,pDictObj,Odie_LiteralStringObj(pField),pValue);
  12080. return result;
  12081. }
  12082. /* *Odie_HashGet */
  12083. Tcl_Obj *Odie_HashGet(Tcl_HashTable *localDict,char *fieldStr){
  12084. Tcl_Obj *valuePtr;
  12085. Tcl_HashEntry *i;
  12086. if(!localDict) {
  12087. return NULL;
  12088. }
  12089. i=Tcl_FindHashEntry(localDict,fieldStr);
  12090. if(!i) {
  12091. return NULL;
  12092. }
  12093. valuePtr=(Tcl_Obj*)Tcl_GetHashValue(i);
  12094. if(!valuePtr) {
  12095. return NULL;
  12096. }
  12097. nOdieDictSpecAccessed++;
  12098. Tcl_IncrRefCount(valuePtr);
  12099. return valuePtr;
  12100. }
  12101. /* Odie_HashPut */
  12102. void Odie_HashPut(Tcl_HashTable **infoDictPtr,const char *key,Tcl_Obj *value){
  12103. Tcl_HashTable *result=*infoDictPtr;
  12104. Tcl_HashEntry *pEntry;
  12105. Tcl_Obj *valuePtr;
  12106. int isNew=0;
  12107. int delete=0,len=0;
  12108. char *valueStr;
  12109. if(value==NULL) {
  12110. delete=1;
  12111. }
  12112. valueStr=Tcl_GetString(value);
  12113. len=strlen(valueStr);
  12114. if(len==0) {
  12115. delete=1;
  12116. }
  12117.  
  12118. if(!result && delete) {
  12119. return;
  12120. }
  12121. if(!result) {
  12122. result=(Tcl_HashTable*)Odie_Alloc( sizeof(Tcl_HashTable) );
  12123. Tcl_InitHashTable(result,TCL_STRING_KEYS);
  12124. nOdieHashTable++;
  12125. nOdieHashTableCreated++;
  12126. *infoDictPtr=result;
  12127. }
  12128. if(delete) {
  12129. /* If we were given a null or an empty string, delete */
  12130. pEntry=Tcl_FindHashEntry(result,key);
  12131. if(!pEntry) return;
  12132. nOdieDictSpecDeleted++;
  12133. nOdieDictSpecCount--;
  12134. valuePtr=(Tcl_Obj*)Tcl_GetHashValue(pEntry);
  12135. Tcl_DecrRefCount(valuePtr);
  12136. Tcl_DeleteHashEntry(pEntry);
  12137. return;
  12138. }
  12139. pEntry=Tcl_CreateHashEntry(result,Odie_LiteralString(key),&isNew);
  12140. if(!isNew) {
  12141. valuePtr=(Tcl_Obj*)Tcl_GetHashValue(pEntry);
  12142. nOdieDictSpecModified++;
  12143. Tcl_DecrRefCount(valuePtr);
  12144. } else {
  12145. nOdieDictSpecCreated++;
  12146. nOdieDictSpecCount++;
  12147. }
  12148. valuePtr=Odie_StoreObj(value);
  12149. Tcl_SetHashValue(pEntry,valuePtr);
  12150. return;
  12151. }
  12152. /* Odie_HashFree */
  12153. void Odie_HashFree(Tcl_HashTable **infoDictPtr){
  12154. if(*infoDictPtr) {
  12155. Tcl_HashSearch searchPtr;
  12156. Tcl_HashEntry *i;
  12157. Tcl_HashTable *ptr=*infoDictPtr;
  12158. for(i=Tcl_FirstHashEntry(ptr,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
  12159. Tcl_Obj *valuePtr=(Tcl_Obj *)Tcl_GetHashValue(i);
  12160. Tcl_DecrRefCount(valuePtr);
  12161. nOdieDictSpecCount--;
  12162. nOdieDictSpecDeleted++;
  12163. }
  12164. nOdieHashTableDeleted++;
  12165. nOdieHashTable--;
  12166. Tcl_DeleteHashTable(ptr);
  12167. Tcl_Free((char*)ptr);
  12168. }
  12169. *infoDictPtr=NULL;
  12170. }
  12171. /* Odie_constant_inject */
  12172. static void Odie_constant_inject(Tcl_Obj *value){
  12173. int len,isNew=0;
  12174. char *zName=Tcl_GetString(value);
  12175. Tcl_HashEntry *pEntry;
  12176. pEntry=Tcl_CreateHashEntry(&OdieLiteralStringTable,zName,&isNew);
  12177. if(isNew) {
  12178. nOdieObjString++;
  12179. Tcl_IncrRefCount(value);
  12180. Tcl_SetHashValue(pEntry,(ClientData)value);
  12181. }
  12182. }
  12183. /* Odie_RoidFromString */
  12184. Roid Odie_RoidFromString(char *idstring,short charcode){
  12185. char prefix[32];
  12186. int id;
  12187. int result;
  12188.  
  12189. if(!idstring) {
  12190. return -1;
  12191. }
  12192. result=sscanf(idstring,"%d",&id);
  12193. if(result>0) {
  12194. return id;
  12195. }
  12196. result=sscanf(idstring,"%c%d",prefix,&id);
  12197. if(result>0) {
  12198. return id;
  12199. }
  12200. return -1;
  12201. }
  12202. /* *Irm_NewLocationObj */
  12203. Tcl_Obj *Irm_NewLocationObj(Irm_Location *loc){
  12204. Tcl_Obj *pResult = Tcl_NewObj();
  12205. Tcl_ListObjAppendElement(NULL, pResult, Odie_LiteralIntObj(loc->deckid));
  12206. Tcl_ListObjAppendElement(NULL, pResult, Tcl_NewIntObj(loc->x));
  12207. Tcl_ListObjAppendElement(NULL, pResult, Tcl_NewIntObj(loc->y));
  12208. return pResult;
  12209. }
  12210. /* Location_FromName */
  12211. int Location_FromName(char *stringVal,int *did,double *x,double *y,double *z){
  12212. /*
  12213. ** Obtain location from name
  12214. */
  12215. #ifdef build_IRM
  12216. int deckid=0;
  12217. char type=0;
  12218. int roid;
  12219. int found=0;
  12220. int result=sscanf(stringVal,"%c%d-%d",&type,&roid,&deckid);
  12221. #endif
  12222. Irm_Location temp;
  12223. temp.deckid=0;
  12224. temp.x=0;
  12225. temp.y=0;
  12226. #ifdef build_IRM
  12227. if(result==2 || result==3) {
  12228. switch(type) {
  12229. case 'c': {
  12230. if(CrewRoute_ComptCenter(roid,deckid,&temp)) {
  12231. if(deckid) {
  12232. temp.deckid=deckid;
  12233. } else {
  12234. temp.deckid=1;
  12235. }
  12236. temp.x=0;
  12237. temp.y=0;
  12238. }
  12239. found=1;
  12240. break;
  12241. }
  12242. case 'e': {
  12243. SimNode *pDest=SimNode_ById(roid,0);
  12244. if(pDest) {
  12245. SimNode_StructLocation(&temp,pDest);
  12246. found=1;
  12247. }
  12248. break;
  12249. }
  12250. case 'p': {
  12251. Portal *pDest=Portal_ById(roid,0);
  12252. if(pDest) {
  12253. Portal_StructLocation(&temp,pDest);
  12254. found=1;
  12255. }
  12256. break;
  12257. }
  12258. case 'v': {
  12259. Crew *pDest=Crew_ById(roid,0);
  12260. if(pDest) {
  12261. Crew_StructLocation(&temp,pDest);
  12262. found=1;
  12263. }
  12264. break;
  12265. }
  12266. }
  12267. }
  12268. if (!found) {
  12269. Entity *pDest=Entity_ByName(stringVal,0);
  12270. if(!pDest) {
  12271. return TCL_ERROR;
  12272. }
  12273. Entity_StructLocation(&temp,pDest);
  12274. }
  12275. #else
  12276. Entity *pDest=Entity_ByName(stringVal,0);
  12277. if(!pDest) {
  12278. return TCL_ERROR;
  12279. }
  12280. Entity_StructLocation(&temp,pDest);
  12281. #endif
  12282. *did=temp.deckid;
  12283. *x=temp.x;
  12284. *y=temp.y;
  12285. *z=temp.zoff;
  12286. return TCL_OK;
  12287. }
  12288. /* Location_FromTclObj */
  12289. int Location_FromTclObj(Tcl_Interp *interp, Tcl_Obj *pList,int *did,double *x,double *y){
  12290. int listlen;
  12291. Tcl_Obj **elist;
  12292. double z;
  12293. if(Tcl_ListObjGetElements(interp,pList,&listlen,&elist)) {
  12294. return TCL_ERROR;
  12295. }
  12296. if(listlen == 1) {
  12297. /*
  12298. ** Obtain location from name
  12299. */
  12300. char *stringVal=Tcl_GetString(pList);
  12301. if (Location_FromName(stringVal,did,x,y,&z)) {
  12302. Tcl_AppendResult(interp, "Unknown entity ", stringVal, 0);
  12303. return TCL_ERROR;
  12304. }
  12305. return TCL_OK;
  12306. }
  12307. if(listlen < 3 || listlen > 4) {
  12308. Tcl_AppendResult(interp, "Could not interpret location ", Tcl_GetString(pList), 0);
  12309. return TCL_ERROR;
  12310. }
  12311. if( Tcl_GetIntFromObj(interp, elist[0], did) ) return TCL_ERROR;
  12312. if( Tcl_GetDoubleFromObj(interp, elist[1], x) ) return TCL_ERROR;
  12313. if( Tcl_GetDoubleFromObj(interp, elist[2], y) ) return TCL_ERROR;
  12314. return TCL_OK;
  12315. }
  12316. /* Location_Base_FromTclObj */
  12317. int Location_Base_FromTclObj(Tcl_Interp *interp, Tcl_Obj *pList,int *did,double *x,double *y,double *z){
  12318. int listlen;
  12319. Tcl_Obj **elist;
  12320.  
  12321. if(Tcl_ListObjGetElements(interp,pList,&listlen,&elist)) {
  12322. return TCL_ERROR;
  12323. }
  12324. if(listlen == 1) {
  12325. /*
  12326. ** Obtain location from name
  12327. */
  12328. char *stringVal=Tcl_GetString(pList);
  12329. if (Location_FromName(stringVal,did,x,y,z)) {
  12330. Tcl_AppendResult(interp, "Unknown entity ", stringVal, 0);
  12331. return TCL_ERROR;
  12332. }
  12333. return TCL_OK;
  12334. }
  12335. if(listlen < 3 || listlen > 4) {
  12336. Tcl_AppendResult(interp, "Could not interpret location ", Tcl_GetString(pList), 0);
  12337. return TCL_ERROR;
  12338. }
  12339. if( Tcl_GetIntFromObj(interp, elist[0], did) ) return TCL_ERROR;
  12340. if( Tcl_GetDoubleFromObj(interp, elist[1], x) ) return TCL_ERROR;
  12341. if( Tcl_GetDoubleFromObj(interp, elist[2], y) ) return TCL_ERROR;
  12342. *z=0.0;
  12343. if(listlen==4) {
  12344. if( Tcl_GetDoubleFromObj(interp, elist[3], z) ) return TCL_ERROR;
  12345. }
  12346. return TCL_OK;
  12347. }
  12348. /* location_match */
  12349. int location_match(Irm_Location *a,Irm_Location *b,int tolerance){
  12350. /*
  12351. ** Returns a 0 if the two points are "close enough"
  12352. */
  12353. int d;
  12354. if(a==b) {
  12355. return 1;
  12356. }
  12357. if(a->deckid!=b->deckid) {
  12358. return 0;
  12359. }
  12360. d=a->x - b->x;
  12361. if(d<-tolerance||d>tolerance) {
  12362. return 0;
  12363. }
  12364. d=a->y - b->y;
  12365. if(d<-tolerance||d>tolerance) {
  12366. return 0;
  12367. }
  12368. return 1;
  12369. }
  12370. /* irm_gridhash_decompose */
  12371. void irm_gridhash_decompose(Tcl_WideInt gridhash,int *style,int *rdeckid,int *rgx,int *rgy){
  12372. Tcl_WideInt mask;
  12373. int gy,gx,deckid;
  12374. int isHex=0;
  12375.  
  12376. /* Unpack the coordinates */
  12377. mask=gridhash;
  12378. gx=mask & 0xFFFF;
  12379. if(gx & 0x8000) {
  12380. /* Restore negative */
  12381. gx-=0xffff;
  12382. gx--;
  12383. }
  12384.  
  12385. mask>>=16;
  12386. gy=mask & 0xFFF;
  12387. if(gy & 0x800) {
  12388. /* Restore negative */
  12389. gy-=0xfff;
  12390. gy--;
  12391. }
  12392.  
  12393. mask>>=12;
  12394. deckid=mask & 0x3F;
  12395.  
  12396. mask>>=6;
  12397. isHex=mask;
  12398.  
  12399. *style=isHex;
  12400. *rdeckid=deckid;
  12401. *rgx=gx;
  12402. *rgy=gy;
  12403. }
  12404. /* irm_gridhash_compose */
  12405. Tcl_WideInt irm_gridhash_compose (int style,int deckid,int gx,int gy){
  12406. Tcl_WideInt result;
  12407. result=(style&1);
  12408. result<<=6;
  12409. /* Encode the coordinate packed into a 32 bit integer */
  12410. result|=(0x3F & deckid);
  12411. result<<=12;
  12412. result|=(0xFFF & gy);
  12413. result<<=16;
  12414. result|=(0xFFFF & gx);
  12415. return result;
  12416. }
  12417. /* irm_squaregrid_hash */
  12418. Tcl_WideInt irm_squaregrid_hash(int grid,int deckid,int x,int y){
  12419. int gx,gy;
  12420. gy=(int)round(y/grid);
  12421. gx=(int)round(x/grid);
  12422.  
  12423. return irm_gridhash_compose(0,deckid,gx,gy);
  12424. }
  12425. /* irm_hexgrid_hash */
  12426. Tcl_WideInt irm_hexgrid_hash(int grid,int deckid,int x,int y){
  12427. int gx,gy;
  12428.  
  12429. gy=(int)round(y/grid);
  12430. if(abs(gy)%2==1){
  12431. gx=(int)round((x-grid/2)/grid);
  12432. } else {
  12433. gx=(int)round(x/grid);
  12434. }
  12435. return irm_gridhash_compose(1,deckid,gx,gy);
  12436. }
  12437. /* irm_gridhash_location */
  12438. void irm_gridhash_location(Irm_Location *lPtr,Tcl_WideInt gridhash,int gridsize){
  12439. int gy,gx,deckid;
  12440. int isHex=0;
  12441. irm_gridhash_decompose(gridhash,&isHex,&deckid,&gx,&gy);
  12442.  
  12443. lPtr->deckid=deckid;
  12444. lPtr->y=gy*gridsize;
  12445. if(isHex) {
  12446. if(abs(gy)%2==1) {
  12447. lPtr->x=gx*gridsize+(gridsize/2);
  12448. } else {
  12449. lPtr->x=gx*gridsize;
  12450. }
  12451. } else {
  12452. lPtr->x=gx*gridsize;
  12453. }
  12454. }
  12455. /* Simulator_Init */
  12456. void Simulator_Init(Simulator *p){}
  12457. /* Simulator_Reset */
  12458. void Simulator_Reset(Simulator *p){}
  12459. /* Structure Entity */
  12460.  
  12461. const struct OdieParamNameMap Entity_paramNameMap[] = {
  12462. { "active", CSTRUCT_ENTITY_ACTIVE, PTYPE_INT },
  12463. { "changed", CSTRUCT_ENTITY_CHANGED, PTYPE_INT },
  12464. { "class", CSTRUCT_ENTITY_CLASS, PTYPE_FLOAT },
  12465. { "drawn", CSTRUCT_ENTITY_DRAWN, PTYPE_INT },
  12466. { "groupid", CSTRUCT_ENTITY_GROUPID, PTYPE_INT },
  12467. { "hidden", CSTRUCT_ENTITY_HIDDEN, PTYPE_INT },
  12468. { "highlight", CSTRUCT_ENTITY_HIGHLIGHT, PTYPE_INT },
  12469. { "is_type", CSTRUCT_ENTITY_IS_TYPE, PTYPE_INT },
  12470. { "moved", CSTRUCT_ENTITY_MOVED, PTYPE_INT },
  12471. { "nchild", CSTRUCT_ENTITY_NCHILD, PTYPE_INT },
  12472. { "oncount", CSTRUCT_ENTITY_ONCOUNT, PTYPE_INT },
  12473. { "open", CSTRUCT_ENTITY_OPEN, PTYPE_INT },
  12474. { "parent", CSTRUCT_ENTITY_PARENT, PTYPE_INT },
  12475. { "redraw", CSTRUCT_ENTITY_REDRAW, PTYPE_INT },
  12476. { "repaint", CSTRUCT_ENTITY_REPAINT, PTYPE_INT },
  12477. { "synthetic", CSTRUCT_ENTITY_SYNTHETIC, PTYPE_INT },
  12478. { "trace", CSTRUCT_ENTITY_TRACE, PTYPE_INT },
  12479. { "visible", CSTRUCT_ENTITY_VISIBLE, PTYPE_INT },
  12480. };
  12481. const struct OdieParamNameMap Entity_canonicalNameMap[] = {
  12482. { "active", CSTRUCT_ENTITY_ACTIVE, PTYPE_INT },
  12483. { "changed", CSTRUCT_ENTITY_CHANGED, PTYPE_INT },
  12484. { "class", CSTRUCT_ENTITY_CLASS, PTYPE_FLOAT },
  12485. { "drawn", CSTRUCT_ENTITY_DRAWN, PTYPE_INT },
  12486. { "groupid", CSTRUCT_ENTITY_GROUPID, PTYPE_INT },
  12487. { "hidden", CSTRUCT_ENTITY_HIDDEN, PTYPE_INT },
  12488. { "highlight", CSTRUCT_ENTITY_HIGHLIGHT, PTYPE_INT },
  12489. { "is_type", CSTRUCT_ENTITY_IS_TYPE, PTYPE_INT },
  12490. { "moved", CSTRUCT_ENTITY_MOVED, PTYPE_INT },
  12491. { "nchild", CSTRUCT_ENTITY_NCHILD, PTYPE_INT },
  12492. { "oncount", CSTRUCT_ENTITY_ONCOUNT, PTYPE_INT },
  12493. { "open", CSTRUCT_ENTITY_OPEN, PTYPE_INT },
  12494. { "parent", CSTRUCT_ENTITY_PARENT, PTYPE_INT },
  12495. { "redraw", CSTRUCT_ENTITY_REDRAW, PTYPE_INT },
  12496. { "repaint", CSTRUCT_ENTITY_REPAINT, PTYPE_INT },
  12497. { "synthetic", CSTRUCT_ENTITY_SYNTHETIC, PTYPE_INT },
  12498. { "trace", CSTRUCT_ENTITY_TRACE, PTYPE_INT },
  12499. { "visible", CSTRUCT_ENTITY_VISIBLE, PTYPE_INT },
  12500. };
  12501.  
  12502.  
  12503. #include <math.h>
  12504. #include <string.h>
  12505.  
  12506. #define ENTITY_SEARCH_NCOUNT 15
  12507.  
  12508. static const char *ENTITY_SEARCH_strs[] = {
  12509. "active",
  12510. "class",
  12511. "comptid",
  12512. "deckid",
  12513. "drawn",
  12514. "groupid",
  12515. "hidden",
  12516. "highlight",
  12517. "moved",
  12518. "redraw",
  12519. "repaint",
  12520. "synthetic",
  12521. "trace",
  12522. "typeid",
  12523. "visible",
  12524. 0
  12525. };
  12526. enum ENTITY_SEARCH_enum {
  12527. ENTITY_SEARCH_ACTIVE,
  12528. ENTITY_SEARCH_CLASS,
  12529. ENTITY_SEARCH_COMPTID,
  12530. ENTITY_SEARCH_DECKID,
  12531. ENTITY_SEARCH_DRAWN,
  12532. ENTITY_SEARCH_GROUPID,
  12533. ENTITY_SEARCH_HIDDEN,
  12534. ENTITY_SEARCH_HIGHLIGHT,
  12535. ENTITY_SEARCH_MOVED,
  12536. ENTITY_SEARCH_REDRAW,
  12537. ENTITY_SEARCH_REPAINT,
  12538. ENTITY_SEARCH_SYNTHETIC,
  12539. ENTITY_SEARCH_TRACE,
  12540. ENTITY_SEARCH_TYPEID,
  12541. ENTITY_SEARCH_VISIBLE
  12542. };
  12543. /* SimType_Walk_Parent */
  12544. int SimType_Walk_Parent(Entity *p){
  12545. /*
  12546. ** Subroutine to decend into children of a simtype
  12547. */
  12548. Entity *parent;
  12549. if(!p) {
  12550. return 0;
  12551. }
  12552. if(p->public_hidden) {
  12553. return -1;
  12554. }
  12555. if(p->public_active==2) {
  12556. return -1;
  12557. }
  12558. if(p->public_active==1) {
  12559. return 1;
  12560. }
  12561. if(p->public_visible) {
  12562. return 1;
  12563. }
  12564. if(p->public_parent) {
  12565. parent=SimType_ById(p->public_parent,0);
  12566. if(parent) {
  12567. return SimType_Walk_Parent(parent);
  12568. }
  12569. }
  12570. return 0;
  12571. }
  12572. /* *Entity_ById */
  12573. Entity *Entity_ById(char prefix,Roid id,int createFlag){
  12574. Entity *p;
  12575. char zName[32];
  12576. sprintf(zName, "%c%d", prefix, id);
  12577. p=Entity_ByName(zName,createFlag);
  12578. if(createFlag) {
  12579. if(!p->id) {
  12580. p->id=id;
  12581. }
  12582. }
  12583. return p;
  12584. }
  12585. /* *Entity_ByName */
  12586. Entity *Entity_ByName(const char *zName,int createFlag){
  12587. Tcl_HashEntry *pEntry;
  12588.  
  12589. assert( zName!=0 );
  12590. if(CurrentSim->GlobalSim) {
  12591. pEntry=Tcl_FindHashEntry(&CurrentSim->GlobalSim->EntityIdSet,zName);
  12592. } else {
  12593. pEntry=Tcl_FindHashEntry(&CurrentSim->EntityIdSet,zName);
  12594. }
  12595. if(pEntry) {
  12596. return (Entity*)Tcl_GetHashValue(pEntry);
  12597. }
  12598. if(createFlag) {
  12599. return EntityCreate(zName);
  12600. }
  12601. return NULL;
  12602. }
  12603. /* *Entity_ExportField */
  12604. Tcl_Obj *Entity_ExportField(Entity *e,Tcl_HashTable *local,char *field,int nullcode){
  12605. Tcl_Obj *result=Entity_GetField(e,local,field);
  12606.  
  12607. if(result) {
  12608. return result;
  12609. }
  12610. if(nullcode==ODIE_NULL_ZERO) {
  12611. return Tcl_NewBooleanObj(0);
  12612. }
  12613. if(nullcode==ODIE_NULL_EMPTY) {
  12614. return Tcl_NewObj();
  12615. }
  12616. return NULL;
  12617. }
  12618. /* *Entity_First */
  12619. Tcl_HashEntry *Entity_First(Simulator *sim,Tcl_HashSearch *search){
  12620. if(sim->GlobalSim) {
  12621. return Tcl_FirstHashEntry(&sim->GlobalSim->EntityIdSet,search);
  12622. } else {
  12623. return Tcl_FirstHashEntry(&sim->EntityIdSet,search);
  12624. }
  12625. }
  12626. /* *Entity_GetDict */
  12627. Tcl_Obj *Entity_GetDict(Entity *e,Tcl_HashTable *local){
  12628. Tcl_HashTable *localDict=NULL;
  12629. Tcl_Obj *pResult=NULL;
  12630. Entity *p=NULL;
  12631. Entity *pStack[10];
  12632. int i,count=-1;
  12633.  
  12634. p=e;
  12635. while(p && count<10) {
  12636. count++;
  12637. pStack[count]=p;
  12638. p=p->pType;
  12639. }
  12640. /*
  12641. ** Add the minimum specs for the class
  12642. */
  12643. for(i=count;i>=0;i--) {
  12644. p=pStack[i];
  12645. localDict=p->infoDict;
  12646. if(localDict) {
  12647. Tcl_HashSearch searchPtr;
  12648. Tcl_HashEntry *i;
  12649. for(i=Tcl_FirstHashEntry(localDict,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
  12650. if(!pResult) pResult=Tcl_NewDictObj();
  12651. Odie_DictObjPut(0,pResult,Tcl_GetHashKey(localDict,i),Tcl_GetHashValue(i));
  12652. }
  12653. }
  12654. }
  12655. localDict=local;
  12656. if(localDict) {
  12657. Tcl_HashSearch searchPtr;
  12658. Tcl_HashEntry *i;
  12659. for(i=Tcl_FirstHashEntry(localDict,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
  12660. if(!pResult) pResult=Tcl_NewDictObj();
  12661. Odie_DictObjPut(0,pResult,Tcl_GetHashKey(localDict,i),Tcl_GetHashValue(i));
  12662. }
  12663. }
  12664. return pResult;
  12665. }
  12666. /* *Entity_GetField */
  12667. Tcl_Obj *Entity_GetField(Entity *e,Tcl_HashTable *local,char *field){
  12668. Tcl_Obj *result=NULL;
  12669. Entity *p=NULL;
  12670.  
  12671. result=Odie_HashGet(local,field);
  12672. if(result) {
  12673. return result;
  12674. }
  12675. p=e;
  12676. while(p) {
  12677. result=Odie_HashGet(p->infoDict,field);
  12678. if(result) {
  12679. return result;
  12680. }
  12681. if(p) p=p->pType;
  12682. }
  12683. return NULL;
  12684. }
  12685. /* *Entity_GroupToTclObj */
  12686. Tcl_Obj *Entity_GroupToTclObj(Entity *pNode){
  12687. Roid groupid;
  12688. if(!pNode) {
  12689. return Tcl_NewBooleanObj(0);
  12690. }
  12691. groupid=Entity_StructGetGroup(pNode);
  12692. if(!groupid) {
  12693. return Tcl_NewBooleanObj(0);
  12694. }
  12695. return Irm_NewRoidObj(groupid);
  12696. }
  12697. /* *Entity_Identify */
  12698. Tcl_Obj *Entity_Identify(Entity *pNode){
  12699. if(!pNode) {
  12700. return Tcl_NewObj();
  12701. }
  12702. if(pNode->public_is_type) {
  12703. return Irm_NewRoidObj(pNode->id);
  12704. }
  12705. if(pNode->name!=NULL) {
  12706. return Odie_LiteralStringObj(pNode->name);
  12707. } else {
  12708. return Irm_NewRoidObj(pNode->id);
  12709. }
  12710. }
  12711. /* *Entity_IdentifyCompartment */
  12712. Entity *Entity_IdentifyCompartment(Tcl_Obj *entryPtr){
  12713. Entity *comptPtr=NULL;
  12714. int intval;
  12715. if(entryPtr==NULL) {
  12716. return NULL;
  12717. }
  12718. if(Tcl_GetIntFromObj(NULL,entryPtr,&intval)==TCL_OK) {
  12719. if(intval<=0) {
  12720. return NULL;
  12721. }
  12722. comptPtr=Entity_ById('c',intval,0);
  12723. } else {
  12724. comptPtr=Entity_ByName(Tcl_GetString(entryPtr),0);
  12725. }
  12726. return comptPtr;
  12727. }
  12728. /* *Entity_PublicId */
  12729. Tcl_Obj *Entity_PublicId(Entity *pNode){
  12730. char idstring[64];
  12731. if(!pNode) {
  12732. return Irm_NewRoidObj(0);
  12733. }
  12734. if(pNode->pType) {
  12735. if(pNode->pType->name!=NULL) {
  12736. return Odie_LiteralStringObj(pNode->pType->name);
  12737. }
  12738. }
  12739. sprintf(idstring,"%d",pNode->id);
  12740. return Odie_LiteralStringObj(idstring);
  12741. }
  12742. /* *Entity_SpecHashGet */
  12743. Tcl_Obj *Entity_SpecHashGet(Entity *p,Tcl_Obj* key,int nulltype){
  12744. return Entity_ExportField(p->pType,p->infoDict,Tcl_GetString(key),nulltype);
  12745. }
  12746. /* *Entity_StructGet */
  12747. Tcl_Obj *Entity_StructGet(Entity *pNode,int field){
  12748. switch (field) {
  12749. case CSTRUCT_ENTITY_HIDDEN: return Odie_LiteralIntObj(pNode->public_hidden);
  12750. case CSTRUCT_ENTITY_IS_TYPE: return Odie_LiteralIntObj(pNode->public_is_type);
  12751. case CSTRUCT_ENTITY_REDRAW: return Odie_LiteralIntObj(pNode->public_redraw);
  12752. case CSTRUCT_ENTITY_ACTIVE: return Odie_LiteralIntObj(pNode->public_active);
  12753. case CSTRUCT_ENTITY_GROUPID: return Irm_NewRoidObj(pNode->public_groupid);
  12754. case CSTRUCT_ENTITY_TRACE: return Odie_LiteralIntObj(pNode->public_trace);
  12755. case CSTRUCT_ENTITY_REPAINT: return Odie_LiteralIntObj(pNode->public_repaint);
  12756. case CSTRUCT_ENTITY_VISIBLE: return Odie_LiteralIntObj(pNode->public_visible);
  12757. case CSTRUCT_ENTITY_MOVED: return Odie_LiteralIntObj(pNode->public_moved);
  12758. case CSTRUCT_ENTITY_CHANGED: return Odie_LiteralIntObj(pNode->public_changed);
  12759. case CSTRUCT_ENTITY_OPEN: return Odie_LiteralIntObj(pNode->public_open);
  12760. case CSTRUCT_ENTITY_CLASS: {
  12761. char zBuf[2];
  12762. zBuf[0]=pNode->public_class;
  12763. zBuf[1]=0;
  12764. return Odie_LiteralStringObj(zBuf);
  12765. }
  12766.  
  12767. case CSTRUCT_ENTITY_PARENT: return Irm_NewRoidObj(pNode->public_parent);
  12768. case CSTRUCT_ENTITY_SYNTHETIC: return Odie_LiteralIntObj(pNode->public_synthetic);
  12769. case CSTRUCT_ENTITY_HIGHLIGHT: return Odie_LiteralIntObj(pNode->public_highlight);
  12770. case CSTRUCT_ENTITY_DRAWN: return Odie_LiteralIntObj(pNode->public_drawn);
  12771. case CSTRUCT_ENTITY_NCHILD: return Odie_LiteralIntObj(pNode->public_nchild);
  12772. case CSTRUCT_ENTITY_ONCOUNT: return Odie_LiteralIntObj(pNode->public_oncount);
  12773. }
  12774. return NULL;
  12775. }
  12776. /* *Entity_StructGetType */
  12777. Entity *Entity_StructGetType(Entity *p){
  12778. return p->pType;
  12779. }
  12780. /* *Entity_StructToDict */
  12781. Tcl_Obj *Entity_StructToDict(Tcl_Interp *interp,Entity *p,int virtual){
  12782. Tcl_Obj *pResult=NULL;
  12783. int i;
  12784. if(virtual) {
  12785. pResult=Entity_GetDict(p->pType,p->infoDict);
  12786. }
  12787. if(!pResult) {
  12788. pResult=Tcl_NewObj();
  12789. }
  12790. /* Finaly, Add the Tcl Data */
  12791. for(i=0;i<CSTRUCT_ENTITY_Count;i++) {
  12792. Tcl_Obj *newElement=Entity_StructGet(p,i);
  12793. Odie_DictObjPut(interp,pResult,Entity_paramNameMap[i].zName,newElement);
  12794. }
  12795. if(virtual) {
  12796. Entity_StructAddLocation(interp,p,pResult);
  12797. }
  12798. return pResult;
  12799. }
  12800. /* *Entity_StructTypeIdToTclObj */
  12801. Tcl_Obj *Entity_StructTypeIdToTclObj(Entity *pNode){
  12802. if(!pNode) {
  12803. return Irm_NewRoidObj(0);
  12804. }
  12805. if(!pNode->pType) {
  12806. return Irm_NewRoidObj(0);
  12807. }
  12808. return Irm_NewRoidObj(pNode->pType->id);
  12809. }
  12810. /* *Entity_TypeToTclObj */
  12811. Tcl_Obj *Entity_TypeToTclObj(Entity *pNode){
  12812. Entity *pType;
  12813. if(!pNode) {
  12814. return Tcl_NewBooleanObj(0);
  12815. }
  12816. pType=Entity_StructGetType(pNode);
  12817. if(!pType) {
  12818. return Tcl_NewBooleanObj(0);
  12819. }
  12820. return Irm_NewRoidObj(pType->id);
  12821. }
  12822. /* *EntityCreate */
  12823. Entity *EntityCreate(const char *zName){
  12824. int len,isNew;
  12825. Tcl_HashEntry *pEntry;
  12826. Entity *p;
  12827. if(CurrentSim->GlobalSim) {
  12828. pEntry = Tcl_CreateHashEntry(&CurrentSim->GlobalSim->EntityIdSet, zName, &isNew);
  12829. } else {
  12830. pEntry = Tcl_CreateHashEntry(&CurrentSim->EntityIdSet, zName, &isNew);
  12831. }
  12832. if(isNew) {
  12833. len = strlen(zName);
  12834. p = (Entity *)Odie_Alloc( sizeof(*p)+len+1 );
  12835. strcpy(p->name, zName);
  12836. p->public_class=zName[0];
  12837. Entity_StructAlloc(p);
  12838. Tcl_SetHashValue(pEntry,(ClientData)p);
  12839. return p;
  12840. }
  12841. if(pEntry) {
  12842. p=(Entity *)Tcl_GetHashValue(pEntry);
  12843. return p;
  12844. }
  12845. return NULL;
  12846. }
  12847. /* Entity_ApplySettings */
  12848. void Entity_ApplySettings(Entity *pNode){
  12849. if(pNode->public_class=='e') {
  12850. Tcl_Obj *comptidObj=Entity_GetField(NULL,pNode->infoDict,"comptid");
  12851. if(comptidObj) {
  12852. /*
  12853. ** If a local spec for "comptid" is given, use that
  12854. ** as an implied "comptdid" statement
  12855. */
  12856. pNode->comptPtr=Entity_IdentifyCompartment(comptidObj);
  12857. }
  12858. }
  12859. }
  12860. /* Entity_BuildMatch */
  12861. int Entity_BuildMatch(Tcl_Interp *interp,Tcl_Obj *matchvar,int *matchStruct){
  12862. int llength,idx;
  12863.  
  12864. /*
  12865. ** Default to universal match
  12866. */
  12867. for(idx=0;idx<ENTITY_SEARCH_NCOUNT;idx++) {
  12868. matchStruct[idx]=-1;
  12869. }
  12870. /* Handle a null */
  12871. if(!matchvar) {
  12872. return TCL_OK;
  12873. }
  12874.  
  12875. if( Tcl_ListObjLength(interp, matchvar, &llength) ) return TCL_ERROR;
  12876. if( llength%2!=0 ){
  12877. Tcl_AppendResult(interp, "Search params must be a key/value list "
  12878. "valid keys: visible hidden class redraw highlighted", 0);
  12879. return TCL_ERROR;
  12880. }
  12881.  
  12882. for(idx=0; idx<llength-1; idx+=2){
  12883. int field;
  12884. int value;
  12885. Tcl_Obj *pObj;
  12886.  
  12887. Tcl_ListObjIndex(0, matchvar, idx, &pObj);
  12888. if( Tcl_GetIndexFromObj(interp, pObj, ENTITY_SEARCH_strs, "option", 0, &field) ){
  12889. return TCL_ERROR;
  12890. }
  12891. Tcl_ListObjIndex(0, matchvar, idx+1, &pObj);
  12892. if(field==ENTITY_SEARCH_CLASS) {
  12893. char *str,prefix;
  12894. str=Tcl_GetString(pObj);
  12895. if(str) {
  12896. prefix=str[0];
  12897. matchStruct[field]=prefix;
  12898. }
  12899. } else {
  12900. if(Tcl_GetIntFromObj(interp, pObj, &value)) {
  12901. return TCL_ERROR;
  12902. }
  12903. matchStruct[field]=value;
  12904. }
  12905. }
  12906. return TCL_OK;
  12907. }
  12908. /* Entity_Delete */
  12909. void Entity_Delete(Entity *p){
  12910. Entity_StructFree(p);
  12911. Odie_Free((char *)p);
  12912. }
  12913. /* Entity_FromTclObj */
  12914. int Entity_FromTclObj(Tcl_Interp *interp, Tcl_Obj *pObj, Entity **ppEntity){
  12915. *ppEntity = NULL;
  12916. int i;
  12917. if( Tcl_GetIntFromObj(interp, pObj, &i) == TCL_OK ) {
  12918. *ppEntity = SimType_ById(i, 0);
  12919. if(*ppEntity) {
  12920. return TCL_OK;
  12921. }
  12922. }
  12923. Tcl_ResetResult(interp);
  12924. *ppEntity = Entity_ByName(Tcl_GetString(pObj),0);
  12925.  
  12926. if( *ppEntity==0 ){
  12927. Tcl_AppendResult(interp, "no such entity: ",
  12928. Tcl_GetString(pObj), 0);
  12929. return TCL_ERROR;
  12930. }
  12931. return TCL_OK;
  12932. }
  12933. /* Entity_Module_Advance */
  12934. void Entity_Module_Advance(Simulator *ActiveSim,int clocktime){
  12935. /* Default empty implementation */
  12936. }
  12937. /* Entity_Module_Free */
  12938. void Entity_Module_Free(Simulator *sim){
  12939. Tcl_HashSearch searchPtr;
  12940. Tcl_HashEntry *i;
  12941.  
  12942. if(!sim->module_entity) return;
  12943. for(i=Entity_First(sim,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
  12944. Entity *p = (Entity*)Tcl_GetHashValue(i);
  12945. Entity_StructFree(p);
  12946. Odie_Free((char *)p);
  12947. }
  12948. for(i=SimType_First(sim,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
  12949. Entity *p = (Entity*)Tcl_GetHashValue(i);
  12950. Entity_StructFree(p);
  12951. Odie_Free((char *)p);
  12952. }
  12953. Tcl_DeleteHashTable(&sim->EntityIdSet);
  12954. Tcl_DeleteHashTable(&sim->SimTypeIdSet);
  12955. sim->module_entity=0;
  12956. }
  12957. /* Entity_Module_Init */
  12958. void Entity_Module_Init(Simulator *sim){}
  12959. /* Entity_Module_Rewind */
  12960. void Entity_Module_Rewind(Simulator *sim){
  12961. Tcl_HashSearch searchPtr;
  12962. Tcl_HashEntry *i;
  12963.  
  12964. if(!sim->module_entity) return;
  12965. for(i=Entity_First(sim,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
  12966. Entity *p = (Entity*)Tcl_GetHashValue(i);
  12967. p->public_redraw=1;
  12968. p->public_repaint=1;
  12969. }
  12970. }
  12971. /* Entity_Node_ApplyLocation */
  12972. void Entity_Node_ApplyLocation(Entity *pNode){
  12973. #ifdef build_IRM
  12974. Entity *comptPtr;
  12975. int cid,sid,c;
  12976. c=CrewrouteSubcompartmentAt(pNode->x,pNode->y,pNode->deckid,&sid,&cid,NULL,NULL);
  12977. comptPtr=Entity_ById('c',c,0);
  12978. pNode->public_moved=1;
  12979. if(comptPtr) {
  12980. pNode->comptPtr=comptPtr;
  12981. } else {
  12982. pNode->comptPtr=NULL;
  12983. }
  12984. #endif
  12985. }
  12986. /* Entity_Node_GetLink */
  12987. void Entity_Node_GetLink(Tcl_Obj *pResult,Entity *pNode,char *linktype){}
  12988. /* Entity_nodeeval */
  12989. int Entity_nodeeval(Tcl_Interp *interp,Entity *p,Tcl_Obj *body,int writeback){
  12990. Tcl_Obj *id;
  12991. int i,len;
  12992. Tcl_Obj *varv[CSTRUCT_ENTITY_Count*2];
  12993. int result;
  12994.  
  12995. Entity_StructWith(interp,p,1,varv);
  12996. id=Entity_Identify(p);
  12997. Tcl_ObjSetVar2(interp,Odie_LiteralStringObj("id"),NULL,id,0);
  12998. Tcl_ObjSetVar2(interp,Odie_LiteralStringObj("typeid"),NULL,Entity_TypeToTclObj(p),0);
  12999. Tcl_ObjSetVar2(interp,Odie_LiteralStringObj("groupid"),NULL,Entity_GroupToTclObj(p),0);
  13000. /*
  13001. for(i=0;i<CSTRUCT_ENTITY_Count*2;i++) {
  13002. Tcl_IncrRefCount(varv[i]);
  13003. }
  13004. */
  13005. result=Tcl_EvalObjEx(interp, body, 0);
  13006.  
  13007. if(result!=TCL_OK) {
  13008. return result;
  13009. }
  13010. if(writeback){
  13011. /*
  13012. ** Read values back into the dict
  13013. ** For now, we limit writeback to state variables
  13014. ** And we don't care about garbage values
  13015. */
  13016. int changed=0;
  13017. for(i=0;i<CSTRUCT_ENTITY_Count*2;i+=2) {
  13018. Tcl_Obj *newValue;
  13019. int offset;
  13020. int type;
  13021. newValue=Tcl_ObjGetVar2(interp,varv[i],(Tcl_Obj*)NULL,0);
  13022. if(newValue==varv[i+1]) {
  13023. /* Undocumented, unsanctioned, but it works in practice
  13024. ** If the pointer hasn't changed, neither has the value
  13025. */
  13026. continue;
  13027. }
  13028. if(!newValue) {
  13029. /* Variable must have been unset... move along */
  13030. continue;
  13031. }
  13032. if( Entity_StructValueOffset(0, varv[i], &offset, &type) == TCL_OK ) {
  13033. Entity_StructSet(interp,p,offset,newValue);
  13034. changed++;
  13035. }
  13036. }
  13037. if(changed) {
  13038. Entity_ApplySettings(p);
  13039. }
  13040. }
  13041. /*
  13042. for(i=0;i<CSTRUCT_ENTITY_Count*2;i++) {
  13043. Tcl_DecrRefCount(varv[i]);
  13044. }
  13045. */
  13046. return TCL_OK;
  13047. }
  13048. /* Entity_Rewind */
  13049. void Entity_Rewind(Entity *p, int revert){}
  13050. /* Entity_SetFromObj */
  13051. int Entity_SetFromObj(Tcl_Interp *interp,Entity *pType, Tcl_Obj *field, Tcl_Obj *value){
  13052. /* Manipulate the DICT representation */
  13053. int err,type,offset=-1;
  13054. /* Reset any cached group pointer */
  13055. pType->gType=NULL;
  13056. if( Entity_StructValueOffset(interp, field, &offset, &type) == TCL_OK ) {
  13057. err=Entity_StructSet(interp,pType->pType,offset,value);
  13058. if(err==TCL_OK) {
  13059. Entity_ApplySettings(pType->pType);
  13060. }
  13061. return err;
  13062. }
  13063. Odie_HashPut(&pType->infoDict,Tcl_GetString(field),value);
  13064. return TCL_OK;
  13065. }
  13066. /* Entity_SpecHashClear */
  13067. void Entity_SpecHashClear(Entity *p){
  13068. Odie_HashFree(&p->infoDict);
  13069. }
  13070. /* Entity_SpecHashPut */
  13071. void Entity_SpecHashPut(Entity *p,Tcl_Obj *key,Tcl_Obj *value){
  13072. Odie_HashPut(&p->infoDict,Tcl_GetString(key),value);
  13073. }
  13074. /* Entity_StructAddLocation */
  13075. void Entity_StructAddLocation(Tcl_Interp *interp,Entity *p, Tcl_Obj *pValueDict){
  13076. Tcl_Obj *tempval;
  13077. #ifdef build_IRM
  13078. if(p->public_class=='k') {
  13079. /* Always provide a path if not given
  13080. ** And only trust the local dict
  13081. */
  13082. Tcl_Obj *pathobj=Entity_ExportField(NULL,p->infoDict,"path",ODIE_NULL_EMPTY);
  13083. Odie_DictObjPut(0,pValueDict,"path",pathobj);
  13084. } else {
  13085. if(p->attached_to) {
  13086. switch (p->attached_type) {
  13087. case CSTRUCT_crew: {
  13088. return Crew_StructAddLocation(interp,p->attached_to,pValueDict);
  13089. }
  13090. case CSTRUCT_entity: {
  13091. return Entity_StructAddLocation(interp,p->attached_to,pValueDict);
  13092. }
  13093. case CSTRUCT_portal: {
  13094. return Portal_StructAddLocation(interp,p->attached_to,pValueDict);
  13095. }
  13096. case CSTRUCT_simnode: {
  13097. return SimNode_StructAddLocation(interp,p->attached_to,pValueDict);
  13098. }
  13099. }
  13100. }
  13101. Odie_DictObjPut(0,pValueDict,"deckid",Odie_LiteralIntObj(p->deckid));
  13102. if(p->deckid) {
  13103. tempval=Tcl_NewObj();
  13104. Tcl_ListObjAppendElement(interp, tempval, Odie_LiteralIntObj(p->deckid));
  13105. Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->x));
  13106. Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->y));
  13107. Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->zoff));
  13108. Odie_DictObjPut(interp,pValueDict,"center",tempval);
  13109. }
  13110. tempval=Tcl_NewObj();
  13111. Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->nx));
  13112. Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->ny));
  13113. Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->nz));
  13114. Odie_DictObjPut(0,pValueDict,"orientation",tempval);
  13115. if(p->comptPtr) {
  13116. Odie_DictObjPut(0,pValueDict,"compartment",Entity_Identify(p->comptPtr));
  13117. }
  13118. }
  13119. #else
  13120. Odie_DictObjPut(0,pValueDict,"deckid",Odie_LiteralIntObj(p->deckid));
  13121. if(p->deckid) {
  13122. tempval=Tcl_NewObj();
  13123. Tcl_ListObjAppendElement(interp, tempval, Odie_LiteralIntObj(p->deckid));
  13124. Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->x));
  13125. Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->y));
  13126. Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->zoff));
  13127. Odie_DictObjPut(interp,pValueDict,"center",tempval);
  13128. }
  13129. tempval=Tcl_NewObj();
  13130. Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->nx));
  13131. Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->ny));
  13132. Tcl_ListObjAppendElement(interp, tempval, Tcl_NewIntObj(p->nz));
  13133. Odie_DictObjPut(0,pValueDict,"orientation",tempval);
  13134. if(p->comptPtr) {
  13135. Odie_DictObjPut(0,pValueDict,"compartment",Entity_Identify(p->comptPtr));
  13136. }
  13137. #endif
  13138. }
  13139. /* Entity_StructAlloc */
  13140. void Entity_StructAlloc(Entity *p){}
  13141. /* Entity_StructAttachLocation */
  13142. int Entity_StructAttachLocation(Tcl_Interp *interp,Entity *pNat,Tcl_Obj *nodeName){
  13143. char type=0;
  13144. int roid;
  13145. char *stringVal=Tcl_GetString(nodeName);
  13146. int result=sscanf(stringVal,"%c%d",&type,&roid);
  13147.  
  13148. if(result!=2) {
  13149. pNat->attached_type=0;
  13150. pNat->attached_to=NULL;
  13151. return TCL_OK;
  13152. }
  13153. #ifdef build_IRM
  13154. switch(type) {
  13155. case 'c': {
  13156. Compartment *pDest;
  13157. if(Compartment_FromTclObj(interp,nodeName,&pDest)) return TCL_ERROR;
  13158. pNat->attached_type=CSTRUCT_compartment;
  13159. pNat->attached_to=pDest;
  13160. return TCL_OK;
  13161. }
  13162. case 'e': {
  13163. SimNode *pDest;
  13164. if(SimNode_FromTclObj(interp,nodeName,&pDest)) return TCL_ERROR;
  13165. pNat->attached_type=CSTRUCT_simnode;
  13166. pNat->attached_to=pDest;
  13167. return TCL_OK;
  13168. }
  13169. case 'p': {
  13170. Portal *pDest;
  13171. if(Portal_FromTclObj(interp,nodeName,&pDest)) return TCL_ERROR;
  13172. pNat->attached_type=CSTRUCT_portal;
  13173. pNat->attached_to=pDest;
  13174. return TCL_OK;
  13175. }
  13176. case 'v': {
  13177. Crew *pDest;
  13178. if(Crew_FromTclObj(interp,nodeName,&pDest)) return TCL_ERROR;
  13179. pNat->attached_type=CSTRUCT_crew;
  13180. pNat->attached_to=pDest;
  13181. return TCL_OK;
  13182. }
  13183. default: {
  13184. Entity *pDest;
  13185. if(Entity_FromTclObj(interp,nodeName,&pDest)) {
  13186. return TCL_ERROR;
  13187. }
  13188. pNat->attached_type=CSTRUCT_entity;
  13189. pNat->attached_to=pDest;
  13190. return TCL_OK;
  13191. }
  13192. }
  13193. return TCL_ERROR;
  13194. #else
  13195. Entity *pDest;
  13196. if(Entity_FromTclObj(interp,nodeName,&pDest)) {
  13197. return TCL_ERROR;
  13198. }
  13199. pNat->attached_type=CSTRUCT_entity;
  13200. pNat->attached_to=pDest;
  13201. return TCL_OK;
  13202. #endif
  13203. }
  13204. /* Entity_StructChanged */
  13205. int Entity_StructChanged(Entity *p){ return 0; }
  13206. /* Entity_StructFree */
  13207. void Entity_StructFree(Entity *p){
  13208. Odie_HashFree(&p->infoDict);
  13209. p->infoDict=NULL;
  13210. }
  13211. /* Entity_StructFree_Private */
  13212. void Entity_StructFree_Private(Entity *p){}
  13213. /* Entity_StructGetGroup */
  13214. Roid Entity_StructGetGroup(Entity *p){
  13215. Roid groupid=-1;
  13216. if(p->public_groupid>0) {
  13217. return p->public_groupid;
  13218. }
  13219.  
  13220. if(p->pType) {
  13221. groupid=SimType_StructGetGroup(p->pType);
  13222. if(groupid>0) {
  13223. return groupid;
  13224. }
  13225. }
  13226. /*
  13227. ** Nodes defaults to the compartment they are within
  13228. ** If no group is given through the type or adopted type
  13229. */
  13230. if(p->comptPtr) {
  13231. groupid=Entity_StructGetGroup(p->comptPtr);
  13232. if(groupid>0) {
  13233. return groupid;
  13234. }
  13235. }
  13236. return 0;
  13237. }
  13238. /* Entity_StructLocation */
  13239. void Entity_StructLocation (Irm_Location *lstruct,Entity *p){
  13240. #ifdef build_IRM
  13241. if(p->attached_to) {
  13242. switch (p->attached_type) {
  13243. case CSTRUCT_crew: {
  13244. return Crew_StructLocation(lstruct,p->attached_to);
  13245. }
  13246. case CSTRUCT_entity: {
  13247. return Entity_StructLocation(lstruct,p->attached_to);
  13248. }
  13249. case CSTRUCT_portal: {
  13250. return Portal_StructLocation(lstruct,p->attached_to);
  13251. }
  13252. case CSTRUCT_simnode: {
  13253. return SimNode_StructLocation(lstruct,p->attached_to);
  13254. }
  13255. }
  13256. }
  13257. #endif
  13258. lstruct->deckid=p->deckid;
  13259. lstruct->x=p->x;
  13260. lstruct->y=p->y;
  13261. lstruct->zoff=p->zoff;
  13262. }
  13263. /* Entity_StructMatches */
  13264. int Entity_StructMatches(Entity *p,int *matchSearch){
  13265.  
  13266. if(matchSearch[ENTITY_SEARCH_CLASS]>=0) {
  13267. if(matchSearch[ENTITY_SEARCH_CLASS]!=(int)p->public_class) return 0;
  13268. }
  13269. if(matchSearch[ENTITY_SEARCH_DECKID]>=0) {
  13270. if(matchSearch[ENTITY_SEARCH_DECKID]!=(int)p->deckid) return 0;
  13271. }
  13272. if(matchSearch[ENTITY_SEARCH_DRAWN]>=0) {
  13273. if(matchSearch[ENTITY_SEARCH_DRAWN]!=(int)p->public_drawn) return 0;
  13274. }
  13275.  
  13276. if(matchSearch[ENTITY_SEARCH_COMPTID]>=0) {
  13277. Entity *gPtr=p->comptPtr;
  13278. if(!gPtr) {
  13279. return 0;
  13280. } else {
  13281. if(gPtr->id != matchSearch[ENTITY_SEARCH_COMPTID]) {
  13282. return 0;
  13283. }
  13284. }
  13285. }
  13286.  
  13287. if(matchSearch[ENTITY_SEARCH_GROUPID]>=0) {
  13288. Roid groupid=Entity_StructGetGroup(p);
  13289. if(groupid != matchSearch[ENTITY_SEARCH_GROUPID]) {
  13290. return 0;
  13291. }
  13292. }
  13293.  
  13294. if(matchSearch[ENTITY_SEARCH_HIDDEN]>=0) {
  13295. if(matchSearch[ENTITY_SEARCH_HIDDEN]!=p->public_hidden) return 0;
  13296. }
  13297. if(matchSearch[ENTITY_SEARCH_ACTIVE]>=0) {
  13298. if(matchSearch[ENTITY_SEARCH_ACTIVE]!=p->public_active) return 0;
  13299. }
  13300. if(matchSearch[ENTITY_SEARCH_HIGHLIGHT]>=0) {
  13301. if(matchSearch[ENTITY_SEARCH_HIGHLIGHT]!=p->public_highlight) return 0;
  13302. }
  13303. if(matchSearch[ENTITY_SEARCH_MOVED]>=0) {
  13304. if(matchSearch[ENTITY_SEARCH_MOVED]!=p->public_moved) return 0;
  13305. }
  13306. if(matchSearch[ENTITY_SEARCH_REDRAW]>=0) {
  13307. if(matchSearch[ENTITY_SEARCH_REDRAW]!=p->public_redraw) return 0;
  13308. }
  13309.  
  13310. if(matchSearch[ENTITY_SEARCH_REPAINT]>=0) {
  13311. if(matchSearch[ENTITY_SEARCH_REPAINT]!=p->public_repaint) return 0;
  13312. }
  13313. if(matchSearch[ENTITY_SEARCH_SYNTHETIC]>=0) {
  13314. if(matchSearch[ENTITY_SEARCH_SYNTHETIC]!=p->public_synthetic) return 0;
  13315. }
  13316.  
  13317. if(matchSearch[ENTITY_SEARCH_TYPEID]>=0) {
  13318. if(!p->pType) {
  13319. return 0;
  13320. } else {
  13321. if(p->pType->id != matchSearch[ENTITY_SEARCH_TYPEID]) {
  13322. return 0;
  13323. }
  13324. }
  13325. }
  13326. if(matchSearch[ENTITY_SEARCH_TRACE]>=0) {
  13327. if(matchSearch[ENTITY_SEARCH_TRACE]!=p->public_trace) return 0;
  13328. }
  13329. if(matchSearch[ENTITY_SEARCH_VISIBLE]>=0) {
  13330. if(matchSearch[ENTITY_SEARCH_VISIBLE]!=p->public_visible) return 0;
  13331. }
  13332. return 1;
  13333. }
  13334. /* Entity_StructSet */
  13335. int Entity_StructSet(Tcl_Interp *interp,Entity *pNode,int field,Tcl_Obj *value){
  13336.  
  13337. if(field < 0 ) {
  13338. return TCL_ERROR;
  13339. }
  13340.  
  13341. switch (field) {
  13342. case CSTRUCT_ENTITY_HIDDEN: {
  13343. int intValue;
  13344. double floatValue;
  13345. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13346. Tcl_ResetResult(interp);
  13347. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13348. intValue=(int)floatValue;
  13349. }
  13350. pNode->public_hidden=intValue;
  13351. return TCL_OK;
  13352. }
  13353. case CSTRUCT_ENTITY_IS_TYPE: {
  13354. int intValue;
  13355. double floatValue;
  13356. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13357. Tcl_ResetResult(interp);
  13358. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13359. intValue=(int)floatValue;
  13360. }
  13361. pNode->public_is_type=intValue;
  13362. return TCL_OK;
  13363. }
  13364. case CSTRUCT_ENTITY_REDRAW: {
  13365. int intValue;
  13366. double floatValue;
  13367. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13368. Tcl_ResetResult(interp);
  13369. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13370. intValue=(int)floatValue;
  13371. }
  13372. pNode->public_redraw=intValue;
  13373. return TCL_OK;
  13374. }
  13375. case CSTRUCT_ENTITY_ACTIVE: {
  13376. int intValue;
  13377. double floatValue;
  13378. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13379. Tcl_ResetResult(interp);
  13380. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13381. intValue=(int)floatValue;
  13382. }
  13383. pNode->public_active=intValue;
  13384. return TCL_OK;
  13385. }
  13386. case CSTRUCT_ENTITY_GROUPID: {
  13387. Roid roidValue;
  13388. if(Irm_GetRoidFromObj(interp,value,&roidValue)) return TCL_ERROR;
  13389. pNode->public_groupid=(Roid)roidValue;
  13390. return TCL_OK;
  13391. }
  13392. case CSTRUCT_ENTITY_TRACE: {
  13393. int intValue;
  13394. double floatValue;
  13395. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13396. Tcl_ResetResult(interp);
  13397. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13398. intValue=(int)floatValue;
  13399. }
  13400. pNode->public_trace=intValue;
  13401. return TCL_OK;
  13402. }
  13403. case CSTRUCT_ENTITY_REPAINT: {
  13404. int intValue;
  13405. double floatValue;
  13406. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13407. Tcl_ResetResult(interp);
  13408. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13409. intValue=(int)floatValue;
  13410. }
  13411. pNode->public_repaint=intValue;
  13412. return TCL_OK;
  13413. }
  13414. case CSTRUCT_ENTITY_VISIBLE: {
  13415. int intValue;
  13416. double floatValue;
  13417. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13418. Tcl_ResetResult(interp);
  13419. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13420. intValue=(int)floatValue;
  13421. }
  13422. pNode->public_visible=intValue;
  13423. return TCL_OK;
  13424. }
  13425. case CSTRUCT_ENTITY_MOVED: {
  13426. int intValue;
  13427. double floatValue;
  13428. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13429. Tcl_ResetResult(interp);
  13430. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13431. intValue=(int)floatValue;
  13432. }
  13433. pNode->public_moved=intValue;
  13434. return TCL_OK;
  13435. }
  13436. case CSTRUCT_ENTITY_CHANGED: {
  13437. int intValue;
  13438. double floatValue;
  13439. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13440. Tcl_ResetResult(interp);
  13441. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13442. intValue=(int)floatValue;
  13443. }
  13444. pNode->public_changed=intValue;
  13445. return TCL_OK;
  13446. }
  13447. case CSTRUCT_ENTITY_OPEN: {
  13448. int intValue;
  13449. double floatValue;
  13450. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13451. Tcl_ResetResult(interp);
  13452. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13453. intValue=(int)floatValue;
  13454. }
  13455. pNode->public_open=intValue;
  13456. return TCL_OK;
  13457. }
  13458. case CSTRUCT_ENTITY_CLASS: {
  13459. char *str;
  13460. str=Tcl_GetString(value);
  13461. if(str) {
  13462. pNode->public_class=str[0];
  13463. }
  13464. return TCL_OK;
  13465. }
  13466. case CSTRUCT_ENTITY_PARENT: {
  13467. Roid roidValue;
  13468. if(Irm_GetRoidFromObj(interp,value,&roidValue)) return TCL_ERROR;
  13469. pNode->public_parent=(Roid)roidValue;
  13470. return TCL_OK;
  13471. }
  13472. case CSTRUCT_ENTITY_SYNTHETIC: {
  13473. int intValue;
  13474. double floatValue;
  13475. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13476. Tcl_ResetResult(interp);
  13477. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13478. intValue=(int)floatValue;
  13479. }
  13480. pNode->public_synthetic=intValue;
  13481. return TCL_OK;
  13482. }
  13483. case CSTRUCT_ENTITY_HIGHLIGHT: {
  13484. int intValue;
  13485. double floatValue;
  13486. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13487. Tcl_ResetResult(interp);
  13488. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13489. intValue=(int)floatValue;
  13490. }
  13491. pNode->public_highlight=intValue;
  13492. return TCL_OK;
  13493. }
  13494. case CSTRUCT_ENTITY_DRAWN: {
  13495. int intValue;
  13496. double floatValue;
  13497. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13498. Tcl_ResetResult(interp);
  13499. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13500. intValue=(int)floatValue;
  13501. }
  13502. pNode->public_drawn=intValue;
  13503. return TCL_OK;
  13504. }
  13505. case CSTRUCT_ENTITY_NCHILD: {
  13506. int intValue;
  13507. double floatValue;
  13508. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13509. Tcl_ResetResult(interp);
  13510. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13511. intValue=(int)floatValue;
  13512. }
  13513. pNode->public_nchild=intValue;
  13514. return TCL_OK;
  13515. }
  13516. case CSTRUCT_ENTITY_ONCOUNT: {
  13517. int intValue;
  13518. double floatValue;
  13519. if(Tcl_GetIntFromObj(interp,value,&intValue)) {
  13520. Tcl_ResetResult(interp);
  13521. if(Tcl_GetDoubleFromObj(interp,value,&floatValue)) return TCL_ERROR;
  13522. intValue=(int)floatValue;
  13523. }
  13524. pNode->public_oncount=intValue;
  13525. return TCL_OK;
  13526. }
  13527. }
  13528. return TCL_OK;
  13529. }
  13530. /* Entity_StructSetGroup */
  13531. void Entity_StructSetGroup(Entity *p,Roid groupid){
  13532. p->public_groupid=groupid;
  13533. }
  13534. /* Entity_StructSetType */
  13535. void Entity_StructSetType(Entity *p,Entity *pType){
  13536. p->pType=pType;
  13537. if(pType) {
  13538. if(pType->public_class=='g') {
  13539. p->gType=pType;
  13540. }
  13541. }
  13542. }
  13543. /* Entity_StructSizeZ */
  13544. int Entity_StructSizeZ(Entity *pNode){
  13545. int zheight=TypeSpec_GetInt(pNode,"size.z");
  13546. return zheight;
  13547. }
  13548. /* Entity_StructValueOffset */
  13549. int Entity_StructValueOffset(Tcl_Interp *interp,Tcl_Obj *pObj,int *pIndex,int *pType){
  13550. /*
  13551. ** Given the name of one of the arState[] values in the Entity structure,
  13552. ** return the index of the particular arState[]. Return TCL_OK.
  13553. **
  13554. ** Leave an error message in interp and return TCL_ERROR if
  13555. ** anything goes wrong.
  13556. */
  13557.  
  13558. int lo, hi, mid, c, max, i;
  13559. int nName;
  13560. const char *zName;
  13561. const struct OdieParamNameMap *aParam = Entity_canonicalNameMap;
  13562.  
  13563. lo = 0;
  13564. hi = max = CSTRUCT_ENTITY_AliasCount - 1;
  13565. zName = Tcl_GetStringFromObj(pObj, &nName);
  13566. mid = (lo+hi)/2;
  13567. if(nName>32) {
  13568. nName=32;
  13569. }
  13570. while( lo<=hi ){
  13571. mid = (lo+hi)/2;
  13572. c = strncmp(zName, aParam[mid].zName, nName);
  13573. if( c<0 ){
  13574. hi = mid-1;
  13575. }else if( c>0 ){
  13576. lo = mid+1;
  13577. }else if(
  13578. (mid>0 && strncmp(zName, aParam[mid-1].zName, nName)==0) ||
  13579. (mid<max && strncmp(zName, aParam[mid+1].zName, nName)==0)
  13580. ){
  13581. i = mid;
  13582. while( i>0 && strncmp(zName, aParam[i-1].zName, nName)==0 ){
  13583. i--;
  13584. }
  13585. if( strlen(aParam[i].zName)==nName ){
  13586. *pIndex = aParam[i].iCode;
  13587. *pType = aParam[i].pType;
  13588. return TCL_OK;
  13589. }
  13590. if(interp) {
  13591. Tcl_AppendResult(interp, "ambiguous parameter:", 0);
  13592. do{
  13593. Tcl_AppendResult(interp, " ", aParam[i++].zName, 0);
  13594. }while( i<=max && strncmp(zName, aParam[i].zName, nName)==0 );
  13595. }
  13596. return TCL_ERROR;
  13597. }else{
  13598. *pIndex = aParam[mid].iCode;
  13599. *pType = aParam[mid].pType;
  13600. return TCL_OK;
  13601. }
  13602. }
  13603. if(interp) {
  13604. Tcl_AppendResult(interp, "unknown parameter \"", zName,
  13605. "\" - nearby choices:", 0);
  13606. for(i=mid-3; i<mid+3; i++){
  13607. if( i<0 || i>max ) continue;
  13608. Tcl_AppendResult(interp, " ", aParam[i].zName, 0);
  13609. }
  13610. }
  13611. return TCL_ERROR;
  13612. }
  13613. /* Entity_StructWith */
  13614. void Entity_StructWith(Tcl_Interp *interp,Entity *p,int virtual,Tcl_Obj **objvPtr){
  13615. int i;
  13616. if (virtual) {
  13617. Entity_With(interp,p->pType,NULL);
  13618. }
  13619. /* Finaly, Add the Tcl Data */
  13620. for(i=0;i<CSTRUCT_ENTITY_Count;i++) {
  13621. Tcl_Obj *newElement=Entity_StructGet(p,i);
  13622. Tcl_Obj *fieldName=Odie_LiteralStringObj(Entity_paramNameMap[i].zName);
  13623. if(objvPtr) {
  13624. objvPtr[i*2]=fieldName;
  13625. objvPtr[i*2+1]=newElement;
  13626. }
  13627. Tcl_ObjSetVar2(interp,fieldName,NULL,newElement,0);
  13628. }
  13629. if(virtual) {
  13630. Entity_StructWithLocation(interp,p);
  13631. }
  13632. }
  13633. /* Entity_StructWithLocation */
  13634. void Entity_StructWithLocation(Tcl_Interp *interp,Entity *pNode){}
  13635. /* Entity_Unlink */
  13636. void Entity_Unlink(Entity *objPtr){
  13637. Tcl_HashEntry *pEntry;
  13638.  
  13639. if (!objPtr) return;
  13640. if(CurrentSim->GlobalSim) {
  13641. pEntry=Tcl_FindHashEntry(&CurrentSim->GlobalSim->EntityIdSet,(const char *)objPtr->name);
  13642. } else {
  13643. pEntry=Tcl_FindHashEntry(&CurrentSim->EntityIdSet,(const char *)objPtr->name);
  13644. }
  13645. if(pEntry) {
  13646. Tcl_DeleteHashEntry(pEntry);
  13647. }
  13648. #ifdef build_IRM
  13649. if(objPtr->public_class=='v') {
  13650. Crew *pNode=Crew_ById(objPtr->id,0);
  13651. if(pNode) {
  13652. Crew_Unlink(pNode);
  13653. Crew_Delete(pNode);
  13654. }
  13655. }
  13656. if(objPtr->public_class=='p') {
  13657. Portal *pNode=Portal_ById(objPtr->id,0);
  13658. if(pNode) {
  13659. Portal_Unlink(pNode);
  13660. Portal_Delete(pNode);
  13661. }
  13662. }
  13663. if(objPtr->public_class=='k') {
  13664. SimLink *pNode=SimLink_ById(objPtr->id,0);
  13665. if(pNode) {
  13666. SimLink_Unlink(pNode);
  13667. SimLink_Delete(pNode);
  13668. }
  13669. }
  13670. if(objPtr->public_class=='e') {
  13671. SimNode *pNode=SimNode_ById(objPtr->id,0);
  13672. if(pNode) {
  13673. if(pNode->aLink->pCommon->public_rupture_node == pNode->id) {
  13674. /*
  13675. ** Run link repair for rupture nodes instead of delete simnode
  13676. */
  13677. SimLink_Repair(NULL,pNode->aLink->pCommon);
  13678. } else {
  13679. SimNode_Unlink(pNode);
  13680. SimNode_Delete(pNode);
  13681. }
  13682. }
  13683. }
  13684. #endif
  13685. }
  13686. /* Entity_With */
  13687. void Entity_With(Tcl_Interp *interp,Entity *e,Tcl_HashTable *local){
  13688. Tcl_HashTable *localDict=NULL;
  13689. Entity *p=NULL;
  13690. Entity *pStack[10];
  13691. int i,count=-1;
  13692.  
  13693. p=e;
  13694. while(p && count<10) {
  13695. count++;
  13696. pStack[count]=p;
  13697. p=p->pType;
  13698. }
  13699. /*
  13700. ** Add the minimum specs for the class
  13701. */
  13702. for(i=count;i>=0;i--) {
  13703. p=pStack[i];
  13704. localDict=p->infoDict;
  13705. if(localDict) {
  13706. Tcl_HashSearch searchPtr;
  13707. Tcl_HashEntry *i;
  13708. for(i=Tcl_FirstHashEntry(localDict,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
  13709. Tcl_Obj *pKey,*pValue;
  13710. pKey=Odie_LiteralStringObj(Tcl_GetHashKey(localDict,i));
  13711. pValue=(Tcl_Obj *)Tcl_GetHashValue(i);
  13712. Tcl_ObjSetVar2(interp,pKey,NULL,pValue,0);
  13713. }
  13714. }
  13715. }
  13716. localDict=local;
  13717. if(localDict) {
  13718. Tcl_HashSearch searchPtr;
  13719. Tcl_HashEntry *i;
  13720. for(i=Tcl_FirstHashEntry(localDict,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
  13721. Tcl_Obj *pKey,*pValue;
  13722. pKey=Odie_LiteralStringObj(Tcl_GetHashKey(localDict,i));
  13723. pValue=(Tcl_Obj *)Tcl_GetHashValue(i);
  13724. Tcl_ObjSetVar2(interp,pKey,NULL,pValue,0);
  13725. }
  13726. }
  13727. }
  13728. #define ENTITY_SEARCH_NCOUNT 15
  13729. /* *SimType_ById */
  13730. Entity *SimType_ById(Roid id, int createFlag){
  13731. /*
  13732. ** Return a pointer to a SimType with the given ID. Return NULL
  13733. ** if there is no such type. Create a new one if the createFlag
  13734. ** is true and the type does not previously exist.
  13735. */
  13736. Tcl_HashEntry *pEntry;
  13737. if(CurrentSim->GlobalSim) {
  13738. pEntry=Tcl_FindHashEntry(&CurrentSim->GlobalSim->SimTypeIdSet,(char *)id);
  13739. } else {
  13740. pEntry=Tcl_FindHashEntry(&CurrentSim->SimTypeIdSet,(char *)id);
  13741. }
  13742. if(pEntry) {
  13743. return (Entity*)Tcl_GetHashValue(pEntry);
  13744. }
  13745. if(createFlag) {
  13746. int isNew;
  13747. Entity *p;
  13748. if(CurrentSim->GlobalSim) {
  13749. pEntry = Tcl_CreateHashEntry(&CurrentSim->GlobalSim->SimTypeIdSet,(char *)id, &isNew);
  13750. } else {
  13751. pEntry = Tcl_CreateHashEntry(&CurrentSim->SimTypeIdSet,(char *)id, &isNew);
  13752. }
  13753. p = (Entity *)Odie_Alloc( sizeof(*p) );
  13754. p->id = id;
  13755. p->pType=NULL;
  13756. Entity_StructAlloc(p);
  13757. p->public_is_type=1;
  13758. Tcl_SetHashValue(pEntry,(ClientData)p);
  13759.  
  13760. return p;
  13761. }
  13762. return NULL;
  13763. }
  13764. /* *SimType_ByName */
  13765. Entity *SimType_ByName(char *idstring, int createFlag){
  13766. Roid i=-1;
  13767. i=Odie_RoidFromString(idstring,'y');
  13768.  
  13769. if(i<0) {
  13770. return NULL;
  13771. }
  13772. return SimType_ById(i,createFlag);
  13773. }
  13774. /* *SimType_First */
  13775. Tcl_HashEntry *SimType_First(Simulator *sim,Tcl_HashSearch *search){
  13776. /*
  13777. ** Return the first entity in a list of them all
  13778. */
  13779. if(sim->GlobalSim) {
  13780. return Tcl_FirstHashEntry(&sim->GlobalSim->SimTypeIdSet,search);
  13781. } else {
  13782. return Tcl_FirstHashEntry(&sim->SimTypeIdSet,search);
  13783. }
  13784. }
  13785. /* *SimType_GroupToTclObj */
  13786. Tcl_Obj *SimType_GroupToTclObj(Entity *pNode){
  13787. Roid groupid;
  13788. if(!pNode) {
  13789. return Tcl_NewBooleanObj(0);
  13790. }
  13791. groupid=SimType_StructGetGroup(pNode);
  13792. if(!groupid) {
  13793. return Tcl_NewBooleanObj(0);
  13794. }
  13795. return Irm_NewRoidObj(groupid);
  13796. }
  13797. /* *SimType_Identify */
  13798. Tcl_Obj *SimType_Identify(Entity *pNode){
  13799. if(!pNode) {
  13800. return Irm_NewRoidObj(0);
  13801. }
  13802. return Irm_NewRoidObj(pNode->id);
  13803. }
  13804. /* *SimType_PublicId */
  13805. Tcl_Obj *SimType_PublicId(Entity *pNode){
  13806. char idstring[64];
  13807. if(!pNode) {
  13808. return Irm_NewRoidObj(0);
  13809. }
  13810. if(pNode->pType) {
  13811. if(pNode->pType->name!=NULL) {
  13812. return Odie_LiteralStringObj(pNode->pType->name);
  13813. }
  13814. }
  13815. sprintf(idstring,"y%d",pNode->id);
  13816. return Odie_LiteralStringObj(idstring);
  13817. }
  13818. /* *SimType_StructGetType */
  13819. Entity *SimType_StructGetType(Entity *p){
  13820. if(p->pType) {
  13821. return Entity_StructGetType(p->pType);
  13822. }
  13823. return NULL;
  13824. }
  13825. /* *SimType_StructToDict */
  13826. Tcl_Obj *SimType_StructToDict(Tcl_Interp *interp,Entity *p,int virtual){
  13827. Tcl_Obj *pResult=NULL;
  13828. if (virtual) {
  13829. pResult=Entity_GetDict(p->pType,NULL);
  13830. }
  13831. return pResult;
  13832. }
  13833. /* *SimType_TypeToTclObj */
  13834. Tcl_Obj *SimType_TypeToTclObj(Entity *pNode){
  13835. Entity *pType;
  13836. if(!pNode) {
  13837. return Tcl_NewBooleanObj(0);
  13838. }
  13839. pType=SimType_StructGetType(pNode);
  13840. if(!pType) {
  13841. return Tcl_NewBooleanObj(0);
  13842. }
  13843. return Irm_NewRoidObj(pType->id);
  13844. }
  13845. /* SimType_ApplySettings */
  13846. inline extern void SimType_ApplySettings(Entity *p){
  13847. /* Default implementation does nothing */
  13848. }
  13849. /* SimType_FromTclObj */
  13850. int SimType_FromTclObj(Tcl_Interp *interp, Tcl_Obj *pObj, Entity **ppEntity){
  13851. /*
  13852. ** Find a SimType given a Tcl_Obj that contains the SimType ID.
  13853. ** Leave an error message in interp and return TCL_ERROR if anything
  13854. ** goes wrong.
  13855. */
  13856. Roid i=-1;
  13857. i=Odie_RoidFromString(Tcl_GetString(pObj),'y');
  13858.  
  13859. if(i<0) {
  13860. if(interp) {
  13861. Tcl_AppendResult(interp, "no such SimType: ",
  13862. Tcl_GetStringFromObj(pObj, 0), 0);
  13863. }
  13864. }
  13865. *ppEntity = SimType_ById(i, 0);
  13866. if( *ppEntity==0 ){
  13867. if(interp) {
  13868. Tcl_AppendResult(interp, "no such SimType: ",
  13869. Tcl_GetStringFromObj(pObj, 0), 0);
  13870. }
  13871. return TCL_ERROR;
  13872. }
  13873. return TCL_OK;
  13874. }
  13875. /* SimType_Module_Advance */
  13876. void SimType_Module_Advance(Simulator *ActiveSim,int clocktime){}
  13877. /* SimType_nodeeval */
  13878. int SimType_nodeeval(Tcl_Interp *interp,Entity *p,Tcl_Obj *body,int writeback){
  13879. Tcl_Obj *id;
  13880. int i,len;
  13881. Tcl_Obj *varv[CSTRUCT_ENTITY_Count*2];
  13882. int result;
  13883.  
  13884. Entity_StructWith(interp,p,1,varv);
  13885. id=SimType_Identify(p);
  13886. Tcl_ObjSetVar2(interp,Odie_LiteralStringObj("id"),NULL,id,0);
  13887. Tcl_ObjSetVar2(interp,Odie_LiteralStringObj("typeid"),NULL,SimType_TypeToTclObj(p),0);
  13888. Tcl_ObjSetVar2(interp,Odie_LiteralStringObj("groupid"),NULL,SimType_GroupToTclObj(p),0);
  13889. /*
  13890. for(i=0;i<CSTRUCT_ENTITY_Count*2;i++) {
  13891. Tcl_IncrRefCount(varv[i]);
  13892. }
  13893. */
  13894. result=Tcl_EvalObjEx(interp, body, 0);
  13895.  
  13896. if(result!=TCL_OK) {
  13897. return result;
  13898. }
  13899. if(writeback){
  13900. /*
  13901. ** Read values back into the dict
  13902. ** For now, we limit writeback to state variables
  13903. ** And we don't care about garbage values
  13904. */
  13905. int changed=0;
  13906. for(i=0;i<CSTRUCT_ENTITY_Count*2;i+=2) {
  13907. Tcl_Obj *newValue;
  13908. int offset;
  13909. int type;
  13910. newValue=Tcl_ObjGetVar2(interp,varv[i],(Tcl_Obj*)NULL,0);
  13911. if(newValue==varv[i+1]) {
  13912. /* Undocumented, unsanctioned, but it works in practice
  13913. ** If the pointer hasn't changed, neither has the value
  13914. */
  13915. continue;
  13916. }
  13917. if(!newValue) {
  13918. /* Variable must have been unset... move along */
  13919. continue;
  13920. }
  13921. if( Entity_StructValueOffset(0, varv[i], &offset, &type) == TCL_OK ) {
  13922. Entity_StructSet(interp,p,offset,newValue);
  13923. changed++;
  13924. }
  13925. }
  13926. if(changed) {
  13927. Entity_ApplySettings(p);
  13928. }
  13929. }
  13930. /*
  13931. for(i=0;i<CSTRUCT_ENTITY_Count*2;i++) {
  13932. Tcl_DecrRefCount(varv[i]);
  13933. }
  13934. */
  13935. return TCL_OK;
  13936. }
  13937. /* SimType_Rewind */
  13938. void SimType_Rewind(Entity *p, int revert){}
  13939. /* SimType_StructGetGroup */
  13940. Roid SimType_StructGetGroup(Entity *p){
  13941. if(!p) {
  13942. return 0;
  13943. }
  13944. if (p->public_class=='g') {
  13945. return p->id;
  13946. }
  13947. if(p->public_groupid) {
  13948. return p->public_groupid;
  13949. }
  13950. if(p->public_parent) {
  13951. Entity *pType=SimType_ById(p->public_parent,0);
  13952. if(pType) {
  13953. if (pType->public_class=='g') {
  13954. return pType->id;
  13955. }
  13956. /* Otherwise, keep looking for parents */
  13957. return SimType_StructGetGroup(pType);
  13958. }
  13959. }
  13960. return 0;
  13961. }
  13962. /* SimType_StructSetGroup */
  13963. void SimType_StructSetGroup(Entity *p,Roid groupid){
  13964. p->public_groupid=groupid;
  13965. }
  13966. /* SimType_StructSetType */
  13967. void SimType_StructSetType(Entity *p,Entity *pType){
  13968. if(!p->pType) {
  13969. return;
  13970. }
  13971. Entity_StructSetType(p->pType,pType);
  13972. }
  13973. /* SimType_StructWith */
  13974. void SimType_StructWith(Tcl_Interp *interp,Entity *p,int virtual){
  13975. if (virtual) {
  13976. Entity_With(interp,p->pType,p->infoDict);
  13977. }
  13978. }
  13979. /* SimType_Unlink */
  13980. void SimType_Unlink(Entity *objPtr){
  13981. Tcl_HashEntry *pEntry;
  13982. if(CurrentSim->GlobalSim) {
  13983. pEntry=Tcl_FindHashEntry(&CurrentSim->GlobalSim->SimTypeIdSet,(char *)objPtr->id);
  13984. } else {
  13985. pEntry=Tcl_FindHashEntry(&CurrentSim->SimTypeIdSet,(char *)objPtr->id);
  13986. }
  13987. if(pEntry) {
  13988. Tcl_DeleteHashEntry(pEntry);
  13989. }
  13990. }
  13991. /* TypeSpec_SetInt */
  13992. void TypeSpec_SetInt(Entity *pType,char *field, int value){
  13993. Tcl_Obj *newValue;
  13994. if(!pType) return;
  13995. newValue=Tcl_NewIntObj(value);
  13996. Odie_HashPut(&pType->infoDict,field,newValue);
  13997. //Tcl_DecrRefCount(newValue);
  13998. }
  13999. /* TypeSpec_SetReal */
  14000. void TypeSpec_SetReal(Entity *pType,char *field, IrmReal value){
  14001. Tcl_Obj *newValue;
  14002. if(!pType) return;
  14003. double fabsvalue=fabs(value);
  14004. if(fabsvalue == value && fabsvalue < 10 ) {
  14005. TypeSpec_SetInt(pType,field,(int)value);
  14006. return;
  14007. }
  14008. newValue=Tcl_NewDoubleObj((double)value);
  14009. Odie_HashPut(&pType->infoDict,field,newValue);
  14010. //Tcl_DecrRefCount(newValue);
  14011. }
  14012. /* TypeSpec_SetWideInt */
  14013. void TypeSpec_SetWideInt(Entity *pType, char *field, Tcl_WideInt value){
  14014. Tcl_Obj *newValue;
  14015. if(!pType) return;
  14016. if(value > -10 && value < 10) {
  14017. TypeSpec_SetInt(pType,field,(int)value);
  14018. return;
  14019. }
  14020. newValue=Tcl_NewWideIntObj(value);
  14021. Odie_HashPut(&pType->infoDict,field,newValue);
  14022. //Tcl_DecrRefCount(newValue);
  14023. }
  14024. /* TypeSpec_Exists */
  14025. IrmReal TypeSpec_Exists(Entity *pType, char *field){
  14026. Tcl_Obj *result=NULL;
  14027. if(field && pType) {
  14028. result=Entity_GetField(pType->pType,pType->infoDict,field);
  14029. }
  14030. if(result) {
  14031. return 1;
  14032. }
  14033. return 0;
  14034. }
  14035. /* TypeSpec_GetReal */
  14036. IrmReal TypeSpec_GetReal(Entity *pType, char *field){
  14037. Tcl_Obj *result=NULL;
  14038. if(field && pType) {
  14039. result=Entity_GetField(pType->pType,pType->infoDict,field);
  14040. }
  14041. if(result) {
  14042. double s;
  14043. if (Tcl_GetDoubleFromObj(NULL,result,&s)==TCL_OK) {
  14044. return s;
  14045. }
  14046. }
  14047. return 0.0;
  14048. }
  14049. /* TypeSpec_GetReal_Or_Default */
  14050. IrmReal TypeSpec_GetReal_Or_Default(Entity *pType, char *field,IrmReal defaultValue){
  14051. Tcl_Obj *result=NULL;
  14052. if(field && pType) {
  14053. result=Entity_GetField(pType->pType,pType->infoDict,field);
  14054. }
  14055. if(result) {
  14056. double s;
  14057. if (Tcl_GetDoubleFromObj(NULL,result,&s)==TCL_OK) {
  14058. return s;
  14059. }
  14060. }
  14061. return defaultValue;
  14062. }
  14063. /* TypeSpec_GetInt */
  14064. int TypeSpec_GetInt(Entity *pType, char *field){
  14065. Tcl_Obj *result=NULL;
  14066. if(field && pType) {
  14067. result=Entity_GetField(pType->pType,pType->infoDict,field);
  14068. }
  14069. if(result) {
  14070. int sint;
  14071. double s;
  14072. if (Tcl_GetIntFromObj(NULL,result,&sint)==TCL_OK) {
  14073. return sint;
  14074. }
  14075. if (Tcl_GetDoubleFromObj(NULL,result,&s)==TCL_OK) {
  14076. return (int)round(s);
  14077. }
  14078. }
  14079. return 0;
  14080. }
  14081. /* TypeSpec_GetInt_or_Default */
  14082. int TypeSpec_GetInt_or_Default(Entity *pType, char *field,int dValue){
  14083. Tcl_Obj *result=NULL;
  14084. if(field && pType) {
  14085. result=Entity_GetField(pType->pType,pType->infoDict,field);
  14086. }
  14087. if(result) {
  14088. int sint;
  14089. double s;
  14090. if (Tcl_GetIntFromObj(NULL,result,&sint)==TCL_OK) {
  14091. return sint;
  14092. }
  14093. if (Tcl_GetDoubleFromObj(NULL,result,&s)==TCL_OK) {
  14094. return (int)round(s);
  14095. }
  14096. }
  14097. return dValue;
  14098. }
  14099. /* TypeSpec_WideInt */
  14100. Tcl_WideInt TypeSpec_WideInt(Entity *pType, char *field){
  14101. Tcl_Obj *result=NULL;
  14102. if(field && pType) {
  14103. result=Entity_GetField(pType->pType,pType->infoDict,field);
  14104. }
  14105. if(result) {
  14106. Tcl_WideInt c;
  14107. if(Tcl_GetWideIntFromObj(NULL,result,&c)==TCL_OK) {
  14108. return c;
  14109. }
  14110. }
  14111. return 0;
  14112. }
  14113. /* *TypeSpec_GetTclObj */
  14114. Tcl_Obj *TypeSpec_GetTclObj(Entity *pType, char *field){
  14115. Tcl_Obj *result=NULL;
  14116.  
  14117. if(field && pType) {
  14118. result=Entity_GetField(pType->pType,pType->infoDict,field);
  14119. }
  14120. if(result) {
  14121. return result;
  14122. }
  14123. return Tcl_NewObj();
  14124. }
  14125. /* *TypeSpec_GetTclObj_OR_NULL */
  14126. Tcl_Obj *TypeSpec_GetTclObj_OR_NULL(Entity *pType, char *field){
  14127. Tcl_Obj *result=NULL;
  14128.  
  14129. if(field && pType) {
  14130. result=Entity_GetField(pType->pType,pType->infoDict,field);
  14131. }
  14132. return result;
  14133. }
  14134. /* *TypeSpec_GetLogicSet */
  14135. Tcl_Obj *TypeSpec_GetLogicSet(Entity *pType, char *field){
  14136. if(field && pType) {
  14137. return Entity_GetField(pType->pType,pType->infoDict,field);
  14138. }
  14139. return NULL;
  14140. }
  14141. /* END generate-cfile-functions */
  14142. /* BEGIN generate-cfile-tclapi */
  14143. /* Tcl Proc ::odiemath::distance */
  14144. static int TclCmd_odiemath_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14145. int i;
  14146. double result;
  14147. if( objc<1 ){
  14148. Tcl_WrongNumArgs(interp, 1, objv, "i1 i2 ?j1 j2? ?k1 k2?");
  14149. return TCL_ERROR;
  14150. }
  14151. result=0.0;
  14152. for(i=1;i<objc;i+=2) {
  14153. double a,b,dx;
  14154. if(Tcl_GetDoubleFromObj(interp,objv[i],&a)) return TCL_ERROR;
  14155. if(i+1>=objc) {
  14156. Tcl_AppendResult(interp, "Odd number of arguments",(char*)0);
  14157. return TCL_ERROR;
  14158. }
  14159. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&b)) return TCL_ERROR;
  14160. dx=b-a;
  14161. result=result+dx*dx;
  14162. }
  14163. result=sqrt(result);
  14164. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  14165. return TCL_OK;
  14166. }
  14167. /* Tcl Proc ::odiemath::dist3d */
  14168. static int TclCmd_odiemath_dist3d(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14169. double result,ax,ay,az,bx,by,bz,dx,dy,dz;
  14170. if( objc!=7 ){
  14171. Tcl_WrongNumArgs(interp, 1, objv, "x0 y0 z0 x1 y1 z1");
  14172. return TCL_ERROR;
  14173. }
  14174. result=0.0;
  14175. if(Tcl_GetDoubleFromObj(interp,objv[1],&ax)) return TCL_ERROR;
  14176. if(Tcl_GetDoubleFromObj(interp,objv[2],&ay)) return TCL_ERROR;
  14177. if(Tcl_GetDoubleFromObj(interp,objv[3],&az)) return TCL_ERROR;
  14178. if(Tcl_GetDoubleFromObj(interp,objv[4],&bx)) return TCL_ERROR;
  14179. if(Tcl_GetDoubleFromObj(interp,objv[5],&by)) return TCL_ERROR;
  14180. if(Tcl_GetDoubleFromObj(interp,objv[6],&bz)) return TCL_ERROR;
  14181. dx=bx-ax;
  14182. dy=by-ay;
  14183. dz=bz-az;
  14184.  
  14185. result=sqrt(dx*dx + dy*dy + dz*dz);
  14186. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  14187. return TCL_OK;
  14188. }
  14189. /* Tcl Proc ::odiemath::grid_hex */
  14190. static int TclCmd_odiemath_grid_hex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14191. double grid, x, y;
  14192. int gx,gy;
  14193. Tcl_Obj *pResult;
  14194.  
  14195. if( objc != 4 ){
  14196. Tcl_WrongNumArgs(interp, 1, objv, "gridsize x y");
  14197. return TCL_ERROR;
  14198. }
  14199. if(Tcl_GetDoubleFromObj(interp,objv[1],&grid)) return TCL_ERROR;
  14200. if(Tcl_GetDoubleFromObj(interp,objv[2],&x)) return TCL_ERROR;
  14201. if(Tcl_GetDoubleFromObj(interp,objv[3],&y)) return TCL_ERROR;
  14202. pResult=Tcl_NewObj();
  14203. gy=(int)round(y/grid);
  14204. if(gy%2==1){
  14205. gx=(int)round((x-grid/2)/grid);
  14206. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*gx+grid/2));
  14207. } else {
  14208. gx=(int)round(x/grid);
  14209. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*gx));
  14210. }
  14211. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*gy));
  14212. Tcl_SetObjResult(interp, pResult);
  14213. return TCL_OK;
  14214. }
  14215. /* Tcl Proc ::odiemath::grid_round */
  14216. static int TclCmd_odiemath_grid_round(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14217. double x,q;
  14218. int i;
  14219. Tcl_Obj *pResult;
  14220. pResult=Tcl_NewObj();
  14221. for(i=1;i<objc;i++) {
  14222. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) {
  14223. Tcl_DecrRefCount(pResult);
  14224. return TCL_ERROR;
  14225. }
  14226. q=OdieGrain*round(x/OdieGrain);
  14227. if(x-q>(OdieGrain*0.5)) {
  14228. q+=OdieGrain;
  14229. }
  14230. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(q));
  14231. }
  14232. Tcl_SetObjResult(interp, pResult);
  14233. return TCL_OK;
  14234. }
  14235. /* Tcl Proc ::odiemath::grid_square */
  14236. static int TclCmd_odiemath_grid_square(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14237. double grid;
  14238. double x;
  14239. double y;
  14240. Tcl_Obj *pResult;
  14241. if( objc < 3 ){
  14242. Tcl_WrongNumArgs(interp, 1, objv, "gridsize x y...");
  14243. return TCL_ERROR;
  14244. }
  14245. if(Tcl_GetDoubleFromObj(interp,objv[1],&grid)) return TCL_ERROR;
  14246. if(Tcl_GetDoubleFromObj(interp,objv[2],&x)) return TCL_ERROR;
  14247. if(Tcl_GetDoubleFromObj(interp,objv[3],&y)) return TCL_ERROR;
  14248. pResult=Tcl_NewObj();
  14249. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*round(x/grid)));
  14250. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*round(y/grid)));
  14251. Tcl_SetObjResult(interp, pResult);
  14252. return TCL_OK;
  14253. }
  14254. /* Tcl Proc ::odiemath::list_round */
  14255. static int TclCmd_odiemath_list_round(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14256. int i, n;
  14257. double factor;
  14258. Tcl_Obj *pResult;
  14259. if( objc < 3 ){
  14260. Tcl_WrongNumArgs(interp, 1, objv, "gridsize list\ngridsize element ?element?...");
  14261. return TCL_ERROR;
  14262. }
  14263. if(Tcl_GetDoubleFromObj(interp,objv[1],&factor)) return TCL_ERROR;
  14264. if(objc==3) {
  14265. if( Tcl_ListObjLength(interp, objv[2], &n) ) return TCL_ERROR;
  14266. pResult=Tcl_NewObj();
  14267. for(i=0;i<n;i++) {
  14268. double thisval,remainder;
  14269. Tcl_Obj *pObj;
  14270. Tcl_ListObjIndex(0, objv[2], i, &pObj);
  14271. if(Tcl_GetDoubleFromObj(interp,pObj,&thisval)) {
  14272. Tcl_DecrRefCount(pResult);
  14273. return TCL_ERROR;
  14274. }
  14275. remainder=fmod(thisval,factor);
  14276. Tcl_ListObjAppendElement(interp, pResult, ODIE_NewFuzzyObj(thisval-remainder));
  14277. }
  14278. } else {
  14279. pResult=Tcl_NewObj();
  14280. for(i=2;i<objc;i++) {
  14281. double thisval,remainder;
  14282. if(Tcl_GetDoubleFromObj(interp,objv[i],&thisval)) {
  14283. Tcl_DecrRefCount(pResult);
  14284. return TCL_ERROR;
  14285. }
  14286. remainder=fmod(thisval,factor);
  14287. Tcl_ListObjAppendElement(interp, pResult, ODIE_NewFuzzyObj(thisval-remainder));
  14288. }
  14289. }
  14290. Tcl_SetObjResult(interp,pResult);
  14291. return TCL_OK;
  14292. }
  14293. /* Tcl Proc ::odiemath::list_to_int */
  14294. static int TclCmd_odiemath_list_to_int(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14295. Tcl_Obj *pResult=Tcl_NewObj();
  14296. int i;
  14297. for(i=1;i<objc;i++) {
  14298. double thisval;
  14299. if(Tcl_GetDoubleFromObj(interp,objv[i],&thisval)) return TCL_ERROR;
  14300. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewIntObj((int)thisval));
  14301. }
  14302. Tcl_SetObjResult(interp,pResult);
  14303. return TCL_OK;
  14304. }
  14305. /* Tcl Proc ::odiemath::matrix_rotate_angle */
  14306. static int TclCmd_odiemath_matrix_rotate_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14307. Tcl_Obj *pResult=Tcl_NewObj();
  14308. double angle;
  14309. if( (objc != 2) && (objc != 3) ){
  14310. Tcl_WrongNumArgs(interp, 1, objv, "angle ?units?");
  14311. return TCL_ERROR;
  14312. }
  14313. if(Tcl_GetDoubleFromObj(interp,objv[1],&angle)) return TCL_ERROR;
  14314. if(objc==3) {
  14315. /* Scale by the unit */
  14316. char *units;
  14317. units=Tcl_GetString(objv[2]);
  14318. if(units[0]=='d') {
  14319. angle=angle/180.0*M_PI;
  14320. } else if (units[0]=='g') {
  14321. angle=angle/200.0*M_PI;
  14322. } else if (units[0]=='r') {
  14323. } else {
  14324. Tcl_AppendResult(interp, "Unknown unit ", units, " use d[egrees], r[adians], or g[radients]. Radians are assumed",(char*)0);
  14325. return TCL_ERROR;
  14326. }
  14327. }
  14328. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
  14329. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sin(angle)));
  14330. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(-sin(angle)));
  14331. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
  14332. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(0.0));
  14333. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(0.0));
  14334. Tcl_SetObjResult(interp, pResult);
  14335. return TCL_OK;
  14336. }
  14337. /* Tcl Proc ::odiemath::matrix_rotate_normal */
  14338. static int TclCmd_odiemath_matrix_rotate_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14339. Tcl_Obj *pResult=Tcl_NewObj();
  14340. double nx,ny,angle;
  14341.  
  14342. if( objc != 3 ){
  14343. Tcl_WrongNumArgs(interp, 1, objv, "nx ny");
  14344. return TCL_ERROR;
  14345. }
  14346. if(Tcl_GetDoubleFromObj(interp,objv[1],&nx)) return TCL_ERROR;
  14347. if(Tcl_GetDoubleFromObj(interp,objv[2],&ny)) return TCL_ERROR;
  14348. angle=atan2(ny,nx);
  14349.  
  14350. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
  14351. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sin(angle)));
  14352. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(-sin(angle)));
  14353. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
  14354. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(0.0));
  14355. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(0.0));
  14356. Tcl_SetObjResult(interp, pResult);
  14357. return TCL_OK;
  14358. }
  14359. /* Tcl Proc ::odiemath::normal */
  14360. static int TclCmd_odiemath_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14361. double x0,y0,x1,y1;
  14362. double L,dx,dy;
  14363. Tcl_Obj *pResult;
  14364. if( objc != 5 ){
  14365. Tcl_WrongNumArgs(interp, 1, objv, "x0 y0 x1 y1");
  14366. return TCL_ERROR;
  14367. }
  14368. if(Tcl_GetDoubleFromObj(interp,objv[1],&x0)) return TCL_ERROR;
  14369. if(Tcl_GetDoubleFromObj(interp,objv[2],&y0)) return TCL_ERROR;
  14370. if(Tcl_GetDoubleFromObj(interp,objv[3],&x1)) return TCL_ERROR;
  14371. if(Tcl_GetDoubleFromObj(interp,objv[4],&y1)) return TCL_ERROR;
  14372.  
  14373. dx=x1-x0;
  14374. dy=y1-y0;
  14375. L=sqrt(dx*dx+dy*dy);
  14376. pResult=Tcl_NewObj();
  14377. if(ODIE_Real_Is_Zero(L)) {
  14378. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(100));
  14379. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(0));
  14380. } else {
  14381. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj((int)100*(dx/L)));
  14382. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj((int)100*(dy/L)));
  14383. }
  14384. Tcl_SetObjResult(interp, pResult);
  14385. return TCL_OK;
  14386. }
  14387. /* Tcl Proc ::odiemath::perpendicular */
  14388. static int TclCmd_odiemath_perpendicular(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14389. double x0,y0,x1,y1;
  14390. double L,dx,dy;
  14391. Tcl_Obj *pResult;
  14392. if( objc != 5 ){
  14393. Tcl_WrongNumArgs(interp, 1, objv, "x0 y0 x1 y1");
  14394. return TCL_ERROR;
  14395. }
  14396. if(Tcl_GetDoubleFromObj(interp,objv[1],&x0)) return TCL_ERROR;
  14397. if(Tcl_GetDoubleFromObj(interp,objv[2],&y0)) return TCL_ERROR;
  14398. if(Tcl_GetDoubleFromObj(interp,objv[3],&x1)) return TCL_ERROR;
  14399. if(Tcl_GetDoubleFromObj(interp,objv[4],&y1)) return TCL_ERROR;
  14400.  
  14401. dx=y1-y0;
  14402. dy=x0-x1;
  14403. L=sqrt(dx*dx+dy*dy);
  14404. pResult=Tcl_NewObj();
  14405. if(ODIE_Real_Is_Zero(L)) {
  14406. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(100));
  14407. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(0));
  14408. } else {
  14409. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj((int)100*(dx/L)));
  14410. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj((int)100*(dy/L)));
  14411. }
  14412. Tcl_SetObjResult(interp, pResult);
  14413. return TCL_OK;
  14414. }
  14415. /* Tcl Proc ::odiemath::normal_2d */
  14416. static int TclCmd_odiemath_normal_2d(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14417. double nx,ny,norm;
  14418. int ox,oy;
  14419. Tcl_Obj *pResult;
  14420. if( objc < 3 ){
  14421. ox=100;
  14422. oy=0;
  14423. } else {
  14424. if(Tcl_GetDoubleFromObj(interp,objv[1],&nx)) return TCL_ERROR;
  14425. if(Tcl_GetDoubleFromObj(interp,objv[2],&ny)) return TCL_ERROR;
  14426. norm=sqrt(nx*nx+ny*ny);
  14427. if(norm<=0.0) {
  14428. ox=100.0;
  14429. oy=0.0;
  14430. } else {
  14431. ox=100*nx/norm;
  14432. oy=100*ny/norm;
  14433. }
  14434. }
  14435. pResult=Tcl_NewObj();
  14436. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(ox));
  14437. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(oy));
  14438. Tcl_SetObjResult(interp, pResult);
  14439. return TCL_OK;
  14440. }
  14441. /* Tcl Proc ::odiemath::parallel_segment */
  14442. static int TclCmd_odiemath_parallel_segment(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14443. double x0,y0,x1,y1,offset;
  14444. double L,dx,dy;
  14445. Tcl_Obj *pResult;
  14446. if( objc != 6 ){
  14447. Tcl_WrongNumArgs(interp, 1, objv, "x0 y0 x1 y1 offset");
  14448. return TCL_ERROR;
  14449. }
  14450. if(Tcl_GetDoubleFromObj(interp,objv[1],&x0)) return TCL_ERROR;
  14451. if(Tcl_GetDoubleFromObj(interp,objv[2],&y0)) return TCL_ERROR;
  14452. if(Tcl_GetDoubleFromObj(interp,objv[3],&x1)) return TCL_ERROR;
  14453. if(Tcl_GetDoubleFromObj(interp,objv[4],&y1)) return TCL_ERROR;
  14454. if(Tcl_GetDoubleFromObj(interp,objv[5],&offset)) return TCL_ERROR;
  14455.  
  14456. dx=x0-x1;
  14457. dy=y0-y1;
  14458. L=sqrt(dx*dx+dy*dy);
  14459. if(ODIE_Real_Is_Zero(dx)) {
  14460. offset*=-1.0;
  14461. }
  14462. pResult=Tcl_NewObj();
  14463. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(x0+offset*dy/L));
  14464. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(y0+offset*dx/L));
  14465. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(x1+offset*dy/L));
  14466. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(y1+offset*dx/L));
  14467. Tcl_SetObjResult(interp, pResult);
  14468. return TCL_OK;
  14469. }
  14470. /* Tcl Proc ::odiemath::vector_length */
  14471. static int TclCmd_odiemath_vector_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14472. int i;
  14473. double result,sum=0.0;
  14474. if( objc<1 ){
  14475. Tcl_WrongNumArgs(interp, 1, objv, "x ?y? ?z? ?...?");
  14476. return TCL_ERROR;
  14477. }
  14478. result=0.0;
  14479. for(i=1;i<objc;i++) {
  14480. double a;
  14481. if(Tcl_GetDoubleFromObj(interp,objv[i],&a)) return TCL_ERROR;
  14482. sum+=a*a;
  14483. }
  14484. result=sqrt(sum);
  14485. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  14486. return TCL_OK;
  14487. }
  14488. /* Tcl Proc ::odiemath::vector_rotate_and_size */
  14489. static int TclCmd_odiemath_vector_rotate_and_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14490. /*
  14491. ** Apply Matrices
  14492. */
  14493. Tcl_Obj *pResult=Tcl_NewObj();
  14494. int i;
  14495. double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0};
  14496. double nx,ny,scalex,scaley,angle;
  14497.  
  14498. if( objc < 7 ){
  14499. Tcl_WrongNumArgs(interp, 1, objv, "normalx normaly sizex sizey x1 y1 ?x2 y2?...");
  14500. return TCL_ERROR;
  14501. }
  14502.  
  14503. if(Tcl_GetDoubleFromObj(interp,objv[1],&nx)) return TCL_ERROR;
  14504. if(Tcl_GetDoubleFromObj(interp,objv[2],&ny)) return TCL_ERROR;
  14505. if(Tcl_GetDoubleFromObj(interp,objv[3],&scalex)) return TCL_ERROR;
  14506. if(Tcl_GetDoubleFromObj(interp,objv[4],&scaley)) return TCL_ERROR;
  14507.  
  14508. angle=atan2(ny,nx);
  14509. matA[0]=cos(angle);
  14510. matA[1]=sin(angle);
  14511. matA[2]=-sin(angle);
  14512. matA[3]=cos(angle);
  14513. matA[4]=0.0;
  14514. matA[5]=0.0;
  14515.  
  14516. scalex*=0.5;
  14517. scaley*=0.5;
  14518. for(i=5;i<objc;i+=2) {
  14519. double x,y,sx,sy,newx,newy;
  14520. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
  14521. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
  14522. sx=x*scalex;
  14523. sy=y*scaley;
  14524. newx=matA[0]*sx+matA[1]*sy+matA[4];
  14525. newy=matA[2]*sx+matA[3]*sy+matA[5];
  14526.  
  14527. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
  14528. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
  14529. }
  14530. Tcl_SetObjResult(interp, pResult);
  14531. return TCL_OK;
  14532. }
  14533. /* Tcl Proc ::odiemath::vector_scale */
  14534. static int TclCmd_odiemath_vector_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14535. Tcl_Obj *pResult=Tcl_NewObj();
  14536. int i;
  14537. double scalex,scaley;
  14538.  
  14539. if( objc < 5 ){
  14540. Tcl_WrongNumArgs(interp, 1, objv, "sizex sizey x1 y1 ?x2 y2?...");
  14541. return TCL_ERROR;
  14542. }
  14543.  
  14544. if(Tcl_GetDoubleFromObj(interp,objv[1],&scalex)) return TCL_ERROR;
  14545. if(Tcl_GetDoubleFromObj(interp,objv[2],&scaley)) return TCL_ERROR;
  14546.  
  14547. scalex*=0.5;
  14548. scaley*=0.5;
  14549. for(i=3;i<objc;i+=2) {
  14550. double x,y,sx,sy;
  14551. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
  14552. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
  14553. sx=x*scalex;
  14554. sy=y*scaley;
  14555. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sx));
  14556. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sy));
  14557. }
  14558. Tcl_SetObjResult(interp, pResult);
  14559. return TCL_OK;
  14560. }
  14561. /* Tcl Proc ::odiemath::vector_translate_and_zoom */
  14562. static int TclCmd_odiemath_vector_translate_and_zoom(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14563. /*
  14564. ** Apply Matrices
  14565. */
  14566.  
  14567. Tcl_Obj *pResult=Tcl_NewObj();
  14568. int i;
  14569. double zoom;
  14570. double centerx,centery;
  14571.  
  14572. if( objc < 6 ){
  14573. Tcl_WrongNumArgs(interp, 1, objv, "zoom centerx centery x1 y1 ?x2 y2?...");
  14574. return TCL_ERROR;
  14575. }
  14576. if(Tcl_GetDoubleFromObj(interp,objv[1],&zoom)) return TCL_ERROR;
  14577. if(Tcl_GetDoubleFromObj(interp,objv[2],&centerx)) return TCL_ERROR;
  14578. if(Tcl_GetDoubleFromObj(interp,objv[3],&centery)) return TCL_ERROR;
  14579. for(i=4;i<objc;i+=2) {
  14580. double x,y,newx,newy;
  14581. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
  14582. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
  14583. newx=(x/zoom)+centerx;
  14584. newy=(y/zoom)+centery;
  14585. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
  14586. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
  14587. }
  14588. Tcl_SetObjResult(interp, pResult);
  14589. return TCL_OK;
  14590. }
  14591. /* Tcl Proc ::odiemath::grid */
  14592. static int TclCmd_odiemath_grid(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14593. if( objc > 1 ){
  14594. if(Tcl_GetDoubleFromObj(interp,objv[1],&OdieGrain)) return TCL_ERROR;
  14595. }
  14596. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(OdieGrain));
  14597. return TCL_OK;
  14598. }
  14599. /* Tcl Proc ::odiemath::tolerance */
  14600. static int TclCmd_odiemath_tolerance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14601. if( objc > 1 ){
  14602. if(Tcl_GetDoubleFromObj(interp,objv[1],&OdieTolerance)) return TCL_ERROR;
  14603. }
  14604. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(OdieTolerance));
  14605. return TCL_OK;
  14606. }
  14607. /* Tcl Proc ::odie::aabb::create */
  14608. static int TclCmd_odie_aabb_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14609. MATOBJ *C;
  14610. C=Odie_MatrixObj_Create(MATFORM_aabb_xyz);
  14611. VectorXYZ_AABB_Reset(C->matrix);
  14612. if(objc==7) {
  14613. int i;
  14614. for(i=1;i<objc;i++) {
  14615. if(Tcl_GetDoubleFromObj(interp,objv[1],&C->matrix[i-1])) return TCL_ERROR;
  14616. }
  14617. } else if(objc>1) {
  14618. int i;
  14619. VectorXYZ point;
  14620. for(i=1;i<objc;i++) {
  14621. if(Odie_GetVectorXYZFromTclObj(interp,objv[i],point)) return TCL_ERROR;
  14622. VectorXYZ_AABB_Measure(point,C->matrix);
  14623. }
  14624. }
  14625. Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
  14626. return TCL_OK;
  14627. }
  14628. /* Tcl Proc ::odie::aabb::overlap_two_vectors */
  14629. static int TclCmd_odie_aabb_overlap_two_vectors(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14630. VectorXYZ a1,a2,b1,b2;
  14631. double c;
  14632. if( objc != 5 ){
  14633. Tcl_WrongNumArgs(interp, 1, objv, "A1 A2 B1 B2");
  14634. return TCL_ERROR;
  14635. }
  14636. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],a1)) return TCL_ERROR;
  14637. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],a2)) return TCL_ERROR;
  14638. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],b1)) return TCL_ERROR;
  14639. if(Odie_GetVectorXYZFromTclObj(interp,objv[4],b2)) return TCL_ERROR;
  14640. c=VectorXYZ_BBOX_Overlap_TwoVectors(a1,a2,b1,b2);
  14641. Tcl_SetObjResult(interp, Tcl_NewIntObj(c));
  14642. return TCL_OK;
  14643. }
  14644. /* Tcl Proc ::odie::aabb::measure */
  14645. static int TclCmd_odie_aabb_measure(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14646. MATOBJ *C;
  14647. Tcl_Obj *varname,*pResult;
  14648. int i;
  14649. VectorXYZ point;
  14650. if( objc < 2 ){
  14651. Tcl_WrongNumArgs(interp, 1, objv, "BBOX VECTORXYZ ?VECTORXYZ..?");
  14652. return TCL_ERROR;
  14653. }
  14654. varname=Tcl_ObjGetVar2(interp,objv[1],NULL,0);
  14655. if(Odie_GetMatrixFromTclObj(interp,varname,MATFORM_aabb_xyz,&C)) return TCL_ERROR;
  14656. VectorXYZ_AABB_Normalize(C->matrix);
  14657. for(i=2;i<objc;i++) {
  14658. if(Odie_GetVectorXYZFromTclObj(interp,objv[i],point)) return TCL_ERROR;
  14659. VectorXYZ_AABB_Measure(point,C->matrix);
  14660. }
  14661. Tcl_InvalidateStringRep(varname);
  14662. return TCL_OK;
  14663. }
  14664. /* Tcl Proc ::odie::aabb::faces */
  14665. static int TclCmd_odie_aabb_faces(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14666. double VALUES[6];
  14667. double scale=1.0;
  14668. Tcl_Obj *pResult,*pRow;
  14669. if( objc != 2 && objc != 3 && objc != 7 && objc != 8){
  14670. Tcl_WrongNumArgs(interp, 1, objv, "AABB ?SCALE?\nx0 y0 z0 x1 y1 z1 ?SCALE?");
  14671. return TCL_ERROR;
  14672. }
  14673. if(objc==2 || objc==3) {
  14674. MATOBJ *A;
  14675. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_aabb_xyz,&A)) return TCL_ERROR;
  14676. if(objc==3) {
  14677. if(Tcl_GetDoubleFromObj(interp,objv[2],&scale)) {
  14678. scale=1.0;
  14679. }
  14680. }
  14681. VALUES[X_MIN_IDX]=A->matrix[X_MIN_IDX];
  14682. VALUES[Y_MIN_IDX]=A->matrix[Y_MIN_IDX];
  14683. VALUES[Z_MIN_IDX]=A->matrix[Z_MIN_IDX];
  14684. VALUES[X_MAX_IDX]=A->matrix[X_MAX_IDX];
  14685. VALUES[Y_MAX_IDX]=A->matrix[Y_MAX_IDX];
  14686. VALUES[Z_MAX_IDX]=A->matrix[Z_MAX_IDX];
  14687. } else {
  14688. if(objc==8) {
  14689. if(Tcl_GetDoubleFromObj(interp,objv[7],&scale)) {
  14690. scale=1.0;
  14691. }
  14692. }
  14693. if(Tcl_GetDoubleFromObj(interp,objv[1],&VALUES[0])!=TCL_OK) return TCL_ERROR;
  14694. if(Tcl_GetDoubleFromObj(interp,objv[2],&VALUES[1])!=TCL_OK) return TCL_ERROR;
  14695. if(Tcl_GetDoubleFromObj(interp,objv[3],&VALUES[2])!=TCL_OK) return TCL_ERROR;
  14696. if(Tcl_GetDoubleFromObj(interp,objv[4],&VALUES[3])!=TCL_OK) return TCL_ERROR;
  14697. if(Tcl_GetDoubleFromObj(interp,objv[5],&VALUES[4])!=TCL_OK) return TCL_ERROR;
  14698. if(Tcl_GetDoubleFromObj(interp,objv[6],&VALUES[5])!=TCL_OK) return TCL_ERROR;
  14699. }
  14700. pResult=Tcl_NewObj();
  14701. pRow=Tcl_NewObj();
  14702. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
  14703. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
  14704. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
  14705. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
  14706. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
  14707. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
  14708. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
  14709. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
  14710. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
  14711. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
  14712. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
  14713. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
  14714. Tcl_ListObjAppendElement(interp,pResult,pRow);
  14715. pRow=Tcl_NewObj();
  14716. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
  14717. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
  14718. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
  14719. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
  14720. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
  14721. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
  14722. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
  14723. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
  14724. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
  14725. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
  14726. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
  14727. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
  14728. Tcl_ListObjAppendElement(interp,pResult,pRow);
  14729. pRow=Tcl_NewObj();
  14730. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
  14731. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
  14732. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
  14733. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
  14734. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
  14735. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
  14736. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
  14737. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
  14738. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
  14739. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
  14740. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
  14741. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
  14742. Tcl_ListObjAppendElement(interp,pResult,pRow);
  14743. pRow=Tcl_NewObj();
  14744. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
  14745. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
  14746. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
  14747. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
  14748. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
  14749. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
  14750. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
  14751. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
  14752. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
  14753. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
  14754. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
  14755. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
  14756. Tcl_ListObjAppendElement(interp,pResult,pRow);
  14757. pRow=Tcl_NewObj();
  14758. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
  14759. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
  14760. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
  14761. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
  14762. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
  14763. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
  14764. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
  14765. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
  14766. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
  14767. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
  14768. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MAX_IDX]*scale));
  14769. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
  14770. Tcl_ListObjAppendElement(interp,pResult,pRow);
  14771. pRow=Tcl_NewObj();
  14772. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
  14773. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
  14774. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
  14775. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
  14776. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
  14777. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MAX_IDX]*scale));
  14778. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MIN_IDX]*scale));
  14779. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
  14780. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
  14781. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[X_MAX_IDX]*scale));
  14782. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Y_MIN_IDX]*scale));
  14783. Tcl_ListObjAppendElement(interp,pRow,Tcl_NewDoubleObj(VALUES[Z_MIN_IDX]*scale));
  14784. Tcl_ListObjAppendElement(interp,pResult,pRow);
  14785. Tcl_SetObjResult(interp,pResult);
  14786. return TCL_OK;
  14787. }
  14788. /* Tcl Proc ::odie::aabb::from_vectorxyz */
  14789. static int TclCmd_odie_aabb_from_vectorxyz(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14790. MATOBJ *A,*C;
  14791. if( objc < 2 ){
  14792. Tcl_WrongNumArgs(interp, 1, objv, "BBOX\nor\nA B ?C...?");
  14793. return TCL_ERROR;
  14794. }
  14795. if(objc==2) {
  14796. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_aabb_xyz,&C)) return TCL_ERROR;
  14797. VectorXYZ_AABB_Normalize(C->matrix);
  14798. } else {
  14799. int i;
  14800. C=Odie_MatrixObj_Create(MATFORM_aabb_xyz);
  14801. VectorXYZ_AABB_Reset(C->matrix);
  14802. for(i=1;i<objc;i++) {
  14803. if(Odie_GetMatrixFromTclObj(interp,objv[i],MATFORM_vectorxyz,&A)) return TCL_ERROR;
  14804. VectorXYZ_AABB_Measure(A->matrix,C->matrix);
  14805. }
  14806. }
  14807. Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
  14808. return TCL_OK;
  14809. }
  14810. /* Tcl Proc ::odie::aabb::from_line */
  14811. static int TclCmd_odie_aabb_from_line(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14812. VectorXYZ A,B;
  14813. VectorXYZ AA,BB;
  14814.  
  14815. Tcl_Obj *pResult=Tcl_NewObj();
  14816.  
  14817. if( objc != 3 ){
  14818. Tcl_WrongNumArgs(interp, 1, objv, "A B");
  14819. return TCL_ERROR;
  14820. }
  14821. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  14822. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  14823. AA[X_IDX]=min(A[X_IDX],B[X_IDX]);
  14824. AA[Y_IDX]=min(A[Y_IDX],B[Y_IDX]);
  14825. AA[Z_IDX]=min(A[Z_IDX],B[Z_IDX]);
  14826. BB[X_IDX]=max(A[X_IDX],B[X_IDX]);
  14827. BB[Y_IDX]=max(A[Y_IDX],B[Y_IDX]);
  14828. BB[Z_IDX]=max(A[Z_IDX],B[Z_IDX]);
  14829. pResult=Tcl_NewObj();;
  14830. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(AA));
  14831. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(BB));
  14832. Tcl_SetObjResult(interp, pResult);
  14833. return TCL_OK;
  14834. }
  14835. /* Tcl Proc ::odie::aabb::from_center_size */
  14836. static int TclCmd_odie_aabb_from_center_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14837. VectorXYZ center,size;
  14838. VectorXYZ AA,BB;
  14839.  
  14840. Tcl_Obj *pResult=Tcl_NewObj();
  14841.  
  14842. if( objc != 3 ){
  14843. Tcl_WrongNumArgs(interp, 1, objv, "center size");
  14844. return TCL_ERROR;
  14845. }
  14846. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],center)) return TCL_ERROR;
  14847. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],size)) return TCL_ERROR;
  14848. size[X_IDX]*=0.5;
  14849. size[Y_IDX]*=0.5;
  14850. size[Z_IDX]*=0.5;
  14851. pResult=Tcl_NewObj();
  14852. VectorXYZ_Subtract(AA,center,size);
  14853. VectorXYZ_Add(BB,center,size);
  14854. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(AA));
  14855. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(BB));
  14856. Tcl_SetObjResult(interp, pResult);
  14857. return TCL_OK;
  14858. }
  14859. /* Tcl Proc ::odie::aabb::intersect */
  14860. static int TclCmd_odie_aabb_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14861. MATOBJ *A,*B;
  14862. int c;
  14863. if( objc != 3 ){
  14864. Tcl_WrongNumArgs(interp, 1, objv, "AABB AABB");
  14865. return TCL_ERROR;
  14866. }
  14867. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_aabb_xyz,&A)) return TCL_ERROR;
  14868. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_aabb_xyz,&B)) return TCL_ERROR;
  14869. c=AABB_AABB_Intersect(A->matrix,B->matrix);
  14870. Tcl_SetObjResult(interp, Tcl_NewIntObj(c));
  14871. return TCL_OK;
  14872. }
  14873. /* Tcl Proc ::odie::aabb::within */
  14874. static int TclCmd_odie_aabb_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14875. MATOBJ *A,*B;
  14876. double c;
  14877. if( objc != 3 ){
  14878. Tcl_WrongNumArgs(interp, 1, objv, "AABB POINT");
  14879. return TCL_ERROR;
  14880. }
  14881. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_aabb_xyz,&A)) return TCL_ERROR;
  14882. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_vectorxyz,&B)) return TCL_ERROR;
  14883. c=VectorXYZ_AABB_Within(B->matrix,A->matrix);
  14884. Tcl_SetObjResult(interp, Tcl_NewIntObj(c));
  14885. return TCL_OK;
  14886. }
  14887. /* Tcl Proc ::affine2d::apply */
  14888. static int TclCmd_affine2d_apply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14889. Tcl_Obj *pResult=Tcl_NewObj();
  14890. int i;
  14891. double matA[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
  14892.  
  14893. if( objc < 4 ){
  14894. Tcl_WrongNumArgs(interp, 1, objv, "matrix x1 y1 ?x2 y2?...");
  14895. return TCL_ERROR;
  14896. }
  14897. for(i=0;i<6;i++) {
  14898. Tcl_Obj *temp;
  14899. if(Tcl_ListObjIndex(interp, objv[1], i, &temp)) return TCL_ERROR;
  14900. if(Odie_GetMatrixElementFromObj(interp,temp,matA,i)) return TCL_ERROR;
  14901. }
  14902.  
  14903. for(i=2;i<objc;i+=2) {
  14904. double x,y,newx,newy;
  14905. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
  14906. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
  14907. newx=matA[0]*x+matA[1]*y+matA[4];
  14908. newy=matA[2]*x+matA[3]*y+matA[5];
  14909. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
  14910. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
  14911. }
  14912. Tcl_SetObjResult(interp, pResult);
  14913. return TCL_OK;
  14914. }
  14915. /* Tcl Proc ::affine2d::combine */
  14916. static int TclCmd_affine2d_combine(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14917. int i,idx;
  14918. Tcl_Obj *pResult=Tcl_NewObj();
  14919. double matA[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
  14920. double matB[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
  14921.  
  14922. if( objc < 2){
  14923. Tcl_WrongNumArgs(interp, 1, objv, "transformA transformB ?transformC?...");
  14924. return TCL_ERROR;
  14925. }
  14926.  
  14927. for(i=0;i<6;i++) {
  14928. Tcl_Obj *temp;
  14929. if(Tcl_ListObjIndex(interp, objv[1], i, &temp)) return TCL_ERROR;
  14930. if(Odie_GetMatrixElementFromObj(interp,temp,matA,i)) return TCL_ERROR;
  14931. }
  14932. for(idx=2;idx<objc;idx++) {
  14933. for(i=0;i<6;i++) {
  14934. Tcl_Obj *temp;
  14935. if(Tcl_ListObjIndex(interp, objv[idx], i, &temp)) return TCL_ERROR;
  14936. if(Odie_GetMatrixElementFromObj(interp,temp,matB,i)) return TCL_ERROR;
  14937. }
  14938. matA[0]=matA[0]*matB[0]+matA[2]*matB[2]; /* [expr {$a*$i+$c*$j}] */
  14939. matA[1]=matA[1]*matB[0]+matA[3]*matB[2]; /* [expr {$b*$i+$d*$j}] */
  14940. matA[2]=matA[0]*matB[2]+matA[2]*matB[3]; /* [expr {$a*$k+$c*$l}] */
  14941. matA[3]=matA[1]*matB[2]+matA[3]*matB[3]; /* [expr {$b*$k+$d*$l}] */
  14942. matA[4]=matA[4]*matB[0]+matA[5]*matB[1]+matB[4]; /* [expr {$e*$i+$f*$j+$m}] */
  14943. matA[5]=matA[4]*matB[2]+matA[5]*matB[3]+matB[5]; /* [expr {$e*$k+$f*$l+$n}]] */
  14944. }
  14945. for(i=0;i<6;i++) {
  14946. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(matA[i]));
  14947. }
  14948. Tcl_SetObjResult(interp, pResult);
  14949. return TCL_OK;
  14950. }
  14951. /* Tcl Proc ::affine2d::rotation_from_angle */
  14952. static int TclCmd_affine2d_rotation_from_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14953. Tcl_Obj *pResult=Tcl_NewObj();
  14954. double angle;
  14955. if( (objc != 2) && (objc != 3) ){
  14956. Tcl_WrongNumArgs(interp, 1, objv, "angle ?units?");
  14957. return TCL_ERROR;
  14958. }
  14959. if(Tcl_GetDoubleFromObj(interp,objv[1],&angle)) return TCL_ERROR;
  14960. if(objc==3) {
  14961. /* Scale by the unit */
  14962. char *units;
  14963. units=Tcl_GetString(objv[2]);
  14964. if(units[0]=='d') {
  14965. angle=angle/180.0*M_PI;
  14966. } else if (units[0]=='g') {
  14967. angle=angle/200.0*M_PI;
  14968. } else if (units[0]=='r') {
  14969. } else {
  14970. Tcl_AppendResult(interp, "Unknown unit ", units, " use d[egrees], r[adians], or g[radients]. Radians are assumed",(char*)0);
  14971. return TCL_ERROR;
  14972. }
  14973. }
  14974. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
  14975. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sin(angle)));
  14976. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(-sin(angle)));
  14977. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
  14978. Tcl_ListObjAppendElement(interp,pResult,ODIE_REAL_ZERO());
  14979. Tcl_ListObjAppendElement(interp,pResult,ODIE_REAL_ZERO());
  14980. Tcl_SetObjResult(interp, pResult);
  14981. return TCL_OK;
  14982. }
  14983. /* Tcl Proc ::affine2d::rotation_from_normal */
  14984. static int TclCmd_affine2d_rotation_from_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  14985. Tcl_Obj *pResult=Tcl_NewObj();
  14986. double nx,ny,angle;
  14987.  
  14988. if( objc != 3 ){
  14989. Tcl_WrongNumArgs(interp, 1, objv, "nx ny");
  14990. return TCL_ERROR;
  14991. }
  14992. if(Tcl_GetDoubleFromObj(interp,objv[1],&nx)) return TCL_ERROR;
  14993. if(Tcl_GetDoubleFromObj(interp,objv[2],&ny)) return TCL_ERROR;
  14994. angle=atan2(ny,nx);
  14995.  
  14996. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
  14997. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sin(angle)));
  14998. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(-sin(angle)));
  14999. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cos(angle)));
  15000. Tcl_ListObjAppendElement(interp,pResult,ODIE_REAL_ZERO());
  15001. Tcl_ListObjAppendElement(interp,pResult,ODIE_REAL_ZERO());
  15002. Tcl_SetObjResult(interp, pResult);
  15003. return TCL_OK;
  15004. }
  15005. /* Tcl Proc ::affine4x4::compare */
  15006. static int TclCmd_affine4x4_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15007. Odie_MatrixObj *A,*B;
  15008. int c;
  15009. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_affine,&A)) return TCL_ERROR;
  15010. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_affine,&B)) return TCL_ERROR;
  15011. c=affine_Compare(A->matrix,B->matrix);
  15012. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(c));
  15013. return TCL_OK;
  15014. }
  15015. /* Tcl Proc ::affine4x4::identity */
  15016. static int TclCmd_affine4x4_identity(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15017. /*
  15018. ** description: Pushes an affine identity matrix onto the stack
  15019. */
  15020. Odie_MatrixObj *C;
  15021. C=Odie_MatrixObj_Create(MATFORM_affine);
  15022. Odie_Affine4x4_Identity(C->matrix);
  15023. Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
  15024. return TCL_OK;
  15025. }
  15026. /* Tcl Proc ::affine4x4::translation */
  15027. static int TclCmd_affine4x4_translation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15028. /*
  15029. ** description:
  15030. ** Convert a displacement vector (X Y Z) into an affine transformation
  15031. */
  15032. Odie_MatrixObj *A,*C;
  15033. if(objc != 2) {
  15034. Tcl_WrongNumArgs( interp, 1, objv, "VECTORXYZ" );
  15035. return TCL_ERROR;
  15036. }
  15037. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz,&A)) return TCL_ERROR;
  15038. C=Odie_MatrixObj_Create(MATFORM_affine);
  15039. Odie_Affine4x4_Translation(C->matrix,A->matrix);
  15040. Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
  15041. return TCL_OK;
  15042. }
  15043. /* Tcl Proc ::affine4x4::scale */
  15044. static int TclCmd_affine4x4_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15045. /*
  15046. ** description:
  15047. ** Convert a scale vector (X Y Z) into an affine transformation
  15048. */
  15049. Odie_MatrixObj *A,*C;
  15050. if(objc != 2) {
  15051. Tcl_WrongNumArgs( interp, 1, objv, "VECTORXYZ" );
  15052. return TCL_ERROR;
  15053. }
  15054. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz,&A)) return TCL_ERROR;
  15055. C=Odie_MatrixObj_Create(MATFORM_affine);
  15056. Odie_Affine4x4_Scale(C->matrix,A->matrix);
  15057. Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
  15058. return TCL_OK;
  15059. }
  15060. /* Tcl Proc ::affine4x4::rotate_nutation */
  15061. static int TclCmd_affine4x4_rotate_nutation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15062. double theta;
  15063. Odie_MatrixObj *RESULT;
  15064. if(objc != 2) {
  15065. Tcl_WrongNumArgs( interp, 1, objv, "RADIANS" );
  15066. return TCL_ERROR;
  15067. }
  15068. if(Tcl_GetDoubleFromObj(interp,objv[1],&theta)) return TCL_ERROR;
  15069. RESULT=Odie_MatrixObj_Create(MATFORM_affine);
  15070. affine_rotate_nutation(RESULT->matrix,theta);
  15071. Tcl_SetObjResult(interp,Matrix_To_TclObj(RESULT));
  15072. return TCL_OK;
  15073. }
  15074. /* Tcl Proc ::affine4x4::rotate_precession */
  15075. static int TclCmd_affine4x4_rotate_precession(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15076. double phi;
  15077. Odie_MatrixObj *RESULT;
  15078. Tcl_Obj *pResult;
  15079. if(objc != 2) {
  15080. Tcl_WrongNumArgs( interp, 1, objv, "RADIANS" );
  15081. return TCL_ERROR;
  15082. }
  15083. if(Tcl_GetDoubleFromObj(interp,objv[1],&phi)) return TCL_ERROR;
  15084. RESULT=Odie_MatrixObj_Create(MATFORM_affine);
  15085. affine_rotate_precession(RESULT->matrix,phi);
  15086. Tcl_SetObjResult(interp,Matrix_To_TclObj(RESULT));
  15087. return TCL_OK;
  15088. }
  15089. /* Tcl Proc ::affine4x4::rotate_spin */
  15090. static int TclCmd_affine4x4_rotate_spin(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15091. double psi;
  15092. Odie_MatrixObj *RESULT;
  15093. if(objc != 2) {
  15094. Tcl_WrongNumArgs( interp, 1, objv, "RADIANS" );
  15095. return TCL_ERROR;
  15096. }
  15097. if(Tcl_GetDoubleFromObj(interp,objv[1],&psi)) return TCL_ERROR;
  15098. RESULT=Odie_MatrixObj_Create(MATFORM_affine);
  15099. affine_rotate_spin(RESULT->matrix,psi);
  15100. Tcl_SetObjResult(interp,Matrix_To_TclObj(RESULT));
  15101. return TCL_OK;
  15102. }
  15103. /* Tcl Proc ::affine4x4::from_euler */
  15104. static int TclCmd_affine4x4_from_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15105. /*
  15106. ** description:
  15107. ** Convert a rotation vector (X Y Z) into an affine transformation
  15108. */
  15109. Odie_MatrixObj *A,*C;
  15110. if(objc != 2) {
  15111. Tcl_WrongNumArgs( interp, 1, objv, "EULER" );
  15112. return TCL_ERROR;
  15113. }
  15114. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_euler,&A)) return TCL_ERROR;
  15115. C=Odie_MatrixObj_Create(MATFORM_affine);
  15116. affine_Rotate_From_Euler(C->matrix,A->matrix);
  15117. Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
  15118. return TCL_OK;
  15119. }
  15120. /* Tcl Proc ::affine4x4::multiply */
  15121. static int TclCmd_affine4x4_multiply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15122. /*
  15123. ** description:
  15124. ** Multiply 2 4x4 matrices. Used to combine 2 affine transformations.
  15125. ** Note: Some affine transformations need to be performed in a particular
  15126. ** order to make sense.
  15127. */
  15128. Odie_MatrixObj *A,*B,*C;
  15129. if(objc < 3) {
  15130. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  15131. return TCL_ERROR;
  15132. }
  15133. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_affine,&A)) return TCL_ERROR;
  15134. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_affine,&B)) return TCL_ERROR;
  15135. C=Odie_MatrixObj_Create(MATFORM_affine);
  15136. Odie_Affine4x4_Multiply(C->matrix,A->matrix,B->matrix);
  15137. Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
  15138. return TCL_OK;
  15139. }
  15140. /* Tcl Proc ::affine4x4::multiply_inplace */
  15141. static int TclCmd_affine4x4_multiply_inplace(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15142. /*
  15143. ** description:
  15144. ** Multiply 2 4x4 matrices. Used to combine 2 affine transformations.
  15145. ** Note: Some affine transformations need to be performed in a particular
  15146. ** order to make sense.
  15147. */
  15148. Odie_MatrixObj *A,*B,*C;
  15149. Tcl_Obj *varname;
  15150. if(objc < 3) {
  15151. Tcl_WrongNumArgs( interp, 1, objv, "VARNAME AFFINE" );
  15152. return TCL_ERROR;
  15153. }
  15154. Tcl_ResetResult(interp);
  15155. varname=Tcl_ObjGetVar2(interp,objv[1],NULL,0);
  15156. if(Odie_GetMatrixFromTclObj(interp,varname,MATFORM_affine,&A)) return TCL_ERROR;
  15157. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_affine,&B)) return TCL_ERROR;
  15158. Odie_Affine4x4_Multiply(A->matrix,A->matrix,B->matrix);
  15159. Tcl_InvalidateStringRep(varname);
  15160. return TCL_OK;
  15161. }
  15162. /* Tcl Proc ::affine4x4::inverse */
  15163. static int TclCmd_affine4x4_inverse(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15164. /*
  15165. ** description:
  15166. ** Multiply 2 4x4 matrices. Used to combine 2 affine transformations.
  15167. ** Note: Some affine transformations need to be performed in a particular
  15168. ** order to make sense.
  15169. */
  15170. Odie_MatrixObj *A,*C;
  15171. if(objc < 2) {
  15172. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  15173. return TCL_ERROR;
  15174. }
  15175. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_affine,&A)) return TCL_ERROR;
  15176. C=Odie_MatrixObj_Create(MATFORM_affine);
  15177. Odie_Affine4x4_Inverse(C->matrix,A->matrix);
  15178. Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
  15179. return TCL_OK;
  15180. }
  15181. /* Tcl Proc ::affine4x4::from_normal */
  15182. static int TclCmd_affine4x4_from_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15183. /*
  15184. ** description:
  15185. ** Convert a displacement normal vector (X Y Z) into an affine transformation
  15186. */
  15187. Odie_MatrixObj *A,*C;
  15188. if(objc != 2) {
  15189. Tcl_WrongNumArgs( interp, 1, objv, "VECTORXYZ" );
  15190. return TCL_ERROR;
  15191. }
  15192. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz,&A)) return TCL_ERROR;
  15193. C=Odie_MatrixObj_Create(MATFORM_affine);
  15194. Odie_Affine_From_Normal(C->matrix,A->matrix);
  15195. Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
  15196. return TCL_OK;
  15197. }
  15198. /* Tcl Proc ::odie::bbox::create */
  15199. static int TclCmd_odie_bbox_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15200. MATOBJ *C;
  15201. C=Odie_MatrixObj_Create(MATFORM_bbox_xy);
  15202. VectorXY_BBOX_Reset(C->matrix);
  15203. if(objc>1) {
  15204. int i;
  15205. VectorXY point;
  15206. for(i=1;i<objc;i++) {
  15207. if(Odie_GetVectorXYFromTclObj(interp,objv[i],point)) return TCL_ERROR;
  15208. VectorXY_BBOX_Measure(point,C->matrix);
  15209. }
  15210. }
  15211. Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
  15212. return TCL_OK;
  15213. }
  15214. /* Tcl Proc ::odie::bbox::measure */
  15215. static int TclCmd_odie_bbox_measure(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15216. MATOBJ *C;
  15217. Tcl_Obj *varname,*pResult;
  15218. int i;
  15219. VectorXY point;
  15220. if( objc < 3 ){
  15221. Tcl_WrongNumArgs(interp, 1, objv, "BBOX VECTORXY ?VECTORXY..?");
  15222. return TCL_ERROR;
  15223. }
  15224. varname=Tcl_ObjGetVar2(interp,objv[1],NULL,0);
  15225. if(varname) {
  15226. if(Odie_GetMatrixFromTclObj(interp,varname,MATFORM_bbox_xy,&C)) return TCL_ERROR;
  15227. } else {
  15228. C=Odie_MatrixObj_Create(MATFORM_bbox_xy);
  15229. VectorXY_BBOX_Reset(C->matrix);
  15230. }
  15231. for(i=2;i<objc;i++) {
  15232. if(Odie_GetVectorXYFromTclObj(interp,objv[i],point)) return TCL_ERROR;
  15233. VectorXY_BBOX_Measure(point,C->matrix);
  15234. }
  15235. pResult=Matrix_To_TclObj(C);
  15236. Tcl_ObjSetVar2(interp,objv[1],NULL,pResult,0);
  15237. Tcl_SetObjResult(interp,pResult);
  15238. return TCL_OK;
  15239. }
  15240. /* Tcl Proc ::odie::bbox::elements */
  15241. static int TclCmd_odie_bbox_elements(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15242. MATOBJ *C;
  15243. Tcl_Obj *pResult;
  15244. if( objc != 2 ){
  15245. Tcl_WrongNumArgs(interp, 1, objv, "BBOX");
  15246. return TCL_ERROR;
  15247. }
  15248. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_bbox_xy,&C)) return TCL_ERROR;
  15249. pResult=Tcl_NewObj();
  15250. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(C->matrix[BBOX_X0_IDX]));
  15251. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(C->matrix[BBOX_Y1_IDX]));
  15252. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(C->matrix[BBOX_X1_IDX]));
  15253. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(C->matrix[BBOX_Y0_IDX]));
  15254. Tcl_SetObjResult(interp,pResult);
  15255. return TCL_OK;
  15256. }
  15257. /* Tcl Proc ::odie::bbox::intersect */
  15258. static int TclCmd_odie_bbox_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15259. MATOBJ *A,*B;
  15260. int c;
  15261. if( objc != 3 ){
  15262. Tcl_WrongNumArgs(interp, 1, objv, "BBOX BBOX");
  15263. return TCL_ERROR;
  15264. }
  15265. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_bbox_xy,&A)) return TCL_ERROR;
  15266. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_bbox_xy,&B)) return TCL_ERROR;
  15267. c=BBOX_BBOX_Intersect(A->matrix,B->matrix);
  15268. Tcl_SetObjResult(interp, Tcl_NewIntObj(c));
  15269. return TCL_OK;
  15270. }
  15271. /* Tcl Proc ::odie::bbox::within */
  15272. static int TclCmd_odie_bbox_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15273. VectorXY A;
  15274. MATOBJ *C;
  15275. int result;
  15276. if( objc != 3 && objc != 4 ){
  15277. Tcl_WrongNumArgs(interp, 1, objv, "BBOX ?XY| X? ?y?");
  15278. return TCL_ERROR;
  15279. }
  15280. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_bbox_xy,&C)) return TCL_ERROR;
  15281. if(objc==3) {
  15282. if(Odie_GetVectorXYFromTclObj(interp,objv[2],A)) return TCL_ERROR;
  15283. } else {
  15284. double a1,a2;
  15285.  
  15286. if(Tcl_GetDoubleFromObj(interp,objv[2],&a1)) return TCL_ERROR;
  15287. if(Tcl_GetDoubleFromObj(interp,objv[3],&a2)) return TCL_ERROR;
  15288. A[X_IDX]=a1;
  15289. A[Y_IDX]=a2;
  15290. }
  15291. result=VectorXY_Within_BBOX(A,C->matrix);
  15292. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(result));
  15293. return TCL_OK;
  15294. }
  15295. /* Tcl Proc ::quaternion::add */
  15296. static int TclCmd_quaternion_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15297. QUATERNION A,B,C;
  15298. if(objc < 3) {
  15299. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  15300. return TCL_ERROR;
  15301. }
  15302. if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  15303. if(Odie_GetQuaternionFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  15304. Quaternion_Add(C,A,B);
  15305. Tcl_SetObjResult(interp,Quaternion_To_TclObj(C));
  15306. return TCL_OK;
  15307. }
  15308. /* Tcl Proc ::quaternion::subtract */
  15309. static int TclCmd_quaternion_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15310. QUATERNION A,B,C;
  15311. if(objc < 3) {
  15312. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  15313. return TCL_ERROR;
  15314. }
  15315. if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  15316. if(Odie_GetQuaternionFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  15317. Quaternion_Subtract(C,A,B);
  15318. Tcl_SetObjResult(interp,Quaternion_To_TclObj(C));
  15319. return TCL_OK;
  15320. }
  15321. /* Tcl Proc ::quaternion::multiply */
  15322. static int TclCmd_quaternion_multiply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15323. QUATERNION A,B,C;
  15324. if(objc < 3) {
  15325. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  15326. return TCL_ERROR;
  15327. }
  15328. if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  15329. if(Odie_GetQuaternionFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  15330. Quaternion_Multiply(C,A,B);
  15331. Tcl_SetObjResult(interp,Quaternion_To_TclObj(C));
  15332. return TCL_OK;
  15333. }
  15334. /* Tcl Proc ::quaternion::divide */
  15335. static int TclCmd_quaternion_divide(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15336. QUATERNION A,B,C;
  15337. if(objc < 3) {
  15338. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  15339. return TCL_ERROR;
  15340. }
  15341. if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  15342. if(Odie_GetQuaternionFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  15343. Quaternion_Divide(C,A,B);
  15344. Tcl_SetObjResult(interp,Quaternion_To_TclObj(C));
  15345. return TCL_OK;
  15346. }
  15347. /* Tcl Proc ::quaternion::square_root */
  15348. static int TclCmd_quaternion_square_root(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15349. QUATERNION A,C;
  15350. if(objc < 2) {
  15351. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  15352. return TCL_ERROR;
  15353. }
  15354. if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  15355. Quaternion_Square_Root(C,A);
  15356. Tcl_SetObjResult(interp,Quaternion_To_TclObj(C));
  15357. return TCL_OK;
  15358. }
  15359. /* Tcl Proc ::quaternion::square */
  15360. static int TclCmd_quaternion_square(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15361. QUATERNION A,C;
  15362. if(objc < 2) {
  15363. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  15364. return TCL_ERROR;
  15365. }
  15366. if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  15367. Quaternion_Square(C,A);
  15368. Tcl_SetObjResult(interp,Quaternion_To_TclObj(C));
  15369. return TCL_OK;
  15370. }
  15371. /* Tcl Proc ::quaternion::from_euler */
  15372. static int TclCmd_quaternion_from_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15373. Odie_MatrixObj *A;
  15374. QUATERNION C;
  15375. if(objc < 2) {
  15376. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  15377. return TCL_ERROR;
  15378. }
  15379. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_euler,&A)) return TCL_ERROR;
  15380. EulerRotation_To_Quaternion(C,A->matrix[EULER_HEADING],A->matrix[EULER_ATTITUDE],A->matrix[EULER_BANK]);
  15381. Tcl_SetObjResult(interp,Quaternion_To_TclObj(C));
  15382. return TCL_OK;
  15383. }
  15384. /* Tcl Proc ::vectorxyz::rotate_by_quaternion */
  15385. static int TclCmd_vectorxyz_rotate_by_quaternion(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15386. QUATERNION A;
  15387. VectorXYZ B,C;
  15388. if(objc < 3) {
  15389. Tcl_WrongNumArgs( interp, 1, objv, "QUATERNION VECTOR ?VECTOR ...?" );
  15390. return TCL_ERROR;
  15391. }
  15392. if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  15393. if (objc==3) {
  15394. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  15395. VectorXYZ_Rotate_by_Quaternion(C,A,B);
  15396. Tcl_SetObjResult(interp,VectorXYZ_To_TclObj(C));
  15397. } else {
  15398. Tcl_Obj *pResult=Tcl_NewObj();
  15399. int i;
  15400. for(i=2;i<objc;i++) {
  15401. if(Odie_GetVectorXYZFromTclObj(interp,objv[i],B)) return TCL_ERROR;
  15402. VectorXYZ_Rotate_by_Quaternion(C,A,B);
  15403. Tcl_ListObjAppendElement(interp,pResult,VectorXYZ_To_TclObj(C));
  15404. }
  15405. Tcl_SetObjResult(interp,pResult);
  15406. }
  15407. return TCL_OK;
  15408. }
  15409. /* Tcl Proc ::quaternion::to_euler */
  15410. static int TclCmd_quaternion_to_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15411. QUATERNION A;
  15412. VectorXYZ C;
  15413. Odie_MatrixObj *RESULT;
  15414. if(objc < 2) {
  15415. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  15416. return TCL_ERROR;
  15417. }
  15418. if(Odie_GetQuaternionFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  15419. Quaternion_To_EulerRotation(C,A);
  15420. RESULT=Odie_MatrixObj_Create(MATFORM_euler);
  15421. RESULT->matrix[X_IDX]=A[X_IDX];
  15422. RESULT->matrix[Y_IDX]=A[Y_IDX];
  15423. RESULT->matrix[Z_IDX]=A[Z_IDX];
  15424. Tcl_SetObjResult(interp,Matrix_To_TclObj(RESULT));
  15425. return TCL_OK;
  15426. }
  15427. /* Tcl Proc ::quaternion::from_normal */
  15428. static int TclCmd_quaternion_from_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15429. VectorXYZ FROM,TO;
  15430. Odie_MatrixObj *RESULT;
  15431. if(objc != 2 && objc !=3) {
  15432. Tcl_WrongNumArgs( interp, 1, objv, "?FROM? TO" );
  15433. return TCL_ERROR;
  15434. }
  15435. if(objc==2) {
  15436. FROM[X_IDX]=0.0;
  15437. FROM[Y_IDX]=0.0;
  15438. FROM[Z_IDX]=-1.0;
  15439. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],TO)) return TCL_ERROR;
  15440. } else {
  15441. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],FROM)) return TCL_ERROR;
  15442. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],TO)) return TCL_ERROR;
  15443. }
  15444. RESULT=Odie_MatrixObj_Create(MATFORM_quaternion);
  15445. Quaternion_From_Normal(RESULT->matrix,FROM,TO);
  15446. Tcl_SetObjResult(interp,Matrix_To_TclObj(RESULT));
  15447. return TCL_OK;
  15448. }
  15449. /* Tcl Proc ::odie::tolerance */
  15450. static int TclCmd_odie_tolerance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15451. if(objc==2) {
  15452. double newval;
  15453. if(Tcl_GetDoubleFromObj(interp,objv[1],&newval)) return TCL_ERROR;
  15454. Vector_Set_Tolerance(newval);
  15455. }
  15456. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(Vector_Tolerance));
  15457. return TCL_OK;
  15458. }
  15459. /* Tcl Proc ::odie::vector::to_list */
  15460. static int TclCmd_odie_vector_to_list(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15461. Odie_MatrixObj *A;
  15462. int idx;
  15463. int size_a;
  15464. if(objc != 2) {
  15465. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  15466. return TCL_ERROR;
  15467. }
  15468. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
  15469. size_a=A->rows*A->cols;
  15470. Tcl_Obj **pList=NULL;
  15471.  
  15472. pList=Odie_Alloc(sizeof(Tcl_Obj)*size_a);
  15473. for(idx=0;idx<size_a;idx++) {
  15474. pList[idx]=Tcl_NewDoubleObj(*(A->matrix+idx));
  15475. }
  15476. Tcl_SetObjResult(interp,Tcl_NewListObj(size_a,pList));
  15477. return TCL_OK;
  15478. }
  15479. /* Tcl Proc ::odie::vector::index */
  15480. static int TclCmd_odie_vector_index(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15481. Odie_MatrixObj *A;
  15482. int i=-1,j=-1,idx,n=0;
  15483. int size_a;
  15484. Tcl_Obj **pList=NULL;
  15485.  
  15486. if(objc != 3 && objc != 4) {
  15487. Tcl_WrongNumArgs( interp, 1, objv, "A i ?j?" );
  15488. return TCL_ERROR;
  15489. }
  15490. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
  15491. if(Tcl_GetIntFromObj(interp,objv[2],&i)) return TCL_ERROR;
  15492. size_a=A->rows*A->cols;
  15493.  
  15494. if(i<0) {
  15495. i=0;
  15496. }
  15497. if(i>=size_a) {
  15498. i=size_a-1;
  15499. }
  15500. if(objc==3) {
  15501. j=i;
  15502. } else{
  15503. if(Tcl_GetIntFromObj(interp,objv[3],&j)) return TCL_ERROR;
  15504. }
  15505. if ( j < 0 ) {
  15506. j=size_a-1;
  15507. } else if (j<=i) {
  15508. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(*(A->matrix+i)));
  15509. return TCL_OK;
  15510. }
  15511. if(j>=size_a) {
  15512. j=size_a-1;
  15513. }
  15514. n=(j-i)+1;
  15515. pList=Odie_Alloc(sizeof(Tcl_Obj)*n);
  15516. for(idx=i;idx<=j;idx++) {
  15517. pList[idx]=Tcl_NewDoubleObj(*(A->matrix+idx));
  15518. }
  15519. Tcl_SetObjResult(interp,Tcl_NewListObj(n,pList));
  15520. return TCL_OK;
  15521. }
  15522. /* Tcl Proc ::odie::vector::add */
  15523. static int TclCmd_odie_vector_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15524. Odie_MatrixObj *A,*B,*C;
  15525. int i,size_c;
  15526. if(objc < 3) {
  15527. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  15528. return TCL_ERROR;
  15529. }
  15530. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
  15531. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_null,&B)) return TCL_ERROR;
  15532. C=Odie_Matrix_To_Fit(A,B);
  15533. size_c=C->rows*C->cols;
  15534. for(i=0;i<size_c;i++) {
  15535. *(C->matrix+i) = *(A->matrix+i) + *(B->matrix+i);
  15536. }
  15537. Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
  15538. return TCL_OK;
  15539. }
  15540. /* Tcl Proc ::odie::vector::is_null */
  15541. static int TclCmd_odie_vector_is_null(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15542. Odie_MatrixObj *A,*B,*C;
  15543. int i,size_c;
  15544. if(objc < 2) {
  15545. Tcl_WrongNumArgs( interp, 1, objv, "VECTOR" );
  15546. return TCL_ERROR;
  15547. }
  15548. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) {
  15549. Tcl_ResetResult(interp);
  15550. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(1));
  15551. return TCL_OK;
  15552. }
  15553. int size=A->rows*A->cols;
  15554. if(size<2) {
  15555. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(1));
  15556. return TCL_OK;
  15557. } else {
  15558. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(0));
  15559. }
  15560. return TCL_OK;
  15561. }
  15562. /* Tcl Proc ::odie::vector::subtract */
  15563. static int TclCmd_odie_vector_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15564. Odie_MatrixObj *A,*B,*C;
  15565. int i,size_c;
  15566. if(objc < 3) {
  15567. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  15568. return TCL_ERROR;
  15569. }
  15570. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
  15571. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_null,&B)) return TCL_ERROR;
  15572. C=Odie_Matrix_To_Fit(A,B);
  15573. size_c=C->rows*C->cols;
  15574. for(i=0;i<size_c;i++) {
  15575. *(C->matrix+i) = *(A->matrix+i) - *(B->matrix+i);
  15576. }
  15577. Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
  15578. return TCL_OK;
  15579. }
  15580. /* Tcl Proc ::odie::vector::midpoint */
  15581. static int TclCmd_odie_vector_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15582. Odie_MatrixObj *A,*B,*C;
  15583. int i,size_c;
  15584. if(objc < 3) {
  15585. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  15586. return TCL_ERROR;
  15587. }
  15588. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
  15589. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_null,&B)) return TCL_ERROR;
  15590. C=Odie_Matrix_To_Fit(A,B);
  15591. size_c=C->rows*C->cols;
  15592. for(i=0;i<size_c;i++) {
  15593. *(C->matrix+i) = (*(A->matrix+i) - *(B->matrix+i))*0.5 + *(A->matrix+i);
  15594. }
  15595. Tcl_SetObjResult(interp,Matrix_To_TclObj(C));
  15596. return TCL_OK;
  15597. }
  15598. /* Tcl Proc ::odie::vector::reciprocal */
  15599. static int TclCmd_odie_vector_reciprocal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15600. Odie_MatrixObj *A,*RESULT;
  15601. int i;
  15602. int size_a;
  15603. if(objc != 2) {
  15604. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  15605. return TCL_ERROR;
  15606. }
  15607. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
  15608. RESULT=Odie_Matrix_To_Fit(A,A);
  15609. size_a=A->rows*A->cols;
  15610. for(i=0;i<size_a;i++) {
  15611. *(RESULT->matrix+i) = 1.0 / *(A->matrix+i);
  15612. }
  15613. Tcl_SetObjResult(interp,Matrix_To_TclObj(RESULT));
  15614. return TCL_OK;
  15615. }
  15616. /* Tcl Proc ::odie::vector::dot_product */
  15617. static int TclCmd_odie_vector_dot_product(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15618. Odie_MatrixObj *A,*B;
  15619. int i;
  15620. int size_a;
  15621. int size_b;
  15622. if(objc < 3) {
  15623. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  15624. return TCL_ERROR;
  15625. }
  15626. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
  15627. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_null,&B)) return TCL_ERROR;
  15628. size_a=A->rows*A->cols;
  15629. size_b=B->rows*B->cols;
  15630. double result=0;
  15631. for(i=0;i<size_a && i<size_b;i++) {
  15632. result += *(A->matrix+i) * *(B->matrix+i);
  15633. }
  15634. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  15635. return TCL_OK;
  15636. }
  15637. /* Tcl Proc ::odie::vector::to_matrix */
  15638. static int TclCmd_odie_vector_to_matrix(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15639. Odie_MatrixObj *A;
  15640. if(objc < 2) {
  15641. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  15642. return TCL_ERROR;
  15643. }
  15644. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
  15645. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  15646. return TCL_OK;
  15647. }
  15648. /* Tcl Proc ::odie::vector::to_fuzzy */
  15649. static int TclCmd_odie_vector_to_fuzzy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15650. Odie_MatrixObj *A;
  15651. int i,size_a;
  15652. Tcl_Obj *pResult;
  15653. if(objc < 2) {
  15654. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  15655. return TCL_ERROR;
  15656. }
  15657. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
  15658. pResult=Tcl_NewObj();
  15659. size_a=A->rows*A->cols;
  15660. for(i=0;i<size_a;i++) {
  15661. Tcl_ListObjAppendElement(interp,pResult,ODIE_NewFuzzyObj(*(A->matrix+i)));
  15662. }
  15663. Tcl_SetObjResult(interp,pResult);
  15664. return TCL_OK;
  15665. }
  15666. /* Tcl Proc ::odie::vector::scale */
  15667. static int TclCmd_odie_vector_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15668. Odie_MatrixObj *A,*B,*C=NULL,*RESULT;
  15669. int i,size_a,size_b,size_c;
  15670. if(objc!=3 && objc !=4) {
  15671. Tcl_WrongNumArgs( interp, 1, objv, "A SCALE ?TRANSLATE?" );
  15672. return TCL_ERROR;
  15673. }
  15674. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
  15675. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_null,&B)) return TCL_ERROR;
  15676. size_a=A->rows*A->cols;
  15677. size_b=B->rows*B->cols;
  15678. if(size_b > 1 && size_b!=size_a) {
  15679. Tcl_AppendResult(interp, "B is not a scaler, or arguments are not of the same size", 0);
  15680. return TCL_ERROR;
  15681. }
  15682.  
  15683. if(objc==4) {
  15684. if(Odie_GetMatrixFromTclObj(interp,objv[3],MATFORM_null,&C)) return TCL_ERROR;
  15685. size_c=C->rows*C->cols;
  15686. if(size_c!=size_a) {
  15687. Tcl_AppendResult(interp, "TRANS is not the same size", 0);
  15688. return TCL_ERROR;
  15689. }
  15690. }
  15691. RESULT=Odie_Matrix_Duplicate(A);
  15692. if(size_b==1) {
  15693. double scaler=*(B->matrix+0);
  15694. for(i=0;i<size_a;i++) {
  15695. *(RESULT->matrix+i) *= scaler;
  15696. }
  15697. } else {
  15698. for(i=0;i<size_a;i++) {
  15699. *(RESULT->matrix+i) *= *(B->matrix+i);
  15700. }
  15701. }
  15702. if(C) {
  15703. for(i=0;i<size_a;i++) {
  15704. *(RESULT->matrix+i) -= *(C->matrix+i);
  15705. }
  15706. }
  15707.  
  15708. Tcl_SetObjResult(interp,Matrix_To_TclObj(RESULT));
  15709. return TCL_OK;
  15710. }
  15711. /* Tcl Proc ::odie::vector::length */
  15712. static int TclCmd_odie_vector_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15713. int i,size;
  15714. Odie_MatrixObj *A;
  15715. double result,sum=0.0;
  15716. if( objc!=2 ){
  15717. Tcl_WrongNumArgs(interp, 1, objv, "vector");
  15718. return TCL_ERROR;
  15719. }
  15720. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
  15721. size=A->rows*A->cols;
  15722. result=0.0;
  15723. for(i=1;i<size;i++) {
  15724. double a=*(A->matrix+1);
  15725. sum+=a*a;
  15726. }
  15727. result=sqrt(sum);
  15728. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  15729. return TCL_OK;
  15730. }
  15731. /* Tcl Proc ::odie::vector::length_squared */
  15732. static int TclCmd_odie_vector_length_squared(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15733. int i,size;
  15734. Odie_MatrixObj *A;
  15735. double result,sum=0.0;
  15736. if( objc!=2 ){
  15737. Tcl_WrongNumArgs(interp, 1, objv, "vector");
  15738. return TCL_ERROR;
  15739. }
  15740. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
  15741. size=A->rows*A->cols;
  15742. result=0.0;
  15743. for(i=1;i<size;i++) {
  15744. double a=*(A->matrix+1);
  15745. sum+=a*a;
  15746. }
  15747. result=sum;
  15748. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  15749. return TCL_OK;
  15750. }
  15751. /* Tcl Proc ::odie::grid */
  15752. static int TclCmd_odie_grid(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15753. double grid,grain;
  15754. int gridint,i,asint=0;
  15755. Tcl_Obj *pResult;
  15756. if( objc < 3 ){
  15757. Tcl_WrongNumArgs(interp, 1, objv, "grid DBL ...");
  15758. return TCL_ERROR;
  15759. }
  15760. asint=1;
  15761. if(Tcl_GetIntFromObj(interp,objv[1],&gridint)) {
  15762. asint=0;
  15763. if(Tcl_GetDoubleFromObj(interp,objv[1],&grid)) return TCL_ERROR;
  15764. } else {
  15765. grid=(double)gridint;
  15766. }
  15767. pResult=Tcl_NewObj();
  15768. grain=grid*0.5;
  15769. for(i=2;i<objc;i++) {
  15770. double thisval,remainder;
  15771. if(Tcl_GetDoubleFromObj(interp,objv[i],&thisval)) {
  15772. Tcl_DecrRefCount(pResult);
  15773. return TCL_ERROR;
  15774. }
  15775. thisval=Vector_GridScaler(thisval,grid,grain);
  15776. if(asint) {
  15777. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(thisval));
  15778. } else {
  15779. remainder=fmod(thisval,grid);
  15780. Tcl_ListObjAppendElement(interp, pResult, ODIE_NewFuzzyObj(thisval-remainder));
  15781. }
  15782. }
  15783. Tcl_SetObjResult(interp, pResult);
  15784. return TCL_OK;
  15785. }
  15786. /* Tcl Proc ::odie::gridvar */
  15787. static int TclCmd_odie_gridvar(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15788. double grid,grain,val;
  15789. int gridint,i,asint=0;
  15790. if( objc < 3 ){
  15791. Tcl_WrongNumArgs(interp, 1, objv, "gridsize DBLVAR ...");
  15792. return TCL_ERROR;
  15793. }
  15794. asint=1;
  15795. if(Tcl_GetIntFromObj(interp,objv[1],&gridint)) {
  15796. asint=0;
  15797. if(Tcl_GetDoubleFromObj(interp,objv[1],&grid)) return TCL_ERROR;
  15798. } else {
  15799. grid=(double)gridint;
  15800. }
  15801. grain=grid*0.5;
  15802. for(i=2;i<objc;i++) {
  15803. double thisval,remainder;
  15804. Tcl_Obj *varname;
  15805. varname=Tcl_ObjGetVar2(interp,objv[i],NULL,0);
  15806. if(varname==NULL) continue;
  15807. if(Tcl_GetDoubleFromObj(interp,varname,&val)) continue;
  15808. thisval=Vector_GridScaler(val,grid,grain);
  15809. if(asint) {
  15810. Tcl_ObjSetVar2(interp,objv[i],NULL,Tcl_NewIntObj(thisval),0);
  15811. } else {
  15812. remainder=fmod(thisval,grid);
  15813. Tcl_ObjSetVar2(interp,objv[i],NULL,ODIE_NewFuzzyObj(thisval-remainder),0);
  15814. }
  15815. }
  15816. return TCL_OK;
  15817. }
  15818. /* Tcl Proc ::vector2d::compare */
  15819. static int TclCmd_vector2d_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15820. VectorXY A, B;
  15821. int c;
  15822. if( objc!=5 ){
  15823. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1");
  15824. return TCL_ERROR;
  15825. }
  15826. if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
  15827. if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
  15828. if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
  15829. if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
  15830. c=VectorXY_SamePoint(A,B);
  15831. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(c));
  15832. return TCL_OK;
  15833. }
  15834. /* Tcl Proc ::vector2d::add */
  15835. static int TclCmd_vector2d_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15836. VectorXY A, B, P;
  15837. Tcl_Obj *pResult;
  15838. if( objc!=5 ){
  15839. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1");
  15840. return TCL_ERROR;
  15841. }
  15842. if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
  15843. if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
  15844. if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
  15845. if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
  15846. VectorXY_Add(P,A,B);
  15847. pResult=Tcl_NewObj();
  15848. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[X_IDX]));
  15849. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Y_IDX]));
  15850. Tcl_SetObjResult(interp, pResult);
  15851. return TCL_OK;
  15852. }
  15853. /* Tcl Proc ::vector2d::subtract */
  15854. static int TclCmd_vector2d_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15855. VectorXY A, B, P;
  15856. Tcl_Obj *pResult;
  15857. if( objc!=5 ){
  15858. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1");
  15859. return TCL_ERROR;
  15860. }
  15861. if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
  15862. if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
  15863. if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
  15864. if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
  15865. VectorXY_Subtract(P,A,B);
  15866. pResult=Tcl_NewObj();
  15867. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[X_IDX]));
  15868. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Y_IDX]));
  15869. Tcl_SetObjResult(interp, pResult);
  15870. return TCL_OK;
  15871. }
  15872. /* Tcl Proc ::vector2d::midpoint */
  15873. static int TclCmd_vector2d_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15874. VectorXY A, B, P;
  15875. Tcl_Obj *pResult;
  15876. if( objc!=5 ){
  15877. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1");
  15878. return TCL_ERROR;
  15879. }
  15880. if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
  15881. if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
  15882. if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
  15883. if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
  15884. VectorXY_Midpoint(P,A,B);
  15885. pResult=Tcl_NewObj();
  15886. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[X_IDX]));
  15887. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Y_IDX]));
  15888. Tcl_SetObjResult(interp, pResult);
  15889. return TCL_OK;
  15890. }
  15891. /* Tcl Proc ::vector2d::affine_apply */
  15892. static int TclCmd_vector2d_affine_apply(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15893. Tcl_Obj *pResult;
  15894. int i;
  15895. double matA[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
  15896.  
  15897. if( objc < 4 ){
  15898. Tcl_WrongNumArgs(interp, 1, objv, "matrix x1 y1 ?x2 y2?...");
  15899. return TCL_ERROR;
  15900. }
  15901. for(i=0;i<6;i++) {
  15902. Tcl_Obj *temp;
  15903. if(Tcl_ListObjIndex(interp, objv[1], i, &temp)) return TCL_ERROR;
  15904. if(Odie_GetMatrixElementFromObj(interp,temp,matA,i)) return TCL_ERROR;
  15905. }
  15906. pResult=Tcl_NewObj();
  15907. for(i=2;i<objc;i+=2) {
  15908. double x,y,newx,newy;
  15909. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) {
  15910. Tcl_DecrRefCount(pResult);
  15911. return TCL_ERROR;
  15912. }
  15913. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) {
  15914. Tcl_DecrRefCount(pResult);
  15915. return TCL_ERROR;
  15916. }
  15917. newx=matA[0]*x+matA[1]*y+matA[4];
  15918. newy=matA[2]*x+matA[3]*y+matA[5];
  15919. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
  15920. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
  15921. }
  15922. Tcl_SetObjResult(interp, pResult);
  15923. return TCL_OK;
  15924. }
  15925. /* Tcl Proc ::vector2d::angle */
  15926. static int TclCmd_vector2d_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15927. VectorXY A, B, P;
  15928. if( objc!=7 ){
  15929. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2");
  15930. return TCL_ERROR;
  15931. }
  15932. if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
  15933. if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
  15934. if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
  15935. if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
  15936. if( Odie_GetMatrixElementFromObj(interp, objv[5], P, X_IDX) ) return TCL_ERROR;
  15937. if( Odie_GetMatrixElementFromObj(interp, objv[6], P, Y_IDX) ) return TCL_ERROR;
  15938. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_Angle_Three_Point(A, B, P)));
  15939. return TCL_OK;
  15940. }
  15941. /* Tcl Proc ::vector2d::distance */
  15942. static int TclCmd_vector2d_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15943. double result,ax,ay,bx,by,dx,dy;
  15944. if( objc!=5 ){
  15945. Tcl_WrongNumArgs(interp, 1, objv, "x0 y0 x1 y1");
  15946. return TCL_ERROR;
  15947. }
  15948. result=0.0;
  15949. if(Tcl_GetDoubleFromObj(interp,objv[1],&ax)) return TCL_ERROR;
  15950. if(Tcl_GetDoubleFromObj(interp,objv[2],&ay)) return TCL_ERROR;
  15951. if(Tcl_GetDoubleFromObj(interp,objv[3],&bx)) return TCL_ERROR;
  15952. if(Tcl_GetDoubleFromObj(interp,objv[4],&by)) return TCL_ERROR;
  15953. dx=bx-ax;
  15954. dy=by-ay;
  15955.  
  15956. result=sqrt(dx*dx + dy*dy);
  15957. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  15958. return TCL_OK;
  15959. }
  15960. /* Tcl Proc ::vector2d::dotproduct */
  15961. static int TclCmd_vector2d_dotproduct(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15962. VectorXY A, B, P;
  15963. if( objc!=7 ){
  15964. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2");
  15965. return TCL_ERROR;
  15966. }
  15967. if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
  15968. if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
  15969. if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
  15970. if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
  15971. if( Odie_GetMatrixElementFromObj(interp, objv[5], P, X_IDX) ) return TCL_ERROR;
  15972. if( Odie_GetMatrixElementFromObj(interp, objv[6], P, Y_IDX) ) return TCL_ERROR;
  15973. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_Dot_Product(A, B, P)));
  15974. return TCL_OK;
  15975. }
  15976. /* Tcl Proc ::vector2d::crossproduct */
  15977. static int TclCmd_vector2d_crossproduct(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15978. VectorXY A, B, P;
  15979. if( objc!=7 ){
  15980. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2");
  15981. return TCL_ERROR;
  15982. }
  15983. if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
  15984. if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
  15985. if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
  15986. if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
  15987. if( Odie_GetMatrixElementFromObj(interp, objv[5], P, X_IDX) ) return TCL_ERROR;
  15988. if( Odie_GetMatrixElementFromObj(interp, objv[6], P, Y_IDX) ) return TCL_ERROR;
  15989. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_crossProduct(A, B, P)));
  15990. return TCL_OK;
  15991. }
  15992. /* Tcl Proc ::vector2d::rightof */
  15993. static int TclCmd_vector2d_rightof(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  15994. /*
  15995. ** tclcmd: triag_test_rightof X0 Y0 X1 Y1 X2 Y2
  15996. **
  15997. ** A TCL command for testing the rightOf() function.
  15998. */
  15999. VectorXY A, B, P;
  16000. if( objc!=7 ){
  16001. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2");
  16002. return TCL_ERROR;
  16003. }
  16004. if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
  16005. if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
  16006. if( Odie_GetMatrixElementFromObj(interp, objv[3], B, X_IDX) ) return TCL_ERROR;
  16007. if( Odie_GetMatrixElementFromObj(interp, objv[4], B, Y_IDX) ) return TCL_ERROR;
  16008. if( Odie_GetMatrixElementFromObj(interp, objv[5], P, X_IDX) ) return TCL_ERROR;
  16009. if( Odie_GetMatrixElementFromObj(interp, objv[6], P, Y_IDX) ) return TCL_ERROR;
  16010. Tcl_SetObjResult(interp, Tcl_NewIntObj(VectorXY_BendDirection(A, B, P)));
  16011. return TCL_OK;
  16012. }
  16013. /* Tcl Proc ::vector2d::rotate_and_size */
  16014. static int TclCmd_vector2d_rotate_and_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16015. /*
  16016. ** Apply Matrices
  16017. */
  16018. Tcl_Obj *pResult;
  16019. int i;
  16020. double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0};
  16021. double nx,ny,scalex,scaley,angle;
  16022.  
  16023. if( objc < 7 ){
  16024. Tcl_WrongNumArgs(interp, 1, objv, "normalx normaly sizex sizey x1 y1 ?x2 y2?...");
  16025. return TCL_ERROR;
  16026. }
  16027.  
  16028. if(Tcl_GetDoubleFromObj(interp,objv[1],&nx)) return TCL_ERROR;
  16029. if(Tcl_GetDoubleFromObj(interp,objv[2],&ny)) return TCL_ERROR;
  16030. if(Tcl_GetDoubleFromObj(interp,objv[3],&scalex)) return TCL_ERROR;
  16031. if(Tcl_GetDoubleFromObj(interp,objv[4],&scaley)) return TCL_ERROR;
  16032.  
  16033. angle=atan2(ny,nx);
  16034. matA[0]=cos(angle);
  16035. matA[1]=sin(angle);
  16036. matA[2]=-sin(angle);
  16037. matA[3]=cos(angle);
  16038. matA[4]=0.0;
  16039. matA[5]=0.0;
  16040.  
  16041. scalex*=0.5;
  16042. scaley*=0.5;
  16043. pResult=Tcl_NewObj();
  16044. for(i=5;i<objc;i+=2) {
  16045. double x,y,sx,sy,newx,newy;
  16046. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) {
  16047. Tcl_DecrRefCount(pResult);
  16048. return TCL_ERROR;
  16049. }
  16050. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) {
  16051. Tcl_DecrRefCount(pResult);
  16052. return TCL_ERROR;
  16053. }
  16054. sx=x*scalex;
  16055. sy=y*scaley;
  16056. newx=matA[0]*sx+matA[1]*sy+matA[4];
  16057. newy=matA[2]*sx+matA[3]*sy+matA[5];
  16058.  
  16059. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
  16060. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
  16061. }
  16062. Tcl_SetObjResult(interp, pResult);
  16063. return TCL_OK;
  16064. }
  16065. /* Tcl Proc ::vector2d::scale */
  16066. static int TclCmd_vector2d_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16067. Tcl_Obj *pResult;
  16068. int i;
  16069. double scalex,scaley;
  16070.  
  16071. if( objc < 5 ){
  16072. Tcl_WrongNumArgs(interp, 1, objv, "sizex sizey x1 y1 ?x2 y2?...");
  16073. return TCL_ERROR;
  16074. }
  16075.  
  16076. if(Tcl_GetDoubleFromObj(interp,objv[1],&scalex)) return TCL_ERROR;
  16077. if(Tcl_GetDoubleFromObj(interp,objv[2],&scaley)) return TCL_ERROR;
  16078. pResult=Tcl_NewObj();
  16079. scalex*=0.5;
  16080. scaley*=0.5;
  16081. for(i=3;i<objc;i+=2) {
  16082. double x,y,sx,sy;
  16083. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) {
  16084. Tcl_DecrRefCount(pResult);
  16085. return TCL_ERROR;
  16086. }
  16087. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) {
  16088. Tcl_DecrRefCount(pResult);
  16089. return TCL_ERROR;
  16090. }
  16091. sx=x*scalex;
  16092. sy=y*scaley;
  16093. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sx));
  16094. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(sy));
  16095. }
  16096. Tcl_SetObjResult(interp, pResult);
  16097. return TCL_OK;
  16098. }
  16099. /* Tcl Proc ::vector2d::translate_and_zoom */
  16100. static int TclCmd_vector2d_translate_and_zoom(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16101. /*
  16102. ** Apply Matrices
  16103. */
  16104. Tcl_Obj *pResult;
  16105. int i;
  16106. double zoom;
  16107. double centerx,centery;
  16108.  
  16109. if( objc < 6 ){
  16110. Tcl_WrongNumArgs(interp, 1, objv, "zoom centerx centery x1 y1 ?x2 y2?...");
  16111. return TCL_ERROR;
  16112. }
  16113. if(Tcl_GetDoubleFromObj(interp,objv[1],&zoom)) return TCL_ERROR;
  16114. if(Tcl_GetDoubleFromObj(interp,objv[2],&centerx)) return TCL_ERROR;
  16115. if(Tcl_GetDoubleFromObj(interp,objv[3],&centery)) return TCL_ERROR;
  16116. pResult=Tcl_NewObj();
  16117. for(i=4;i<objc;i+=2) {
  16118. double x,y,newx,newy;
  16119. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) {
  16120. Tcl_DecrRefCount(pResult);
  16121. return TCL_ERROR;
  16122. }
  16123. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) {
  16124. Tcl_DecrRefCount(pResult);
  16125. return TCL_ERROR;
  16126. }
  16127. newx=(x/zoom)+centerx;
  16128. newy=(y/zoom)+centery;
  16129. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
  16130. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
  16131. }
  16132. Tcl_SetObjResult(interp, pResult);
  16133. return TCL_OK;
  16134. }
  16135. /* Tcl Proc ::vector2d::point_on_segment */
  16136. static int TclCmd_vector2d_point_on_segment(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16137. double x1,y1,x2,y2,x3,y3;
  16138. if( objc != 7 ){
  16139. Tcl_WrongNumArgs(interp, 1, objv, "point_on_segment x y x1 y1 x2 y2");
  16140. return TCL_ERROR;
  16141. }
  16142. if (Tcl_GetDoubleFromObj(interp,objv[1],&x1)) return TCL_ERROR;
  16143. if (Tcl_GetDoubleFromObj(interp,objv[2],&y1)) return TCL_ERROR;
  16144. if (Tcl_GetDoubleFromObj(interp,objv[3],&x2)) return TCL_ERROR;
  16145. if (Tcl_GetDoubleFromObj(interp,objv[4],&y2)) return TCL_ERROR;
  16146. if (Tcl_GetDoubleFromObj(interp,objv[5],&x3)) return TCL_ERROR;
  16147. if (Tcl_GetDoubleFromObj(interp,objv[6],&y3)) return TCL_ERROR;
  16148. Tcl_SetObjResult(interp, Tcl_NewIntObj(Vector2d_PointIsOnSegment(x1,y1,x2,y2,x3,y3)));
  16149. return TCL_OK;
  16150. }
  16151. /* Tcl Proc ::vector2d::line_circle_intersect */
  16152. static int TclCmd_vector2d_line_circle_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16153. double ax1,ax2,ay1,ay2;
  16154. double bx1,by1,brad;
  16155. double ix,iy;
  16156.  
  16157. if(objc<8) {
  16158. Tcl_WrongNumArgs(interp, 1, objv, "ax1 ay1 ax2 ay2 bx1 by1 brad");
  16159. return TCL_ERROR;
  16160. }
  16161.  
  16162. if( Tcl_GetDoubleFromObj(interp, objv[1], &ax1) ) return TCL_ERROR;
  16163. if( Tcl_GetDoubleFromObj(interp, objv[2], &ay1) ) return TCL_ERROR;
  16164. if( Tcl_GetDoubleFromObj(interp, objv[3], &ax2) ) return TCL_ERROR;
  16165. if( Tcl_GetDoubleFromObj(interp, objv[4], &ay2) ) return TCL_ERROR;
  16166.  
  16167. if( Tcl_GetDoubleFromObj(interp, objv[5], &bx1) ) return TCL_ERROR;
  16168. if( Tcl_GetDoubleFromObj(interp, objv[6], &by1) ) return TCL_ERROR;
  16169. if( Tcl_GetDoubleFromObj(interp, objv[7], &brad) ) return TCL_ERROR;
  16170.  
  16171. if(ODIE_Math_LineCircleIntersect(ax1,ay1,ax2,ay2,bx1,by1,brad,&ix,&iy)) {
  16172. Tcl_Obj *pResult;
  16173. pResult = Tcl_NewObj();
  16174. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ix));
  16175. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(iy));
  16176. Tcl_SetObjResult(interp, pResult);
  16177. }
  16178. return TCL_OK;
  16179. }
  16180. /* Tcl Proc ::vector2d::line_intersect */
  16181. static int TclCmd_vector2d_line_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16182. double ax1,ax2,ay1,ay2;
  16183. double bx1,bx2,by1,by2;
  16184. double ix,iy;
  16185.  
  16186. if(objc<9) {
  16187. Tcl_WrongNumArgs(interp, 1, objv, "ax1 ay1 ax2 ay2 bx1 by1 bx2 by2");
  16188. return TCL_ERROR;
  16189. }
  16190.  
  16191. if( Tcl_GetDoubleFromObj(interp, objv[1], &ax1) ) return TCL_ERROR;
  16192. if( Tcl_GetDoubleFromObj(interp, objv[2], &ay1) ) return TCL_ERROR;
  16193. if( Tcl_GetDoubleFromObj(interp, objv[3], &ax2) ) return TCL_ERROR;
  16194. if( Tcl_GetDoubleFromObj(interp, objv[4], &ay2) ) return TCL_ERROR;
  16195.  
  16196. if( Tcl_GetDoubleFromObj(interp, objv[5], &bx1) ) return TCL_ERROR;
  16197. if( Tcl_GetDoubleFromObj(interp, objv[6], &by1) ) return TCL_ERROR;
  16198. if( Tcl_GetDoubleFromObj(interp, objv[7], &bx2) ) return TCL_ERROR;
  16199. if( Tcl_GetDoubleFromObj(interp, objv[8], &by2) ) return TCL_ERROR;
  16200.  
  16201. if(ODIE_Math_LineLineIntersect(ax1,ay1,ax2,ay2,bx1,by1,bx2,by2,&ix,&iy)) {
  16202. Tcl_Obj *pResult;
  16203. pResult = Tcl_NewObj();
  16204. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ix));
  16205. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(iy));
  16206. Tcl_SetObjResult(interp, pResult);
  16207. }
  16208. return TCL_OK;
  16209. }
  16210. /* Tcl Proc ::vector2d::line_overlap */
  16211. static int TclCmd_vector2d_line_overlap(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16212. Tcl_Obj *pResult;
  16213. double ax1,ax2,ay1,ay2;
  16214. double bx1,bx2,by1,by2;
  16215.  
  16216. if(objc<9) {
  16217. Tcl_WrongNumArgs(interp, 1, objv, "ax1 ay1 ax2 ay2 bx1 by1 bx2 by2");
  16218. return TCL_ERROR;
  16219. }
  16220.  
  16221. if( Tcl_GetDoubleFromObj(interp, objv[1], &ax1) ) return TCL_ERROR;
  16222. if( Tcl_GetDoubleFromObj(interp, objv[2], &ay1) ) return TCL_ERROR;
  16223. if( Tcl_GetDoubleFromObj(interp, objv[3], &ax2) ) return TCL_ERROR;
  16224. if( Tcl_GetDoubleFromObj(interp, objv[4], &ay2) ) return TCL_ERROR;
  16225.  
  16226. if( Tcl_GetDoubleFromObj(interp, objv[5], &bx1) ) return TCL_ERROR;
  16227. if( Tcl_GetDoubleFromObj(interp, objv[6], &by1) ) return TCL_ERROR;
  16228. if( Tcl_GetDoubleFromObj(interp, objv[7], &bx2) ) return TCL_ERROR;
  16229. if( Tcl_GetDoubleFromObj(interp, objv[8], &by2) ) return TCL_ERROR;
  16230.  
  16231. /*
  16232. ** ignore if the segments connect at endpoints
  16233. if(ax1==bx1 && ay1==by1) return TCL_OK;
  16234. if(ax1==bx2 && ay1==by2) return TCL_OK;
  16235. if(ax2==bx1 && ay2==by1) return TCL_OK;
  16236. if(ax2==bx2 && ay2==by2) return TCL_OK;
  16237. */
  16238.  
  16239. pResult = Tcl_NewIntObj(Vector2d_LineLineCoincident(ax1,ay1,ax2,ay2,bx1,by1,bx2,by2));
  16240. Tcl_SetObjResult(interp, pResult);
  16241.  
  16242. return TCL_OK;
  16243. }
  16244. /* Tcl Proc ::vector2d::colinear */
  16245. static int TclCmd_vector2d_colinear(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16246. double x1,y1,x2,y2,x3,y3;
  16247. if( objc != 7 ){
  16248. Tcl_WrongNumArgs(interp, 1, objv, "colinear x1 y1 x2 y2 x3 y3");
  16249. return TCL_ERROR;
  16250. }
  16251. if (Tcl_GetDoubleFromObj(interp,objv[1],&x1)) return TCL_ERROR;
  16252. if (Tcl_GetDoubleFromObj(interp,objv[2],&y1)) return TCL_ERROR;
  16253. if (Tcl_GetDoubleFromObj(interp,objv[3],&x2)) return TCL_ERROR;
  16254. if (Tcl_GetDoubleFromObj(interp,objv[4],&y2)) return TCL_ERROR;
  16255. if (Tcl_GetDoubleFromObj(interp,objv[5],&x3)) return TCL_ERROR;
  16256. if (Tcl_GetDoubleFromObj(interp,objv[6],&y3)) return TCL_ERROR;
  16257. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Vector2d_IsColinear(x1,y1,x2,y2,x3,y3)));
  16258. return TCL_OK;
  16259. }
  16260. /* Tcl Proc ::vector3d::compare */
  16261. static int TclCmd_vector3d_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16262. VectorXY A, B;
  16263. int c;
  16264. if( objc!=7 ){
  16265. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 Z0 X1 Y1 Z1");
  16266. return TCL_ERROR;
  16267. }
  16268. if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
  16269. if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
  16270. if( Odie_GetMatrixElementFromObj(interp, objv[3], A, Z_IDX) ) return TCL_ERROR;
  16271. if( Odie_GetMatrixElementFromObj(interp, objv[4], B, X_IDX) ) return TCL_ERROR;
  16272. if( Odie_GetMatrixElementFromObj(interp, objv[5], B, Y_IDX) ) return TCL_ERROR;
  16273. if( Odie_GetMatrixElementFromObj(interp, objv[6], B, Z_IDX) ) return TCL_ERROR;
  16274. c=VectorXYZ_SamePoint(A,B);
  16275. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(c));
  16276. return TCL_OK;
  16277. }
  16278. /* Tcl Proc ::vector3d::add */
  16279. static int TclCmd_vector3d_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16280. VectorXYZ A, B, P;
  16281. Tcl_Obj *pResult;
  16282. if( objc!=7 ){
  16283. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 Z0 X1 Y1 Z1");
  16284. return TCL_ERROR;
  16285. }
  16286. if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
  16287. if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
  16288. if( Odie_GetMatrixElementFromObj(interp, objv[3], A, Z_IDX) ) return TCL_ERROR;
  16289. if( Odie_GetMatrixElementFromObj(interp, objv[4], B, X_IDX) ) return TCL_ERROR;
  16290. if( Odie_GetMatrixElementFromObj(interp, objv[5], B, Y_IDX) ) return TCL_ERROR;
  16291. if( Odie_GetMatrixElementFromObj(interp, objv[6], B, Z_IDX) ) return TCL_ERROR;
  16292. VectorXYZ_Add(P,A,B);
  16293. pResult=Tcl_NewObj();
  16294. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[X_IDX]));
  16295. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Y_IDX]));
  16296. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Z_IDX]));
  16297. Tcl_SetObjResult(interp, pResult);
  16298. return TCL_OK;
  16299. }
  16300. /* Tcl Proc ::vector3d::subtract */
  16301. static int TclCmd_vector3d_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16302. VectorXYZ A, B, P;
  16303. Tcl_Obj *pResult;
  16304. if( objc!=7 ){
  16305. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 Z0 X1 Y1 Z1");
  16306. return TCL_ERROR;
  16307. }
  16308. if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
  16309. if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
  16310. if( Odie_GetMatrixElementFromObj(interp, objv[3], A, Z_IDX) ) return TCL_ERROR;
  16311. if( Odie_GetMatrixElementFromObj(interp, objv[4], B, X_IDX) ) return TCL_ERROR;
  16312. if( Odie_GetMatrixElementFromObj(interp, objv[5], B, Y_IDX) ) return TCL_ERROR;
  16313. if( Odie_GetMatrixElementFromObj(interp, objv[6], B, Z_IDX) ) return TCL_ERROR;
  16314. VectorXYZ_Subtract(P,A,B);
  16315. pResult=Tcl_NewObj();
  16316. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[X_IDX]));
  16317. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Y_IDX]));
  16318. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Z_IDX]));
  16319. Tcl_SetObjResult(interp, pResult);
  16320. return TCL_OK;
  16321. }
  16322. /* Tcl Proc ::vector3d::orthagonal */
  16323. static int TclCmd_vector3d_orthagonal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16324. int result;
  16325. VectorXY A, B;
  16326. if( objc!=7 ){
  16327. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 Z0 X1 Y1 Z1");
  16328. return TCL_ERROR;
  16329. }
  16330. if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
  16331. if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
  16332. if( Odie_GetMatrixElementFromObj(interp, objv[3], A, Z_IDX) ) return TCL_ERROR;
  16333. if( Odie_GetMatrixElementFromObj(interp, objv[4], B, X_IDX) ) return TCL_ERROR;
  16334. if( Odie_GetMatrixElementFromObj(interp, objv[5], B, Y_IDX) ) return TCL_ERROR;
  16335. if( Odie_GetMatrixElementFromObj(interp, objv[6], B, Z_IDX) ) return TCL_ERROR;
  16336. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(VectorXYZ_IsOrthagonal(A,B)));
  16337. return TCL_OK;
  16338. }
  16339. /* Tcl Proc ::vector3d::distance */
  16340. static int TclCmd_vector3d_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16341. double result;
  16342. VectorXY A, B;
  16343. if( objc!=7 ){
  16344. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 Z0 X1 Y1 Z1");
  16345. return TCL_ERROR;
  16346. }
  16347. if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
  16348. if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
  16349. if( Odie_GetMatrixElementFromObj(interp, objv[3], A, Z_IDX) ) return TCL_ERROR;
  16350. if( Odie_GetMatrixElementFromObj(interp, objv[4], B, X_IDX) ) return TCL_ERROR;
  16351. if( Odie_GetMatrixElementFromObj(interp, objv[5], B, Y_IDX) ) return TCL_ERROR;
  16352. if( Odie_GetMatrixElementFromObj(interp, objv[6], B, Z_IDX) ) return TCL_ERROR;
  16353. result=VectorXYZ_Distance(A,B);
  16354. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  16355. return TCL_OK;
  16356. }
  16357. /* Tcl Proc ::vector3d::distanceSq */
  16358. static int TclCmd_vector3d_distanceSq(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16359. double result;
  16360. VectorXY A, B;
  16361. if( objc!=7 ){
  16362. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 Z0 X1 Y1 Z1");
  16363. return TCL_ERROR;
  16364. }
  16365. if( Odie_GetMatrixElementFromObj(interp, objv[1], A, X_IDX) ) return TCL_ERROR;
  16366. if( Odie_GetMatrixElementFromObj(interp, objv[2], A, Y_IDX) ) return TCL_ERROR;
  16367. if( Odie_GetMatrixElementFromObj(interp, objv[3], A, Z_IDX) ) return TCL_ERROR;
  16368. if( Odie_GetMatrixElementFromObj(interp, objv[4], B, X_IDX) ) return TCL_ERROR;
  16369. if( Odie_GetMatrixElementFromObj(interp, objv[5], B, Y_IDX) ) return TCL_ERROR;
  16370. if( Odie_GetMatrixElementFromObj(interp, objv[6], B, Z_IDX) ) return TCL_ERROR;
  16371. result=VectorXYZ_DistanceSq(A,B);
  16372. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  16373. return TCL_OK;
  16374. }
  16375. /* Tcl Proc ::vectorN::length */
  16376. static int TclCmd_vectorN_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16377. int i;
  16378. double result,sum=0.0;
  16379. if( objc<1 ){
  16380. Tcl_WrongNumArgs(interp, 1, objv, "x ?y? ?z? ?...?");
  16381. return TCL_ERROR;
  16382. }
  16383. result=0.0;
  16384. for(i=1;i<objc;i++) {
  16385. double a;
  16386. if(Tcl_GetDoubleFromObj(interp,objv[i],&a)) return TCL_ERROR;
  16387. sum+=a*a;
  16388. }
  16389. result=sqrt(sum);
  16390. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  16391. return TCL_OK;
  16392. }
  16393. /* Tcl Proc ::vectorN::distance */
  16394. static int TclCmd_vectorN_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16395. int i;
  16396. double result;
  16397. if( objc<1 ){
  16398. Tcl_WrongNumArgs(interp, 1, objv, "i1 i2 ?j1 j2? ?k1 k2?");
  16399. return TCL_ERROR;
  16400. }
  16401. result=0.0;
  16402. for(i=1;i<objc;i+=2) {
  16403. double a,b,dx;
  16404. if(Tcl_GetDoubleFromObj(interp,objv[i],&a)) return TCL_ERROR;
  16405. if(i+1>=objc) {
  16406. Tcl_AppendResult(interp, "Odd number of arguments",(char*)0);
  16407. return TCL_ERROR;
  16408. }
  16409. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&b)) return TCL_ERROR;
  16410. dx=b-a;
  16411. result=result+dx*dx;
  16412. }
  16413. result=sqrt(result);
  16414. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  16415. return TCL_OK;
  16416. }
  16417. /* Tcl Proc ::vectorN::scale */
  16418. static int TclCmd_vectorN_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16419. int i;
  16420. double scale;
  16421. Tcl_Obj *pResult;
  16422. if( objc<3 ){
  16423. Tcl_WrongNumArgs(interp, 1, objv, "SCALE X Y Z");
  16424. return TCL_ERROR;
  16425. }
  16426. if(Tcl_GetDoubleFromObj(interp,objv[1],&scale)) return TCL_ERROR;
  16427. pResult=Tcl_NewObj();
  16428. for(i=2;i<objc;i++) {
  16429. double a,b,dx;
  16430. if(Tcl_GetDoubleFromObj(interp,objv[i],&a)) {
  16431. Tcl_DecrRefCount(pResult);
  16432. return TCL_ERROR;
  16433. }
  16434. Tcl_ListObjAppendElement(interp,pResult,ODIE_NewFuzzyObj(a*scale));
  16435. }
  16436. Tcl_SetObjResult(interp,pResult);
  16437. return TCL_OK;
  16438. }
  16439. /* Tcl Proc ::vectorN::scalevar */
  16440. static int TclCmd_vectorN_scalevar(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16441. double scale,val;
  16442. int scaleint,i,asint=0;
  16443. if( objc < 3 ){
  16444. Tcl_WrongNumArgs(interp, 1, objv, "scalesize DBLVAR ...");
  16445. return TCL_ERROR;
  16446. }
  16447. asint=1;
  16448. if(Tcl_GetIntFromObj(interp,objv[1],&scaleint)) {
  16449. asint=0;
  16450. if(Tcl_GetDoubleFromObj(interp,objv[1],&scale)) return TCL_ERROR;
  16451. } else {
  16452. scale=(double)scaleint;
  16453. }
  16454. for(i=2;i<objc;i++) {
  16455. double thisval,remainder;
  16456. Tcl_Obj *varname;
  16457. varname=Tcl_ObjGetVar2(interp,objv[i],NULL,0);
  16458. if(varname==NULL) continue;
  16459. if(Tcl_GetDoubleFromObj(interp,varname,&val)) continue;
  16460. thisval=scale*val;
  16461. if(asint) {
  16462. Tcl_ObjSetVar2(interp,objv[i],NULL,Tcl_NewIntObj(thisval),0);
  16463. } else {
  16464. remainder=fmod(thisval,scale);
  16465. Tcl_ObjSetVar2(interp,objv[i],NULL,ODIE_NewFuzzyObj(thisval-remainder),0);
  16466. }
  16467. }
  16468. return TCL_OK;
  16469. }
  16470. /* Tcl Proc ::vectorxy::compare */
  16471. static int TclCmd_vectorxy_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16472. VectorXY A, B;
  16473. int c;
  16474. if( objc!=3 ){
  16475. Tcl_WrongNumArgs(interp, 1, objv, "A B");
  16476. return TCL_ERROR;
  16477. }
  16478. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16479. if(Odie_GetVectorXYFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16480. c=VectorXY_SamePoint(A,B);
  16481. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(c));
  16482. return TCL_OK;
  16483. }
  16484. /* Tcl Proc ::vectorxy::add */
  16485. static int TclCmd_vectorxy_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16486. VectorXYZ A,B,C;
  16487. if(objc < 3) {
  16488. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  16489. return TCL_ERROR;
  16490. }
  16491. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16492. if(Odie_GetVectorXYFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16493. VectorXY_Add(C,A,B);
  16494. Tcl_SetObjResult(interp,VectorXY_To_TclObj(C));
  16495. return TCL_OK;
  16496. }
  16497. /* Tcl Proc ::vectorxy::subtract */
  16498. static int TclCmd_vectorxy_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16499. VectorXYZ A,B,C;
  16500. if(objc < 3) {
  16501. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  16502. return TCL_ERROR;
  16503. }
  16504. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16505. if(Odie_GetVectorXYFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16506. VectorXY_Subtract(C,A,B);
  16507. Tcl_SetObjResult(interp,VectorXY_To_TclObj(C));
  16508. return TCL_OK;
  16509. }
  16510. /* Tcl Proc ::vectorxy::midpoint */
  16511. static int TclCmd_vectorxy_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16512. VectorXYZ A,B,C;
  16513. if(objc < 3) {
  16514. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  16515. return TCL_ERROR;
  16516. }
  16517. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16518. if(Odie_GetVectorXYFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16519. VectorXY_Midpoint(C,A,B);
  16520. Tcl_SetObjResult(interp,VectorXY_To_TclObj(C));
  16521. return TCL_OK;
  16522. }
  16523. /* Tcl Proc ::vectorxy::add_stream */
  16524. static int TclCmd_vectorxy_add_stream(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16525. VectorXY A,B,C;
  16526. int i,n;
  16527. Tcl_Obj *pObj,*pResult;
  16528.  
  16529. if(objc < 3) {
  16530. Tcl_WrongNumArgs( interp, 1, objv, "A BLIST" );
  16531. return TCL_ERROR;
  16532. }
  16533. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16534. if( Tcl_ListObjLength(interp, objv[2], &n) ) return TCL_ERROR;
  16535. pResult=Tcl_NewListObj(0,NULL);
  16536. for(i=0; i<n; i++){
  16537. Tcl_ListObjIndex(0, objv[2], i, &pObj);
  16538. if(Odie_GetVectorXYFromTclObj(interp,pObj,B)) return TCL_ERROR;
  16539. VectorXY_Add(C,A,B);
  16540. Tcl_ListObjAppendElement(0, pResult, VectorXY_To_TclObj(C));
  16541. }
  16542. Tcl_SetObjResult(interp,pResult);
  16543. return TCL_OK;
  16544. }
  16545. /* Tcl Proc ::vectorxy::angle */
  16546. static int TclCmd_vectorxy_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16547. VectorXY A, B, C;
  16548. if( objc!=4 ){
  16549. Tcl_WrongNumArgs(interp, 1, objv, "A B C");
  16550. return TCL_ERROR;
  16551. }
  16552. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16553. if(Odie_GetVectorXYFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16554. if(Odie_GetVectorXYFromTclObj(interp,objv[3],C)) return TCL_ERROR;
  16555. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_Angle_Three_Point(A, B, C)));
  16556. return TCL_OK;
  16557. }
  16558. /* Tcl Proc ::vectorxy::create */
  16559. static int TclCmd_vectorxy_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16560. VectorXY A;
  16561. double x;
  16562. Tcl_Obj *pResult;
  16563. if(objc != 2 && objc !=3) {
  16564. Tcl_WrongNumArgs( interp, 1, objv, "LIST\nor\nx y" );
  16565. return TCL_ERROR;
  16566. }
  16567. if(objc==2) {
  16568. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16569. } else {
  16570. int i;
  16571. for(i=0;i<2;i++) {
  16572. if(Tcl_GetDoubleFromObj(interp,objv[1+i],&x)) return TCL_ERROR;
  16573. A[i]=x;
  16574. }
  16575. }
  16576. pResult=VectorXY_To_TclObj(A);
  16577. Tcl_SetObjResult(interp,pResult);
  16578. return TCL_OK;
  16579. }
  16580. /* Tcl Proc ::vectorxy::toint */
  16581. static int TclCmd_vectorxy_toint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16582. VectorXY A;
  16583. double x;
  16584. Tcl_Obj *pResult;
  16585. int i;
  16586.  
  16587. if(objc != 2 && objc !=4) {
  16588. Tcl_WrongNumArgs( interp, 1, objv, "LIST\nor\nx y" );
  16589. return TCL_ERROR;
  16590. }
  16591. if(objc==2) {
  16592. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16593. } else {
  16594. for(i=0;i<2;i++) {
  16595. if(Tcl_GetDoubleFromObj(interp,objv[1+i],&A[i])) return TCL_ERROR;
  16596. }
  16597. }
  16598. pResult=Tcl_NewObj();
  16599. for(i=0;i<2;i++) {
  16600. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj((int)A[i]));
  16601. }
  16602. Tcl_SetObjResult(interp,pResult);
  16603. return TCL_OK;
  16604. }
  16605. /* Tcl Proc ::vectorxy::crossproduct */
  16606. static int TclCmd_vectorxy_crossproduct(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16607. /*
  16608. ** tclcmd: vectorxy crossproduct A B C
  16609. ** Return the the cross product of AB*BC
  16610. */
  16611. VectorXY A, B, C;
  16612. if( objc!=4 ){
  16613. Tcl_WrongNumArgs(interp, 1, objv, "A B C");
  16614. return TCL_ERROR;
  16615. }
  16616. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16617. if(Odie_GetVectorXYFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16618. if(Odie_GetVectorXYFromTclObj(interp,objv[3],C)) return TCL_ERROR;
  16619. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_crossProduct(A, B, C)));
  16620. return TCL_OK;
  16621. }
  16622. /* Tcl Proc ::vectorxy::distance */
  16623. static int TclCmd_vectorxy_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16624. VECTORXY A,B;
  16625. if( objc!=3 ){
  16626. Tcl_WrongNumArgs(interp, 1, objv, "A B");
  16627. return TCL_ERROR;
  16628. }
  16629. double result=0.0,dx,dy;
  16630. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16631. if(Odie_GetVectorXYFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16632. dx=B[X_IDX]-A[X_IDX];
  16633. dy=B[Y_IDX]-A[Y_IDX];
  16634.  
  16635. result=sqrt(dx*dx + dy*dy);
  16636. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  16637. return TCL_OK;
  16638. }
  16639. /* Tcl Proc ::vectorxy::length */
  16640. static int TclCmd_vectorxy_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16641. VECTORXY A;
  16642. double result=0.0;
  16643. if( objc!=2 ){
  16644. Tcl_WrongNumArgs(interp, 1, objv, "A");
  16645. return TCL_ERROR;
  16646. }
  16647. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16648. result=sqrt(A[X_IDX]*A[X_IDX] + A[Y_IDX]*A[Y_IDX]);
  16649. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  16650. return TCL_OK;
  16651. }
  16652. /* Tcl Proc ::vectorxy::normalize */
  16653. static int TclCmd_vectorxy_normalize(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16654. VectorXY A;
  16655. if( objc!=2 ){
  16656. Tcl_WrongNumArgs(interp, 1, objv, "A");
  16657. return TCL_ERROR;
  16658. }
  16659. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16660. VectorXY_Normalize(A);
  16661. Tcl_SetObjResult(interp,VectorXY_To_TclObj(A));
  16662. return TCL_OK;
  16663. }
  16664. /* Tcl Proc ::vectorxy::dotproduct */
  16665. static int TclCmd_vectorxy_dotproduct(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16666. VectorXY A, B, C;
  16667. if( objc!=4 ){
  16668. Tcl_WrongNumArgs(interp, 1, objv, "A B C");
  16669. return TCL_ERROR;
  16670. }
  16671. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16672. if(Odie_GetVectorXYFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16673. if(Odie_GetVectorXYFromTclObj(interp,objv[3],C)) return TCL_ERROR;
  16674. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_Dot_Product(A, B, C)));
  16675. return TCL_OK;
  16676. }
  16677. /* Tcl Proc ::vectorxy::rightof */
  16678. static int TclCmd_vectorxy_rightof(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16679. /*
  16680. ** tclcmd: triag_test_rightof X0 Y0 X1 Y1 X2 Y2
  16681. **
  16682. ** A TCL command for testing the rightOf() function.
  16683. */
  16684. VectorXY A, B, C;
  16685. if( objc!=4 ){
  16686. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2");
  16687. return TCL_ERROR;
  16688. }
  16689. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16690. if(Odie_GetVectorXYFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16691. if(Odie_GetVectorXYFromTclObj(interp,objv[3],C)) return TCL_ERROR;
  16692. Tcl_SetObjResult(interp, Tcl_NewIntObj(VectorXY_BendDirection(A, B, C)));
  16693. return TCL_OK;
  16694. }
  16695. /* Tcl Proc ::vectorxy::rotate_and_size */
  16696. static int TclCmd_vectorxy_rotate_and_size(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16697. /*
  16698. ** Apply Matrices
  16699. */
  16700. Tcl_Obj *pResult;
  16701. int i;
  16702. double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0};
  16703. double nx,ny,scalex,scaley,angle;
  16704.  
  16705. if( objc < 7 ){
  16706. Tcl_WrongNumArgs(interp, 1, objv, "normalx normaly sizex sizey V ?V?...");
  16707. return TCL_ERROR;
  16708. }
  16709.  
  16710. if(Tcl_GetDoubleFromObj(interp,objv[1],&nx)) return TCL_ERROR;
  16711. if(Tcl_GetDoubleFromObj(interp,objv[2],&ny)) return TCL_ERROR;
  16712. if(Tcl_GetDoubleFromObj(interp,objv[3],&scalex)) return TCL_ERROR;
  16713. if(Tcl_GetDoubleFromObj(interp,objv[4],&scaley)) return TCL_ERROR;
  16714.  
  16715. angle=atan2(ny,nx);
  16716. matA[0]=cos(angle);
  16717. matA[1]=sin(angle);
  16718. matA[2]=-sin(angle);
  16719. matA[3]=cos(angle);
  16720. matA[4]=0.0;
  16721. matA[5]=0.0;
  16722.  
  16723. scalex*=0.5;
  16724. scaley*=0.5;
  16725. pResult=Tcl_NewObj();
  16726. for(i=5;i<objc;i++) {
  16727. double sx,sy;
  16728. VECTORXY A,B;
  16729. if(Odie_GetVectorXYFromTclObj(interp,objv[i],A)) {
  16730. Tcl_DecrRefCount(pResult);
  16731. return TCL_ERROR;
  16732. }
  16733. sx=A[X_IDX] * scalex;
  16734. sy=A[Y_IDX] * scaley;
  16735. B[X_IDX]=matA[0]*sx+matA[1]*sy+matA[4];
  16736. B[Y_IDX]=matA[2]*sx+matA[3]*sy+matA[5];
  16737. Tcl_ListObjAppendElement(interp,pResult,VectorXY_To_TclObj(B));
  16738. }
  16739. Tcl_SetObjResult(interp, pResult);
  16740. return TCL_OK;
  16741. }
  16742. /* Tcl Proc ::vectorxy::scale */
  16743. static int TclCmd_vectorxy_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16744. Tcl_Obj *pResult;
  16745. int i;
  16746. double scalex,scaley;
  16747.  
  16748. if( objc < 5 ){
  16749. Tcl_WrongNumArgs(interp, 1, objv, "sizex sizey V ?V...?");
  16750. return TCL_ERROR;
  16751. }
  16752.  
  16753. if(Tcl_GetDoubleFromObj(interp,objv[1],&scalex)) return TCL_ERROR;
  16754. if(Tcl_GetDoubleFromObj(interp,objv[2],&scaley)) return TCL_ERROR;
  16755.  
  16756. scalex*=0.5;
  16757. scaley*=0.5;
  16758. pResult=Tcl_NewObj();
  16759. for(i=3;i<objc;i+=2) {
  16760. double x,y;
  16761. VECTORXY A,B;
  16762. if(Odie_GetVectorXYFromTclObj(interp,objv[i],A)) {
  16763. Tcl_DecrRefCount(pResult);
  16764. return TCL_ERROR;
  16765. }
  16766. x=A[X_IDX];
  16767. y=A[Y_IDX];
  16768. B[X_IDX]=x*scalex;
  16769. B[Y_IDX]=y*scaley;
  16770. Tcl_ListObjAppendElement(interp,pResult,VectorXY_To_TclObj(B));
  16771. }
  16772. Tcl_SetObjResult(interp, pResult);
  16773. return TCL_OK;
  16774. }
  16775. /* Tcl Proc ::vectorxy::translate_and_zoom */
  16776. static int TclCmd_vectorxy_translate_and_zoom(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16777. /*
  16778. ** Apply Matrices
  16779. */
  16780. Tcl_Obj *pResult;
  16781. int i;
  16782. double zoom;
  16783. VECTORXY center;
  16784.  
  16785. if( objc < 5 ){
  16786. Tcl_WrongNumArgs(interp, 1, objv, "zoom CENTER V ?V...?");
  16787. return TCL_ERROR;
  16788. }
  16789. if(Tcl_GetDoubleFromObj(interp,objv[1],&zoom)) return TCL_ERROR;
  16790. if(Odie_GetVectorXYFromTclObj(interp,objv[2],center)) return TCL_ERROR;
  16791. pResult=Tcl_NewObj();
  16792. for(i=3;i<objc;i++) {
  16793. VECTORXY A,B;
  16794. if(Odie_GetVectorXYFromTclObj(interp,objv[i],A)) {
  16795. Tcl_DecrRefCount(pResult);
  16796. return TCL_ERROR;
  16797. }
  16798. B[X_IDX]=(A[X_IDX]/zoom)+center[X_IDX];
  16799. B[Y_IDX]=(A[Y_IDX]/zoom)+center[Y_IDX];
  16800. Tcl_ListObjAppendElement(interp,pResult,VectorXY_To_TclObj(B));
  16801. }
  16802. Tcl_SetObjResult(interp, pResult);
  16803. return TCL_OK;
  16804. }
  16805. /* Tcl Proc ::vectorxy::flatten */
  16806. static int TclCmd_vectorxy_flatten(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16807. VectorXYZ point;
  16808. int i,j;
  16809. Tcl_Obj *pResult;
  16810. pResult=Tcl_NewObj();
  16811. if(objc==2) {
  16812. Tcl_Obj **rowPtrs;
  16813. int rows;
  16814. if(Tcl_ListObjGetElements(interp, objv[1], &rows, &rowPtrs)) {
  16815. Tcl_DecrRefCount(pResult);
  16816. return TCL_ERROR;
  16817. }
  16818. for(j=0;j<rows;j++) {
  16819. if(Odie_GetVectorXYFromTclObj(interp,rowPtrs[j],point)) return TCL_ERROR;
  16820. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(point[X_IDX]));
  16821. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(point[Y_IDX]));
  16822. }
  16823. } else {
  16824. for(i=1;i<objc;i++) {
  16825. if(Odie_GetVectorXYFromTclObj(interp,objv[i],point)) return TCL_ERROR;
  16826. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(point[X_IDX]));
  16827. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(point[Y_IDX]));
  16828. }
  16829. }
  16830. Tcl_SetObjResult(interp,pResult);
  16831. return TCL_OK;
  16832. }
  16833. /* Tcl Proc ::vectorxyz::scale */
  16834. static int TclCmd_vectorxyz_scale(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16835. VectorXYZ A,C;
  16836. double b;
  16837. if( objc!=3 ){
  16838. Tcl_WrongNumArgs(interp, 1, objv, "A B");
  16839. return TCL_ERROR;
  16840. }
  16841. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16842. if(Tcl_GetDoubleFromObj(interp,objv[2],&b)) return TCL_ERROR;
  16843. VectorXYZ_Copy(C,A);
  16844. VectorXYZ_Scale(C,b);
  16845. Tcl_SetObjResult(interp, VectorXYZ_To_TclObj(C));
  16846. return TCL_OK;
  16847. }
  16848. /* Tcl Proc ::vectorxyz::zero */
  16849. static int TclCmd_vectorxyz_zero(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16850. VectorXYZ A;
  16851. VectorXYZ_Zero(A);
  16852. Tcl_SetObjResult(interp, VectorXYZ_To_TclObj(A));
  16853. return TCL_OK;
  16854. }
  16855. /* Tcl Proc ::vectorxyz::compare */
  16856. static int TclCmd_vectorxyz_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16857. VectorXYZ A, B;
  16858. int c;
  16859. if( objc!=3 ){
  16860. Tcl_WrongNumArgs(interp, 1, objv, "A B");
  16861. return TCL_ERROR;
  16862. }
  16863. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16864. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16865. c=VectorXYZ_SamePoint(A,B);
  16866. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(c));
  16867. return TCL_OK;
  16868. }
  16869. /* Tcl Proc ::vectorxyz::polygon_normal_compare */
  16870. static int TclCmd_vectorxyz_polygon_normal_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16871. VectorXYZ A, B;
  16872. int c;
  16873. if( objc!=3 ){
  16874. Tcl_WrongNumArgs(interp, 1, objv, "A B");
  16875. return TCL_ERROR;
  16876. }
  16877. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16878. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16879. c=1;
  16880. if((fabs(A[X_IDX])-fabs(B[X_IDX]))>0.1) c=0;
  16881. if((fabs(A[Y_IDX])-fabs(B[Y_IDX]))>0.1) c=0;
  16882. if((fabs(A[Z_IDX])-fabs(B[Z_IDX]))>0.1) c=0;
  16883.  
  16884. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(c));
  16885. return TCL_OK;
  16886. }
  16887. /* Tcl Proc ::vectorxyz::create */
  16888. static int TclCmd_vectorxyz_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16889. VectorXYZ A;
  16890. double x;
  16891. Tcl_Obj *pResult;
  16892. if(objc != 2 && objc !=4) {
  16893. Tcl_WrongNumArgs( interp, 1, objv, "LIST\nor\nx y z" );
  16894. return TCL_ERROR;
  16895. }
  16896. if(objc==2) {
  16897. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16898. } else {
  16899. int i;
  16900. for(i=0;i<3;i++) {
  16901. if(Tcl_GetDoubleFromObj(interp,objv[1+i],&x)) return TCL_ERROR;
  16902. A[i]=x;
  16903. }
  16904. }
  16905. pResult=VectorXYZ_To_TclObj(A);
  16906. Tcl_SetObjResult(interp,pResult);
  16907. return TCL_OK;
  16908. }
  16909. /* Tcl Proc ::vectorxyz::toint */
  16910. static int TclCmd_vectorxyz_toint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16911. VectorXYZ A;
  16912. double x;
  16913. Tcl_Obj *pResult;
  16914. int i;
  16915.  
  16916. if(objc != 2 && objc !=5) {
  16917. Tcl_WrongNumArgs( interp, 1, objv, "LIST\nor\nx y z" );
  16918. return TCL_ERROR;
  16919. }
  16920. if(objc==2) {
  16921. if(Odie_GetVectorXYFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16922. } else {
  16923. for(i=0;i<3;i++) {
  16924. if(Tcl_GetDoubleFromObj(interp,objv[1+i],&A[i])) return TCL_ERROR;
  16925. }
  16926. }
  16927. pResult=Tcl_NewObj();
  16928. for(i=0;i<3;i++) {
  16929. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj((int)A[i]));
  16930. }
  16931. Tcl_SetObjResult(interp,pResult);
  16932. return TCL_OK;
  16933. }
  16934. /* Tcl Proc ::vectorxyz::add */
  16935. static int TclCmd_vectorxyz_add(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16936. VectorXYZ A,B,C;
  16937. if(objc < 3) {
  16938. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  16939. return TCL_ERROR;
  16940. }
  16941. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16942. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16943. VectorXYZ_Add(C,A,B);
  16944. Tcl_SetObjResult(interp,VectorXYZ_To_TclObj(C));
  16945. return TCL_OK;
  16946. }
  16947. /* Tcl Proc ::vectorxyz::add_inplace */
  16948. static int TclCmd_vectorxyz_add_inplace(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16949. Odie_MatrixObj *A;
  16950. VectorXYZ B;
  16951. Tcl_Obj *varname;
  16952. if(objc < 3) {
  16953. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  16954. return TCL_ERROR;
  16955. }
  16956. varname=Tcl_ObjGetVar2(interp,objv[1],NULL,0);
  16957. if(varname==NULL) {
  16958. return TCL_ERROR;
  16959. }
  16960. if(Odie_GetMatrixFromTclObj(interp,varname,MATFORM_vectorxyz,&A)) return TCL_ERROR;
  16961. Tcl_ResetResult(interp);
  16962. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16963. VectorXYZ_Add(A->matrix,A->matrix,B);
  16964. Tcl_InvalidateStringRep(varname);
  16965. return TCL_OK;
  16966. }
  16967. /* Tcl Proc ::vectorxyz::orthagonal */
  16968. static int TclCmd_vectorxyz_orthagonal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16969. int result;
  16970. VectorXY A, B;
  16971. if( objc!=7 ){
  16972. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 Z0 X1 Y1 Z1");
  16973. return TCL_ERROR;
  16974. }
  16975. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16976. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16977. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(VectorXYZ_IsOrthagonal(A,B)));
  16978. return TCL_OK;
  16979. }
  16980. /* Tcl Proc ::vectorxyz::subtract */
  16981. static int TclCmd_vectorxyz_subtract(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16982. VectorXYZ A,B,C;
  16983. if(objc < 3) {
  16984. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  16985. return TCL_ERROR;
  16986. }
  16987. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  16988. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  16989. VectorXYZ_Subtract(C,A,B);
  16990. Tcl_SetObjResult(interp,VectorXYZ_To_TclObj(C));
  16991. return TCL_OK;
  16992. }
  16993. /* Tcl Proc ::vectorxyz::midpoint */
  16994. static int TclCmd_vectorxyz_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  16995. VectorXYZ A,B,C;
  16996. if(objc < 3) {
  16997. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  16998. return TCL_ERROR;
  16999. }
  17000. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  17001. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  17002. VectorXYZ_Midpoint(C,A,B);
  17003. Tcl_SetObjResult(interp,VectorXYZ_To_TclObj(C));
  17004. return TCL_OK;
  17005. }
  17006. /* Tcl Proc ::vectorxyz::cross_product */
  17007. static int TclCmd_vectorxyz_cross_product(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17008. VectorXYZ A,B,C;
  17009. if(objc < 3) {
  17010. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  17011. return TCL_ERROR;
  17012. }
  17013. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  17014. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  17015. VectorXYZ_Cross_Product(C,A,B);
  17016. Tcl_SetObjResult(interp,VectorXYZ_To_TclObj(C));
  17017. return TCL_OK;
  17018. }
  17019. /* Tcl Proc ::vectorxyz::dot_product */
  17020. static int TclCmd_vectorxyz_dot_product(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17021. VectorXYZ A,B;
  17022. double result;
  17023. if(objc < 3) {
  17024. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  17025. return TCL_ERROR;
  17026. }
  17027. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  17028. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  17029. result=VectorXYZ_Dot_Product(A,B);
  17030. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  17031. return TCL_OK;
  17032. }
  17033. /* Tcl Proc ::vectorxyz::transform */
  17034. static int TclCmd_vectorxyz_transform(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17035. MATOBJ *Affine;
  17036. VectorXYZ A,C;
  17037. int i,n;
  17038. n=objc-2;
  17039. Tcl_Obj **pArray;
  17040. if(objc < 3) {
  17041. Tcl_WrongNumArgs( interp, 1, objv, "affine vector ?vector...?" );
  17042. return TCL_ERROR;
  17043. }
  17044. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_affine,&Affine)) return TCL_ERROR;
  17045. if(objc==3) {
  17046. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],A)) return TCL_ERROR;
  17047. VectorXYZ_MatrixMultiply(C,A,Affine->matrix);
  17048. Tcl_SetObjResult(interp,VectorXYZ_To_TclObj(C));
  17049. return TCL_OK;
  17050. }
  17051. pArray=(Tcl_Obj **)ckalloc(sizeof(Tcl_Obj)*n);
  17052. for(i=0;i<n;i++) {
  17053. if(Odie_GetVectorXYZFromTclObj(interp,objv[2+i],A)) return TCL_ERROR;
  17054. VectorXYZ_MatrixMultiply(C,A,Affine->matrix);
  17055. pArray[i]=VectorXYZ_To_TclObj(C);
  17056. }
  17057. Tcl_SetObjResult(interp,Tcl_NewListObj(n,pArray));
  17058. ckfree((char *)pArray);
  17059. return TCL_OK;
  17060. }
  17061. /* Tcl Proc ::vectorxyz::length */
  17062. static int TclCmd_vectorxyz_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17063. VectorXYZ A;
  17064. double result;
  17065. if(objc != 2) {
  17066. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17067. return TCL_ERROR;
  17068. }
  17069. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  17070. result=VectorXYZ_Magnitude(A);
  17071. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  17072. return TCL_OK;
  17073. }
  17074. /* Tcl Proc ::vectorxyz::distance */
  17075. static int TclCmd_vectorxyz_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17076. VectorXYZ A,B;
  17077. double result;
  17078. if(objc != 3) {
  17079. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  17080. return TCL_ERROR;
  17081. }
  17082. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  17083. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  17084.  
  17085. result=VectorXYZ_Distance(A,B);
  17086. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  17087. return TCL_OK;
  17088. }
  17089. /* Tcl Proc ::vectorxyz::distanceSq */
  17090. static int TclCmd_vectorxyz_distanceSq(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17091. VectorXYZ A,B;
  17092. double result;
  17093. if(objc != 3) {
  17094. Tcl_WrongNumArgs( interp, 1, objv, "A B" );
  17095. return TCL_ERROR;
  17096. }
  17097. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  17098. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  17099.  
  17100. result=VectorXYZ_DistanceSq(A,B);
  17101. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  17102. return TCL_OK;
  17103. }
  17104. /* Tcl Proc ::vectorxyz::length_inv_sqr */
  17105. static int TclCmd_vectorxyz_length_inv_sqr(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17106. VectorXYZ A;
  17107. double result;
  17108. if(objc != 2) {
  17109. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17110. return TCL_ERROR;
  17111. }
  17112. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  17113. result=VectorXYZ_MagnitudeInvSqr(A);
  17114. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  17115. return TCL_OK;
  17116. }
  17117. /* Tcl Proc ::vectorxyz::normalize */
  17118. static int TclCmd_vectorxyz_normalize(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17119. VectorXYZ A;
  17120. if(objc != 2) {
  17121. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17122. return TCL_ERROR;
  17123. }
  17124. /* This is save because Odie_GetVectorXYZFromTclObj copies values and
  17125. ** doesn't redirect to the point in memory where the value actually lives
  17126. */
  17127. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  17128. VectorXYZ_Normalize(A);
  17129. Tcl_SetObjResult(interp,VectorXYZ_To_TclObj(A));
  17130. return TCL_OK;
  17131. }
  17132. /* Tcl Proc ::vectorxyz::point_on_segment */
  17133. static int TclCmd_vectorxyz_point_on_segment(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17134. VectorXYZ A,B,X;
  17135. if( objc != 4 ){
  17136. Tcl_WrongNumArgs(interp, 1, objv, "point_on_segment X A B");
  17137. return TCL_ERROR;
  17138. }
  17139. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],X)) return TCL_ERROR;
  17140. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],A)) return TCL_ERROR;
  17141. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],B)) return TCL_ERROR;
  17142. Tcl_SetObjResult(interp, Tcl_NewIntObj(VectorXYZ_PointIsOnSegment(X,A,B)));
  17143. return TCL_OK;
  17144. }
  17145. /* Tcl Proc ::vectorxyz::point_on_segment_x */
  17146. static int TclCmd_vectorxyz_point_on_segment_x(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17147. VectorXYZ A,B,X;
  17148. VectorXYZ v1, v2;
  17149. double t;
  17150.  
  17151. if( objc != 4 ){
  17152. Tcl_WrongNumArgs(interp, 1, objv, "point_on_segment_x X A B");
  17153. return TCL_ERROR;
  17154. }
  17155. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],X)) return TCL_ERROR;
  17156. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],A)) return TCL_ERROR;
  17157. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],B)) return TCL_ERROR;
  17158.  
  17159.  
  17160. VectorXYZ_Subtract(v1, X, A);
  17161. VectorXYZ_Subtract(v2, B, A);
  17162. if(VectorXYZ_DistanceSq(v1,v2)<Vector_Tolerance_Sq) {
  17163. /* X, A, and B are all the same point */
  17164. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(0.5));
  17165. return TCL_OK;
  17166. }
  17167. t = VectorXYZ_Dot_Product(v1, v2)/VectorXYZ_MagnitudeSq(v2);
  17168. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(t));
  17169. return TCL_OK;
  17170. }
  17171. /* Tcl Proc ::vectorxyz::axis_of_normal */
  17172. static int TclCmd_vectorxyz_axis_of_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17173. VectorXYZ A;
  17174. int axis;
  17175.  
  17176. if( objc != 2 ){
  17177. Tcl_WrongNumArgs(interp, 1, objv, "axis_of_normal X");
  17178. return TCL_ERROR;
  17179. }
  17180. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  17181. axis=VectorXYZ_AxisOfNormal(A);
  17182. Tcl_SetObjResult(interp, Tcl_NewIntObj(axis));
  17183. return TCL_OK;
  17184. }
  17185. /* Tcl Proc ::vectorxyz::bend_direction */
  17186. static int TclCmd_vectorxyz_bend_direction(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17187. VectorXYZ A,B,C;
  17188. int result;
  17189. if(objc != 4) {
  17190. Tcl_WrongNumArgs( interp, 1, objv, "A B C" );
  17191. return TCL_ERROR;
  17192. }
  17193. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  17194. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  17195. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],C)) return TCL_ERROR;
  17196. result=VectorXYZ_BendDirection(A,B,C);
  17197. Tcl_SetObjResult(interp,Tcl_NewIntObj(result));
  17198. return TCL_OK;
  17199. }
  17200. /* Tcl Proc ::vectorxyz::angle_three_points */
  17201. static int TclCmd_vectorxyz_angle_three_points(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17202. VectorXYZ A,B,C,normal;
  17203. double result;
  17204. if(objc != 4 && objc != 5) {
  17205. Tcl_WrongNumArgs( interp, 1, objv, "A B C ?normal?" );
  17206. return TCL_ERROR;
  17207. }
  17208. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  17209. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  17210. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],C)) return TCL_ERROR;
  17211. if(objc==5) {
  17212. if(Odie_GetVectorXYZFromTclObj(interp,objv[4],normal)) return TCL_ERROR;
  17213. } else {
  17214. VectorXYZ_Normal_of_Three_Points(normal,A,B,C);
  17215. }
  17216. result=VectorXYZ_Angle_Three_Point(A,B,C,normal);
  17217. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result));
  17218. return TCL_OK;
  17219. }
  17220. /* Tcl Proc ::vectorxyz::colinear */
  17221. static int TclCmd_vectorxyz_colinear(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17222. int i,c;
  17223. VectorXYZ P[3];
  17224.  
  17225. if(objc != 4) {
  17226. Tcl_WrongNumArgs( interp, 1, objv, "A B C" );
  17227. return TCL_ERROR;
  17228. }
  17229. for(i=0;i<3;i++) {
  17230. if(Odie_GetVectorXYZFromTclObj(interp,objv[1+i],P[i])) return TCL_ERROR;
  17231. }
  17232. c=VectorXYZ_IsColinear(P[0],P[1],P[2]);
  17233. Tcl_SetObjResult(interp,Tcl_NewIntObj(c));
  17234. return TCL_OK;
  17235. }
  17236. /* Tcl Proc ::vectorxyz::coplaner */
  17237. static int TclCmd_vectorxyz_coplaner(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17238. int i,c;
  17239. VectorXYZ P[3],Q;
  17240.  
  17241. if(objc < 5) {
  17242. Tcl_WrongNumArgs( interp, 1, objv, "A B C D ..." );
  17243. return TCL_ERROR;
  17244. }
  17245. for(i=0;i<3;i++) {
  17246. if(Odie_GetVectorXYZFromTclObj(interp,objv[1+i],P[i])) return TCL_ERROR;
  17247. }
  17248. for(i=4;i<objc;i++) {
  17249. if(Odie_GetVectorXYZFromTclObj(interp,objv[i],Q)) return TCL_ERROR;
  17250. if(!VectorXYZ_IsCoplaner(P[0],P[1],P[2],Q)) {
  17251. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(0));
  17252. return TCL_OK;
  17253. }
  17254. }
  17255. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(1));
  17256. return TCL_OK;
  17257. }
  17258. /* Tcl Proc ::vectorxyz::linelinecoincident_int */
  17259. static int TclCmd_vectorxyz_linelinecoincident_int(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17260. int i,c;
  17261. VectorXYZ P[4];
  17262. VectorXYZ ICEPT[2];
  17263.  
  17264. if(objc != 5) {
  17265. Tcl_WrongNumArgs( interp, 1, objv, "A B C D" );
  17266. return TCL_ERROR;
  17267. }
  17268. for(i=0;i<4;i++) {
  17269. if(Odie_GetVectorXYZFromTclObj(interp,objv[1+i],P[i])) return TCL_ERROR;
  17270. }
  17271. c=VectorXYZ_LineLineCoincident(P[0],P[1],P[2],P[3],ICEPT[0],ICEPT[1]);
  17272. Tcl_SetObjResult(interp,Tcl_NewIntObj(c));
  17273. return TCL_OK;
  17274. }
  17275. /* Tcl Proc ::vectorxyz::linelinecoincident */
  17276. static int TclCmd_vectorxyz_linelinecoincident(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17277. int i,c;
  17278. VectorXYZ P[4];
  17279. VectorXYZ ICEPT[2];
  17280.  
  17281. if(objc != 5) {
  17282. Tcl_WrongNumArgs( interp, 1, objv, "A B C D" );
  17283. return TCL_ERROR;
  17284. }
  17285. for(i=0;i<4;i++) {
  17286. if(Odie_GetVectorXYZFromTclObj(interp,objv[1+i],P[i])) return TCL_ERROR;
  17287. }
  17288. c=VectorXYZ_LineLineCoincident(P[0],P[1],P[2],P[3],ICEPT[0],ICEPT[1]);
  17289. if(c>0) {
  17290. Tcl_Obj *pResult=Tcl_NewObj();
  17291. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(c));
  17292. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(ICEPT[0]));
  17293. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(ICEPT[1]));
  17294. Tcl_SetObjResult(interp,pResult);
  17295. } else {
  17296. Tcl_SetObjResult(interp,Tcl_NewIntObj(c));
  17297. }
  17298. return TCL_OK;
  17299. }
  17300. /* Tcl Proc ::vectorxyz::linelineintersect */
  17301. static int TclCmd_vectorxyz_linelineintersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17302. int i,c;
  17303. VectorXYZ P[4];
  17304. VectorXYZ PA,PB;
  17305. double mua,mub;
  17306. Tcl_Obj *pResult;
  17307.  
  17308. if(objc != 5) {
  17309. Tcl_WrongNumArgs( interp, 1, objv, "A B C D" );
  17310. return TCL_ERROR;
  17311. }
  17312. for(i=0;i<4;i++) {
  17313. if(Odie_GetVectorXYZFromTclObj(interp,objv[1+i],P[i])) return TCL_ERROR;
  17314. }
  17315. c=VectorXYZ_LineLineIntersect(P[0],P[1],P[2],P[3],PA,PB,&mua,&mub);
  17316. if(c==0) {
  17317. Tcl_ResetResult(interp);
  17318. return TCL_OK;
  17319. }
  17320. if(c<=0) {
  17321. Tcl_ResetResult(interp);
  17322. return TCL_OK;
  17323. }
  17324. if(mua>=1.0 || mua<=0.0) {
  17325. Tcl_ResetResult(interp);
  17326. return TCL_OK;
  17327. }
  17328. if(mub>=1.0 || mub<=0.0) {
  17329. Tcl_ResetResult(interp);
  17330. return TCL_OK;
  17331. }
  17332. pResult=Tcl_NewObj();
  17333. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(PA));
  17334. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(PB));
  17335. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(mua));
  17336. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(mub));
  17337. Tcl_SetObjResult(interp,pResult);
  17338. return TCL_OK;
  17339. }
  17340. /* Tcl Proc ::vectorxyz::linelineintersect_distance */
  17341. static int TclCmd_vectorxyz_linelineintersect_distance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17342. int i,c;
  17343. VectorXYZ P[4];
  17344. VectorXYZ PA,PB;
  17345. double mua,mub;
  17346. Tcl_Obj *pResult;
  17347.  
  17348. if(objc != 5) {
  17349. Tcl_WrongNumArgs( interp, 1, objv, "A B C D" );
  17350. return TCL_ERROR;
  17351. }
  17352. for(i=0;i<4;i++) {
  17353. if(Odie_GetVectorXYZFromTclObj(interp,objv[1+i],P[i])) return TCL_ERROR;
  17354. }
  17355. c=VectorXYZ_LineLineIntersect(P[0],P[1],P[2],P[3],PA,PB,&mua,&mub);
  17356. if(c==0) {
  17357. Tcl_ResetResult(interp);
  17358. return TCL_OK;
  17359. }
  17360. if(c<=0) {
  17361. Tcl_SetObjResult(interp,Tcl_NewIntObj(c));
  17362. return TCL_OK;
  17363. }
  17364. pResult=Tcl_NewObj();
  17365. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(PA));
  17366. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(PB));
  17367. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(mua));
  17368. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(mub));
  17369. Tcl_SetObjResult(interp,pResult);
  17370. return TCL_OK;
  17371. }
  17372. /* Tcl Proc ::vectorxyz::sizeof */
  17373. static int TclCmd_vectorxyz_sizeof(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17374. Tcl_Obj *pResult;
  17375. pResult=Tcl_NewObj();
  17376. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(sizeof(VectorXYZ)));
  17377.  
  17378. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(X_IDX));
  17379. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(Y_IDX));
  17380. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(Z_IDX));
  17381.  
  17382. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(QW_IDX));
  17383. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(QX_IDX));
  17384. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(QY_IDX));
  17385. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(QZ_IDX));
  17386.  
  17387. Tcl_SetObjResult(interp, pResult);
  17388. return TCL_OK;
  17389. }
  17390. /* Tcl Proc ::vectorxyz::closest_point_on_segment */
  17391. static int TclCmd_vectorxyz_closest_point_on_segment(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17392. VectorXYZ A,B,R,X;
  17393. if(objc!=4) {
  17394. Tcl_WrongNumArgs(interp, 1, objv, "A B X");
  17395. return TCL_ERROR;
  17396. }
  17397. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],A)) return TCL_ERROR;
  17398. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],B)) return TCL_ERROR;
  17399. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],X)) return TCL_ERROR;
  17400. VectorXYZ_ClosestPointOnSegment(A,B,X,R);
  17401. Tcl_SetObjResult(interp, VectorXYZ_To_TclObj(R));
  17402. return TCL_OK;
  17403. }
  17404. /* Tcl Proc ::vectorxyz::point_in_triangle */
  17405. static int TclCmd_vectorxyz_point_in_triangle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17406. VectorXYZ TA,TB,TC,POINT,LA,LB,INTERSECT,normal,center;
  17407. double t,d1,d2;
  17408. if(objc!=5) {
  17409. Tcl_WrongNumArgs(interp, 1, objv, "TA TB TC POINT");
  17410. return TCL_ERROR;
  17411. }
  17412. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],TA)) return TCL_ERROR;
  17413. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],TB)) return TCL_ERROR;
  17414. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],TC)) return TCL_ERROR;
  17415. if(Odie_GetVectorXYZFromTclObj(interp,objv[4],POINT)) return TCL_ERROR;
  17416. center[X_IDX] = (TA[X_IDX]+TB[X_IDX]+TC[X_IDX])/3.0;
  17417. center[Y_IDX] = (TA[X_IDX]+TB[Y_IDX]+TC[Y_IDX])/3.0;
  17418. center[Z_IDX] = (TA[Z_IDX]+TB[Z_IDX]+TC[Z_IDX])/3.0;
  17419.  
  17420. VectorXYZ_Normal_of_Three_Points(normal,TA,TB,TC);
  17421.  
  17422. d1 = VectorXYZ_Distance(POINT, center)*2;
  17423. d2 = normal[X_IDX]*d1;
  17424. LA[X_IDX] = POINT[X_IDX] + d2;
  17425. LB[X_IDX] = POINT[X_IDX] - d2;
  17426. d2 = normal[Y_IDX]*d1;
  17427. LA[Y_IDX] = POINT[Y_IDX] + d2;
  17428. LB[Y_IDX] = POINT[Y_IDX] - d2;
  17429. d2 = normal[Z_IDX]*d1;
  17430. LA[Z_IDX] = POINT[Z_IDX] + d2;
  17431. LB[Z_IDX] = POINT[Z_IDX] - d2;
  17432.  
  17433. t=VectorXYZ_TriangleLineIntersect(TA,TB,TC,LA,LB,INTERSECT);
  17434. if(t<0) {
  17435. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  17436. return TCL_OK;
  17437. }
  17438. d1=VectorXYZ_DistanceSq(POINT,INTERSECT);
  17439. if(d1<=Vector_Tolerance_Sq) {
  17440. Tcl_SetObjResult(interp,Tcl_NewIntObj(1));
  17441. } else {
  17442. Tcl_SetObjResult(interp,Tcl_NewIntObj(0));
  17443. }
  17444. return TCL_OK;
  17445. }
  17446. /* Tcl Proc ::vectorxyz::triangle_line_intersect */
  17447. static int TclCmd_vectorxyz_triangle_line_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17448. VectorXYZ TA,TB,TC,LA,LB,INTERSECT;
  17449. double t;
  17450. Tcl_Obj *pResult;
  17451. if(objc!=6) {
  17452. Tcl_WrongNumArgs(interp, 1, objv, "TA TB TC LA LB");
  17453. return TCL_ERROR;
  17454. }
  17455. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],TA)) return TCL_ERROR;
  17456. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],TB)) return TCL_ERROR;
  17457. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],TC)) return TCL_ERROR;
  17458. if(Odie_GetVectorXYZFromTclObj(interp,objv[4],LA)) return TCL_ERROR;
  17459. if(Odie_GetVectorXYZFromTclObj(interp,objv[5],LB)) return TCL_ERROR;
  17460. t=VectorXYZ_TriangleLineIntersect(TA,TB,TC,LA,LB,INTERSECT);
  17461. pResult=Tcl_NewObj();
  17462. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(t));
  17463. if(t>=0) {
  17464. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(INTERSECT));
  17465. }
  17466. Tcl_SetObjResult(interp, pResult);
  17467. return TCL_OK;
  17468. }
  17469. /* Tcl Proc ::vectorxyz::line_sphere_intersect_length */
  17470. static int TclCmd_vectorxyz_line_sphere_intersect_length(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17471. MATOBJ *A,*B,*C;
  17472. double brad;
  17473. double ix,iy;
  17474.  
  17475. if(objc<5) {
  17476. Tcl_WrongNumArgs(interp, 1, objv, "A B C brad");
  17477. return TCL_ERROR;
  17478. }
  17479. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz,&A)) return TCL_ERROR;
  17480. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_vectorxyz,&B)) return TCL_ERROR;
  17481. if(Odie_GetMatrixFromTclObj(interp,objv[3],MATFORM_vectorxyz,&C)) return TCL_ERROR;
  17482. if( Tcl_GetDoubleFromObj(interp, objv[4], &brad) ) return TCL_ERROR;
  17483.  
  17484. if(!VectorXYZ_LineSphereIntersect(
  17485. A->matrix[X_IDX],A->matrix[Y_IDX],A->matrix[Z_IDX],
  17486. B->matrix[X_IDX],B->matrix[Y_IDX],B->matrix[Z_IDX],
  17487. C->matrix[X_IDX],C->matrix[Y_IDX],C->matrix[Z_IDX],
  17488. brad,&ix,&iy)) {
  17489. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(0.0));
  17490. return TCL_OK;
  17491. }
  17492. if(ix>=0.0 && ix <= 1.0 && iy>=0.0 && iy <= 1.0) {
  17493. double dx,dy,dz,len;
  17494. dx=B->matrix[X_IDX]-A->matrix[X_IDX];
  17495. dy=B->matrix[Y_IDX]-A->matrix[Y_IDX];
  17496. dz=B->matrix[Z_IDX]-A->matrix[Z_IDX];
  17497. len=sqrt(dx*dx+dy*dy+dz*dz);
  17498. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(len*fabs(iy-ix)));
  17499. } else {
  17500. /* Intersection outside of segment or tangental to segment*/
  17501. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(0.0));
  17502. }
  17503. return TCL_OK;
  17504. }
  17505. /* Tcl Proc ::vectorxyz::line_sphere_intersect_area */
  17506. static int TclCmd_vectorxyz_line_sphere_intersect_area(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17507. MATOBJ *A,*B,*C;
  17508. double brad;
  17509. double ix,iy;
  17510.  
  17511. if(objc<5) {
  17512. Tcl_WrongNumArgs(interp, 1, objv, "A B C brad");
  17513. return TCL_ERROR;
  17514. }
  17515. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz,&A)) return TCL_ERROR;
  17516. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_vectorxyz,&B)) return TCL_ERROR;
  17517. if(Odie_GetMatrixFromTclObj(interp,objv[3],MATFORM_vectorxyz,&C)) return TCL_ERROR;
  17518. if( Tcl_GetDoubleFromObj(interp, objv[4], &brad) ) return TCL_ERROR;
  17519.  
  17520. if(!VectorXYZ_LineSphereIntersect(
  17521. A->matrix[X_IDX],A->matrix[Y_IDX],A->matrix[Z_IDX],
  17522. B->matrix[X_IDX],B->matrix[Y_IDX],B->matrix[Z_IDX],
  17523. C->matrix[X_IDX],C->matrix[Y_IDX],C->matrix[Z_IDX],
  17524. brad,&ix,&iy)) {
  17525. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(0.0));
  17526. return TCL_OK;
  17527. }
  17528. if(ix>=0.0 && ix <= 1.0 && iy>=0.0 && iy <= 1.0) {
  17529. double dx,dy,dz,len;
  17530. dx=B->matrix[X_IDX]-A->matrix[X_IDX];
  17531. dy=B->matrix[Y_IDX]-A->matrix[Y_IDX];
  17532. dz=B->matrix[Z_IDX]-A->matrix[Z_IDX];
  17533. len=sqrt(dx*dx+dy*dy+dz*dz)*fabs(iy-ix);
  17534. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(M_PI*(len*len)));
  17535. } else {
  17536. /* Intersection outside of segment or tangental to segment*/
  17537. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(0.0));
  17538. }
  17539. return TCL_OK;
  17540. }
  17541. /* Tcl Proc ::vectorxyz::line_sphere_intersect */
  17542. static int TclCmd_vectorxyz_line_sphere_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17543. MATOBJ *A,*B,*C;
  17544. double brad;
  17545. double ix,iy;
  17546. Tcl_Obj *pResult;
  17547.  
  17548. if(objc<5) {
  17549. Tcl_WrongNumArgs(interp, 1, objv, "A B C brad");
  17550. return TCL_ERROR;
  17551. }
  17552. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz,&A)) return TCL_ERROR;
  17553. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_vectorxyz,&B)) return TCL_ERROR;
  17554. if(Odie_GetMatrixFromTclObj(interp,objv[3],MATFORM_vectorxyz,&C)) return TCL_ERROR;
  17555. if( Tcl_GetDoubleFromObj(interp, objv[4], &brad) ) return TCL_ERROR;
  17556.  
  17557. if(!VectorXYZ_LineSphereIntersect(
  17558. A->matrix[X_IDX],A->matrix[Y_IDX],A->matrix[Z_IDX],
  17559. B->matrix[X_IDX],B->matrix[Y_IDX],B->matrix[Z_IDX],
  17560. C->matrix[X_IDX],C->matrix[Y_IDX],C->matrix[Z_IDX],
  17561. brad,&ix,&iy)) {
  17562. return TCL_OK;
  17563. }
  17564. pResult=Tcl_NewObj();
  17565. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(ix));
  17566. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(iy));
  17567. Tcl_SetObjResult(interp, pResult);
  17568. return TCL_OK;
  17569. }
  17570. /* Tcl Proc ::vectorxyz::polygon_normal */
  17571. static int TclCmd_vectorxyz_polygon_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17572. VectorXYZ normal,*element;
  17573. int i,j,n;
  17574. AABBXYZ bbox;
  17575. VectorXYZ_AABB_Reset(bbox);
  17576. VectorXYZ_Zero(normal);
  17577. if(objc<2) {
  17578. Tcl_WrongNumArgs(interp, 1, objv, "A B C ?D...?");
  17579. return TCL_ERROR;
  17580. }
  17581. if(objc==2) {
  17582. Tcl_Obj **elemPtrs;
  17583. int result;
  17584. result = Tcl_ListObjGetElements(interp, objv[1], &n, &elemPtrs);
  17585. if (result != TCL_OK) {
  17586. return result;
  17587. }
  17588. if(n<3) {
  17589. Tcl_AppendResult(interp, "Needs at least points", 0);
  17590. return TCL_ERROR;
  17591. }
  17592. element=(VectorXYZ *)Vector_Alloc(sizeof(VectorXYZ)*n);
  17593. for(i=0;i<n;i++) {
  17594. if(Odie_GetVectorXYZFromTclObj(interp,elemPtrs[i],element[i])) goto error;
  17595. }
  17596. } else {
  17597. n=objc-1;
  17598. if(n<3) {
  17599. Tcl_AppendResult(interp, "Needs at least points", 0);
  17600. return TCL_ERROR;
  17601. }
  17602. element=(VectorXYZ *)Vector_Alloc(sizeof(VectorXYZ)*n);
  17603. for(i=1;i<objc;i++) {
  17604. if(Odie_GetVectorXYZFromTclObj(interp,objv[i],element[i-1])) goto error;
  17605. VectorXYZ_AABB_Measure(element[i-1],bbox);
  17606. }
  17607. }
  17608. if(n==3) {
  17609. VectorXYZ one,two;
  17610. VectorXYZ_Subtract(one, element[1], element[0]);
  17611. VectorXYZ_Subtract(two, element[2], element[0]);
  17612. normal[X_IDX] = one[Y_IDX]*two[Z_IDX] - one[Z_IDX]*two[Y_IDX];
  17613. normal[Y_IDX] = one[Z_IDX]*two[X_IDX] - one[X_IDX]*two[Z_IDX];
  17614. normal[Z_IDX] = one[X_IDX]*two[Y_IDX] - one[Y_IDX]*two[X_IDX];
  17615. } else {
  17616. for(i=0;i<n;i++) {
  17617. j=(i+1)%n;
  17618. normal[X_IDX] += (element[j][Y_IDX]-element[i][Y_IDX]) * (element[j][Z_IDX]+element[i][Z_IDX]);
  17619. normal[Y_IDX] += (element[j][Z_IDX]-element[i][Z_IDX]) * (element[j][X_IDX]+element[i][X_IDX]);
  17620. normal[Z_IDX] += (element[j][X_IDX]-element[i][X_IDX]) * (element[j][Y_IDX]+element[i][Y_IDX]);
  17621. }
  17622. }
  17623. /* symmetrical axis aligned figures will produce a zero normal */
  17624. if(VectorXYZ_IsZero(normal)) {
  17625. if(fabs((bbox[Z_MIN_IDX]-bbox[Z_MAX_IDX])) < Vector_Tolerance) {
  17626. normal[X_IDX]=0.0;
  17627. normal[Y_IDX]=0.0;
  17628. normal[Z_IDX]=1.0;
  17629. } else if (fabs((bbox[Z_MIN_IDX]-bbox[Z_MAX_IDX])) < Vector_Tolerance) {
  17630. normal[X_IDX]=0.0;
  17631. normal[Y_IDX]=1.0;
  17632. normal[Z_IDX]=0.0;
  17633. } else {
  17634. normal[X_IDX]=1.0;
  17635. normal[Y_IDX]=0.0;
  17636. normal[Z_IDX]=0.0;
  17637. }
  17638. } else {
  17639. VectorXYZ_Normalize(normal);
  17640. }
  17641.  
  17642. Tcl_SetObjResult(interp,VectorXYZ_To_TclObj(normal));
  17643. Odie_Free((char *)element);
  17644. return TCL_OK;
  17645. error:
  17646. Odie_Free((char *)element);
  17647. return TCL_ERROR;
  17648. }
  17649. /* Tcl Proc ::vectorxyz::polygon_center */
  17650. static int TclCmd_vectorxyz_polygon_center(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17651. VectorXYZ center,*element;
  17652. int i,n;
  17653.  
  17654. VectorXYZ_Zero(center);
  17655. if(objc<2) {
  17656. Tcl_WrongNumArgs(interp, 1, objv, "A B C ?D...?");
  17657. return TCL_ERROR;
  17658. }
  17659. if(objc==2) {
  17660. Tcl_Obj **elemPtrs;
  17661. int result;
  17662. result = Tcl_ListObjGetElements(interp, objv[1], &n, &elemPtrs);
  17663. if (result != TCL_OK) {
  17664. return result;
  17665. }
  17666. if(n<3) {
  17667. Tcl_AppendResult(interp, "Needs at least points", 0);
  17668. return TCL_ERROR;
  17669. }
  17670. element=(VectorXYZ *)Vector_Alloc(sizeof(VectorXYZ)*n);
  17671. for(i=0;i<n;i++) {
  17672. if(Odie_GetVectorXYZFromTclObj(interp,elemPtrs[i],element[i])) goto error;
  17673. }
  17674. } else {
  17675. n=objc-1;
  17676. if(n<3) {
  17677. Tcl_AppendResult(interp, "Needs at least points", 0);
  17678. return TCL_ERROR;
  17679. }
  17680. element=(VectorXYZ *)Vector_Alloc(sizeof(VectorXYZ)*n);
  17681. for(i=1;i<objc;i++) {
  17682. if(Odie_GetVectorXYZFromTclObj(interp,objv[i],element[i-1])) goto error;
  17683. }
  17684. }
  17685. for(i=0;i<n;i++) {
  17686. center[X_IDX] += element[i][X_IDX];
  17687. center[Y_IDX] += element[i][Y_IDX];
  17688. center[Z_IDX] += element[i][Z_IDX];
  17689. }
  17690.  
  17691. center[X_IDX] /= n;
  17692. center[Y_IDX] /= n;
  17693. center[Z_IDX] /= n;
  17694.  
  17695. Tcl_SetObjResult(interp,VectorXYZ_To_TclObj(center));
  17696. Odie_Free((char *)element);
  17697. return TCL_OK;
  17698. error:
  17699. Odie_Free((char *)element);
  17700. return TCL_ERROR;
  17701. }
  17702. /* Tcl Proc ::vectorxyz::flatten */
  17703. static int TclCmd_vectorxyz_flatten(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17704. VectorXYZ point;
  17705. int i,j;
  17706. Tcl_Obj *pResult;
  17707. pResult=Tcl_NewObj();
  17708. if(objc==2) {
  17709. Tcl_Obj **rowPtrs;
  17710. int rows;
  17711. if(Tcl_ListObjGetElements(interp, objv[1], &rows, &rowPtrs)) {
  17712. Tcl_DecrRefCount(pResult);
  17713. return TCL_ERROR;
  17714. }
  17715. for(j=0;j<rows;j++) {
  17716. if(Odie_GetVectorXYZFromTclObj(interp,rowPtrs[j],point)) return TCL_ERROR;
  17717. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(point[X_IDX]));
  17718. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(point[Y_IDX]));
  17719. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(point[Z_IDX]));
  17720. }
  17721. } else {
  17722. for(i=1;i<objc;i++) {
  17723. if(Odie_GetVectorXYZFromTclObj(interp,objv[i],point)) return TCL_ERROR;
  17724. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(point[X_IDX]));
  17725. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(point[Y_IDX]));
  17726. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(point[Z_IDX]));
  17727. }
  17728. }
  17729. Tcl_SetObjResult(interp,pResult);
  17730. return TCL_OK;
  17731. }
  17732. /* Tcl Proc ::matrix::to_aabb_xyz */
  17733. static int TclCmd_matrix_to_aabb_xyz(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17734. Odie_MatrixObj *A;
  17735. if(objc < 3) {
  17736. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17737. return TCL_ERROR;
  17738. }
  17739. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_aabb_xyz,&A)) return TCL_ERROR;
  17740. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17741. return TCL_OK;
  17742. }
  17743. /* Tcl Proc ::matrix::to_affine */
  17744. static int TclCmd_matrix_to_affine(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17745. Odie_MatrixObj *A;
  17746. if(objc < 3) {
  17747. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17748. return TCL_ERROR;
  17749. }
  17750. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_affine,&A)) return TCL_ERROR;
  17751. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17752. return TCL_OK;
  17753. }
  17754. /* Tcl Proc ::matrix::to_bbox_xy */
  17755. static int TclCmd_matrix_to_bbox_xy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17756. Odie_MatrixObj *A;
  17757. if(objc < 3) {
  17758. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17759. return TCL_ERROR;
  17760. }
  17761. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_bbox_xy,&A)) return TCL_ERROR;
  17762. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17763. return TCL_OK;
  17764. }
  17765. /* Tcl Proc ::matrix::to_cylindrical */
  17766. static int TclCmd_matrix_to_cylindrical(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17767. Odie_MatrixObj *A;
  17768. if(objc < 3) {
  17769. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17770. return TCL_ERROR;
  17771. }
  17772. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_cylindrical,&A)) return TCL_ERROR;
  17773. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17774. return TCL_OK;
  17775. }
  17776. /* Tcl Proc ::matrix::to_euler */
  17777. static int TclCmd_matrix_to_euler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17778. Odie_MatrixObj *A;
  17779. if(objc < 3) {
  17780. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17781. return TCL_ERROR;
  17782. }
  17783. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_euler,&A)) return TCL_ERROR;
  17784. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17785. return TCL_OK;
  17786. }
  17787. /* Tcl Proc ::matrix::to_heading */
  17788. static int TclCmd_matrix_to_heading(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17789. Odie_MatrixObj *A;
  17790. if(objc < 3) {
  17791. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17792. return TCL_ERROR;
  17793. }
  17794. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_heading,&A)) return TCL_ERROR;
  17795. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17796. return TCL_OK;
  17797. }
  17798. /* Tcl Proc ::matrix::to_mat2 */
  17799. static int TclCmd_matrix_to_mat2(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17800. Odie_MatrixObj *A;
  17801. if(objc < 3) {
  17802. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17803. return TCL_ERROR;
  17804. }
  17805. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_mat2,&A)) return TCL_ERROR;
  17806. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17807. return TCL_OK;
  17808. }
  17809. /* Tcl Proc ::matrix::to_mat3 */
  17810. static int TclCmd_matrix_to_mat3(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17811. Odie_MatrixObj *A;
  17812. if(objc < 3) {
  17813. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17814. return TCL_ERROR;
  17815. }
  17816. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_mat3,&A)) return TCL_ERROR;
  17817. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17818. return TCL_OK;
  17819. }
  17820. /* Tcl Proc ::matrix::to_mat4 */
  17821. static int TclCmd_matrix_to_mat4(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17822. Odie_MatrixObj *A;
  17823. if(objc < 3) {
  17824. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17825. return TCL_ERROR;
  17826. }
  17827. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_mat4,&A)) return TCL_ERROR;
  17828. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17829. return TCL_OK;
  17830. }
  17831. /* Tcl Proc ::matrix::to_null */
  17832. static int TclCmd_matrix_to_null(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17833. Odie_MatrixObj *A;
  17834. if(objc < 3) {
  17835. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17836. return TCL_ERROR;
  17837. }
  17838. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null,&A)) return TCL_ERROR;
  17839. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17840. return TCL_OK;
  17841. }
  17842. /* Tcl Proc ::matrix::to_polar */
  17843. static int TclCmd_matrix_to_polar(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17844. Odie_MatrixObj *A;
  17845. if(objc < 3) {
  17846. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17847. return TCL_ERROR;
  17848. }
  17849. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_polar,&A)) return TCL_ERROR;
  17850. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17851. return TCL_OK;
  17852. }
  17853. /* Tcl Proc ::matrix::to_quaternion */
  17854. static int TclCmd_matrix_to_quaternion(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17855. Odie_MatrixObj *A;
  17856. if(objc < 3) {
  17857. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17858. return TCL_ERROR;
  17859. }
  17860. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_quaternion,&A)) return TCL_ERROR;
  17861. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17862. return TCL_OK;
  17863. }
  17864. /* Tcl Proc ::matrix::to_scaler */
  17865. static int TclCmd_matrix_to_scaler(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17866. Odie_MatrixObj *A;
  17867. if(objc < 3) {
  17868. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17869. return TCL_ERROR;
  17870. }
  17871. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_scaler,&A)) return TCL_ERROR;
  17872. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17873. return TCL_OK;
  17874. }
  17875. /* Tcl Proc ::matrix::to_spherical */
  17876. static int TclCmd_matrix_to_spherical(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17877. Odie_MatrixObj *A;
  17878. if(objc < 3) {
  17879. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17880. return TCL_ERROR;
  17881. }
  17882. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_spherical,&A)) return TCL_ERROR;
  17883. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17884. return TCL_OK;
  17885. }
  17886. /* Tcl Proc ::matrix::to_unknown */
  17887. static int TclCmd_matrix_to_unknown(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17888. Odie_MatrixObj *A;
  17889. if(objc < 3) {
  17890. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17891. return TCL_ERROR;
  17892. }
  17893. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_unknown,&A)) return TCL_ERROR;
  17894. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17895. return TCL_OK;
  17896. }
  17897. /* Tcl Proc ::matrix::to_vector_xy */
  17898. static int TclCmd_matrix_to_vector_xy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17899. Odie_MatrixObj *A;
  17900. if(objc < 3) {
  17901. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17902. return TCL_ERROR;
  17903. }
  17904. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vector_xy,&A)) return TCL_ERROR;
  17905. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17906. return TCL_OK;
  17907. }
  17908. /* Tcl Proc ::matrix::to_vector_xyz */
  17909. static int TclCmd_matrix_to_vector_xyz(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17910. Odie_MatrixObj *A;
  17911. if(objc < 3) {
  17912. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17913. return TCL_ERROR;
  17914. }
  17915. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vector_xyz,&A)) return TCL_ERROR;
  17916. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17917. return TCL_OK;
  17918. }
  17919. /* Tcl Proc ::matrix::to_vector_xyzw */
  17920. static int TclCmd_matrix_to_vector_xyzw(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17921. Odie_MatrixObj *A;
  17922. if(objc < 3) {
  17923. Tcl_WrongNumArgs( interp, 1, objv, "A" );
  17924. return TCL_ERROR;
  17925. }
  17926. if(Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vector_xyzw,&A)) return TCL_ERROR;
  17927. Tcl_SetObjResult(interp,Matrix_To_TclObj(A));
  17928. return TCL_OK;
  17929. }
  17930. /* Tcl Proc ::tcl::mathfunc::to_fuzzy */
  17931. static int TclCmd_tcl_mathfunc_to_fuzzy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17932. double ax;
  17933. if(Tcl_GetDoubleFromObj(interp,objv[1],&ax)) {
  17934. Tcl_SetObjResult(interp,objv[1]);
  17935. return TCL_OK;
  17936. }
  17937. Tcl_SetObjResult(interp,ODIE_NewFuzzyObj(ax));
  17938. return TCL_OK;
  17939. }
  17940. /* Tcl Proc ::tcl::mathfunc::fuzzy_abs */
  17941. static int TclCmd_tcl_mathfunc_fuzzy_abs(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17942. double value;
  17943. if(objc!=2) {
  17944. Tcl_WrongNumArgs(interp, 1, objv, "avalue");
  17945. return TCL_ERROR;
  17946. }
  17947. if(Tcl_GetDoubleFromObj(NULL,objv[1],&value)) {
  17948. return TCL_ERROR;
  17949. }
  17950. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(fabs(value)));
  17951. return TCL_OK;
  17952. }
  17953. /* Tcl Proc ::tcl::mathfunc::fuzzy_compare */
  17954. static int TclCmd_tcl_mathfunc_fuzzy_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17955. int result;
  17956. double epsilon=0.01;
  17957. if(objc!=3 && objc!=4) {
  17958. Tcl_WrongNumArgs(interp, 1, objv, "avalue bvalue ?epsilon?");
  17959. return TCL_ERROR;
  17960. }
  17961. if(objc==4) {
  17962. if(Tcl_GetDoubleFromObj(interp,objv[3],&epsilon)) return TCL_ERROR;
  17963. }
  17964. result=ODIE_Fuzzy_Compare_TclObj(objv[1],objv[2],epsilon);
  17965. Tcl_SetObjResult(interp,Tcl_NewIntObj(result));
  17966. return TCL_OK;
  17967. }
  17968. /* Tcl Proc ::tcl::mathfunc::fuzzy_is_zero */
  17969. static int TclCmd_tcl_mathfunc_fuzzy_is_zero(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17970. int result;
  17971. double value;
  17972. if(objc!=2) {
  17973. Tcl_WrongNumArgs(interp, 1, objv, "avalue");
  17974. return TCL_ERROR;
  17975. }
  17976. if(Tcl_GetDoubleFromObj(NULL,objv[1],&value)) {
  17977. result=0;
  17978. } else {
  17979. result=ODIE_Real_Is_Zero(value);
  17980. }
  17981. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(result));
  17982. return TCL_OK;
  17983. }
  17984. /* Tcl Proc ::tcl::mathfunc::fuzzy_gt_zero */
  17985. static int TclCmd_tcl_mathfunc_fuzzy_gt_zero(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  17986. int result;
  17987. double value;
  17988. if(objc!=2) {
  17989. Tcl_WrongNumArgs(interp, 1, objv, "avalue");
  17990. return TCL_ERROR;
  17991. }
  17992. if(Tcl_GetDoubleFromObj(NULL,objv[1],&value)) {
  17993. result=0;
  17994. } else {
  17995. result=ODIE_Real_Is_Zero(value) ? 1 : 0;
  17996. }
  17997. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(result));
  17998. return TCL_OK;
  17999. }
  18000. /* Tcl Proc ::tcl::mathfunc::fuzzy_epsilon */
  18001. static int TclCmd_tcl_mathfunc_fuzzy_epsilon(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18002. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(__FLT_EPSILON__));
  18003. return TCL_OK;
  18004. }
  18005. /* Tcl Proc ::triag_test_rightof */
  18006. static int TclCmd_triag_test_rightof(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18007. TriagPoint A, B, P;
  18008. if( objc!=7 ){
  18009. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2");
  18010. return TCL_ERROR;
  18011. }
  18012. if( Tcl_GetDoubleFromObj(interp, objv[1], &A.x) ) return TCL_ERROR;
  18013. if( Tcl_GetDoubleFromObj(interp, objv[2], &A.y) ) return TCL_ERROR;
  18014. if( Tcl_GetDoubleFromObj(interp, objv[3], &B.x) ) return TCL_ERROR;
  18015. if( Tcl_GetDoubleFromObj(interp, objv[4], &B.y) ) return TCL_ERROR;
  18016. if( Tcl_GetDoubleFromObj(interp, objv[5], &P.x) ) return TCL_ERROR;
  18017. if( Tcl_GetDoubleFromObj(interp, objv[6], &P.y) ) return TCL_ERROR;
  18018. Tcl_SetObjResult(interp, Odie_LiteralIntObj(rightOf(&A, &B, &P)));
  18019. return TCL_OK;
  18020. }
  18021. /* Tcl Proc ::triag_test_dotprod */
  18022. static int TclCmd_triag_test_dotprod(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18023. TriagPoint A, B, P;
  18024. if( objc!=7 ){
  18025. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2");
  18026. return TCL_ERROR;
  18027. }
  18028. if( Tcl_GetDoubleFromObj(interp, objv[1], &A.x) ) return TCL_ERROR;
  18029. if( Tcl_GetDoubleFromObj(interp, objv[2], &A.y) ) return TCL_ERROR;
  18030. if( Tcl_GetDoubleFromObj(interp, objv[3], &B.x) ) return TCL_ERROR;
  18031. if( Tcl_GetDoubleFromObj(interp, objv[4], &B.y) ) return TCL_ERROR;
  18032. if( Tcl_GetDoubleFromObj(interp, objv[5], &P.x) ) return TCL_ERROR;
  18033. if( Tcl_GetDoubleFromObj(interp, objv[6], &P.y) ) return TCL_ERROR;
  18034. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(Dot_Product(&A, &B, &P)));
  18035. return TCL_OK;
  18036. }
  18037. /* Tcl Proc ::triag_test_angle */
  18038. static int TclCmd_triag_test_angle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18039. TriagPoint A, B, P;
  18040. if( objc!=7 ){
  18041. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2");
  18042. return TCL_ERROR;
  18043. }
  18044. if( Tcl_GetDoubleFromObj(interp, objv[1], &A.x) ) return TCL_ERROR;
  18045. if( Tcl_GetDoubleFromObj(interp, objv[2], &A.y) ) return TCL_ERROR;
  18046. if( Tcl_GetDoubleFromObj(interp, objv[3], &B.x) ) return TCL_ERROR;
  18047. if( Tcl_GetDoubleFromObj(interp, objv[4], &B.y) ) return TCL_ERROR;
  18048. if( Tcl_GetDoubleFromObj(interp, objv[5], &P.x) ) return TCL_ERROR;
  18049. if( Tcl_GetDoubleFromObj(interp, objv[6], &P.y) ) return TCL_ERROR;
  18050. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(angleOf(&A, &B, &P)));
  18051. return TCL_OK;
  18052. }
  18053. /* Tcl Proc ::triag_test_ideal */
  18054. static int TclCmd_triag_test_ideal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18055. TriagPoint A, B, P;
  18056. if( objc!=7 ){
  18057. Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2");
  18058. return TCL_ERROR;
  18059. }
  18060. if( Tcl_GetDoubleFromObj(interp, objv[1], &A.x) ) return TCL_ERROR;
  18061. if( Tcl_GetDoubleFromObj(interp, objv[2], &A.y) ) return TCL_ERROR;
  18062. if( Tcl_GetDoubleFromObj(interp, objv[3], &B.x) ) return TCL_ERROR;
  18063. if( Tcl_GetDoubleFromObj(interp, objv[4], &B.y) ) return TCL_ERROR;
  18064. if( Tcl_GetDoubleFromObj(interp, objv[5], &P.x) ) return TCL_ERROR;
  18065. if( Tcl_GetDoubleFromObj(interp, objv[6], &P.y) ) return TCL_ERROR;
  18066. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(idealAngle(&A, &B, &P)));
  18067. return TCL_OK;
  18068. }
  18069. /* Tcl Proc ::polygon::create */
  18070. static int TclCmd_polygon_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18071. if( objc!=2 ){
  18072. Tcl_WrongNumArgs(interp, 1, objv, "N");
  18073. return TCL_ERROR;
  18074. }
  18075. int isnew;
  18076. Odie_Polygon *p;
  18077. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  18078. if(isnew) {
  18079. Tcl_SetObjResult(interp, Odie_Polygon_NewTclObj(p));
  18080. } else {
  18081. Tcl_SetObjResult(interp, objv[1]);
  18082. }
  18083. return TCL_OK;
  18084. }
  18085. /* Tcl Proc ::polygon::compare */
  18086. static int TclCmd_polygon_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18087. Odie_Polygon *polyA,*polyB;
  18088. int isNewA,isNewB,result=0;
  18089. int i;
  18090. if( objc!=3 ){
  18091. Tcl_WrongNumArgs(interp, 1, objv, "A B");
  18092. return TCL_ERROR;
  18093. }
  18094. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &polyA, &isNewA) ) return TCL_ERROR;
  18095. if( Odie_Polygon_GetFromTclObj(interp, objv[2], &polyB, &isNewB) ) return TCL_ERROR;
  18096. result=Odie_Poly_Compare(polyA,polyB);
  18097. if(isNewA) Odie_Poly_ShimmerOrFree_TclObj(objv[1],polyA);
  18098. if(isNewB) Odie_Poly_ShimmerOrFree_TclObj(objv[2],polyB);
  18099. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(result));
  18100. return TCL_OK;
  18101.  
  18102. }
  18103. /* Tcl Proc ::polygon::simplify */
  18104. static int TclCmd_polygon_simplify(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18105. if( objc!=2 ){
  18106. Tcl_WrongNumArgs(interp, 1, objv, "N");
  18107. return TCL_ERROR;
  18108. }
  18109. Odie_Polygon *pPoly,*pNewPoly;
  18110. int i,isnew;
  18111. int colinear;
  18112. double ax,ay,bx,by,cx,cy;
  18113. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &pPoly, &isnew) ) return TCL_ERROR;
  18114.  
  18115. pNewPoly=(Odie_Polygon *)Odie_Alloc(sizeof(*pNewPoly)+(pPoly->nVertex+2)*sizeof(pNewPoly->v[0]));
  18116. pNewPoly->nVertex=0;
  18117.  
  18118. ax=pPoly->v[pPoly->nVertex-1][X_IDX];
  18119. ay=pPoly->v[pPoly->nVertex-1][Y_IDX];
  18120. bx=pPoly->v[0][X_IDX];
  18121. by=pPoly->v[0][Y_IDX];
  18122. if(ax==bx && ay==by) {
  18123. ax=pPoly->v[pPoly->nVertex-2][X_IDX];
  18124. ay=pPoly->v[pPoly->nVertex-2][Y_IDX];
  18125. }
  18126. for(i=1;i<pPoly->nVertex;i++) {
  18127. cx=pPoly->v[i][X_IDX];
  18128. cy=pPoly->v[i][Y_IDX];
  18129. colinear=Odie_IsColinear(ax,ay,bx,by,cx,cy);
  18130. if(!colinear) {
  18131. pNewPoly->v[pNewPoly->nVertex][X_IDX]=bx;
  18132. pNewPoly->v[pNewPoly->nVertex][Y_IDX]=by;
  18133. pNewPoly->nVertex++;
  18134. }
  18135. ax=bx;
  18136. ay=by;
  18137. bx=cx;
  18138. by=cy;
  18139. }
  18140. cx=pPoly->v[0][X_IDX];
  18141. cy=pPoly->v[0][Y_IDX];
  18142. colinear=Odie_IsColinear(ax,ay,bx,by,cx,cy);
  18143. if(!Odie_IsColinear(ax,ay,bx,by,cx,cy)) {
  18144. pNewPoly->v[pNewPoly->nVertex][X_IDX]=bx;
  18145. pNewPoly->v[pNewPoly->nVertex][Y_IDX]=by;
  18146. pNewPoly->nVertex++;
  18147. }
  18148. if( pNewPoly->v[pNewPoly->nVertex-1][X_IDX]!=pNewPoly->v[0][X_IDX] || pNewPoly->v[pNewPoly->nVertex-1][Y_IDX]!=pNewPoly->v[0][Y_IDX] ){
  18149. pNewPoly->v[pNewPoly->nVertex][X_IDX] = pNewPoly->v[0][X_IDX];
  18150. pNewPoly->v[pNewPoly->nVertex][Y_IDX] = pNewPoly->v[0][Y_IDX];
  18151. pNewPoly->nVertex++;
  18152. }
  18153. Odie_Polygon_ComputeArea(interp,pNewPoly);
  18154. Tcl_SetObjResult(interp, Odie_Polygon_NewTclObj(pNewPoly));
  18155. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],pPoly);
  18156. return TCL_OK;
  18157. }
  18158. /* Tcl Proc ::polygon::area */
  18159. static int TclCmd_polygon_area(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18160. Odie_Polygon *p;
  18161. int isnew;
  18162. int i;
  18163. double area;
  18164. if( objc<2 ){
  18165. Tcl_WrongNumArgs(interp, 1, objv, "N ?N...?");
  18166. return TCL_ERROR;
  18167. }
  18168. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  18169. area=p->area;
  18170. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p);
  18171. for(i=2;i<objc;i++) {
  18172. if( Odie_Polygon_GetFromTclObj(interp, objv[i], &p, &isnew) ) return TCL_ERROR;
  18173. area+=p->area;
  18174. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[i],p);
  18175. }
  18176. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(area));
  18177. return TCL_OK;
  18178. }
  18179. /* Tcl Proc ::polygon::bbox */
  18180. static int TclCmd_polygon_bbox(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18181. /* poly bbox N
  18182. **
  18183. ** Return the bounding box for a polygon
  18184. */
  18185. Odie_Polygon *p;
  18186. int isnew;
  18187. Tcl_Obj *pResult;
  18188. double bbox_x0,bbox_y1,bbox_x1,bbox_y0;
  18189. int i;
  18190.  
  18191. if( objc<2 ){
  18192. Tcl_WrongNumArgs(interp, 1, objv, "N ?N...?");
  18193. return TCL_ERROR;
  18194. }
  18195. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  18196. bbox_x0=p->bbox[BBOX_X0_IDX];
  18197. bbox_x1=p->bbox[BBOX_X1_IDX];
  18198. bbox_y0=p->bbox[BBOX_Y0_IDX];
  18199. bbox_y1=p->bbox[BBOX_Y1_IDX];
  18200. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p);
  18201. for(i=2;i<objc;i++) {
  18202. if( Odie_Polygon_GetFromTclObj(interp, objv[i], &p, &isnew) ) return TCL_ERROR;
  18203. if(p->bbox[BBOX_X0_IDX] < bbox_x0) bbox_x0=p->bbox[BBOX_X0_IDX];
  18204. if(p->bbox[BBOX_X1_IDX] > bbox_x1) bbox_x1=p->bbox[BBOX_X1_IDX];
  18205. if(p->bbox[BBOX_Y0_IDX] < bbox_y0) bbox_y0=p->bbox[BBOX_Y0_IDX];
  18206. if(p->bbox[BBOX_Y1_IDX] > bbox_y1) bbox_y1=p->bbox[BBOX_Y1_IDX];
  18207. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[i],p);
  18208. }
  18209. pResult = Tcl_NewObj();
  18210. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(bbox_x0));
  18211. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(bbox_y1));
  18212. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(bbox_x1));
  18213. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(bbox_y0));
  18214. Tcl_SetObjResult(interp, pResult);
  18215. return TCL_OK;
  18216. }
  18217. /* Tcl Proc ::polygon::info */
  18218. static int TclCmd_polygon_info(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18219. /* poly info N
  18220. **
  18221. ** Return the coordinates for a polygon
  18222. */
  18223. Tcl_Obj *pResult;
  18224. Odie_Polygon *p;
  18225. int i,isnew;
  18226. if( objc!=2 ){
  18227. Tcl_WrongNumArgs(interp, 1, objv, "N");
  18228. return TCL_ERROR;
  18229. }
  18230. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  18231. pResult = Tcl_NewObj();
  18232. for(i=0; i<p->nVertex-1; i++){
  18233. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(p->v[i][X_IDX]));
  18234. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(p->v[i][Y_IDX]));
  18235. }
  18236. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p);
  18237. Tcl_SetObjResult(interp, pResult);
  18238. return TCL_OK;
  18239. }
  18240. /* Tcl Proc ::polygon::intersect */
  18241. static int TclCmd_polygon_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18242. /* poly intersect N1 N2
  18243. **
  18244. ** Return a list of 3 elements where the first element is the
  18245. ** area of intersection between polygons N1 and N2 and the remaining
  18246. ** 3 elements are the X and Y coordinates of a point within both
  18247. ** polygons.
  18248. **
  18249. ** The current implementation returns an approximation. We might
  18250. ** change it to compute the exact intersection later.
  18251. */
  18252. Odie_Polygon *p1, *p2;
  18253. int isnew1,isnew2;
  18254. double area;
  18255. double xInside = 0.0, yInside = 0.0;
  18256. Tcl_Obj *pResult;
  18257. if( objc!=3 ){
  18258. Tcl_WrongNumArgs(interp, 1, objv, "N1 N2");
  18259. return TCL_ERROR;
  18260. }
  18261. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &p1, &isnew1) ) return TCL_ERROR;
  18262. if( Odie_Polygon_GetFromTclObj(interp, objv[2], &p2, &isnew2) ) {
  18263. if(isnew1) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p1);
  18264. return TCL_ERROR;
  18265. }
  18266. if( p1->bbox[BBOX_X1_IDX]<=p2->bbox[BBOX_X0_IDX] || p1->bbox[BBOX_X0_IDX]>=p2->bbox[BBOX_X1_IDX]
  18267. || p1->bbox[BBOX_Y1_IDX]<=p2->bbox[BBOX_Y0_IDX] || p1->bbox[BBOX_Y0_IDX]>=p2->bbox[BBOX_Y1_IDX] ){
  18268. area = 0.0;
  18269. }else if( p1->area==0.0 || p2->area==0.0 ){
  18270. area = 0.0;
  18271. }else{
  18272. double x0, y0, x1, y1, dx, dy, xP, yP, xC, yC;
  18273. int i, j, cnt;
  18274. int score, bestScore;
  18275. static const int n = 50;
  18276. char hit[50][50];
  18277.  
  18278. /* Compute the overlap of the bounding boxes of the two polygons. */
  18279. x0 = p1->bbox[BBOX_X0_IDX] < p2->bbox[BBOX_X0_IDX] ? p2->bbox[BBOX_X0_IDX] : p1->bbox[BBOX_X0_IDX];
  18280. y0 = p1->bbox[BBOX_Y1_IDX] > p2->bbox[BBOX_Y1_IDX] ? p2->bbox[BBOX_Y1_IDX] : p1->bbox[BBOX_Y1_IDX];
  18281. x1 = p1->bbox[BBOX_X1_IDX] > p2->bbox[BBOX_X1_IDX] ? p2->bbox[BBOX_X1_IDX] : p1->bbox[BBOX_X1_IDX];
  18282. y1 = p1->bbox[BBOX_Y0_IDX] < p2->bbox[BBOX_Y0_IDX] ? p2->bbox[BBOX_Y0_IDX] : p1->bbox[BBOX_Y0_IDX];
  18283.  
  18284. /* Divide the intersection of the bounding boxes into a n-by-n grid
  18285. ** and count the number of elements in this grid whose centers fall
  18286. ** within both polygons. This will be our approximation for the
  18287. ** intersection of the polygons themselves.
  18288. */
  18289. dx = (x1-x0)/n;
  18290. dy = (y1-y0)/n;
  18291. cnt = 0;
  18292. xC = yC = 0.0;
  18293. for(i=0; i<n; i++){
  18294. xP = x0 + dx*(i+0.5);
  18295. for(j=0; j<n; j++){
  18296. yP = y0 + dy*(j+0.5);
  18297. if( withinPolygon(p1, xP, yP)>0 && withinPolygon(p2, xP, yP)>0 ){
  18298. cnt++;
  18299. hit[i][j] = 1;
  18300. xC += xP;
  18301. yC += yP;
  18302. }else{
  18303. hit[i][j] = 0;
  18304. }
  18305. }
  18306. }
  18307.  
  18308. /* We need to find a good approximation for the center of the
  18309. ** overlap. Begin by computing the center of mass for the
  18310. ** overlapping region. Then find the point inside the intersection
  18311. ** that is nearest the center of mass.
  18312. */
  18313. if( cnt>0 ){
  18314. area = cnt*(x1-x0)*(y0-y1)/(n*n);
  18315. xC /= cnt;
  18316. yC /= cnt;
  18317. bestScore = -1.0;
  18318. for(i=0; i<n; i++){
  18319. xP = x0 + dx*(i+0.5);
  18320. for(j=0; j<n; j++){
  18321. if( !hit[i][j] ) continue;
  18322. yP = y0 + dy*(j+0.5);
  18323. score = dist(xP,yP,xC,yC);
  18324. if( score<bestScore || bestScore<0.0 ){
  18325. xInside = xP;
  18326. yInside = yP;
  18327. bestScore = score;
  18328. }
  18329. }
  18330. }
  18331. } else {
  18332. area=0.0;
  18333. }
  18334. }
  18335. if(isnew1) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p1);
  18336. if(isnew2) Odie_Poly_ShimmerOrFree_TclObj(objv[2],p2);
  18337.  
  18338. pResult = Tcl_NewObj();
  18339. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(area));
  18340. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(xInside));
  18341. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(yInside));
  18342. Tcl_SetObjResult(interp, pResult);
  18343. return TCL_OK;
  18344. }
  18345. /* Tcl Proc ::polygon::within */
  18346. static int TclCmd_polygon_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18347. /* poly within X Y N ?N...?
  18348. **
  18349. ** Return -1, 0, or +1 if the point X,Y is outside, on, or inside
  18350. ** polygon N.
  18351. */
  18352. Odie_Polygon *p;
  18353. int res,isnew;
  18354. double x, y;
  18355. if( objc<4 ){
  18356. Tcl_WrongNumArgs(interp, 1, objv, "X Y ?N...?");
  18357. return TCL_ERROR;
  18358. }
  18359. if( Tcl_GetDoubleFromObj(interp, objv[1], &x) ) return TCL_ERROR;
  18360. if( Tcl_GetDoubleFromObj(interp, objv[2], &y) ) return TCL_ERROR;
  18361. if(objc==4) {
  18362. if( Odie_Polygon_GetFromTclObj(interp, objv[3], &p, &isnew) ) return TCL_ERROR;
  18363. res = withinPolygon(p, x, y);
  18364. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[3],p);
  18365. Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
  18366. return TCL_OK;
  18367. } else {
  18368. int i;
  18369. for(i=3;i<objc;i++) {
  18370. if( Odie_Polygon_GetFromTclObj(interp, objv[i], &p, &isnew) ) return TCL_ERROR;
  18371. res = withinPolygon(p, x, y);
  18372. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[i],p);
  18373. if(res>=0) {
  18374. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
  18375. return TCL_OK;
  18376. }
  18377. }
  18378. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  18379. return TCL_OK;
  18380. }
  18381. }
  18382. /* Tcl Proc ::polygon::center */
  18383. static int TclCmd_polygon_center(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18384. int i;
  18385. int isnew;
  18386. Odie_Polygon *p;
  18387. if( objc!=2 ){
  18388. Tcl_WrongNumArgs(interp, 1, objv, "N");
  18389. return TCL_ERROR;
  18390. }
  18391. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  18392. Tcl_SetObjResult(interp, VectorXY_To_TclObj(p->center));
  18393. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p);
  18394. return TCL_OK;
  18395. }
  18396. /* Tcl Proc ::polygon::canvascoords */
  18397. static int TclCmd_polygon_canvascoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18398. int i;
  18399. Tcl_Obj *pResult;
  18400. int isnew;
  18401. Odie_Polygon *p;
  18402. if( objc!=2 ){
  18403. Tcl_WrongNumArgs(interp, 1, objv, "N");
  18404. return TCL_ERROR;
  18405. }
  18406. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  18407. pResult=Tcl_NewObj();
  18408. for(i=0; i<p->nVertex; i++){
  18409. Tcl_ListObjAppendElement(interp,pResult, Tcl_NewDoubleObj(p->v[i][X_IDX]));
  18410. Tcl_ListObjAppendElement(interp,pResult, Tcl_NewDoubleObj(p->v[i][Y_IDX]));
  18411.  
  18412. }
  18413. Tcl_SetObjResult(interp, pResult);
  18414. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p);
  18415. return TCL_OK;
  18416. }
  18417. /* Tcl Proc ::polygon::coords */
  18418. static int TclCmd_polygon_coords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18419. int i;
  18420. Tcl_Obj *pResult;
  18421. int isnew;
  18422. Odie_Polygon *p;
  18423. if( objc!=2 ){
  18424. Tcl_WrongNumArgs(interp, 1, objv, "N");
  18425. return TCL_ERROR;
  18426. }
  18427. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  18428. pResult=Tcl_NewObj();
  18429. for(i=0; i<p->nVertex; i++){
  18430. Tcl_ListObjAppendElement(interp,pResult, Tcl_NewDoubleObj(p->v[i][X_IDX]));
  18431. Tcl_ListObjAppendElement(interp,pResult, Tcl_NewDoubleObj(p->v[i][Y_IDX]));
  18432.  
  18433. }
  18434. Tcl_SetObjResult(interp, pResult);
  18435. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p);
  18436. return TCL_OK;
  18437. }
  18438. /* Tcl Proc ::polygon::xycoords */
  18439. static int TclCmd_polygon_xycoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18440. int i;
  18441. Tcl_Obj *pResult;
  18442. int isnew;
  18443. Odie_Polygon *p;
  18444. if( objc!=2 ){
  18445. Tcl_WrongNumArgs(interp, 1, objv, "N");
  18446. return TCL_ERROR;
  18447. }
  18448. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  18449. pResult=Tcl_NewObj();
  18450. for(i=0; i<p->nVertex; i++){
  18451. Tcl_ListObjAppendElement(interp,pResult, VectorXY_To_TclObj(p->v[i]));
  18452. }
  18453. Tcl_SetObjResult(interp, pResult);
  18454. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p);
  18455. return TCL_OK;
  18456. }
  18457. /* Tcl Proc ::polygon::edges */
  18458. static int TclCmd_polygon_edges(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18459. Tcl_Obj *pResult;
  18460. int isnew;
  18461. int i,j,start,end;
  18462. Odie_Polygon *p;
  18463. if( objc!=2 ){
  18464. Tcl_WrongNumArgs(interp, 1, objv, "N");
  18465. return TCL_ERROR;
  18466. }
  18467. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  18468. if(objc==2) {
  18469. pResult=Tcl_NewObj();
  18470. for(i=0; i<p->nVertex; i++){
  18471. j=(i+1)%p->nVertex;
  18472. if(VectorXY_SamePoint(p->v[i],p->v[j])) continue;
  18473. Tcl_ListObjAppendElement(interp,pResult, VectorXY_To_TclObj(p->v[i]));
  18474. Tcl_ListObjAppendElement(interp,pResult, VectorXY_To_TclObj(p->v[j]));
  18475. }
  18476. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p);
  18477. Tcl_SetObjResult(interp, pResult);
  18478. return TCL_OK;
  18479. }
  18480. if(objc==3) {
  18481. if(Tcl_GetIntFromObj(interp,objv[2],&start)) goto fail;
  18482. pResult=Tcl_NewObj();
  18483. start=start%p->nVertex;
  18484. end=(start+1)%p->nVertex;
  18485. Tcl_ListObjAppendElement(interp,pResult, VectorXY_To_TclObj(p->v[start]));
  18486. Tcl_ListObjAppendElement(interp,pResult, VectorXY_To_TclObj(p->v[end]));
  18487. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p);
  18488. Tcl_SetObjResult(interp, pResult);
  18489. return TCL_OK;
  18490. }
  18491. if(objc==4) {
  18492. if(Tcl_GetIntFromObj(interp,objv[2],&start)) goto fail;
  18493. if(Tcl_GetIntFromObj(interp,objv[3],&end)) goto fail;
  18494. pResult=Tcl_NewObj();
  18495. i=start%p->nVertex;
  18496. end=end%p->nVertex;
  18497. while(i!=end) {
  18498. j=(i+1)%p->nVertex;
  18499. Tcl_ListObjAppendElement(interp,pResult, VectorXY_To_TclObj(p->v[i]));
  18500. Tcl_ListObjAppendElement(interp,pResult, VectorXY_To_TclObj(p->v[j]));
  18501. i=(i+1)%p->nVertex;
  18502. }
  18503. j=(i+1)%p->nVertex;
  18504. Tcl_ListObjAppendElement(interp,pResult, VectorXY_To_TclObj(p->v[i]));
  18505. Tcl_ListObjAppendElement(interp,pResult, VectorXY_To_TclObj(p->v[j]));
  18506. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p);
  18507. Tcl_SetObjResult(interp, pResult);
  18508. return TCL_OK;
  18509. }
  18510. fail:
  18511. if(pResult) Tcl_DecrRefCount(pResult);
  18512. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p);
  18513. return TCL_ERROR;
  18514. }
  18515. /* Tcl Proc ::polygon::bend */
  18516. static int TclCmd_polygon_bend(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18517. int isnew;
  18518. Odie_Polygon *p;
  18519. int i,j,k;
  18520. int total_bend=0;
  18521. if( objc!=2 ){
  18522. Tcl_WrongNumArgs(interp, 1, objv, "N");
  18523. return TCL_ERROR;
  18524. }
  18525. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  18526. for(i=1; i<p->nVertex; i++){
  18527. j=(i+1)%(p->nVertex);
  18528. k=(i+2)%(p->nVertex);
  18529. total_bend+=VectorXY_BendDirection(p->v[i],p->v[j],p->v[k]);
  18530. }
  18531. Tcl_SetObjResult(interp, Tcl_NewIntObj(total_bend));
  18532. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p);
  18533. return TCL_OK;
  18534. }
  18535. /* Tcl Proc ::polygon::is_convex */
  18536. static int TclCmd_polygon_is_convex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18537. int isnew;
  18538. Odie_Polygon *p;
  18539. int i,j,k;
  18540. int is_convex=1,total_bend=0;
  18541. if( objc!=2 ){
  18542. Tcl_WrongNumArgs(interp, 1, objv, "N");
  18543. return TCL_ERROR;
  18544. }
  18545. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  18546. for(i=1; i<p->nVertex-1; i++){
  18547. j=(i+1)%(p->nVertex-1);
  18548. k=(i+2)%(p->nVertex-1);
  18549. total_bend+=VectorXY_BendDirection(p->v[i],p->v[j],p->v[k]);
  18550. }
  18551. for(i=1; i<p->nVertex-1; i++){
  18552. int bend;
  18553. j=(i+1)%(p->nVertex-1);
  18554. k=(i+2)%(p->nVertex-1);
  18555. bend=VectorXY_BendDirection(p->v[i],p->v[j],p->v[k]);
  18556. if(bend>0 && total_bend<0) {
  18557. is_convex=0;
  18558. } else if(bend<0 && total_bend>0) {
  18559. is_convex=0;
  18560. }
  18561. }
  18562. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(is_convex));
  18563. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p);
  18564. return TCL_OK;
  18565. }
  18566. /* Tcl Proc ::polygon::segments */
  18567. static int TclCmd_polygon_segments(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18568. Tcl_Obj *pResult;
  18569. int isnew;
  18570. Odie_Polygon *p;
  18571. if( objc!=2 ){
  18572. Tcl_WrongNumArgs(interp, 1, objv, "N");
  18573. return TCL_ERROR;
  18574. }
  18575. if( Odie_Polygon_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  18576. int i;
  18577. double px,py;
  18578. pResult=Tcl_NewObj();
  18579. px=p->v[0][X_IDX];
  18580. py=p->v[0][Y_IDX];
  18581. for(i=1; i<p->nVertex-1; i++){
  18582. Tcl_Obj *segment=Tcl_NewObj();
  18583. Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(px));
  18584. Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(py));
  18585. Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(p->v[i][X_IDX]));
  18586. Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(p->v[i][Y_IDX]));
  18587. Tcl_ListObjAppendElement(interp,pResult, segment);
  18588. px=p->v[i][X_IDX];
  18589. py=p->v[i][Y_IDX];
  18590. }
  18591. Tcl_Obj *segment=Tcl_NewObj();
  18592. Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(px));
  18593. Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(py));
  18594. Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(p->v[0][X_IDX]));
  18595. Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(p->v[0][Y_IDX]));
  18596. Tcl_ListObjAppendElement(interp,pResult, segment);
  18597. Tcl_SetObjResult(interp, pResult);
  18598. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[1],p);
  18599. return TCL_OK;
  18600. }
  18601. /* Tcl Proc ::polygon::rectangle */
  18602. static int TclCmd_polygon_rectangle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18603. double cx, cy, radx,rady;
  18604. Tcl_Obj *pResult=Tcl_NewObj();
  18605.  
  18606. if( objc != 5 ){
  18607. Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy");
  18608. return TCL_ERROR;
  18609. }
  18610.  
  18611. if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR;
  18612. if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR;
  18613. if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR;
  18614. if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR;
  18615. radx=radx/2.0;
  18616. rady=rady/2.0;
  18617. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx));
  18618. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady));
  18619.  
  18620. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx));
  18621. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady));
  18622.  
  18623. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx));
  18624. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady));
  18625.  
  18626. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx));
  18627. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady));
  18628.  
  18629. Tcl_SetObjResult(interp, pResult);
  18630. return TCL_OK;
  18631. }
  18632. /* Tcl Proc ::polygon::vector_place */
  18633. static int TclCmd_polygon_vector_place(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18634. /*
  18635. ** Apply Matrices
  18636. */
  18637. Tcl_Obj *pResult=Tcl_NewObj();
  18638. int i;
  18639. double zoom;
  18640. double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0};
  18641. double centerx,centery,normalx,normaly,angle;
  18642.  
  18643. if( objc < 8 ){
  18644. Tcl_WrongNumArgs(interp, 1, objv, "zoom centerx centery normalx normaly x1 y1 ?x2 y2?...");
  18645. return TCL_ERROR;
  18646. }
  18647. if(Tcl_GetDoubleFromObj(interp,objv[1],&zoom)) return TCL_ERROR;
  18648. if(Tcl_GetDoubleFromObj(interp,objv[2],&centerx)) return TCL_ERROR;
  18649. if(Tcl_GetDoubleFromObj(interp,objv[3],&centery)) return TCL_ERROR;
  18650. if(Tcl_GetDoubleFromObj(interp,objv[4],&normalx)) return TCL_ERROR;
  18651. if(Tcl_GetDoubleFromObj(interp,objv[5],&normaly)) return TCL_ERROR;
  18652.  
  18653. angle=atan2(normaly,normalx);
  18654. matA[0]=cos(angle);
  18655. matA[1]=sin(angle);
  18656. matA[2]=-sin(angle);
  18657. matA[3]=cos(angle);
  18658. matA[4]=0.0;
  18659. matA[5]=0.0;
  18660.  
  18661.  
  18662. for(i=6;i<objc;i+=2) {
  18663. double x,y,sx,sy,newx,newy;
  18664. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
  18665. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
  18666.  
  18667. sx=(x/zoom);
  18668. sy=(y/zoom);
  18669. newx=matA[0]*sx+matA[1]*sy+matA[4]+centerx;
  18670. newy=matA[2]*sx+matA[3]*sy+matA[5]+centery;
  18671.  
  18672. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
  18673. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
  18674. }
  18675. Tcl_SetObjResult(interp, pResult);
  18676. return TCL_OK;
  18677. }
  18678. /* Tcl Proc ::polygon::hexagon */
  18679. static int TclCmd_polygon_hexagon(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18680. int i,flip=0;
  18681. double cx, cy, radx,rady;
  18682.  
  18683. Tcl_Obj *pResult=Tcl_NewObj();
  18684. double coords[7][2]= {
  18685. {1.00, 0.00} , {0.50, M_SQRT3_2} ,
  18686. {-0.50, M_SQRT3_2} , {-1.00, -0.00} ,
  18687. {-0.50, -M_SQRT3_2} , {0.50, -M_SQRT3_2},
  18688. {1.00, 0.00}
  18689. };
  18690. if( objc != 5 && objc != 6){
  18691. Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy ?flip?");
  18692. return TCL_ERROR;
  18693. }
  18694.  
  18695. if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR;
  18696. if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR;
  18697. if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR;
  18698. if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR;
  18699. if(objc==6) {
  18700. if(Tcl_GetBooleanFromObj(interp,objv[5],&flip)) return TCL_ERROR;
  18701. }
  18702. radx=radx/2.0;
  18703. rady=rady/2.0;
  18704.  
  18705. for(i=0;i<6;i++) {
  18706. if(flip) {
  18707. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i][1]));
  18708. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i][0]));
  18709. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i+1][1]));
  18710. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i+1][0]));
  18711. } else {
  18712. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i][0]));
  18713. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i][1]));
  18714. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i+1][0]));
  18715. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i+1][1]));
  18716. }
  18717. }
  18718.  
  18719. Tcl_SetObjResult(interp, pResult);
  18720. return TCL_OK;
  18721. }
  18722. /* Tcl Proc ::polygon::poly_place */
  18723. static int TclCmd_polygon_poly_place(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18724. /*
  18725. ** Apply Matrices
  18726. */
  18727. Tcl_Obj *pResult=Tcl_NewObj();
  18728. int i;
  18729. double zoom;
  18730. double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0};
  18731. double centerx,centery,normalx,normaly,angle;
  18732.  
  18733. if( objc < 8 ){
  18734. Tcl_WrongNumArgs(interp, 1, objv, "zoom centerx centery normalx normaly x1 y1 ?x2 y2?...");
  18735. return TCL_ERROR;
  18736. }
  18737. if(Tcl_GetDoubleFromObj(interp,objv[1],&zoom)) return TCL_ERROR;
  18738. if(Tcl_GetDoubleFromObj(interp,objv[2],&centerx)) return TCL_ERROR;
  18739. if(Tcl_GetDoubleFromObj(interp,objv[3],&centery)) return TCL_ERROR;
  18740. if(Tcl_GetDoubleFromObj(interp,objv[4],&normalx)) return TCL_ERROR;
  18741. if(Tcl_GetDoubleFromObj(interp,objv[5],&normaly)) return TCL_ERROR;
  18742.  
  18743. angle=atan2(normaly,normalx);
  18744. matA[0]=cos(angle);
  18745. matA[1]=sin(angle);
  18746. matA[2]=-sin(angle);
  18747. matA[3]=cos(angle);
  18748. matA[4]=0.0;
  18749. matA[5]=0.0;
  18750. double startx,starty,prevx,prevy;
  18751.  
  18752. i=6;
  18753. {
  18754. double x,y,sx,sy,newx,newy;
  18755. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
  18756. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
  18757.  
  18758. sx=(x/zoom);
  18759. sy=(y/zoom);
  18760. newx=matA[0]*sx+matA[1]*sy+matA[4]+centerx;
  18761. newy=matA[2]*sx+matA[3]*sy+matA[5]+centery;
  18762.  
  18763. startx=newx;
  18764. starty=newy;
  18765. prevx=newx;
  18766. prevy=newy;
  18767. }
  18768.  
  18769. for(i=8;i<objc;i+=2) {
  18770. double x,y,sx,sy,newx,newy;
  18771. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
  18772. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
  18773.  
  18774. sx=(x/zoom);
  18775. sy=(y/zoom);
  18776. newx=matA[0]*sx+matA[1]*sy+matA[4]+centerx;
  18777. newy=matA[2]*sx+matA[3]*sy+matA[5]+centery;
  18778.  
  18779. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(prevx));
  18780. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(prevy));
  18781. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
  18782. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
  18783.  
  18784. prevx=newx;
  18785. prevy=newy;
  18786. }
  18787. if(startx != prevx && starty!= prevy) {
  18788. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(prevx));
  18789. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(prevy));
  18790. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(startx));
  18791. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(starty));
  18792. }
  18793. Tcl_SetObjResult(interp, pResult);
  18794. return TCL_OK;
  18795. }
  18796. /* Tcl Proc ::polygon::drawobj_orientation */
  18797. static int TclCmd_polygon_drawobj_orientation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18798. Tcl_Obj *temp;
  18799. int len;
  18800. double nx=100,ny=0;
  18801. if( objc !=4 ){
  18802. Tcl_WrongNumArgs(interp, 1, objv, "orientation nxvar nyvar");
  18803. return TCL_ERROR;
  18804. }
  18805.  
  18806. if(Tcl_ListObjLength(interp,objv[1],&len)) return TCL_ERROR;
  18807. if(len>0) {
  18808. if(Tcl_ListObjIndex(interp, objv[1], 0, &temp)) return TCL_ERROR;
  18809. if(Tcl_GetDoubleFromObj(interp,temp,&nx)) return TCL_ERROR;
  18810. }
  18811. if(len>1) {
  18812. if(Tcl_ListObjIndex(interp, objv[1], 1, &temp)) return TCL_ERROR;
  18813. if(Tcl_GetDoubleFromObj(interp,temp,&ny)) return TCL_ERROR;
  18814. }
  18815. Tcl_ObjSetVar2(interp,objv[2],NULL,Tcl_NewDoubleObj(nx),0);
  18816. Tcl_ObjSetVar2(interp,objv[3],NULL,Tcl_NewDoubleObj(ny),0);
  18817. return TCL_OK;
  18818. }
  18819. /* Tcl Proc ::polygon::corners */
  18820. static int TclCmd_polygon_corners(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18821. double cx, cy, radx,rady;
  18822.  
  18823. if( objc != 5 && objc != 9 ){
  18824. Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy ?x0var y0var x1var y1var?");
  18825. return TCL_ERROR;
  18826. }
  18827.  
  18828. if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR;
  18829. if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR;
  18830. if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR;
  18831. if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR;
  18832. if (objc == 5) {
  18833. Tcl_Obj *pResult=Tcl_NewObj();
  18834. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx));
  18835. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady));
  18836. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx));
  18837. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady));
  18838. Tcl_SetObjResult(interp, pResult);
  18839. return TCL_OK;
  18840. }
  18841. /*
  18842. Replaces
  18843. set x0 [expr {$cx-$d}]
  18844. set y0 [expr {$cy-$d}]
  18845. set x1 [expr {$cx+$d}]
  18846. set y1 [expr {$cy+$d}]
  18847. */
  18848.  
  18849. Tcl_ObjSetVar2(interp,objv[5],NULL,Tcl_NewDoubleObj(cx+radx),0);
  18850. Tcl_ObjSetVar2(interp,objv[6],NULL,Tcl_NewDoubleObj(cy-rady),0);
  18851. Tcl_ObjSetVar2(interp,objv[7],NULL,Tcl_NewDoubleObj(cx-radx),0);
  18852. Tcl_ObjSetVar2(interp,objv[8],NULL,Tcl_NewDoubleObj(cy+rady),0);
  18853.  
  18854. return TCL_OK;
  18855. }
  18856. /* Tcl Proc ::polygon::hexgrid_location */
  18857. static int TclCmd_polygon_hexgrid_location(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18858. /* poly hexgrid
  18859. **
  18860. ** Reduce the polygons to a series
  18861. ** of grid coordinates
  18862. */
  18863. Tcl_Obj *pResult,*pX,*pY;
  18864. double gridsize=500.0;
  18865. double x,y;
  18866. int ix,iy;
  18867. int flipped=0;
  18868. if(objc !=4 && objc !=5 && objc !=7 ) {
  18869. Tcl_WrongNumArgs(interp, 1, objv, "GRIDSIZE X Y ?flipped? ?xvar yvar?");
  18870. return TCL_ERROR;
  18871. }
  18872. if( Tcl_GetDoubleFromObj(interp, objv[1], &gridsize) ) return TCL_ERROR;
  18873. if( Tcl_GetIntFromObj(interp, objv[2], &ix) ) return TCL_ERROR;
  18874. if( Tcl_GetIntFromObj(interp, objv[3], &iy) ) return TCL_ERROR;
  18875. if( objc>4 ) {
  18876. if( Tcl_GetBooleanFromObj(interp, objv[4], &flipped) ) return TCL_ERROR;
  18877. }
  18878. pResult = Tcl_NewObj();
  18879. if(flipped) {
  18880. if(iy%2==1) {
  18881. x=(ix+0.5)*gridsize*M_SQRT3_2;
  18882. } else {
  18883. x=ix*gridsize*M_SQRT3_2;
  18884. }
  18885. y=iy*gridsize*0.75;
  18886. } else {
  18887. if(ix%2==1) {
  18888. y=(iy+0.5)*gridsize*M_SQRT3_2;
  18889. } else {
  18890. y=iy*gridsize*M_SQRT3_2;
  18891. }
  18892. x=ix*gridsize*0.75;
  18893. }
  18894. pX=Tcl_NewDoubleObj(x);
  18895. pY=Tcl_NewDoubleObj(y);
  18896. Tcl_ListObjAppendElement(interp, pResult, pX);
  18897. Tcl_ListObjAppendElement(interp, pResult, pY);
  18898. if(objc==7) {
  18899. Tcl_ObjSetVar2(interp,objv[5],NULL,pX,0);
  18900. Tcl_ObjSetVar2(interp,objv[6],NULL,pY,0);
  18901. }
  18902. Tcl_SetObjResult(interp, pResult);
  18903. return TCL_OK;
  18904. }
  18905. /* Tcl Proc ::polygon::hexgrid_create */
  18906. static int TclCmd_polygon_hexgrid_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18907. /* poly hexgrid
  18908. **
  18909. ** Reduce the polygons to a series
  18910. ** of grid coordinates
  18911. */
  18912. Tcl_Obj *pResult;
  18913. Odie_Polygon *p;
  18914. int isnew;
  18915. pResult = Tcl_NewObj();
  18916. double gridsize=500.0;
  18917. double x,y;
  18918.  
  18919. if(objc < 3) {
  18920. Tcl_WrongNumArgs(interp, 1, objv, "GRIDSIZE ?POLY ...?");
  18921. return TCL_ERROR;
  18922. }
  18923. if( Tcl_GetDoubleFromObj(interp, objv[1], &gridsize) ) return TCL_ERROR;
  18924.  
  18925. if( Odie_Polygon_GetFromTclObj(interp, objv[2], &p, &isnew) ) return TCL_ERROR;
  18926. double left=p->bbox[BBOX_X0_IDX];
  18927. double top=p->bbox[BBOX_Y1_IDX];
  18928. double right=p->bbox[BBOX_X1_IDX];
  18929. double bottom=p->bbox[BBOX_Y0_IDX];
  18930. int i;
  18931. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[2],p);
  18932. for(i=3;i<objc;i++) {
  18933. if( Odie_Polygon_GetFromTclObj(interp, objv[i], &p, &isnew) ) return TCL_ERROR;
  18934. if(p->bbox[BBOX_X0_IDX] < left) left=p->bbox[BBOX_X0_IDX];
  18935. if(p->bbox[BBOX_Y1_IDX] > top) top=p->bbox[BBOX_Y1_IDX];
  18936. if(p->bbox[BBOX_X1_IDX] > right) right=p->bbox[BBOX_X1_IDX];
  18937. if(p->bbox[BBOX_Y0_IDX] < bottom) bottom=p->bbox[BBOX_Y0_IDX];
  18938. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[i],p);
  18939. }
  18940.  
  18941. pResult = Tcl_NewObj();
  18942. left-=gridsize;
  18943. top+=gridsize;
  18944. right+=gridsize;
  18945. bottom-=gridsize;
  18946. int row=0;
  18947. for(y=bottom;y<=top;y+=gridsize) {
  18948. double lstartx=left;
  18949. double gy=floor(y/gridsize)*gridsize;
  18950. row++;
  18951. if(row%2==1) {
  18952. lstartx-=gridsize/2;
  18953. }
  18954. for(x=lstartx;x<=right;x+=gridsize) {
  18955. double gx=floor(x/gridsize)*gridsize;
  18956. int found=0;
  18957. for(i=2;i<objc;i++) {
  18958. int isnew,isWithin;
  18959. Odie_Polygon_GetFromTclObj(interp, objv[i], &p, &isnew);
  18960. isWithin=withinPolygon(p,gx,gy);
  18961. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[i],p);
  18962. if(isWithin>0) {
  18963. found=1;
  18964. break;
  18965. }
  18966. }
  18967. if(found) {
  18968. Tcl_Obj *coord=Tcl_NewObj();
  18969. Tcl_ListObjAppendElement(interp, coord, Tcl_NewDoubleObj(gx));
  18970. Tcl_ListObjAppendElement(interp, coord, Tcl_NewDoubleObj(gy));
  18971. Tcl_ListObjAppendElement(interp, pResult, coord);
  18972. }
  18973. }
  18974. }
  18975. Tcl_SetObjResult(interp, pResult);
  18976. return TCL_OK;
  18977. }
  18978. /* Tcl Proc ::polygon::squaregrid_create */
  18979. static int TclCmd_polygon_squaregrid_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  18980. /* poly hexgrid
  18981. **
  18982. ** Reduce the polygons to a series
  18983. ** of grid coordinates
  18984. */
  18985. Tcl_Obj *pResult;
  18986. Odie_Polygon *p;
  18987. int isnew;
  18988. pResult = Tcl_NewObj();
  18989. double gridsize=500.0;
  18990. double x,y;
  18991. if(objc < 3) {
  18992. Tcl_WrongNumArgs(interp, 1, objv, "GRIDSIZE ?POLY ...?");
  18993. return TCL_ERROR;
  18994. }
  18995. if( Tcl_GetDoubleFromObj(interp, objv[1], &gridsize) ) return TCL_ERROR;
  18996.  
  18997. if( Odie_Polygon_GetFromTclObj(interp, objv[2], &p, &isnew) ) return TCL_ERROR;
  18998. double left=p->bbox[BBOX_X0_IDX];
  18999. double top=p->bbox[BBOX_Y1_IDX];
  19000. double right=p->bbox[BBOX_X1_IDX];
  19001. double bottom=p->bbox[BBOX_Y0_IDX];
  19002. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[2],p);
  19003.  
  19004. int i;
  19005. for(i=3;i<objc;i++) {
  19006. if( Odie_Polygon_GetFromTclObj(interp, objv[i], &p, &isnew) ) return TCL_ERROR;
  19007. if(p->bbox[BBOX_X0_IDX] < left) left=p->bbox[BBOX_X0_IDX];
  19008. if(p->bbox[BBOX_Y1_IDX] > top) top=p->bbox[BBOX_Y1_IDX];
  19009. if(p->bbox[BBOX_X1_IDX] > right) right=p->bbox[BBOX_X1_IDX];
  19010. if(p->bbox[BBOX_Y0_IDX] < bottom) bottom=p->bbox[BBOX_Y0_IDX];
  19011. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[i],p);
  19012. }
  19013.  
  19014. pResult = Tcl_NewObj();
  19015. left-=gridsize;
  19016. top+=gridsize;
  19017. right+=gridsize;
  19018. bottom-=gridsize;
  19019.  
  19020. for(y=bottom;y<=top;y+=gridsize) {
  19021. double gy=floor(y/gridsize)*gridsize;
  19022. for(x=left;x<=right;x+=gridsize) {
  19023. double gx=floor(x/gridsize)*gridsize;
  19024. int found=0;
  19025. for(i=2;i<objc;i++) {
  19026. int isnew,isWithin;
  19027. Odie_Polygon_GetFromTclObj(interp, objv[i], &p, &isnew);
  19028. isWithin=withinPolygon(p,gx,gy);
  19029. if(isnew) Odie_Poly_ShimmerOrFree_TclObj(objv[i],p);
  19030. if(isWithin>0) {
  19031. found=1;
  19032. break;
  19033. }
  19034. }
  19035. if(found) {
  19036. Tcl_Obj *coord=Tcl_NewObj();
  19037. Tcl_ListObjAppendElement(interp, coord, Tcl_NewDoubleObj(gx));
  19038. Tcl_ListObjAppendElement(interp, coord, Tcl_NewDoubleObj(gy));
  19039. Tcl_ListObjAppendElement(interp, pResult, coord);
  19040. }
  19041. }
  19042. }
  19043. Tcl_SetObjResult(interp, pResult);
  19044. return TCL_OK;
  19045. }
  19046. /* Tcl Proc ::polygonxyz::info */
  19047. static int TclCmd_polygonxyz_info(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19048. Odie_FaceXYZ *pPoly;
  19049. int isnew,i,option;
  19050. static const char *POLYGON_fields[] =
  19051. { "id", "area", "bbox", "bend", "center", "is_2d", "is_convex", "normal", "nVertex", "radius", "rotation", "rotation_inv", 0 };
  19052. enum POLYGON_enum { POLYGON_FIELD_ID, POLYGON_FIELD_AREA, POLYGON_FIELD_BBOX, POLYGON_FIELD_BEND, POLYGON_FIELD_CENTER, POLYGON_FIELD_IS_2D, POLYGON_FIELD_IS_CONVEX, POLYGON_FIELD_NORMAL, POLYGON_FIELD_NVERTEX, POLYGON_FIELD_RADIUS, POLYGON_FIELD_ROTATION, POLYGON_FIELD_ROTATION_INV };
  19053. if(objc<2) {
  19054. Tcl_WrongNumArgs(interp, 1, objv, "ID ?field value...?");
  19055. return TCL_ERROR;
  19056. }
  19057. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPoly, &isnew) ) return TCL_ERROR;
  19058. for(i=2;i<objc;i+=2) {
  19059. Tcl_Obj *field,*value;
  19060. int option;
  19061. if((i+1) == objc) break;
  19062. field=objv[i];
  19063. value=objv[i+1];
  19064. if( Tcl_GetIndexFromObj(interp, field, POLYGON_fields, "option", 0, &option) ) return TCL_ERROR;
  19065. switch(option) {
  19066. case POLYGON_FIELD_ID: {
  19067. int temp;
  19068. if(Tcl_GetIntFromObj(interp,value,&temp)) {
  19069. Tcl_AppendResult(interp," while processing id",NULL);
  19070. return TCL_ERROR;
  19071. }
  19072. pPoly->id=temp;
  19073.  
  19074. break;
  19075. }
  19076. }
  19077. }
  19078. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPoly);
  19079. Tcl_SetObjResult(interp, Odie_FaceXYZ_ToDict(pPoly));
  19080. return TCL_OK;
  19081. }
  19082. /* Tcl Proc ::polygonxyz::create */
  19083. static int TclCmd_polygonxyz_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19084. int isnew=0,i;
  19085. Odie_FaceXYZ *p;
  19086. if( objc<2 ){
  19087. Tcl_WrongNumArgs(interp, 1, objv, "XYZLIST\nor\nXYZ XYZ XYZ XYZ");
  19088. return TCL_ERROR;
  19089. }
  19090. if(objc==2) {
  19091. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  19092. if(isnew) {
  19093. Tcl_SetObjResult(interp, Odie_FaceXYZ_NewTclObj(p));
  19094. } else {
  19095. Tcl_SetObjResult(interp, objv[1]);
  19096. }
  19097. } else {
  19098. int nVertex=objc-1;
  19099. p=Odie_FaceXYZ_Create(nVertex);
  19100. for(i=0;i<nVertex;i++) {
  19101. if(Odie_GetVectorXYZFromTclObj(interp,objv[i+1],p->vertex_xyz[i])) goto createfail;
  19102. }
  19103. if(Odie_FaceXYZ_Compute(interp,p)) goto createfail;
  19104. Tcl_SetObjResult(interp, Odie_FaceXYZ_NewTclObj(p));
  19105. }
  19106. return TCL_OK;
  19107. createfail:
  19108. if(isnew) Odie_Free((char *)p);
  19109. return TCL_ERROR;
  19110. }
  19111. /* Tcl Proc ::polygonxyz::createxy */
  19112. static int TclCmd_polygonxyz_createxy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19113. int isnew=0;
  19114. Odie_FaceXYZ *p;
  19115. if( objc!=2 ){
  19116. Tcl_WrongNumArgs(interp, 1, objv, "N\nor\nX Y X Y X Y...");
  19117. return TCL_ERROR;
  19118. }
  19119. if(objc==2) {
  19120. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  19121. if(isnew) {
  19122. Tcl_SetObjResult(interp, Odie_FaceXYZ_NewTclObj(p));
  19123. } else {
  19124. Tcl_SetObjResult(interp, objv[1]);
  19125. }
  19126. } else {
  19127. int i;
  19128. int nVertex=(objc-1)/2;
  19129. if((objc-1)%2!=0) {
  19130. Tcl_AppendResult(interp, "coordinates should come in pairs", 0);
  19131. return TCL_ERROR;
  19132. }
  19133. p=Odie_FaceXYZ_Create(nVertex);
  19134. for(i=0; i<nVertex; i++){
  19135. double d;
  19136. if(Tcl_GetDoubleFromObj(interp, objv[i*2+1], &d)) goto createfail;
  19137. p->vertex_xyz[i][X_IDX] = d;
  19138.  
  19139. if(Tcl_GetDoubleFromObj(interp, objv[i*2+2], &d)) goto createfail;
  19140. p->vertex_xyz[i][Y_IDX] = d;
  19141. p->vertex_xyz[i][Z_IDX] = 0.0;
  19142. }
  19143. if(Odie_FaceXYZ_Compute(interp,p)) goto createfail;
  19144. Tcl_SetObjResult(interp, Odie_FaceXYZ_NewTclObj(p));
  19145. }
  19146. return TCL_OK;
  19147. createfail:
  19148. Odie_Free((char *)p);
  19149. return TCL_ERROR;
  19150. }
  19151. /* Tcl Proc ::polygonxyz::simplify */
  19152. static int TclCmd_polygonxyz_simplify(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19153. Odie_FaceXYZ *pPolygonXYZ,*pNewPolygonXYZ;
  19154. int isnew;
  19155. if( objc!=2 ){
  19156. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19157. return TCL_ERROR;
  19158. }
  19159.  
  19160. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPolygonXYZ, &isnew) ) return TCL_ERROR;
  19161. pNewPolygonXYZ=Odie_FaceXYZ_Simplify(pPolygonXYZ);
  19162. Odie_FaceXYZ_Compute(interp,pNewPolygonXYZ);
  19163. Tcl_SetObjResult(interp, Odie_FaceXYZ_NewTclObj(pNewPolygonXYZ));
  19164. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPolygonXYZ);
  19165. return TCL_OK;
  19166. }
  19167. /* Tcl Proc ::polygonxyz::id */
  19168. static int TclCmd_polygonxyz_id(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19169. Odie_FaceXYZ *pPoly;
  19170. int isnew;
  19171. if( objc!=2 && objc!=3){
  19172. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19173. return TCL_ERROR;
  19174. }
  19175. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPoly, &isnew) ) return TCL_ERROR;
  19176. if (objc==3) {
  19177. Tcl_Obj *value=objv[2];
  19178. int temp;
  19179. if(Tcl_GetIntFromObj(interp,value,&temp)) {
  19180. Tcl_AppendResult(interp," while processing id",NULL);
  19181. return TCL_ERROR;
  19182. }
  19183. pPoly->id=temp;
  19184.  
  19185. }
  19186. {
  19187. Tcl_Obj *value;
  19188. value=Tcl_NewIntObj(pPoly->id);
  19189. Tcl_SetObjResult(interp,value);
  19190. }
  19191. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPoly);
  19192. return TCL_OK;
  19193. }
  19194. /* Tcl Proc ::polygonxyz::area */
  19195. static int TclCmd_polygonxyz_area(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19196. Odie_FaceXYZ *p;
  19197. int isnew;
  19198. int i;
  19199. double area;
  19200. if( objc<2 ){
  19201. Tcl_WrongNumArgs(interp, 1, objv, "N ?N...?");
  19202. return TCL_ERROR;
  19203. }
  19204. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  19205. area=p->area;
  19206. if(isnew) Odie_Free((char *)p);
  19207. for(i=2;i<objc;i++) {
  19208. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[i], &p, &isnew) ) return TCL_ERROR;
  19209. area+=p->area;
  19210. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[i],p);
  19211. }
  19212. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(area));
  19213. return TCL_OK;
  19214. }
  19215. /* Tcl Proc ::polygonxyz::bbox */
  19216. static int TclCmd_polygonxyz_bbox(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19217. Odie_FaceXYZ *pPoly;
  19218. int isnew;
  19219. if( objc!=2 ){
  19220. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19221. return TCL_ERROR;
  19222. }
  19223. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPoly, &isnew) ) return TCL_ERROR;
  19224. {
  19225. Tcl_Obj *value;
  19226. Odie_MatrixObj *C;
  19227. if(pPoly->is_2d) {
  19228. C=Odie_MatrixObj_Create(MATFORM_bbox_xy);
  19229. VectorXY_BBOX_Copy(C->matrix,pPoly->bbox_uv);
  19230. value=Matrix_To_TclObj(C);
  19231. } else {
  19232. C=Odie_MatrixObj_Create(MATFORM_aabb_xyz);
  19233. VectorXYZ_AABB_Copy(C->matrix,pPoly->bbox_xyz);
  19234. value=Matrix_To_TclObj(C);
  19235. }
  19236.  
  19237. Tcl_SetObjResult(interp,value);
  19238. }
  19239. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPoly);
  19240. return TCL_OK;
  19241. }
  19242. /* Tcl Proc ::polygonxyz::bend */
  19243. static int TclCmd_polygonxyz_bend(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19244. Odie_FaceXYZ *pPoly;
  19245. int isnew;
  19246. if( objc!=2 ){
  19247. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19248. return TCL_ERROR;
  19249. }
  19250. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPoly, &isnew) ) return TCL_ERROR;
  19251. {
  19252. Tcl_Obj *value;
  19253. value=Tcl_NewIntObj(pPoly->bend);
  19254. Tcl_SetObjResult(interp,value);
  19255. }
  19256. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPoly);
  19257. return TCL_OK;
  19258. }
  19259. /* Tcl Proc ::polygonxyz::center */
  19260. static int TclCmd_polygonxyz_center(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19261. Odie_FaceXYZ *pPoly;
  19262. int isnew;
  19263. if( objc!=2 ){
  19264. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19265. return TCL_ERROR;
  19266. }
  19267. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPoly, &isnew) ) return TCL_ERROR;
  19268. {
  19269. Tcl_Obj *value;
  19270. value=VectorXYZ_To_TclObj(pPoly->center);
  19271. Tcl_SetObjResult(interp,value);
  19272. }
  19273. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPoly);
  19274. return TCL_OK;
  19275. }
  19276. /* Tcl Proc ::polygonxyz::is_2d */
  19277. static int TclCmd_polygonxyz_is_2d(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19278. Odie_FaceXYZ *pPoly;
  19279. int isnew;
  19280. if( objc!=2 ){
  19281. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19282. return TCL_ERROR;
  19283. }
  19284. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPoly, &isnew) ) return TCL_ERROR;
  19285. {
  19286. Tcl_Obj *value;
  19287. value=Tcl_NewBooleanObj(pPoly->is_convex);
  19288. Tcl_SetObjResult(interp,value);
  19289. }
  19290. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPoly);
  19291. return TCL_OK;
  19292. }
  19293. /* Tcl Proc ::polygonxyz::is_convex */
  19294. static int TclCmd_polygonxyz_is_convex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19295. Odie_FaceXYZ *pPoly;
  19296. int isnew;
  19297. if( objc!=2 ){
  19298. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19299. return TCL_ERROR;
  19300. }
  19301. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPoly, &isnew) ) return TCL_ERROR;
  19302. {
  19303. Tcl_Obj *value;
  19304. value=Tcl_NewBooleanObj(pPoly->is_convex);
  19305. Tcl_SetObjResult(interp,value);
  19306. }
  19307. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPoly);
  19308. return TCL_OK;
  19309. }
  19310. /* Tcl Proc ::polygonxyz::normal */
  19311. static int TclCmd_polygonxyz_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19312. Odie_FaceXYZ *pPoly;
  19313. int isnew;
  19314. if( objc!=2 ){
  19315. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19316. return TCL_ERROR;
  19317. }
  19318. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPoly, &isnew) ) return TCL_ERROR;
  19319. {
  19320. Tcl_Obj *value;
  19321. value=VectorXYZ_To_TclObj(pPoly->normal);
  19322. Tcl_SetObjResult(interp,value);
  19323. }
  19324. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPoly);
  19325. return TCL_OK;
  19326. }
  19327. /* Tcl Proc ::polygonxyz::nVertex */
  19328. static int TclCmd_polygonxyz_nVertex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19329. Odie_FaceXYZ *pPoly;
  19330. int isnew;
  19331. if( objc!=2 ){
  19332. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19333. return TCL_ERROR;
  19334. }
  19335. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPoly, &isnew) ) return TCL_ERROR;
  19336. {
  19337. Tcl_Obj *value;
  19338. value=Tcl_NewIntObj(pPoly->nVertex);
  19339. Tcl_SetObjResult(interp,value);
  19340. }
  19341. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPoly);
  19342. return TCL_OK;
  19343. }
  19344. /* Tcl Proc ::polygonxyz::radius */
  19345. static int TclCmd_polygonxyz_radius(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19346. Odie_FaceXYZ *pPoly;
  19347. int isnew;
  19348. if( objc!=2 ){
  19349. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19350. return TCL_ERROR;
  19351. }
  19352. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPoly, &isnew) ) return TCL_ERROR;
  19353. {
  19354. Tcl_Obj *value;
  19355. value=Tcl_NewDoubleObj(pPoly->radius);
  19356. Tcl_SetObjResult(interp,value);
  19357. }
  19358. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPoly);
  19359. return TCL_OK;
  19360. }
  19361. /* Tcl Proc ::polygonxyz::rotation */
  19362. static int TclCmd_polygonxyz_rotation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19363. Odie_FaceXYZ *pPoly;
  19364. int isnew;
  19365. if( objc!=2 ){
  19366. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19367. return TCL_ERROR;
  19368. }
  19369. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPoly, &isnew) ) return TCL_ERROR;
  19370. {
  19371. Tcl_Obj *value;
  19372. Odie_MatrixObj *C;
  19373. C=Odie_MatrixObj_Create(MATFORM_affine);
  19374. Odie_Affine4x4_Copy(C->matrix,pPoly->rotation);
  19375. value=Matrix_To_TclObj(C);
  19376.  
  19377. Tcl_SetObjResult(interp,value);
  19378. }
  19379. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPoly);
  19380. return TCL_OK;
  19381. }
  19382. /* Tcl Proc ::polygonxyz::rotation_inv */
  19383. static int TclCmd_polygonxyz_rotation_inv(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19384. Odie_FaceXYZ *pPoly;
  19385. int isnew;
  19386. if( objc!=2 ){
  19387. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19388. return TCL_ERROR;
  19389. }
  19390. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPoly, &isnew) ) return TCL_ERROR;
  19391. {
  19392. Tcl_Obj *value;
  19393. Odie_MatrixObj *C;
  19394. C=Odie_MatrixObj_Create(MATFORM_affine);
  19395. Odie_Affine4x4_Copy(C->matrix,pPoly->rotation_inv);
  19396. value=Matrix_To_TclObj(C);
  19397.  
  19398. Tcl_SetObjResult(interp,value);
  19399. }
  19400. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPoly);
  19401. return TCL_OK;
  19402. }
  19403. /* Tcl Proc ::polygonxyz::axis_of_normal */
  19404. static int TclCmd_polygonxyz_axis_of_normal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19405. Odie_FaceXYZ *p;
  19406. int axis,isnew;
  19407.  
  19408. if( objc != 2 ){
  19409. Tcl_WrongNumArgs(interp, 1, objv, "axis_of_normal X");
  19410. return TCL_ERROR;
  19411. }
  19412. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  19413. axis=VectorXYZ_AxisOfNormal(p->normal);
  19414. Tcl_SetObjResult(interp, Tcl_NewIntObj(axis));
  19415. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p);
  19416. return TCL_OK;
  19417. }
  19418. /* Tcl Proc ::polygonxyz::canvascoords */
  19419. static int TclCmd_polygonxyz_canvascoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19420. /* poly info N
  19421. **
  19422. ** Return the coordinates for a polygonxyz
  19423. */
  19424. Tcl_Obj *pResult;
  19425. Odie_FaceXYZ *p;
  19426. int i,isnew;
  19427. double xoff=0;
  19428. double yoff=0;
  19429. double xscale=1.0;
  19430. double yscale=-1.0;
  19431. if( objc!=2 && objc != 4 && objc != 6){
  19432. Tcl_WrongNumArgs(interp, 1, objv, "N ?xoff yoff? ?xscale yscale?");
  19433. return TCL_ERROR;
  19434. }
  19435. if(objc>3) {
  19436. if(Tcl_GetDoubleFromObj(interp,objv[2],&xoff)) return TCL_ERROR;
  19437. if(Tcl_GetDoubleFromObj(interp,objv[3],&yoff)) return TCL_ERROR;
  19438. }
  19439. if(objc==6) {
  19440. if(Tcl_GetDoubleFromObj(interp,objv[4],&xscale)) return TCL_ERROR;
  19441. if(Tcl_GetDoubleFromObj(interp,objv[5],&yscale)) return TCL_ERROR;
  19442. }
  19443.  
  19444. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  19445.  
  19446. pResult = Tcl_NewObj();
  19447. for(i=0; i<p->nVertex; i++){
  19448. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(p->vertex_uv[i][X_IDX]*xscale+xoff));
  19449. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(p->vertex_uv[i][Y_IDX]*yscale+yoff));
  19450. }
  19451. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p);
  19452. Tcl_SetObjResult(interp, pResult);
  19453. return TCL_OK;
  19454. }
  19455. /* Tcl Proc ::polygonxyz::coords */
  19456. static int TclCmd_polygonxyz_coords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19457. /* poly info N
  19458. **
  19459. ** Return the coordinates for a polygonxyz
  19460. */
  19461. Tcl_Obj *pResult;
  19462. Odie_FaceXYZ *p;
  19463. int i,isnew;
  19464. if( objc!=2 ){
  19465. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19466. return TCL_ERROR;
  19467. }
  19468. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  19469. pResult = Tcl_NewObj();
  19470. for(i=0; i<p->nVertex; i++){
  19471. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(p->vertex_xyz[i]));
  19472. }
  19473. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p);
  19474. Tcl_SetObjResult(interp, pResult);
  19475. return TCL_OK;
  19476. }
  19477. /* Tcl Proc ::polygonxyz::intcoordsxy */
  19478. static int TclCmd_polygonxyz_intcoordsxy(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19479. /* poly info N
  19480. **
  19481. ** Return the coordinates for a polygonxyz
  19482. */
  19483. Tcl_DString result;
  19484. Odie_FaceXYZ *p;
  19485. int i,isnew,len;
  19486. char *cResult;
  19487. if( objc!=2 ){
  19488. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19489. return TCL_ERROR;
  19490. }
  19491. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  19492. Tcl_DStringInit(&result);
  19493. for(i=0; i<p->nVertex; i++){
  19494. char out[256];
  19495. sprintf(out,"%d %d",(int)p->vertex_xyz[i][X_IDX],(int)p->vertex_xyz[i][Y_IDX]);
  19496. Tcl_DStringAppendElement(&result,out);
  19497. }
  19498. len=Tcl_DStringLength(&result);
  19499. cResult=Tcl_DStringValue(&result);
  19500. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p);
  19501. Tcl_SetObjResult(interp, Tcl_NewStringObj(cResult,len));
  19502. Tcl_DStringFree(&result);
  19503. return TCL_OK;
  19504. }
  19505. /* Tcl Proc ::polygonxyz::intcoords */
  19506. static int TclCmd_polygonxyz_intcoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19507. /* poly info N
  19508. **
  19509. ** Return the coordinates for a polygonxyz
  19510. */
  19511. Tcl_DString result;
  19512. Odie_FaceXYZ *p;
  19513. int i,isnew,len;
  19514. char *cResult;
  19515. if( objc!=2 ){
  19516. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19517. return TCL_ERROR;
  19518. }
  19519. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  19520. Tcl_DStringInit(&result);
  19521. for(i=0; i<p->nVertex; i++){
  19522. char out[256];
  19523. sprintf(out,"%d %d %d",(int)p->vertex_xyz[i][X_IDX],(int)p->vertex_xyz[i][Y_IDX],(int)p->vertex_xyz[i][Z_IDX]);
  19524. Tcl_DStringAppendElement(&result,out);
  19525. }
  19526. len=Tcl_DStringLength(&result);
  19527. cResult=Tcl_DStringValue(&result);
  19528. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p);
  19529. Tcl_SetObjResult(interp, Tcl_NewStringObj(cResult,len));
  19530. Tcl_DStringFree(&result);
  19531. return TCL_OK;
  19532. }
  19533. /* Tcl Proc ::polygonxyz::edges */
  19534. static int TclCmd_polygonxyz_edges(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19535. Tcl_Obj *pResult=NULL;
  19536. int isnew;
  19537. Odie_FaceXYZ *p;
  19538. int i,j;
  19539. int start,end;
  19540.  
  19541. if( objc != 2 && objc!=3 && objc != 4){
  19542. Tcl_WrongNumArgs(interp, 1, objv, "N ?start? ?end?");
  19543. return TCL_ERROR;
  19544. }
  19545. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  19546. if(objc==2) {
  19547. pResult=Tcl_NewObj();
  19548. for(i=0; i<p->nVertex; i++){
  19549. j=(i+1)%p->nVertex;
  19550. Tcl_ListObjAppendElement(interp,pResult, VectorXYZ_To_TclObj(p->vertex_xyz[i]));
  19551. Tcl_ListObjAppendElement(interp,pResult, VectorXYZ_To_TclObj(p->vertex_xyz[j]));
  19552. }
  19553. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p);
  19554. Tcl_SetObjResult(interp, pResult);
  19555. return TCL_OK;
  19556. }
  19557. if(objc==3) {
  19558. if(Tcl_GetIntFromObj(interp,objv[2],&start)) goto fail;
  19559. pResult=Tcl_NewObj();
  19560. start=start%p->nVertex;
  19561. end=(start+1)%p->nVertex;
  19562. Tcl_ListObjAppendElement(interp,pResult, VectorXYZ_To_TclObj(p->vertex_xyz[start]));
  19563. Tcl_ListObjAppendElement(interp,pResult, VectorXYZ_To_TclObj(p->vertex_xyz[end]));
  19564. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p);
  19565. Tcl_SetObjResult(interp, pResult);
  19566. return TCL_OK;
  19567. }
  19568. if(objc==4) {
  19569. if(Tcl_GetIntFromObj(interp,objv[2],&start)) goto fail;
  19570. if(Tcl_GetIntFromObj(interp,objv[3],&end)) goto fail;
  19571. pResult=Tcl_NewObj();
  19572. i=start%p->nVertex;
  19573. end=end%p->nVertex;
  19574. while(i!=end) {
  19575. j=(i+1)%p->nVertex;
  19576. Tcl_ListObjAppendElement(interp,pResult, VectorXYZ_To_TclObj(p->vertex_xyz[i]));
  19577. Tcl_ListObjAppendElement(interp,pResult, VectorXYZ_To_TclObj(p->vertex_xyz[j]));
  19578. i=(i+1)%p->nVertex;
  19579. }
  19580. j=(i+1)%p->nVertex;
  19581. Tcl_ListObjAppendElement(interp,pResult, VectorXYZ_To_TclObj(p->vertex_xyz[i]));
  19582. Tcl_ListObjAppendElement(interp,pResult, VectorXYZ_To_TclObj(p->vertex_xyz[j]));
  19583. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[i],p);
  19584. Tcl_SetObjResult(interp, pResult);
  19585. return TCL_OK;
  19586. }
  19587. fail:
  19588. if(pResult) Tcl_DecrRefCount(pResult);
  19589. if(isnew) Odie_Free((char *)p);
  19590. return TCL_ERROR;
  19591. }
  19592. /* Tcl Proc ::polygonxyz::triangles */
  19593. static int TclCmd_polygonxyz_triangles(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19594. Tcl_Obj *pResult=NULL;
  19595. int isnew;
  19596. Odie_FaceXYZ *p;
  19597. int i,j;
  19598.  
  19599. if( objc != 2 ){
  19600. Tcl_WrongNumArgs(interp, 1, objv, "N");
  19601. return TCL_ERROR;
  19602. }
  19603. if( Odie_ConvexPolygon_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  19604. pResult=Tcl_NewObj();
  19605. if(p->nVertex==3) {
  19606. Tcl_ListObjAppendElement(interp,pResult, VectorXYZ_To_TclObj(p->vertex_xyz[0]));
  19607. Tcl_ListObjAppendElement(interp,pResult, VectorXYZ_To_TclObj(p->vertex_xyz[1]));
  19608. Tcl_ListObjAppendElement(interp,pResult, VectorXYZ_To_TclObj(p->vertex_xyz[2]));
  19609. } else {
  19610. for(i=1; i<p->nVertex; i++){
  19611. j=(i+1)%p->nVertex;
  19612. if(j==0) j=1;
  19613. Tcl_ListObjAppendElement(interp,pResult, VectorXYZ_To_TclObj(p->vertex_xyz[0]));
  19614. Tcl_ListObjAppendElement(interp,pResult, VectorXYZ_To_TclObj(p->vertex_xyz[i]));
  19615. Tcl_ListObjAppendElement(interp,pResult, VectorXYZ_To_TclObj(p->vertex_xyz[j]));
  19616. }
  19617. }
  19618. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p);
  19619. Tcl_SetObjResult(interp, pResult);
  19620. return TCL_OK;
  19621. }
  19622. /* Tcl Proc ::polygonxyz::uvcoords */
  19623. static int TclCmd_polygonxyz_uvcoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19624. /* poly info N
  19625. **
  19626. ** Return the coordinates for a polygonxyz
  19627. */
  19628. Tcl_Obj *pResult;
  19629. Odie_FaceXYZ *p;
  19630. int i,isnew;
  19631. if( objc!=2 ){
  19632. Tcl_WrongNumArgs(interp, 1, objv, "N ");
  19633. return TCL_ERROR;
  19634. }
  19635. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  19636. pResult = Tcl_NewObj();
  19637. for(i=0; i<p->nVertex; i++){
  19638. Tcl_ListObjAppendElement(0, pResult, VectorXY_To_TclObj(p->vertex_uv[i]));
  19639. }
  19640. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p);
  19641. Tcl_SetObjResult(interp, pResult);
  19642. return TCL_OK;
  19643. }
  19644. /* Tcl Proc ::polygonxyz::xycoords */
  19645. static int TclCmd_polygonxyz_xycoords(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19646. /* poly info N
  19647. **
  19648. ** Return the coordinates for a polygonxyz
  19649. */
  19650. Tcl_Obj *pResult;
  19651. Odie_FaceXYZ *p;
  19652. int i,isnew,axis,u,v;
  19653. double xoff=0;
  19654. double yoff=0;
  19655. double xscale=1.0;
  19656. double yscale=-1.0;
  19657. if( objc!=2 && objc != 4 && objc != 6){
  19658. Tcl_WrongNumArgs(interp, 1, objv, "N ?xoff yoff? ?xscale yscale?");
  19659. return TCL_ERROR;
  19660. }
  19661. if(objc>3) {
  19662. if(Tcl_GetDoubleFromObj(interp,objv[2],&xoff)) return TCL_ERROR;
  19663. if(Tcl_GetDoubleFromObj(interp,objv[3],&yoff)) return TCL_ERROR;
  19664. }
  19665. if(objc==6) {
  19666. if(Tcl_GetDoubleFromObj(interp,objv[4],&xscale)) return TCL_ERROR;
  19667. if(Tcl_GetDoubleFromObj(interp,objv[5],&yscale)) return TCL_ERROR;
  19668. }
  19669. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  19670. axis=VectorXYZ_AxisOfNormal(p->normal);
  19671. switch(axis) {
  19672. case Z_IDX: u=X_IDX; v=Y_IDX; break;
  19673. case Y_IDX: u=Z_IDX; v=X_IDX; break;
  19674. case X_IDX: u=Y_IDX; v=Z_IDX; break;
  19675. }
  19676. pResult = Tcl_NewObj();
  19677. for(i=0; i<p->nVertex; i++){
  19678. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(p->vertex_xyz[i][u]*xscale+xoff));
  19679. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(p->vertex_xyz[i][v]*yscale+yoff));
  19680. }
  19681. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p);
  19682. Tcl_SetObjResult(interp, pResult);
  19683. return TCL_OK;
  19684. }
  19685. /* Tcl Proc ::polygonxyz::compare */
  19686. static int TclCmd_polygonxyz_compare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19687. Odie_FaceXYZ *pPolygonXYZA,*pPolygonXYZB;
  19688. int isnewa,isnewb,result=1;
  19689. if( objc!=3 ){
  19690. Tcl_WrongNumArgs(interp, 1, objv, "POLY POLY");
  19691. return TCL_ERROR;
  19692. }
  19693.  
  19694. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPolygonXYZA, &isnewa) ) return TCL_ERROR;
  19695. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[2], &pPolygonXYZB, &isnewb) ) return TCL_ERROR;
  19696. result=Odie_FaceXYZ_Compare(pPolygonXYZA,pPolygonXYZB);
  19697. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(result));
  19698. if(isnewa) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPolygonXYZA);
  19699. if(isnewb) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[2],pPolygonXYZB);
  19700. return TCL_OK;
  19701. }
  19702. /* Tcl Proc ::polygonxyz::coplaner */
  19703. static int TclCmd_polygonxyz_coplaner(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19704. Odie_FaceXYZ *pPolygonXYZA,*pPolygonXYZB;
  19705. int isnewa,isnewb,result=1;
  19706. if( objc!=3 ){
  19707. Tcl_WrongNumArgs(interp, 1, objv, "POLY POLY");
  19708. return TCL_ERROR;
  19709. }
  19710.  
  19711. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &pPolygonXYZA, &isnewa) ) return TCL_ERROR;
  19712. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[2], &pPolygonXYZB, &isnewb) ) return TCL_ERROR;
  19713. result=Odie_FaceXYZ_Coplaner(pPolygonXYZA,pPolygonXYZB);
  19714. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(result));
  19715. if(isnewa) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],pPolygonXYZA);
  19716. if(isnewb) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[2],pPolygonXYZB);
  19717. return TCL_OK;
  19718. }
  19719. /* Tcl Proc ::polygonxyz::flipped */
  19720. static int TclCmd_polygonxyz_flipped(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19721. Odie_FaceXYZ *p,*q;
  19722. int isnewp,isnewq;
  19723. double dp;
  19724. if( objc != 3 ){
  19725. Tcl_WrongNumArgs(interp, 1, objv, "POLYGON POLYGON");
  19726. return TCL_ERROR;
  19727. }
  19728. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p, &isnewp) ) return TCL_ERROR;
  19729. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[2], &q, &isnewq) ) return TCL_ERROR;
  19730.  
  19731. dp = VectorXYZ_Dot_Product(p->normal, q->normal);
  19732. if(dp>=0) {
  19733. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  19734. } else {
  19735. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
  19736. }
  19737. if(isnewp) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p);
  19738. if(isnewq) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[2],q);
  19739. return TCL_OK;
  19740. }
  19741. /* Tcl Proc ::polygonxyz::side */
  19742. static int TclCmd_polygonxyz_side(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19743. Odie_FaceXYZ *p;
  19744. int isnew;
  19745. VectorXYZ point,vec;
  19746. double dp;
  19747. if( objc != 3 ){
  19748. Tcl_WrongNumArgs(interp, 1, objv, "POLYGON POINT");
  19749. return TCL_ERROR;
  19750. }
  19751. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  19752. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],point)) return TCL_ERROR;
  19753. VectorXYZ_Subtract(vec, point, p->center);
  19754. dp = VectorXYZ_Dot_Product(vec, p->normal);
  19755. if(dp<=0) {
  19756. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  19757. } else {
  19758. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
  19759. }
  19760. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p);
  19761. return TCL_OK;
  19762. }
  19763. /* Tcl Proc ::polygonxyz::intersect_test */
  19764. static int TclCmd_polygonxyz_intersect_test(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19765. /* poly intersect N1 N2
  19766. **
  19767. ** Return a list of 3 elements where the first element is the
  19768. ** area of intersection between polygons N1 and N2 and the remaining
  19769. ** 3 elements are the X and Y coordinates of a point within both
  19770. ** polygons.
  19771. **
  19772. ** The current implementation returns an approximation. We might
  19773. ** change it to compute the exact intersection later.
  19774. */
  19775. Odie_FaceXYZ *p1, *p2;
  19776. int isnew1,isnew2,c=0;
  19777. if( objc!=3 ){
  19778. Tcl_WrongNumArgs(interp, 1, objv, "N1 N2");
  19779. return TCL_ERROR;
  19780. }
  19781. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p1, &isnew1) ) return TCL_ERROR;
  19782. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[2], &p2, &isnew2) ) {
  19783. if(isnew1) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p1);
  19784. return TCL_ERROR;
  19785. }
  19786. if(!Odie_FaceXYZ_Coplaner(p1,p2)) {
  19787. c=0;
  19788. } else if(!AABB_AABB_Intersect(p1->bbox_xyz,p2->bbox_xyz)) {
  19789. c=0;
  19790. }else if( p1->area==0.0 || p2->area==0.0 ){
  19791. c=0;
  19792. }else{
  19793. c = Odie_FaceXYZ_IntersectTest(p1,p2);
  19794. }
  19795. if(isnew1) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p1);
  19796. if(isnew2) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[2],p2);
  19797. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(c));
  19798. return TCL_OK;
  19799. }
  19800. /* Tcl Proc ::polygonxyz::intersect_test_uv */
  19801. static int TclCmd_polygonxyz_intersect_test_uv(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19802. /* poly intersect N1 N2
  19803. **
  19804. ** Return a list of 3 elements where the first element is the
  19805. ** area of intersection between polygons N1 and N2 and the remaining
  19806. ** 3 elements are the X and Y coordinates of a point within both
  19807. ** polygons.
  19808. **
  19809. ** The current implementation returns an approximation. We might
  19810. ** change it to compute the exact intersection later.
  19811. */
  19812. Odie_FaceXYZ *p1, *p2;
  19813. int isnew1,isnew2,c=0;
  19814. Tcl_Obj *pResult;
  19815. if( objc!=3 ){
  19816. Tcl_WrongNumArgs(interp, 1, objv, "N1 N2");
  19817. return TCL_ERROR;
  19818. }
  19819. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p1, &isnew1) ) return TCL_ERROR;
  19820. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[2], &p2, &isnew2) ) {
  19821. if(isnew1) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p1);
  19822. return TCL_ERROR;
  19823. }
  19824. if(!BBOX_BBOX_Intersect(p1->bbox_uv,p2->bbox_uv)) {
  19825. c=0;
  19826. } else if( p1->area==0.0 || p2->area==0.0 ){
  19827. c=0;
  19828. }else{
  19829. c = Odie_FaceXYZ_IntersectTest(p1,p2);
  19830. }
  19831. if(isnew1) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p1);
  19832. if(isnew2) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[2],p2);
  19833. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(c));
  19834. return TCL_OK;
  19835. }
  19836. /* Tcl Proc ::polygonxyz::intersect */
  19837. static int TclCmd_polygonxyz_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19838. /* poly intersect N1 N2
  19839. **
  19840. ** Return a list of 3 elements where the first element is the
  19841. ** area of intersection between polygons N1 and N2 and the remaining
  19842. ** 3 elements are the X and Y coordinates of a point within both
  19843. ** polygons.
  19844. **
  19845. ** The current implementation returns an approximation. We might
  19846. ** change it to compute the exact intersection later.
  19847. */
  19848. Odie_FaceXYZ *p1, *p2;
  19849. int isnew1,isnew2;
  19850. double area;
  19851. double xInside = 0.0, yInside = 0.0;
  19852. Tcl_Obj *pResult;
  19853. if( objc!=3 ){
  19854. Tcl_WrongNumArgs(interp, 1, objv, "N1 N2");
  19855. return TCL_ERROR;
  19856. }
  19857. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p1, &isnew1) ) return TCL_ERROR;
  19858. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[2], &p2, &isnew2) ) {
  19859. if(isnew1) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p1);
  19860. return TCL_ERROR;
  19861. }
  19862. if(!Odie_FaceXYZ_Coplaner(p1,p2)) {
  19863. area=0.0;
  19864. } else if(!AABB_AABB_Intersect(p1->bbox_xyz,p2->bbox_xyz)) {
  19865. area = 0.0;
  19866. }else if( p1->area==0.0 || p2->area==0.0 ){
  19867. area = 0.0;
  19868. }else{
  19869. area = Odie_FaceXYZ_AreaOfIntersection(p1,p2,&xInside,&yInside);
  19870. }
  19871. if(isnew1) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p1);
  19872. if(isnew2) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[2],p2);
  19873.  
  19874. pResult = Tcl_NewObj();
  19875. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(area));
  19876. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(xInside));
  19877. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(yInside));
  19878. Tcl_SetObjResult(interp, pResult);
  19879. return TCL_OK;
  19880. }
  19881. /* Tcl Proc ::polygonxyz::intersect_uv */
  19882. static int TclCmd_polygonxyz_intersect_uv(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19883. /* poly intersect N1 N2
  19884. **
  19885. ** Return a list of 3 elements where the first element is the
  19886. ** area of intersection between polygons N1 and N2 and the remaining
  19887. ** 3 elements are the X and Y coordinates of a point within both
  19888. ** polygons.
  19889. **
  19890. ** The current implementation returns an approximation. We might
  19891. ** change it to compute the exact intersection later.
  19892. */
  19893. Odie_FaceXYZ *p1, *p2;
  19894. int isnew1,isnew2;
  19895. double area;
  19896. double xInside = 0.0, yInside = 0.0;
  19897. Tcl_Obj *pResult;
  19898. if( objc!=3 ){
  19899. Tcl_WrongNumArgs(interp, 1, objv, "N1 N2");
  19900. return TCL_ERROR;
  19901. }
  19902. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p1, &isnew1) ) return TCL_ERROR;
  19903. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[2], &p2, &isnew2) ) {
  19904. if(isnew1) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p1);
  19905. return TCL_ERROR;
  19906. }
  19907. if(!BBOX_BBOX_Intersect(p1->bbox_uv,p2->bbox_uv)) {
  19908. area = 0.0;
  19909. }else if( p1->area==0.0 || p2->area==0.0 ){
  19910. area = 0.0;
  19911. }else{
  19912. area = Odie_FaceXYZ_AreaOfIntersection(p1,p2,&xInside,&yInside);
  19913. }
  19914. if(isnew1) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p1);
  19915. if(isnew2) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[2],p2);
  19916.  
  19917. pResult = Tcl_NewObj();
  19918. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(area));
  19919. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(xInside));
  19920. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(yInside));
  19921. Tcl_SetObjResult(interp, pResult);
  19922. return TCL_OK;
  19923. }
  19924. /* Tcl Proc ::polygonxyz::points_within */
  19925. static int TclCmd_polygonxyz_points_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19926. /* poly within POLY XYZ ?XYZ...?
  19927. **
  19928. ** Return a list of XYZ points from the arguments that are contained within
  19929. ** a convex POLY
  19930. */
  19931. VectorXYZ POINT;
  19932. Odie_FaceXYZ *p;
  19933. int res,isnew,i;
  19934. Tcl_Obj *pResult;
  19935. if( objc<3 ){
  19936. Tcl_WrongNumArgs(interp, 1, objv, "POLY ?XYZ...?");
  19937. return TCL_ERROR;
  19938. }
  19939. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR;
  19940. pResult=Tcl_NewObj();
  19941. for(i=2;i<objc;i++) {
  19942. if(Odie_GetVectorXYZFromTclObj(interp,objv[i],POINT)) goto error;
  19943. res = Odie_FaceXYZ_Within(p, POINT);
  19944. if(res>=0) {
  19945. Tcl_ListObjAppendElement(interp, pResult, VectorXYZ_To_TclObj(POINT));
  19946. }
  19947. }
  19948. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p);
  19949. Tcl_SetObjResult(interp, pResult);
  19950. return TCL_OK;
  19951. error:
  19952. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[1],p);
  19953. Tcl_DecrRefCount(pResult);
  19954. return TCL_OK;
  19955. }
  19956. /* Tcl Proc ::polygonxyz::within */
  19957. static int TclCmd_polygonxyz_within(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19958. /* poly within X Y N
  19959. ** or
  19960. ** poly within POINT N
  19961. **
  19962. ** Return -1, 0, or +1 if the point X,Y is outside, on, or inside
  19963. ** polygonxyz N.
  19964. */
  19965. VectorXYZ POINT;
  19966. Odie_FaceXYZ *p;
  19967. int res,isnew;
  19968. if( objc != 3 && objc != 4 ){
  19969. Tcl_WrongNumArgs(interp, 1, objv, "POINT POLY\nor\nX Y POLY");
  19970. return TCL_ERROR;
  19971. }
  19972. if(objc==3) {
  19973. if(Odie_GetVectorXYZFromTclObj(interp, objv[1],POINT)) return TCL_ERROR;
  19974. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[2], &p, &isnew) ) return TCL_ERROR;
  19975. res = Odie_FaceXYZ_Within(p, POINT);
  19976. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[2],p);
  19977. } else {
  19978. double x,y;
  19979. if(Tcl_GetDoubleFromObj(interp,objv[1],&x)) return TCL_ERROR;
  19980. if(Tcl_GetDoubleFromObj(interp,objv[2],&y)) return TCL_ERROR;
  19981. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[3], &p, &isnew) ) return TCL_ERROR;
  19982. POINT[X_IDX]=x;
  19983. POINT[Y_IDX]=y;
  19984. res=PolygonUV_Within(p,x,y);
  19985. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[3],p);
  19986. }
  19987. Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
  19988. return TCL_OK;
  19989. }
  19990. /* Tcl Proc ::polygonxyz::within_set */
  19991. static int TclCmd_polygonxyz_within_set(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  19992. /* poly within X N ?N...?
  19993. **
  19994. ** polygonxyz N.
  19995. */
  19996. VectorXYZ POINT;
  19997. Odie_FaceXYZ *p;
  19998. int res,isnew;
  19999. if( objc<3 ){
  20000. Tcl_WrongNumArgs(interp, 1, objv, "POINT ?N...?");
  20001. return TCL_ERROR;
  20002. }
  20003. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],POINT)) return TCL_ERROR;
  20004. if(objc==3) {
  20005.  
  20006. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[2], &p, &isnew) ) return TCL_ERROR;
  20007. res = Odie_FaceXYZ_Within(p, POINT);
  20008. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[2],p);
  20009. Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
  20010. return TCL_OK;
  20011. } else {
  20012. int i;
  20013. for(i=2;i<objc;i++) {
  20014. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[i], &p, &isnew) ) return TCL_ERROR;
  20015. res = Odie_FaceXYZ_Within(p, POINT);
  20016. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[i],p);
  20017. if(res>=0) {
  20018. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(res));
  20019. return TCL_OK;
  20020. }
  20021. }
  20022. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(-1));
  20023. return TCL_OK;
  20024. }
  20025. }
  20026. /* OO Method SegmentSet segment_info */
  20027. static int OOMethod_SegmentSet_segment_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20028.  
  20029. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20030. int id,i;
  20031. Segment *pSeg;
  20032. static const char *SEGMENT_fields[] = { "id", "virtual", "from", "to", "exported", "id_left", "id_right", "ignore", "facefwd", "faceback", 0 };
  20033. enum SEGMENT_enum { SEGMENT_FIELD_ID, SEGMENT_FIELD_VIRTUAL, SEGMENT_FIELD_FROM, SEGMENT_FIELD_TO, SEGMENT_FIELD_EXPORTED, SEGMENT_FIELD_ID_LEFT, SEGMENT_FIELD_ID_RIGHT, SEGMENT_FIELD_IGNORE, SEGMENT_FIELD_FACEFWD, SEGMENT_FIELD_FACEBACK };
  20034.  
  20035. if(objc<3) {
  20036. Tcl_WrongNumArgs(interp, 2, objv, "ID ?field value...?");
  20037. return TCL_ERROR;
  20038. }
  20039. if(Tcl_GetIntFromObj(interp,objv[2],&id)) return TCL_ERROR;
  20040. pSeg=SegmentSet_FindById(pSet, id);
  20041. if(!pSeg) {
  20042. Tcl_AppendResult(interp, "Segment does not exist",0);
  20043. return TCL_ERROR;
  20044. }
  20045. for(i=3;i<objc;i+=2) {
  20046. Tcl_Obj *field,*value;
  20047. int option;
  20048. if((i+1) == objc) break;
  20049. field=objv[i];
  20050. value=objv[i+1];
  20051. if( Tcl_GetIndexFromObj(interp, field, SEGMENT_fields, "option", 0, &option) ) return TCL_ERROR;
  20052. switch(option) {
  20053. case SEGMENT_FIELD_ID: {
  20054. int temp,h;
  20055. if(Tcl_GetIntFromObj(interp,value,&temp)) return TCL_ERROR;
  20056. if(temp!=pSeg->id && temp>0) {
  20057. if(SegmentSet_FindById(pSet, temp)) {
  20058. Tcl_AppendResult(interp, "Segment ID already exists",0);
  20059. return TCL_ERROR;
  20060. }
  20061. LinkRemove(&pSeg->pHash);
  20062. pSeg->id=temp;
  20063. h = hashInt(pSeg->id);
  20064. LinkInsert(&pSet->hashId[h], &pSeg->pHash);
  20065. }
  20066. break; } case SEGMENT_FIELD_VIRTUAL: {
  20067. int temp;
  20068. if(Tcl_GetBooleanFromObj(interp,value,&temp)) return TCL_ERROR;
  20069. pSeg->isVirtual=temp;
  20070. pSet->modified=1;
  20071. break; } case SEGMENT_FIELD_FROM: { break; } case SEGMENT_FIELD_TO: { break; } case SEGMENT_FIELD_EXPORTED: {
  20072. int temp;
  20073. if(Tcl_GetBooleanFromObj(interp,value,&temp)) return TCL_ERROR;
  20074. pSeg->exported=temp;
  20075. pSet->modified=1;
  20076. break; } case SEGMENT_FIELD_ID_LEFT: {
  20077. int temp;
  20078. if(Tcl_GetIntFromObj(interp,value,&temp)) return TCL_ERROR;
  20079. pSeg->idLC=temp;
  20080. pSet->modified=1;
  20081. break; } case SEGMENT_FIELD_ID_RIGHT: {
  20082. int temp;
  20083. if(Tcl_GetIntFromObj(interp,value,&temp)) return TCL_ERROR;
  20084. pSeg->idRC=temp;
  20085. pSet->modified=1;
  20086. break; } case SEGMENT_FIELD_IGNORE: {
  20087. int temp;
  20088. if(Tcl_GetBooleanFromObj(interp,value,&temp)) return TCL_ERROR;
  20089. pSeg->ignore=temp;
  20090. pSet->modified=1;
  20091. break; } case SEGMENT_FIELD_FACEFWD: { break; } case SEGMENT_FIELD_FACEBACK: { break; } }
  20092. }
  20093.  
  20094. Tcl_SetObjResult(interp, Segment_To_Dict(pSeg));
  20095. return TCL_OK;
  20096. }
  20097. /* OO Method SegmentSet SegmentSet_Init */
  20098. static int OOMethod_SegmentSet_SegmentSet_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20099.  
  20100. SegmentSet *pSet;
  20101. pSet=(SegmentSet *)Odie_Alloc(sizeof(SegmentSet));
  20102. pSet->rXZoom = 100.0;
  20103. pSet->rYZoom = -100.0;
  20104. pSet->grid = Vector_Tolerance*2;
  20105. pSet->grain = pSet->grid*0.5;
  20106. pSet->gridSq = pSet->grid*pSet->grid;
  20107.  
  20108. VectorXY_BBOX_Reset(pSet->bbox_uv);
  20109. VectorXYZ_Copy(pSet->normal,Odie_Up_Direction);
  20110. Odie_Affine_From_Normal(pSet->rotation_inv,pSet->normal);
  20111. Odie_Affine4x4_Inverse(pSet->rotation,pSet->rotation_inv);
  20112. Tcl_ObjectSetMetadata(thisObject, &SegmentSetDataType, (ClientData) pSet);
  20113. return TCL_OK;
  20114. }
  20115. /* OO Method SegmentSet modified */
  20116. static int OOMethod_SegmentSet_modified(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20117.  
  20118. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20119. if (objc==3) {
  20120. int temp;
  20121. /* No matter what, wipe the cache face */
  20122. SegmentSet_ClearFaceEdgeCache(pSet);
  20123. if(Tcl_GetBooleanFromObj(interp,objv[2],&temp)) return TCL_ERROR;
  20124. pSet->modified=temp;
  20125. }
  20126. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(pSet->modified));
  20127. return TCL_OK;
  20128. }
  20129. /* OO Method SegmentSet segment_count */
  20130. static int OOMethod_SegmentSet_segment_count(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20131.  
  20132. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20133. Tcl_SetObjResult(interp, Tcl_NewIntObj(pSet->nSeg));
  20134. return TCL_OK;
  20135. }
  20136. /* OO Method SegmentSet bbox */
  20137. static int OOMethod_SegmentSet_bbox(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20138.  
  20139. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20140. Tcl_Obj *pResult;
  20141.  
  20142. pResult=Tcl_NewObj();
  20143. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSet->bbox_uv[BBOX_X0_IDX]));
  20144. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSet->bbox_uv[BBOX_Y1_IDX]));
  20145. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSet->bbox_uv[BBOX_X1_IDX]));
  20146. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSet->bbox_uv[BBOX_Y0_IDX]));
  20147. Tcl_SetObjResult(interp, pResult);
  20148. return TCL_OK;
  20149. }
  20150. /* OO Method SegmentSet segment_reset */
  20151. static int OOMethod_SegmentSet_segment_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20152.  
  20153. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20154. SegmentSetClear(pSet);
  20155. return TCL_OK;
  20156. }
  20157. /* OO Method SegmentSet segment_add */
  20158. static int OOMethod_SegmentSet_segment_add(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20159.  
  20160. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20161. VectorXYZ A,B;
  20162. int id=-1;
  20163. int lc,rc,virtual=0;
  20164. Segment *pSeg;
  20165.  
  20166. if( objc!=4 && objc!=5 && objc!=8) {
  20167. Tcl_WrongNumArgs(interp, 2, objv, "A B ?ID? ?LC RC VIRTUAL?");
  20168. return TCL_ERROR;
  20169. }
  20170. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],A)) return TCL_ERROR;
  20171. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],B)) return TCL_ERROR;
  20172. VectorXYZ_GridAlign(A,pSet->grid);
  20173. VectorXYZ_GridAlign(B,pSet->grid);
  20174. if(VectorXYZ_SamePoint(A,B)) {
  20175. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(0));
  20176. return TCL_OK;
  20177. }
  20178.  
  20179. if(objc>4) {
  20180. if(Tcl_GetIntFromObj(interp, objv[4], &id) ) return TCL_ERROR;
  20181. }
  20182. if(objc==8) {
  20183. if(Tcl_GetIntFromObj(interp, objv[5], &lc) ) {
  20184. Tcl_ResetResult(interp);
  20185. lc=0;
  20186. }
  20187. if(Tcl_GetIntFromObj(interp, objv[6], &rc) ) {
  20188. Tcl_ResetResult(interp);
  20189. rc=0;
  20190. }
  20191. if(Tcl_GetIntFromObj(interp, objv[7], &virtual) ) {
  20192. Tcl_ResetResult(interp);
  20193. virtual=0;
  20194. }
  20195. }
  20196. pSeg=SegmentSet_Insert_XYZ(pSet,id,A,B);
  20197. if(pSeg) {
  20198. int count=1;
  20199. pSeg->isVirtual=virtual;
  20200. pSeg->idLC=lc;
  20201. pSeg->idRC=rc;
  20202. count+=SegmentSet_Cleanup_Coincident(pSet,pSeg);
  20203. Tcl_SetObjResult(interp,Tcl_NewIntObj(count));
  20204. } else {
  20205. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(0));
  20206. }
  20207. return TCL_OK;
  20208. }
  20209. /* OO Method SegmentSet segment_add_virtual */
  20210. static int OOMethod_SegmentSet_segment_add_virtual(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20211.  
  20212. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20213. int i,j,count=0,type;
  20214. VectorXYZ A,B;
  20215.  
  20216. if( objc<4 ) {
  20217. Tcl_WrongNumArgs(interp, 2, objv, "?type? A B ?C...?");
  20218. return TCL_ERROR;
  20219. }
  20220. if(Tcl_GetIntFromObj(interp,objv[2],&type)) {
  20221. Tcl_ResetResult(interp);
  20222. j=3;
  20223. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],A)) return TCL_ERROR;
  20224. } else {
  20225. j=4;
  20226. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],A)) return TCL_ERROR;
  20227. }
  20228. VectorXYZ_GridAlign(A,pSet->grid);
  20229. count+=SegmentSet_AddVertex(pSet,A);
  20230. for(i=j;i<objc;i++) {
  20231. Segment *pSeg;
  20232. if(Odie_GetVectorXYZFromTclObj(interp,objv[i],B)) return TCL_ERROR;
  20233. VectorXYZ_GridAlign(B,pSet->grid);
  20234. count+=SegmentSet_AddVertex(pSet,B);
  20235. if(VectorXYZ_SamePoint(A,B)) continue;
  20236. pSeg=Segment_FindByLocation(pSet,A,B);
  20237. if(!pSeg) {
  20238. pSeg=SegmentSet_Insert_XYZ(pSet,-1,A,B);
  20239. if(pSeg) {
  20240. count++;
  20241. pSeg->isVirtual=1;
  20242. count+=SegmentSet_Cleanup_Coincident(pSet,pSeg);
  20243. }
  20244. }
  20245. VectorXYZ_Copy(A,B);
  20246. }
  20247. Tcl_SetObjResult(interp,Tcl_NewIntObj(count));
  20248. return TCL_OK;
  20249. }
  20250. /* OO Method SegmentSet polygon_add */
  20251. static int OOMethod_SegmentSet_polygon_add(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20252.  
  20253. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20254. int i;
  20255. int comptid=1;
  20256. if( objc<3 ){
  20257. Tcl_WrongNumArgs(interp, 2, objv, "ID POLYGON ?POLYGON...?");
  20258. return TCL_ERROR;
  20259. }
  20260. if(Tcl_GetIntFromObj(interp, objv[2], &comptid) ) return TCL_ERROR;
  20261. for(i=3;i<objc;i++) {
  20262. Odie_FaceXYZ *p;
  20263. int isnew;
  20264. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[i], &p, &isnew) ) return TCL_ERROR;
  20265. if(Segset_Insert_Polygon(pSet,p,comptid)) {
  20266.  
  20267. }
  20268. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[i],p);
  20269. }
  20270. return TCL_OK;
  20271. }
  20272. /* OO Method SegmentSet vertex_add */
  20273. static int OOMethod_SegmentSet_vertex_add(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20274.  
  20275. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20276. int i;
  20277. VectorXYZ A;
  20278. for(i=2;i<objc;i++) {
  20279. if(Odie_GetVectorXYZFromTclObj(interp,objv[i],A)) continue;
  20280. SegmentSet_AddVertex(pSet,A);
  20281. }
  20282. return TCL_OK;
  20283. }
  20284. /* OO Method SegmentSet segment_delete */
  20285. static int OOMethod_SegmentSet_segment_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20286.  
  20287. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20288. int i;
  20289. VectorXYZ A,B;
  20290. if( objc<4 ){
  20291. Tcl_WrongNumArgs(interp, 2, objv, "A B ?C?...");
  20292. return TCL_ERROR;
  20293. }
  20294. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],A)) return TCL_ERROR;
  20295. for(i=3;i<objc;i++) {
  20296. Segment *found;
  20297. if(Odie_GetVectorXYZFromTclObj(interp,objv[i],B)) return TCL_ERROR;
  20298. if(VectorXYZ_SamePoint(A,B)) continue;
  20299. found=Segment_FindByLocation(pSet,A,B);
  20300. if(found) SegmentSetRemove(pSet,found);
  20301. VectorXYZ_Copy(A,B);
  20302. }
  20303. return TCL_OK;
  20304. }
  20305. /* OO Method SegmentSet delete */
  20306. static int OOMethod_SegmentSet_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20307.  
  20308. SegmentSet *p = GETSEGMENTSET(thisObject);
  20309. int id;
  20310. Segment *pSeg;
  20311. if( objc!=3 ){
  20312. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  20313. return TCL_ERROR;
  20314. }
  20315. if( p->busy ){
  20316. Tcl_AppendResult(interp, "cannot \"delete\" from within a \"foreach\"",0);
  20317. return TCL_ERROR;
  20318. }
  20319. if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR;
  20320. if( (pSeg = SegmentSet_FindById(p, id))==0 ){
  20321. Tcl_AppendResult(interp, "segment ",
  20322. Tcl_GetStringFromObj(objv[2],0), " does not exist", 0);
  20323. return TCL_ERROR;
  20324. }
  20325. SegmentSetRemove(p,pSeg);
  20326. return TCL_OK;
  20327. }
  20328. /* OO Method SegmentSet cleanup */
  20329. static int OOMethod_SegmentSet_cleanup(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20330.  
  20331. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20332. int count=0;
  20333. count+=SegmentSet_Cleanup(pSet,0);
  20334. Tcl_SetObjResult(interp,Tcl_NewIntObj(count));
  20335. return TCL_OK;
  20336. }
  20337. /* OO Method SegmentSet cleanup_looseend */
  20338. static int OOMethod_SegmentSet_cleanup_looseend(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20339.  
  20340. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20341. int count=0;
  20342. count+=SegmentSet_Cleanup(pSet,1);
  20343. Tcl_SetObjResult(interp,Tcl_NewIntObj(count));
  20344. return TCL_OK;
  20345. }
  20346. /* OO Method SegmentSet edge_connection */
  20347. static int OOMethod_SegmentSet_edge_connection(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20348.  
  20349. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20350. VectorXYZ A,RESULT;
  20351. int comptid=0;
  20352. if( objc!=3 && objc!=4){
  20353. Tcl_WrongNumArgs(interp, 2, objv, "A ?comptid?");
  20354. return TCL_ERROR;
  20355. }
  20356. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],A)) return TCL_ERROR;
  20357. if(objc==4) {
  20358. if(Tcl_GetIntFromObj(interp,objv[3],&comptid)) return TCL_ERROR;
  20359. }
  20360. if(SegmentSet_Edge_Connection(pSet,A,comptid,RESULT)) {
  20361. Tcl_ResetResult(interp);
  20362. } else {
  20363. Tcl_SetObjResult(interp, VectorXYZ_To_TclObj(RESULT));
  20364. }
  20365. return TCL_OK;
  20366. }
  20367. /* OO Method SegmentSet check_intersecting */
  20368. static int OOMethod_SegmentSet_check_intersecting(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20369.  
  20370. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20371. Link *pLoop,*pNext;
  20372. Tcl_Obj *pResult;
  20373.  
  20374. pResult=Tcl_NewObj();
  20375. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  20376. Link *qLoop,*qNext;
  20377. Segment *pAB;
  20378. pAB = pLoop->pLinkNode;
  20379. pNext = pLoop->pNext;
  20380. for(qLoop=pSet->pAll; qLoop; qLoop=qNext){
  20381. Tcl_Obj *element;
  20382. int c;
  20383. double mua,mub;
  20384. VectorXYZ I1,I2;
  20385. Segment *pCD;
  20386. pCD = qLoop->pLinkNode;
  20387. qNext = qLoop->pNext;
  20388. /* Evaluate lower to higher */
  20389. if(pCD->id==pAB->id) continue;
  20390. if(!VectorXYZ_BBOX_Overlap_TwoVectors(pAB->from,pAB->to,pCD->from,pCD->to)) continue;
  20391. c=VectorXYZ_LineLineIntersect(pAB->from, pAB->to,pCD->from,pCD->to,I1,I2,&mua,&mub);
  20392. if(c==0) continue;
  20393. if(c<=0) continue;
  20394. if(mua>=1.0 || mua<=0.0) continue;
  20395. if(mub>=1.0 || mub<=0.0) continue;
  20396. element=Tcl_NewObj();
  20397. Odie_DictObjPut(interp,element,"result_type:",Odie_LiteralStringObj("intercept"));
  20398. Odie_DictObjPut(interp,element,"result_code:",Tcl_NewIntObj(c));
  20399. Odie_DictObjPut(interp,element,"segment",Segment_To_Dict(pAB));
  20400. Odie_DictObjPut(interp,element,"segment_other",Segment_To_Dict(pCD));
  20401. Odie_DictObjPut(interp,element,"mua:",Tcl_NewDoubleObj(mua));
  20402. Odie_DictObjPut(interp,element,"mub:",Tcl_NewDoubleObj(mub));
  20403. Odie_DictObjPut(interp,element,"intercept1:",VectorXYZ_To_TclObj(I1));
  20404. Odie_DictObjPut(interp,element,"intercept2:",VectorXYZ_To_TclObj(I2));
  20405. Tcl_ListObjAppendElement(interp,pResult,element);
  20406. }
  20407. }
  20408. Tcl_SetObjResult(interp, pResult);
  20409. return TCL_OK;
  20410. }
  20411. /* OO Method SegmentSet check_coincident */
  20412. static int OOMethod_SegmentSet_check_coincident(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20413.  
  20414. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20415. Link *pLoop,*pNext;
  20416. Tcl_Obj *pResult;
  20417.  
  20418. pResult=Tcl_NewObj();
  20419. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  20420. Link *qLoop,*qNext;
  20421. Segment *pAB;
  20422. pAB = pLoop->pLinkNode;
  20423. pNext = pLoop->pNext;
  20424. for(qLoop=pSet->pAll; qLoop; qLoop=qNext){
  20425. Tcl_Obj *element;
  20426. int c;
  20427. Segment *pCD;
  20428. VectorXYZ ICEPT1,ICEPT2;
  20429. pCD = qLoop->pLinkNode;
  20430. qNext = qLoop->pNext;
  20431. /* Evaluate lower to higher */
  20432. if(pCD->id <= pAB->id) continue;
  20433. c=VectorXYZ_LineLineCoincident(pAB->from,pAB->to,pCD->from,pCD->to,ICEPT1,ICEPT2);
  20434. if(c>0) {
  20435. element=Tcl_NewObj();
  20436. Odie_DictObjPut(interp,element,"result_type:",Odie_LiteralStringObj("coincident"));
  20437. Odie_DictObjPut(interp,element,"result_code:",Tcl_NewIntObj(c));
  20438. Odie_DictObjPut(interp,element,"intercept1:",VectorXYZ_To_TclObj(ICEPT1));
  20439. Odie_DictObjPut(interp,element,"intercept2:",VectorXYZ_To_TclObj(ICEPT2));
  20440. Tcl_ListObjAppendElement(interp,pResult,element);
  20441. }
  20442. }
  20443. }
  20444. Tcl_SetObjResult(interp, pResult);
  20445. return TCL_OK;
  20446. }
  20447. /* OO Method SegmentSet segment_linelineintersect */
  20448. static int OOMethod_SegmentSet_segment_linelineintersect(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20449.  
  20450. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20451. VectorXYZ A,B;
  20452. Link *pLoop,*pNext;
  20453. Segment *pAB;
  20454. Tcl_Obj *pResult;
  20455.  
  20456. if( objc!=4 ){
  20457. Tcl_WrongNumArgs(interp, 2, objv, "A B");
  20458. return TCL_ERROR;
  20459. }
  20460. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],A)) return TCL_ERROR;
  20461. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],B)) return TCL_ERROR;
  20462. pResult=Tcl_NewObj();
  20463. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  20464. Tcl_Obj *element;
  20465. int c;
  20466. double mua,mub;
  20467. VectorXYZ I1,I2;
  20468. pAB = pLoop->pLinkNode;
  20469. pNext = pLoop->pNext;
  20470. if(!VectorXYZ_BBOX_Overlap_TwoVectors(A,B,pAB->from,pAB->to)) continue;
  20471. c=VectorXYZ_LineLineIntersect(A, B, pAB->from, pAB->to,I1,I2,&mua,&mub);
  20472. if(c==0) continue;
  20473. if(c<=0) continue;
  20474. if(mua>=1.0 || mua<=0.0) continue;
  20475. if(mub>=1.0 || mub<=0.0) continue;
  20476. element=Tcl_NewObj();
  20477. Odie_DictObjPut(interp,element,"result_type:",Odie_LiteralStringObj("intercept"));
  20478. Odie_DictObjPut(interp,element,"result_code:",Tcl_NewIntObj(c));
  20479. Odie_DictObjPut(interp,element,"segment",Segment_To_Dict(pAB));
  20480. Odie_DictObjPut(interp,element,"mua:",Tcl_NewDoubleObj(mua));
  20481. Odie_DictObjPut(interp,element,"mub:",Tcl_NewDoubleObj(mub));
  20482. Odie_DictObjPut(interp,element,"intercept1:",VectorXYZ_To_TclObj(I1));
  20483. Odie_DictObjPut(interp,element,"intercept2:",VectorXYZ_To_TclObj(I2));
  20484. Tcl_ListObjAppendElement(interp,pResult,element);
  20485. }
  20486. Tcl_SetObjResult(interp, pResult);
  20487. return TCL_OK;
  20488. }
  20489. /* OO Method SegmentSet segment_coincident */
  20490. static int OOMethod_SegmentSet_segment_coincident(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20491.  
  20492. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20493. VectorXYZ A,B;
  20494. Link *pLoop,*pNext;
  20495. Segment *pAB;
  20496. Tcl_Obj *pResult;
  20497.  
  20498. if( objc!=4 ){
  20499. Tcl_WrongNumArgs(interp, 2, objv, "A B");
  20500. return TCL_ERROR;
  20501. }
  20502. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],A)) return TCL_ERROR;
  20503. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],B)) return TCL_ERROR;
  20504. pResult=Tcl_NewObj();
  20505. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  20506. int c;
  20507. VectorXYZ ICEPT1,ICEPT2;
  20508. pAB = pLoop->pLinkNode;
  20509. pNext = pLoop->pNext;
  20510. c=VectorXYZ_LineLineCoincident(A,B,pAB->from,pAB->to,ICEPT1,ICEPT2);
  20511. if(c>0) {
  20512. Tcl_Obj *element=Tcl_NewObj();
  20513. Odie_DictObjPut(interp,element,"result_type:",Odie_LiteralStringObj("coincident"));
  20514. Odie_DictObjPut(interp,element,"result_code:",Tcl_NewIntObj(c));
  20515. Odie_DictObjPut(interp,element,"segment",Segment_To_Dict(pAB));
  20516. Odie_DictObjPut(interp,element,"intersect1:",VectorXYZ_To_TclObj(ICEPT1));
  20517. Odie_DictObjPut(interp,element,"intersect2:",VectorXYZ_To_TclObj(ICEPT2));
  20518. Tcl_ListObjAppendElement(interp,pResult,element);
  20519. }
  20520. }
  20521. Tcl_SetObjResult(interp, pResult);
  20522. return TCL_OK;
  20523. }
  20524. /* OO Method SegmentSet segment_find */
  20525. static int OOMethod_SegmentSet_segment_find(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20526.  
  20527. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20528. int i;
  20529. VectorXYZ A;
  20530. Link *pLoop,*pNext;
  20531. Tcl_Obj *pResult;
  20532. if( objc<3 ){
  20533. Tcl_WrongNumArgs(interp, 2, objv, "A ?B?...");
  20534. return TCL_ERROR;
  20535. }
  20536. pResult=Tcl_NewObj();
  20537. for(i=2;i<objc;i++) {
  20538. Segment *pAB;
  20539. if(Odie_GetVectorXYZFromTclObj(interp,objv[i],A)) return TCL_ERROR;
  20540. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  20541. pAB = pLoop->pLinkNode;
  20542. pNext = pLoop->pNext;
  20543. if( VectorXYZ_SamePoint(pAB->from,A) || VectorXYZ_SamePoint(pAB->to,A) ) {
  20544. Tcl_ListObjAppendElement(0, pResult, Segment_To_Dict(pAB));
  20545. }
  20546. }
  20547. }
  20548. Tcl_SetObjResult(interp, pResult);
  20549. return TCL_OK;
  20550. }
  20551. /* OO Method SegmentSet vertex_delete */
  20552. static int OOMethod_SegmentSet_vertex_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20553.  
  20554. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20555. int i;
  20556. VectorXY A;
  20557. Link *pLoop,*pNext;
  20558. if( objc<3 ){
  20559. Tcl_WrongNumArgs(interp, 2, objv, "A ?B?...");
  20560. return TCL_ERROR;
  20561. }
  20562. for(i=2;i<objc;i++) {
  20563. Segment *pAB;
  20564. if(Odie_GetVectorXYFromTclObj(interp,objv[i],A)) return TCL_ERROR;
  20565. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  20566. pAB = pLoop->pLinkNode;
  20567. pNext = pLoop->pNext;
  20568. if( VectorXYZ_SamePoint(pAB->from,A) || VectorXYZ_SamePoint(pAB->to,A) ) {
  20569. SegmentSetRemove(pSet, pAB);
  20570. }
  20571. }
  20572. }
  20573. return TCL_OK;
  20574. }
  20575. /* OO Method SegmentSet segment_next */
  20576. static int OOMethod_SegmentSet_segment_next(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20577.  
  20578. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20579. VectorXYZ A,B;
  20580. Segment *pAB,*pBC;
  20581. int pBCBack,pBCBend;
  20582. double pBCAngle;
  20583. Tcl_Obj *pResult;
  20584. int backwards;
  20585. if( objc!=4 ){
  20586. Tcl_WrongNumArgs(interp, 2, objv, "A B");
  20587. return TCL_ERROR;
  20588. }
  20589. //if(SegmentSetCheck(interp,pSet)) return TCL_ERROR;
  20590. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],A)) return TCL_ERROR;
  20591. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],B)) return TCL_ERROR;
  20592. pResult=Tcl_NewObj();
  20593.  
  20594. pAB=Segment_FindByLocation(pSet,A,B);
  20595. if(!pAB) {
  20596. Tcl_ResetResult(interp);
  20597. return TCL_OK;
  20598. }
  20599. backwards=VectorXYZ_SamePoint(B,pAB->from);
  20600. SegmentSetNext(pSet, pAB, backwards,&pBC,&pBCBack,&pBCBend,&pBCAngle);
  20601. if(!pBC) {
  20602. Tcl_ResetResult(interp);
  20603. return TCL_OK;
  20604. }
  20605. if(pBCBack) {
  20606. Tcl_SetObjResult(interp,VectorXYZ_To_TclObj(pBC->from));
  20607. } else {
  20608. Tcl_SetObjResult(interp, VectorXYZ_To_TclObj(pBC->to));
  20609. }
  20610. return TCL_OK;
  20611. }
  20612. /* OO Method SegmentSet check_oblique */
  20613. static int OOMethod_SegmentSet_check_oblique(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20614.  
  20615. /*
  20616. ** tclmethod: WALLSET check_oblique
  20617. ** title: Return a list of points and comptids that form oblique angles
  20618. */
  20619. SegmentSet *pSet = GETSEGMENTSET(thisObject);
  20620. Tcl_Obj *pResult = Tcl_NewObj();
  20621. int back;
  20622. Link *pAll;
  20623. static double critical=2.0*M_PI/8.0;
  20624.  
  20625. /*
  20626. ** Fill out the skip fields for counter-clockwise faces
  20627. ** and degenerate edges
  20628. */
  20629. for(pAll=pSet->pAll; pAll; pAll=pAll->pNext){
  20630. Segment *pSeg=pAll->pLinkNode;
  20631. pSeg->ignore=0;
  20632. pSeg->test=0;
  20633. pSeg->isBoundary=0;
  20634. pSeg->not_oblique_fwd=0;
  20635. pSeg->not_oblique_back=0;
  20636. }
  20637. for(back=0;back<2;back++) {
  20638. for(pAll=pSet->pAll; pAll; pAll=pAll->pNext){
  20639. int match=0;
  20640. Segment *pAB,*pBC,*pCD,*pDE,*pEF,*pFG;
  20641. VectorXYZ ICEPT;
  20642. int pBCBack,pBCBend,pCDBack,pCDBend,pDEBack,pDEBend,pEFBack,pEFBend,pFGBack,pFGBend;
  20643. double pBCAngle,pCDAngle,pDEAngle,pEFAngle,pFGAngle;
  20644. VectorXYZ pStart,pBCPoint,pCDPoint,pDEPoint,pEFPoint,pFGPoint;
  20645. pAB=pAll->pLinkNode;
  20646. if(SegmentSetNext(pSet, pAB, back,&pBC,&pBCBack,&pBCBend,&pBCAngle)) continue;
  20647. if(pBC==pAB) {
  20648. continue;
  20649. }
  20650. if(pBCBend<0) continue;
  20651. if(SegmentSetNext(pSet, pBC, pBCBack,&pCD,&pCDBack,&pCDBend,&pCDAngle)) continue;
  20652. if(pCD==pAB) {
  20653. continue;
  20654. }
  20655. if(pCDBend<0) continue;
  20656. if(SegmentSetNext(pSet, pCD, pCDBack,&pDE,&pDEBack,&pDEBend,&pDEAngle)) continue;
  20657. if(pDE==pAB) {
  20658. continue;
  20659. }
  20660. if(pDEBend>=0) {
  20661. if(pDEBack) {
  20662. pDE->not_oblique_back=1;
  20663. } else {
  20664. pDE->not_oblique_fwd=1;
  20665. }
  20666. continue;
  20667. }
  20668. if(pDEBack) {
  20669. if(pDE->not_oblique_back) continue;
  20670. } else {
  20671. if(pDE->not_oblique_fwd) continue;
  20672. }
  20673. /* Don't do bends on small deflections (<10 deg) */
  20674. if(fabs(pDEAngle)<critical) continue;
  20675. if(SegmentSetNext(pSet, pDE, pDEBack,&pEF,&pEFBack,&pEFBend,&pEFAngle)) continue;
  20676. if(SegmentSetNext(pSet, pEF, pEFBack,&pFG,&pFGBack,&pFGBend,&pFGAngle)) continue;
  20677. if(back) {
  20678. VectorXYZ_Copy(pStart,pAB->from);
  20679. } else {
  20680. VectorXYZ_Copy(pStart,pAB->to);
  20681. }
  20682. if(pBCBack) {
  20683. VectorXYZ_Copy(pBCPoint,pBC->from);
  20684. } else {
  20685. VectorXYZ_Copy(pBCPoint,pBC->to);
  20686. }
  20687. if(pCDBack) {
  20688. VectorXYZ_Copy(pCDPoint,pCD->from);
  20689. } else {
  20690. VectorXYZ_Copy(pCDPoint,pCD->to);
  20691. }
  20692. if(pDEBack) {
  20693. VectorXYZ_Copy(pDEPoint,pDE->to);
  20694. } else {
  20695. VectorXYZ_Copy(pDEPoint,pDE->from);
  20696. }
  20697. if(pEFBack) {
  20698. VectorXYZ_Copy(pEFPoint,pEF->from);
  20699. } else {
  20700. VectorXYZ_Copy(pEFPoint,pEF->to);
  20701. }
  20702. if(pFGBack) {
  20703. VectorXYZ_Copy(pFGPoint,pFG->from);
  20704. } else {
  20705. VectorXYZ_Copy(pFGPoint,pFG->to);
  20706. }
  20707. match=0;
  20708. if(pDE->test) continue;
  20709. /*
  20710. pAB->ignore=1;
  20711. pBC->ignore=1;
  20712. pCD->ignore=1;
  20713. pDE->ignore=1;
  20714. pEF->ignore=1;
  20715. pFG->ignore=1;
  20716. */
  20717. /* Win lose or fail, mark this segment so we don't try it again */
  20718. if(pDEBack) {
  20719. pDE->not_oblique_back=1;
  20720. } else {
  20721. pDE->not_oblique_fwd=1;
  20722. }
  20723. if(!SegmentSet_Convex_Connection(pSet,pDE,pDEBack,ICEPT)) {
  20724. pDE->test=1;
  20725. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(pDEPoint));
  20726. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(ICEPT));
  20727. }
  20728. pAB->ignore=0;
  20729. pCD->ignore=0;
  20730. pDE->ignore=0;
  20731. pEF->ignore=0;
  20732. pFG->ignore=0;
  20733. }
  20734. }
  20735. #ifdef ODIE_DEBUG
  20736. fflush(stdout);
  20737. #endif
  20738. Tcl_SetObjResult(interp, pResult);
  20739. return TCL_OK;
  20740. }
  20741. /* OO Method SegmentSet check_looseends */
  20742. static int OOMethod_SegmentSet_check_looseends(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20743.  
  20744. SegmentSet *p = GETSEGMENTSET(thisObject);
  20745. Segment *pSeg;
  20746. Link *pAll, *pList;
  20747. Tcl_Obj *pTrue=ODIE_INT_ONE();
  20748. Tcl_Obj *pFalse=ODIE_INT_ZERO();
  20749. Tcl_Obj *pRes = Tcl_NewObj();
  20750. for(pAll=p->pAll; pAll; pAll=pAll->pNext){
  20751. Tcl_Obj *element,*subelement;
  20752. int nSeg;
  20753. pSeg = pAll->pLinkNode;
  20754. pList = SegmentSet_Segments_AtVertex(p, pSeg->from,&nSeg);
  20755. if( nSeg == 1 ){
  20756. element=Tcl_NewObj();
  20757. Odie_DictObjPut(interp,element,"result_type:",Odie_LiteralStringObj("looseend"));
  20758. Odie_DictObjPut(interp,element,"result_code:",pFalse);
  20759. Odie_DictObjPut(interp,element,"id:",Tcl_NewIntObj(pSeg->id));
  20760. Odie_DictObjPut(interp,element,"location:",VectorXYZ_To_TclObj(pSeg->from));
  20761. Odie_DictObjPut(interp,element,"side:",pFalse);
  20762. subelement=Tcl_NewObj();
  20763. Tcl_ListObjAppendElement(0, subelement, Tcl_NewDoubleObj(pSeg->from[X_IDX]/p->rXZoom));
  20764. Tcl_ListObjAppendElement(0, subelement, Tcl_NewDoubleObj(pSeg->from[Y_IDX]/p->rYZoom));
  20765. Odie_DictObjPut(interp,element,"canvas_xy:",subelement);
  20766. Odie_DictObjPut(interp,element,"segment",Segment_To_Dict(pSeg));
  20767. Tcl_ListObjAppendElement(0, pRes, element);
  20768. }
  20769. pList = SegmentSet_Segments_AtVertex(p, pSeg->to,&nSeg);
  20770. if( nSeg ){
  20771. element=Tcl_NewObj();
  20772. Odie_DictObjPut(interp,element,"result_type:",Odie_LiteralStringObj("looseend"));
  20773. Odie_DictObjPut(interp,element,"result_code:",pTrue);
  20774. Odie_DictObjPut(interp,element,"location:",VectorXYZ_To_TclObj(pSeg->to));
  20775. Odie_DictObjPut(interp,element,"side:",pTrue);
  20776. subelement=Tcl_NewObj();
  20777. Tcl_ListObjAppendElement(0, subelement, Tcl_NewDoubleObj(pSeg->to[X_IDX]/p->rXZoom));
  20778. Tcl_ListObjAppendElement(0, subelement, Tcl_NewDoubleObj(pSeg->to[Y_IDX]/p->rYZoom));
  20779. Odie_DictObjPut(interp,element,"canvas_xy:",subelement);
  20780. Odie_DictObjPut(interp,element,"segment",Segment_To_Dict(pSeg));
  20781. Tcl_ListObjAppendElement(0, pRes, element);
  20782. }
  20783. }
  20784. Tcl_SetObjResult(interp, pRes);
  20785. return TCL_OK;
  20786. }
  20787. /* OO Method SegmentSet fix_looseends */
  20788. static int OOMethod_SegmentSet_fix_looseends(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20789.  
  20790. SegmentSet *pSet = GETSEGMENTSET(thisObject);
  20791. Segment *pSeg;
  20792. Link *pAll;
  20793. Tcl_Obj *pRes = Tcl_NewObj();
  20794. for(pAll=pSet->pAll; pAll; pAll=pAll->pNext){
  20795. int nSeg;
  20796. Link *pList;
  20797. pSeg = pAll->pLinkNode;
  20798. pList = SegmentSet_Segments_AtVertex(pSet, pSeg->from,&nSeg);
  20799. if( nSeg <= 1 ){
  20800. VectorXYZ ICEPT;
  20801. int comptid=pSeg->idLC;
  20802. if(!SegmentSet_Edge_Connection(pSet,pSeg->from,comptid,ICEPT)) {
  20803. Tcl_ListObjAppendElement(0, pRes, VectorXYZ_To_TclObj(pSeg->from));
  20804. Tcl_ListObjAppendElement(interp, pRes, VectorXYZ_To_TclObj(ICEPT));
  20805. }
  20806. }
  20807. pList = SegmentSet_Segments_AtVertex(pSet, pSeg->to,&nSeg);
  20808. if( nSeg <= 1 ){
  20809. VectorXYZ ICEPT;
  20810. int comptid=pSeg->idRC;
  20811. if(!SegmentSet_Edge_Connection(pSet,pSeg->to,comptid,ICEPT)) {
  20812. Tcl_ListObjAppendElement(0, pRes, VectorXYZ_To_TclObj(pSeg->to));
  20813. Tcl_ListObjAppendElement(interp, pRes, VectorXYZ_To_TclObj(ICEPT));
  20814. }
  20815. }
  20816. }
  20817. Tcl_SetObjResult(interp, pRes);
  20818. return TCL_OK;
  20819. }
  20820. /* OO Method SegmentSet grid */
  20821. static int OOMethod_SegmentSet_grid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20822.  
  20823. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20824. if(objc!=2 && objc!=3) {
  20825. Tcl_WrongNumArgs(interp, 2, objv, "?NEWVALUE?");
  20826. return TCL_ERROR;
  20827. }
  20828. if(objc==3) {
  20829. double temp;
  20830. Tcl_GetDoubleFromObj(interp,objv[2],&temp);
  20831. pSet->grid=temp;
  20832. pSet->gridSq=temp*temp;
  20833. pSet->grain=temp*0.5;
  20834. }
  20835. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(pSet->grid));
  20836. return TCL_OK;
  20837. }
  20838. /* OO Method SegmentSet segment_list */
  20839. static int OOMethod_SegmentSet_segment_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20840.  
  20841. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20842. Tcl_Obj *pResult;
  20843. Link *pLoop,*pNext;
  20844.  
  20845. if( objc!=2 ){
  20846. Tcl_WrongNumArgs(interp, 2, objv, "");
  20847. return TCL_ERROR;
  20848. }
  20849. pResult=Tcl_NewObj();
  20850. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  20851. Segment *pAB;
  20852. pAB = pLoop->pLinkNode;
  20853. pNext=pLoop->pNext;
  20854. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pAB->id));
  20855. Tcl_ListObjAppendElement(0, pResult, Segment_To_Dict(pAB));
  20856. }
  20857. Tcl_SetObjResult(interp, pResult);
  20858. return TCL_OK;
  20859. }
  20860. /* OO Method SegmentSet segment_coords */
  20861. static int OOMethod_SegmentSet_segment_coords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20862.  
  20863. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20864. Tcl_Obj *pResult;
  20865. Link *pLoop,*pNext;
  20866.  
  20867. if( objc!=2 ){
  20868. Tcl_WrongNumArgs(interp, 2, objv, "");
  20869. return TCL_ERROR;
  20870. }
  20871. pResult=Tcl_NewObj();
  20872. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  20873. Segment *pSeg;
  20874. pSeg = pLoop->pLinkNode;
  20875. pNext=pLoop->pNext;
  20876. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(pSeg->from));
  20877. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(pSeg->to));
  20878. }
  20879. Tcl_SetObjResult(interp, pResult);
  20880. return TCL_OK;
  20881. }
  20882. /* OO Method SegmentSet segment_uvcoords */
  20883. static int OOMethod_SegmentSet_segment_uvcoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20884.  
  20885. SegmentSet *pSet=GETSEGMENTSET(thisObject);
  20886. Tcl_Obj *pResult;
  20887. Link *pLoop,*pNext;
  20888.  
  20889. if( objc!=2 ){
  20890. Tcl_WrongNumArgs(interp, 2, objv, "");
  20891. return TCL_ERROR;
  20892. }
  20893. pResult=Tcl_NewObj();
  20894. for(pLoop=pSet->pAll; pLoop; pLoop=pNext){
  20895. VectorXYZ uvfrom,uvto;
  20896. Segment *pSeg;
  20897. pSeg = pLoop->pLinkNode;
  20898. pNext=pLoop->pNext;
  20899. VectorXYZ_MatrixMultiply(uvfrom,pSeg->from,pSet->rotation);
  20900. VectorXYZ_MatrixMultiply(uvto,pSeg->to,pSet->rotation);
  20901. Tcl_ListObjAppendElement(0, pResult, VectorXY_To_TclObj(uvfrom));
  20902. Tcl_ListObjAppendElement(0, pResult, VectorXY_To_TclObj(uvto));
  20903. }
  20904. Tcl_SetObjResult(interp, pResult);
  20905. return TCL_OK;
  20906. }
  20907. /* OO Method SegmentSet selfcheck */
  20908. static int OOMethod_SegmentSet_selfcheck(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20909.  
  20910. SegmentSet *p = GETSEGMENTSET(thisObject);
  20911. return SegmentSet_SelfCheck(interp, p);
  20912. }
  20913. /* OO Method SegmentSet uv_transform */
  20914. static int OOMethod_SegmentSet_uv_transform(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20915.  
  20916. VectorXYZ normal,translation;
  20917. SegmentSet *pSet = GETSEGMENTSET(thisObject);
  20918. int i,option;
  20919. if( objc<3){
  20920. Tcl_WrongNumArgs(interp, 2, objv, "?normal NORMAL? ?rotation AFFINE4x4? ?translate XYZ?");
  20921. return TCL_ERROR;
  20922. }
  20923. static const char *TRANSFORM_opts[] = { "affine", "normal", "polygon", "translate", 0 };
  20924. enum TRANSFORM_enum { TRANSFORM_AFFINE, TRANSFORM_NORMAL, TRANSFORM_POLYGON, TRANSFORM_TRANSLATE };
  20925. for(i=2;i<objc;i+=2) {
  20926. if( Tcl_GetIndexFromObj(interp, objv[i], TRANSFORM_opts, "option", 0, &option) ) return TCL_ERROR;
  20927. switch(option) {
  20928. case TRANSFORM_AFFINE: {
  20929.  
  20930. Odie_MatrixObj *A;
  20931. if(i>=objc) return TCL_ERROR;
  20932. if(Odie_GetMatrixFromTclObj(interp,objv[i+1],MATFORM_affine,&A)) return TCL_ERROR;
  20933. Odie_Affine4x4_Copy(pSet->rotation,A->matrix);
  20934. Odie_Affine4x4_Inverse(pSet->rotation_inv,pSet->rotation);
  20935. return TCL_OK;
  20936.  
  20937. break;
  20938. }
  20939. case TRANSFORM_NORMAL: {
  20940.  
  20941. if(i>=objc) return TCL_ERROR;
  20942. if(Odie_GetVectorXYZFromTclObj(interp,objv[i+1],normal)) return TCL_ERROR;
  20943. VectorXYZ_Copy(pSet->normal,normal);
  20944.  
  20945. break;
  20946. }
  20947. case TRANSFORM_POLYGON: {
  20948.  
  20949. Odie_FaceXYZ *p;
  20950. int isnew;
  20951. if( Odie_FaceXYZ_GetFromTclObj(interp, objv[i+1], &p, &isnew) ) return TCL_ERROR;
  20952. VectorXYZ_Copy(pSet->normal,p->normal);
  20953. VectorXYZ_Copy(pSet->center,p->center);
  20954. Odie_Affine4x4_Copy(pSet->rotation,p->rotation);
  20955. Odie_Affine4x4_Copy(pSet->rotation_inv,p->rotation_inv);
  20956. if(isnew) Odie_FaceXYZ_ShimmerOrFree_TclObj(objv[i],p);
  20957. return TCL_OK;
  20958.  
  20959. break;
  20960. }
  20961. case TRANSFORM_TRANSLATE: {
  20962.  
  20963. if(i>=objc) return TCL_ERROR;
  20964. if(Odie_GetVectorXYZFromTclObj(interp,objv[i+1],translation)) return TCL_ERROR;
  20965. VectorXYZ_Copy(pSet->center,translation);
  20966.  
  20967. break;
  20968. }
  20969. } }
  20970. AFFINE rotation_matrix,translation_matrix;
  20971. Odie_Affine_From_Normal(rotation_matrix,pSet->normal);
  20972. Odie_Affine4x4_Translation(translation_matrix,pSet->center);
  20973. Odie_Affine4x4_Multiply(pSet->rotation_inv,translation_matrix,rotation_matrix);
  20974. Odie_Affine4x4_Inverse(pSet->rotation,pSet->rotation_inv);
  20975. return TCL_OK;
  20976. }
  20977. /* OO Method SegmentSet polygons_xyz */
  20978. static int OOMethod_SegmentSet_polygons_xyz(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  20979.  
  20980. /*
  20981. ** tclmethod: WALLSET polygon_list
  20982. ** title: Return the set of polygons define by segments
  20983. **
  20984. ** The closure is a path of walls going clockwise from the wall given.
  20985. ** The return value is a list consisting of wall IDs alternating with
  20986. ** keywords "left" or "right" indicating which side of the wall applies.
  20987. ** If the CHECKPRIMARY flag is true and the WALLID/BACKWARDS is not the
  20988. ** primary wall id for the closure, then return an empty string. The
  20989. ** primary wall id is the wall id with the lowest id number, or if
  20990. ** two walls in the closure have the same id, then the one that goes
  20991. ** on the right side of the wall.
  20992. */
  20993. SegmentSet *pSet = GETSEGMENTSET(thisObject);
  20994. Tcl_Obj *pResult = Tcl_NewObj();
  20995. int i;
  20996. SegmentSet_BuildFaceEdgeCache(pSet);
  20997. for(i=0;i<(pSet->nSeg*2);i++) {
  20998. FaceBoundary *pStart,*pThis;
  20999. Odie_FaceXYZ *pPolyOut;
  21000. int nVertex=0;
  21001. int j,invalid=0,inside_edge=0,outside_edge=0;
  21002. if(pSet->aBoundary[i].faceid!=pSet->aBoundary[i].id) continue;
  21003. if(pSet->aBoundary[i].facebend<0 && !pSet->aBoundary[i].inside_edge) continue;
  21004. if(pSet->aBoundary[i].nSeg<3) continue;
  21005. pStart=pThis=&pSet->aBoundary[i];
  21006. nVertex=pStart->nSeg;
  21007. pPolyOut=Odie_FaceXYZ_Create(nVertex+1);
  21008. pPolyOut->nVertex=nVertex;
  21009. for(pThis=pStart,j=0;j<nVertex;pThis=pThis->pNext,j++) {
  21010. Segment *pSeg;
  21011. if(!pThis) {
  21012. invalid=1;
  21013. break;
  21014. }
  21015. if(pThis->inside_edge) {
  21016. inside_edge++;
  21017. } else if(pThis->outside_edge) {
  21018. outside_edge++;
  21019. }
  21020. pSeg = pThis->pSeg;
  21021. if( pThis->backwards ){
  21022. VectorXYZ_Copy(pPolyOut->vertex_xyz[j],pSeg->to);
  21023. } else {
  21024. VectorXYZ_Copy(pPolyOut->vertex_xyz[j],pSeg->from);
  21025. }
  21026. }
  21027. /*
  21028. if(outside_edge>0 && !inside_edge) {
  21029. invalid=1;
  21030. }
  21031. */
  21032. if(!invalid && nVertex>2) {
  21033. Odie_FaceXYZ_Compute(interp,pPolyOut);
  21034. Tcl_ListObjAppendElement(interp, pResult, Odie_FaceXYZ_NewTclObj(pPolyOut));
  21035. } else {
  21036. Odie_Free(pPolyOut);
  21037. }
  21038. }
  21039. Tcl_SetObjResult(interp, pResult);
  21040. return TCL_OK;
  21041. }
  21042. /* OO Method SegmentSet polygons */
  21043. static int OOMethod_SegmentSet_polygons(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  21044.  
  21045. /*
  21046. ** tclmethod: WALLSET polygon_list
  21047. ** title: Return the set of polygons define by segments
  21048. **
  21049. ** The closure is a path of walls going clockwise from the wall given.
  21050. ** The return value is a list consisting of wall IDs alternating with
  21051. ** keywords "left" or "right" indicating which side of the wall applies.
  21052. ** If the CHECKPRIMARY flag is true and the WALLID/BACKWARDS is not the
  21053. ** primary wall id for the closure, then return an empty string. The
  21054. ** primary wall id is the wall id with the lowest id number, or if
  21055. ** two walls in the closure have the same id, then the one that goes
  21056. ** on the right side of the wall.
  21057. */
  21058. SegmentSet *pSet = GETSEGMENTSET(thisObject);
  21059. Tcl_Obj *pResult = Tcl_NewObj();
  21060. Odie_Polygon *pPolyPrior=NULL;
  21061. int i;
  21062. SegmentSet_BuildFaceEdgeCache(pSet);
  21063. for(i=0;i<(pSet->nSeg*2);i++) {
  21064. FaceBoundary *pStart,*pThis;
  21065. Odie_Polygon *pPolyOut;
  21066. int nVertex=0;
  21067. int j,invalid=0,inside_edge=0,outside_edge=0;
  21068. if(pSet->aBoundary[i].faceid!=pSet->aBoundary[i].id) continue;
  21069. //if(pSet->aBoundary[i].facebend<0 && !pSet->aBoundary[i].inside_edge) continue;
  21070. if(pSet->aBoundary[i].nSeg<3) continue;
  21071. pStart=pThis=&pSet->aBoundary[i];
  21072. nVertex=pStart->nSeg;
  21073. pPolyOut=Odie_Poly_Create(nVertex+1);
  21074. pPolyOut->nVertex=nVertex;
  21075. for(pThis=pStart,j=0;j<nVertex;pThis=pThis->pNext,j++) {
  21076. Segment *pSeg;
  21077. if(!pThis) {
  21078. invalid=1;
  21079. break;
  21080. }
  21081. if(pThis->inside_edge) {
  21082. inside_edge++;
  21083. } else if(pThis->outside_edge) {
  21084. outside_edge++;
  21085. }
  21086. pSeg = pThis->pSeg;
  21087. if( pThis->backwards ){
  21088. VectorXY_Copy(pPolyOut->v[j],pSeg->from);
  21089. } else {
  21090. VectorXY_Copy(pPolyOut->v[j],pSeg->to);
  21091. }
  21092. }
  21093. if(pPolyPrior && Odie_Poly_Compare(pPolyPrior,pPolyOut)==1) {
  21094. invalid=1;
  21095. }
  21096. if(!invalid && nVertex>2) {
  21097. pPolyPrior=pPolyOut;
  21098. Odie_Polygon_ComputeArea(interp,pPolyOut);
  21099. Tcl_ListObjAppendElement(interp, pResult, Odie_Polygon_NewTclObj(pPolyOut));
  21100. } else {
  21101. Odie_Free(pPolyOut);
  21102. }
  21103. }
  21104. Tcl_SetObjResult(interp, pResult);
  21105. return TCL_OK;
  21106. }
  21107. /* OO Method SegmentSet polygon_faces */
  21108. static int OOMethod_SegmentSet_polygon_faces(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  21109.  
  21110. /*
  21111. ** tclmethod: WALLSET polygon_faces
  21112. ** title: Return the set of polygons defined by segments
  21113. **
  21114. ** The closure is a path of walls going clockwise from the wall given.
  21115. ** The return value is a list consisting of wall IDs alternating with
  21116. ** keywords "left" or "right" indicating which side of the wall applies.
  21117. ** If the CHECKPRIMARY flag is true and the WALLID/BACKWARDS is not the
  21118. ** primary wall id for the closure, then return an empty string. The
  21119. ** primary wall id is the wall id with the lowest id number, or if
  21120. ** two walls in the closure have the same id, then the one that goes
  21121. ** on the right side of the wall.
  21122. */
  21123. SegmentSet *pSet = GETSEGMENTSET(thisObject);
  21124. Tcl_Obj *pResult = Tcl_NewObj();
  21125. Odie_Polygon *pPolyPrior=NULL;
  21126. int i;
  21127. SegmentSet_BuildFaceEdgeCache(pSet);
  21128. for(i=0;i<(pSet->nSeg*2);i++) {
  21129. FaceBoundary *pStart,*pThis;
  21130. Odie_Polygon *pPolyOut;
  21131. int nVertex=0;
  21132. int j,invalid=0,inside_edge=0,outside_edge=0;
  21133. if(pSet->aBoundary[i].faceid!=pSet->aBoundary[i].id) continue;
  21134. //if(pSet->aBoundary[i].facebend<0 && !pSet->aBoundary[i].inside_edge) continue;
  21135. if(pSet->aBoundary[i].nSeg<3) continue;
  21136. pStart=pThis=&pSet->aBoundary[i];
  21137. nVertex=pStart->nSeg;
  21138. pPolyOut=Odie_Poly_Create(nVertex+1);
  21139. pPolyOut->nVertex=nVertex;
  21140. for(pThis=pStart,j=0;j<nVertex;pThis=pThis->pNext,j++) {
  21141. Segment *pSeg;
  21142. if(!pThis) {
  21143. invalid=1;
  21144. break;
  21145. }
  21146. if(pThis->inside_edge) {
  21147. inside_edge++;
  21148. } else if(pThis->outside_edge) {
  21149. outside_edge++;
  21150. }
  21151. pSeg = pThis->pSeg;
  21152. if( pThis->backwards ){
  21153. VectorXY_Copy(pPolyOut->v[j],pSeg->from);
  21154. } else {
  21155. VectorXY_Copy(pPolyOut->v[j],pSeg->to);
  21156. }
  21157. }
  21158. if(pPolyPrior && Odie_Poly_Compare(pPolyPrior,pPolyOut)==1) {
  21159. invalid=1;
  21160. }
  21161. if(!invalid && nVertex>2) {
  21162. pPolyPrior=pPolyOut;
  21163. Odie_Polygon_ComputeArea(interp,pPolyOut);
  21164. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewIntObj(i));
  21165. Tcl_ListObjAppendElement(interp, pResult, Odie_Polygon_NewTclObj(pPolyOut));
  21166. } else {
  21167. Odie_Free(pPolyOut);
  21168. }
  21169. }
  21170. Tcl_SetObjResult(interp, pResult);
  21171. return TCL_OK;
  21172. }
  21173. /* OO Method SegmentSet polygon_info */
  21174. static int OOMethod_SegmentSet_polygon_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  21175.  
  21176. /*
  21177. ** tclmethod: WALLSET polygon_list
  21178. ** title: Return the set of polygons define by segments
  21179. **
  21180. ** The closure is a path of walls going clockwise from the wall given.
  21181. ** The return value is a list consisting of wall IDs alternating with
  21182. ** keywords "left" or "right" indicating which side of the wall applies.
  21183. ** If the CHECKPRIMARY flag is true and the WALLID/BACKWARDS is not the
  21184. ** primary wall id for the closure, then return an empty string. The
  21185. ** primary wall id is the wall id with the lowest id number, or if
  21186. ** two walls in the closure have the same id, then the one that goes
  21187. ** on the right side of the wall.
  21188. */
  21189. SegmentSet *pSet = GETSEGMENTSET(thisObject);
  21190. Tcl_Obj *pResult = Tcl_NewObj();
  21191. int i;
  21192. SegmentSet_BuildFaceEdgeCache(pSet);
  21193. for(i=0;i<(pSet->nSeg*2);i++) {
  21194. FaceBoundary *pStart,*pThis;
  21195. int j;
  21196. Tcl_Obj *element=Tcl_NewObj();
  21197. Tcl_Obj *coords=Tcl_NewObj();
  21198. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewIntObj(i));
  21199. Odie_DictObjPut(interp,element,"isloop",Tcl_NewIntObj(pSet->aBoundary[i].isloop));
  21200. Odie_DictObjPut(interp,element,"facebend",Tcl_NewIntObj(pSet->aBoundary[i].facebend));
  21201. Odie_DictObjPut(interp,element,"faceid",Tcl_NewIntObj(pSet->aBoundary[i].faceid));
  21202. Odie_DictObjPut(interp,element,"nSeg",Tcl_NewIntObj(pSet->aBoundary[i].nSeg));
  21203. Odie_DictObjPut(interp,element,"bend",Tcl_NewIntObj(pSet->aBoundary[i].bend));
  21204. Odie_DictObjPut(interp,element,"segid",Tcl_NewIntObj(pSet->aBoundary[i].pSeg->id));
  21205. Odie_DictObjPut(interp,element,"backwards",Tcl_NewIntObj(pSet->aBoundary[i].backwards));
  21206.  
  21207. if(pSet->aBoundary[i].backwards) {
  21208. Tcl_ListObjAppendElement(interp, coords, VectorXYZ_To_TclObj(pSet->aBoundary[i].pSeg->to));
  21209. Tcl_ListObjAppendElement(interp, coords, VectorXYZ_To_TclObj(pSet->aBoundary[i].pSeg->from));
  21210. } else {
  21211. Tcl_ListObjAppendElement(interp, coords, VectorXYZ_To_TclObj(pSet->aBoundary[i].pSeg->from));
  21212. Tcl_ListObjAppendElement(interp, coords, VectorXYZ_To_TclObj(pSet->aBoundary[i].pSeg->to));
  21213. }
  21214. Odie_DictObjPut(interp,element,"coords",coords);
  21215. Tcl_ListObjAppendElement(interp, pResult,element);
  21216. pStart=pThis=&pSet->aBoundary[i];
  21217. if(pStart->id==pStart->faceid) {
  21218. Tcl_Obj *coords=Tcl_NewObj();
  21219. for(j=0;j<pSet->aBoundary[i].nSeg && pThis;j++,pThis=pThis->pNext) {
  21220. Tcl_ListObjAppendElement(interp,coords,Tcl_NewIntObj(pThis->id));
  21221. }
  21222. Odie_DictObjPut(interp,element,"next",coords);
  21223. } else {
  21224. if(pSet->aBoundary[i].pNext) {
  21225. Odie_DictObjPut(interp,element,"next",Tcl_NewIntObj(pSet->aBoundary[i].pNext->id));
  21226. } else {
  21227. Odie_DictObjPut(interp,element,"next",Tcl_NewObj());
  21228. }
  21229. }
  21230. }
  21231. Tcl_SetObjResult(interp, pResult);
  21232. return TCL_OK;
  21233. }
  21234. /* Loader for SegmentSet */
  21235. static int SegmentSet_OO_Init(Tcl_Interp *interp) {
  21236. /*
  21237. ** Build the "::odielib::segset" class
  21238. */
  21239. Tcl_Obj* nameObj; /* Name of a class or method being looked up */
  21240. Tcl_Object curClassObject; /* Tcl_Object representing the current class */
  21241. Tcl_Class curClass; /* Tcl_Class representing the current class */
  21242.  
  21243. /*
  21244. * Find the "::odielib::segset" class, and attach an 'init' method to it.
  21245. */
  21246.  
  21247. nameObj = Tcl_NewStringObj("::odielib::segset", -1);
  21248. Tcl_IncrRefCount(nameObj);
  21249. if ((curClassObject = Tcl_GetObjectFromObj(interp, nameObj)) == NULL) {
  21250. Tcl_DecrRefCount(nameObj);
  21251. return TCL_ERROR;
  21252. }
  21253. Tcl_DecrRefCount(nameObj);
  21254. curClass = Tcl_GetObjectAsClass(curClassObject);
  21255. nameObj=Tcl_NewStringObj("segment_info",-1);
  21256. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_segment_info, (ClientData) NULL);
  21257. Tcl_DecrRefCount(nameObj);
  21258. nameObj=Tcl_NewStringObj("SegmentSet_Init",-1);
  21259. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_SegmentSet_Init, (ClientData) NULL);
  21260. Tcl_DecrRefCount(nameObj);
  21261. nameObj=Tcl_NewStringObj("modified",-1);
  21262. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_modified, (ClientData) NULL);
  21263. Tcl_DecrRefCount(nameObj);
  21264. nameObj=Tcl_NewStringObj("segment_count",-1);
  21265. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_segment_count, (ClientData) NULL);
  21266. Tcl_DecrRefCount(nameObj);
  21267. nameObj=Tcl_NewStringObj("bbox",-1);
  21268. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_bbox, (ClientData) NULL);
  21269. Tcl_DecrRefCount(nameObj);
  21270. nameObj=Tcl_NewStringObj("segment_reset",-1);
  21271. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_segment_reset, (ClientData) NULL);
  21272. Tcl_DecrRefCount(nameObj);
  21273. nameObj=Tcl_NewStringObj("segment_add",-1);
  21274. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_segment_add, (ClientData) NULL);
  21275. Tcl_DecrRefCount(nameObj);
  21276. nameObj=Tcl_NewStringObj("segment_add_virtual",-1);
  21277. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_segment_add_virtual, (ClientData) NULL);
  21278. Tcl_DecrRefCount(nameObj);
  21279. nameObj=Tcl_NewStringObj("polygon_add",-1);
  21280. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_polygon_add, (ClientData) NULL);
  21281. Tcl_DecrRefCount(nameObj);
  21282. nameObj=Tcl_NewStringObj("vertex_add",-1);
  21283. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_vertex_add, (ClientData) NULL);
  21284. Tcl_DecrRefCount(nameObj);
  21285. nameObj=Tcl_NewStringObj("segment_delete",-1);
  21286. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_segment_delete, (ClientData) NULL);
  21287. Tcl_DecrRefCount(nameObj);
  21288. nameObj=Tcl_NewStringObj("delete",-1);
  21289. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_delete, (ClientData) NULL);
  21290. Tcl_DecrRefCount(nameObj);
  21291. nameObj=Tcl_NewStringObj("cleanup",-1);
  21292. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_cleanup, (ClientData) NULL);
  21293. Tcl_DecrRefCount(nameObj);
  21294. nameObj=Tcl_NewStringObj("delete_overlapping",-1);
  21295. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_cleanup, (ClientData) NULL);
  21296. Tcl_DecrRefCount(nameObj);
  21297. nameObj=Tcl_NewStringObj("cleanup_looseend",-1);
  21298. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_cleanup_looseend, (ClientData) NULL);
  21299. Tcl_DecrRefCount(nameObj);
  21300. nameObj=Tcl_NewStringObj("delete_overlapping",-1);
  21301. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_cleanup_looseend, (ClientData) NULL);
  21302. Tcl_DecrRefCount(nameObj);
  21303. nameObj=Tcl_NewStringObj("edge_connection",-1);
  21304. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_edge_connection, (ClientData) NULL);
  21305. Tcl_DecrRefCount(nameObj);
  21306. nameObj=Tcl_NewStringObj("check_intersecting",-1);
  21307. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_check_intersecting, (ClientData) NULL);
  21308. Tcl_DecrRefCount(nameObj);
  21309. nameObj=Tcl_NewStringObj("check_coincident",-1);
  21310. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_check_coincident, (ClientData) NULL);
  21311. Tcl_DecrRefCount(nameObj);
  21312. nameObj=Tcl_NewStringObj("segment_linelineintersect",-1);
  21313. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_segment_linelineintersect, (ClientData) NULL);
  21314. Tcl_DecrRefCount(nameObj);
  21315. nameObj=Tcl_NewStringObj("segment_coincident",-1);
  21316. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_segment_coincident, (ClientData) NULL);
  21317. Tcl_DecrRefCount(nameObj);
  21318. nameObj=Tcl_NewStringObj("segment_find",-1);
  21319. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_segment_find, (ClientData) NULL);
  21320. Tcl_DecrRefCount(nameObj);
  21321. nameObj=Tcl_NewStringObj("vertex_delete",-1);
  21322. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_vertex_delete, (ClientData) NULL);
  21323. Tcl_DecrRefCount(nameObj);
  21324. nameObj=Tcl_NewStringObj("segment_next",-1);
  21325. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_segment_next, (ClientData) NULL);
  21326. Tcl_DecrRefCount(nameObj);
  21327. nameObj=Tcl_NewStringObj("check_oblique",-1);
  21328. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_check_oblique, (ClientData) NULL);
  21329. Tcl_DecrRefCount(nameObj);
  21330. nameObj=Tcl_NewStringObj("check_looseends",-1);
  21331. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_check_looseends, (ClientData) NULL);
  21332. Tcl_DecrRefCount(nameObj);
  21333. nameObj=Tcl_NewStringObj("fix_looseends",-1);
  21334. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_fix_looseends, (ClientData) NULL);
  21335. Tcl_DecrRefCount(nameObj);
  21336. nameObj=Tcl_NewStringObj("grid",-1);
  21337. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_grid, (ClientData) NULL);
  21338. Tcl_DecrRefCount(nameObj);
  21339. nameObj=Tcl_NewStringObj("segment_list",-1);
  21340. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_segment_list, (ClientData) NULL);
  21341. Tcl_DecrRefCount(nameObj);
  21342. nameObj=Tcl_NewStringObj("segment_coords",-1);
  21343. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_segment_coords, (ClientData) NULL);
  21344. Tcl_DecrRefCount(nameObj);
  21345. nameObj=Tcl_NewStringObj("segment_uvcoords",-1);
  21346. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_segment_uvcoords, (ClientData) NULL);
  21347. Tcl_DecrRefCount(nameObj);
  21348. nameObj=Tcl_NewStringObj("selfcheck",-1);
  21349. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_selfcheck, (ClientData) NULL);
  21350. Tcl_DecrRefCount(nameObj);
  21351. nameObj=Tcl_NewStringObj("uv_transform",-1);
  21352. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_uv_transform, (ClientData) NULL);
  21353. Tcl_DecrRefCount(nameObj);
  21354. nameObj=Tcl_NewStringObj("polygons_xyz",-1);
  21355. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_polygons_xyz, (ClientData) NULL);
  21356. Tcl_DecrRefCount(nameObj);
  21357. nameObj=Tcl_NewStringObj("polygons",-1);
  21358. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_polygons, (ClientData) NULL);
  21359. Tcl_DecrRefCount(nameObj);
  21360. nameObj=Tcl_NewStringObj("polygon_faces",-1);
  21361. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_polygon_faces, (ClientData) NULL);
  21362. Tcl_DecrRefCount(nameObj);
  21363. nameObj=Tcl_NewStringObj("polygon_info",-1);
  21364. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SegmentSet_polygon_info, (ClientData) NULL);
  21365. Tcl_DecrRefCount(nameObj);
  21366. return TCL_OK;
  21367. }
  21368. /* Tcl Proc ::shapes::corners */
  21369. static int TclCmd_shapes_corners(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  21370.  
  21371.  
  21372. double cx, cy, radx,rady;
  21373.  
  21374. if( objc != 5 && objc != 9 ){
  21375. Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy ?x0var y0var x1var y1var?");
  21376. return TCL_ERROR;
  21377. }
  21378.  
  21379. if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR;
  21380. if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR;
  21381. if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR;
  21382. if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR;
  21383. if (objc == 5) {
  21384. Tcl_Obj *pResult=Tcl_NewObj();
  21385. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx));
  21386. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady));
  21387. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx));
  21388. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady));
  21389. Tcl_SetObjResult(interp, pResult);
  21390. return TCL_OK;
  21391. }
  21392. /*
  21393. Replaces
  21394. set x0 [expr {$cx-$d}]
  21395. set y0 [expr {$cy-$d}]
  21396. set x1 [expr {$cx+$d}]
  21397. set y1 [expr {$cy+$d}]
  21398. */
  21399.  
  21400. Tcl_ObjSetVar2(interp,objv[5],NULL,Tcl_NewDoubleObj(cx+radx),0);
  21401. Tcl_ObjSetVar2(interp,objv[6],NULL,Tcl_NewDoubleObj(cy-rady),0);
  21402. Tcl_ObjSetVar2(interp,objv[7],NULL,Tcl_NewDoubleObj(cx-radx),0);
  21403. Tcl_ObjSetVar2(interp,objv[8],NULL,Tcl_NewDoubleObj(cy+rady),0);
  21404.  
  21405. return TCL_OK;
  21406. }
  21407. /* Tcl Proc ::shapes::drawobj_orientation */
  21408. static int TclCmd_shapes_drawobj_orientation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  21409. Tcl_Obj *temp;
  21410. int len;
  21411. double nx=100,ny=0;
  21412. if( objc !=4 ){
  21413. Tcl_WrongNumArgs(interp, 1, objv, "orientation nxvar nyvar");
  21414. return TCL_ERROR;
  21415. }
  21416.  
  21417. if(Tcl_ListObjLength(interp,objv[1],&len)) return TCL_ERROR;
  21418. if(len>0) {
  21419. if(Tcl_ListObjIndex(interp, objv[1], 0, &temp)) return TCL_ERROR;
  21420. if(Tcl_GetDoubleFromObj(interp,temp,&nx)) return TCL_ERROR;
  21421. }
  21422. if(len>1) {
  21423. if(Tcl_ListObjIndex(interp, objv[1], 1, &temp)) return TCL_ERROR;
  21424. if(Tcl_GetDoubleFromObj(interp,temp,&ny)) return TCL_ERROR;
  21425. }
  21426. Tcl_ObjSetVar2(interp,objv[2],NULL,Tcl_NewDoubleObj(nx),0);
  21427. Tcl_ObjSetVar2(interp,objv[3],NULL,Tcl_NewDoubleObj(ny),0);
  21428. return TCL_OK;
  21429. }
  21430. /* Tcl Proc ::shapes::poly_hex */
  21431. static int TclCmd_shapes_poly_hex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  21432. int i,flip=0;
  21433. double cx, cy, radx,rady;
  21434.  
  21435. Tcl_Obj *pResult=Tcl_NewObj();
  21436. double coords[7][2]= {
  21437. {1.00, 0.00} , {0.50, M_SQRT3_2} ,
  21438. {-0.50, M_SQRT3_2} , {-1.00, -0.00} ,
  21439. {-0.50, -M_SQRT3_2} , {0.50, -M_SQRT3_2},
  21440. {1.00, 0.00}
  21441. };
  21442. if( objc != 5 && objc != 6){
  21443. Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy ?flip?");
  21444. return TCL_ERROR;
  21445. }
  21446.  
  21447. if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR;
  21448. if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR;
  21449. if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR;
  21450. if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR;
  21451. if(objc==6) {
  21452. if(Tcl_GetBooleanFromObj(interp,objv[5],&flip)) return TCL_ERROR;
  21453. }
  21454. radx=radx/2.0;
  21455. rady=rady/2.0;
  21456.  
  21457. for(i=0;i<6;i++) {
  21458. if(flip) {
  21459. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i][1]));
  21460. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i][0]));
  21461. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i+1][1]));
  21462. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i+1][0]));
  21463. } else {
  21464. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i][0]));
  21465. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i][1]));
  21466. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i+1][0]));
  21467. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i+1][1]));
  21468. }
  21469. }
  21470.  
  21471. Tcl_SetObjResult(interp, pResult);
  21472. return TCL_OK;
  21473. }
  21474. /* Tcl Proc ::shapes::poly_place */
  21475. static int TclCmd_shapes_poly_place(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  21476. /*
  21477. ** Apply Matrices
  21478. */
  21479. Tcl_Obj *pResult=Tcl_NewObj();
  21480. int i;
  21481. double zoom;
  21482. double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0};
  21483. double centerx,centery,normalx,normaly,angle;
  21484.  
  21485. if( objc < 8 ){
  21486. Tcl_WrongNumArgs(interp, 1, objv, "zoom centerx centery normalx normaly x1 y1 ?x2 y2?...");
  21487. return TCL_ERROR;
  21488. }
  21489. if(Tcl_GetDoubleFromObj(interp,objv[1],&zoom)) return TCL_ERROR;
  21490. if(Tcl_GetDoubleFromObj(interp,objv[2],&centerx)) return TCL_ERROR;
  21491. if(Tcl_GetDoubleFromObj(interp,objv[3],&centery)) return TCL_ERROR;
  21492. if(Tcl_GetDoubleFromObj(interp,objv[4],&normalx)) return TCL_ERROR;
  21493. if(Tcl_GetDoubleFromObj(interp,objv[5],&normaly)) return TCL_ERROR;
  21494.  
  21495. angle=atan2(normaly,normalx);
  21496. matA[0]=cos(angle);
  21497. matA[1]=sin(angle);
  21498. matA[2]=-sin(angle);
  21499. matA[3]=cos(angle);
  21500. matA[4]=0.0;
  21501. matA[5]=0.0;
  21502. double startx,starty,prevx,prevy;
  21503.  
  21504. i=6;
  21505. {
  21506. double x,y,sx,sy,newx,newy;
  21507. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
  21508. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
  21509.  
  21510. sx=(x/zoom);
  21511. sy=(y/zoom);
  21512. newx=matA[0]*sx+matA[1]*sy+matA[4]+centerx;
  21513. newy=matA[2]*sx+matA[3]*sy+matA[5]+centery;
  21514.  
  21515. startx=newx;
  21516. starty=newy;
  21517. prevx=newx;
  21518. prevy=newy;
  21519. }
  21520.  
  21521. for(i=8;i<objc;i+=2) {
  21522. double x,y,sx,sy,newx,newy;
  21523. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
  21524. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
  21525.  
  21526. sx=(x/zoom);
  21527. sy=(y/zoom);
  21528. newx=matA[0]*sx+matA[1]*sy+matA[4]+centerx;
  21529. newy=matA[2]*sx+matA[3]*sy+matA[5]+centery;
  21530.  
  21531. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(prevx));
  21532. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(prevy));
  21533. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
  21534. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
  21535.  
  21536. prevx=newx;
  21537. prevy=newy;
  21538. }
  21539. if(startx != prevx && starty!= prevy) {
  21540. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(prevx));
  21541. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(prevy));
  21542. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(startx));
  21543. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(starty));
  21544. }
  21545. Tcl_SetObjResult(interp, pResult);
  21546. return TCL_OK;
  21547. }
  21548. /* Tcl Proc ::shapes::polygon_to_vectors */
  21549. static int TclCmd_shapes_polygon_to_vectors(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  21550. Tcl_Obj *pResult=Tcl_NewObj();
  21551. int i;
  21552. double px,py,fx,fy;
  21553.  
  21554. if(objc<6 || (objc-1)%2!=0) {
  21555. Tcl_AppendResult(interp, "arguments should contain at least 6 and "
  21556. " a multiple of 2 values", 0);
  21557. return TCL_ERROR;
  21558.  
  21559. }
  21560. if(Tcl_GetDoubleFromObj(interp,objv[1],&px)) return TCL_ERROR;
  21561. if(Tcl_GetDoubleFromObj(interp,objv[2],&py)) return TCL_ERROR;
  21562. fx=px;
  21563. fy=py;
  21564. for(i=3;i<objc;i+=2) {
  21565. double x,y;
  21566. if(i+1>objc) break;
  21567. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
  21568. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
  21569. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(px));
  21570. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(py));
  21571. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(x));
  21572. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(y));
  21573. px=x;
  21574. py=y;
  21575. }
  21576. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(px));
  21577. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(py));
  21578. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(fx));
  21579. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(fy));
  21580. Tcl_SetObjResult(interp, pResult);
  21581. return TCL_OK;
  21582. }
  21583. /* Tcl Proc ::shapes::rectangle_as_polygon */
  21584. static int TclCmd_shapes_rectangle_as_polygon(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  21585. double cx, cy, radx,rady;
  21586. Tcl_Obj *pResult=Tcl_NewObj();
  21587.  
  21588. if( objc != 5 ){
  21589. Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy");
  21590. return TCL_ERROR;
  21591. }
  21592.  
  21593. if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR;
  21594. if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR;
  21595. if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR;
  21596. if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR;
  21597. radx=radx/2.0;
  21598. rady=rady/2.0;
  21599. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx));
  21600. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady));
  21601.  
  21602. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx));
  21603. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady));
  21604.  
  21605. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx));
  21606. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady));
  21607.  
  21608. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx));
  21609. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady));
  21610.  
  21611. Tcl_SetObjResult(interp, pResult);
  21612. return TCL_OK;
  21613. }
  21614. /* Tcl Proc ::shapes::rectangle_as_vectors */
  21615. static int TclCmd_shapes_rectangle_as_vectors(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  21616.  
  21617. double cx, cy, radx,rady;
  21618. Tcl_Obj *pResult=Tcl_NewObj();
  21619.  
  21620. if( objc != 5 ){
  21621. Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy");
  21622. return TCL_ERROR;
  21623. }
  21624.  
  21625. if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR;
  21626. if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR;
  21627. if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR;
  21628. if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR;
  21629. radx=radx/2.0;
  21630. rady=rady/2.0;
  21631. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx));
  21632. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady));
  21633.  
  21634. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx));
  21635. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady));
  21636.  
  21637. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx));
  21638. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady));
  21639.  
  21640. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx));
  21641. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady));
  21642.  
  21643. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx));
  21644. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady));
  21645.  
  21646. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx));
  21647. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady));
  21648.  
  21649. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx));
  21650. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady));
  21651.  
  21652. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx));
  21653. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady));
  21654. Tcl_SetObjResult(interp, pResult);
  21655. return TCL_OK;
  21656. }
  21657. /* Tcl Proc ::shapes::vector_place */
  21658. static int TclCmd_shapes_vector_place(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  21659. /*
  21660. ** Apply Matrices
  21661. */
  21662. Tcl_Obj *pResult=Tcl_NewObj();
  21663. int i;
  21664. double zoom;
  21665. double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0};
  21666. double centerx,centery,normalx,normaly,angle;
  21667.  
  21668. if( objc < 8 ){
  21669. Tcl_WrongNumArgs(interp, 1, objv, "zoom centerx centery normalx normaly x1 y1 ?x2 y2?...");
  21670. return TCL_ERROR;
  21671. }
  21672. if(Tcl_GetDoubleFromObj(interp,objv[1],&zoom)) return TCL_ERROR;
  21673. if(Tcl_GetDoubleFromObj(interp,objv[2],&centerx)) return TCL_ERROR;
  21674. if(Tcl_GetDoubleFromObj(interp,objv[3],&centery)) return TCL_ERROR;
  21675. if(Tcl_GetDoubleFromObj(interp,objv[4],&normalx)) return TCL_ERROR;
  21676. if(Tcl_GetDoubleFromObj(interp,objv[5],&normaly)) return TCL_ERROR;
  21677.  
  21678. angle=atan2(normaly,normalx);
  21679. matA[0]=cos(angle);
  21680. matA[1]=sin(angle);
  21681. matA[2]=-sin(angle);
  21682. matA[3]=cos(angle);
  21683. matA[4]=0.0;
  21684. matA[5]=0.0;
  21685.  
  21686.  
  21687. for(i=6;i<objc;i+=2) {
  21688. double x,y,sx,sy,newx,newy;
  21689. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
  21690. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
  21691.  
  21692. sx=(x/zoom);
  21693. sy=(y/zoom);
  21694. newx=matA[0]*sx+matA[1]*sy+matA[4]+centerx;
  21695. newy=matA[2]*sx+matA[3]*sy+matA[5]+centery;
  21696.  
  21697. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
  21698. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
  21699. }
  21700. Tcl_SetObjResult(interp, pResult);
  21701. return TCL_OK;
  21702. }
  21703. /* Tcl Proc ::shapes::hexagon */
  21704. static int TclCmd_shapes_hexagon(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  21705. int i,flip=0;
  21706. double cx, cy, radx,rady;
  21707.  
  21708. Tcl_Obj *pResult=Tcl_NewObj();
  21709. double coords[7][2]= {
  21710. {1.00, 0.00} , {0.50, M_SQRT3_2} ,
  21711. {-0.50, M_SQRT3_2} , {-1.00, -0.00} ,
  21712. {-0.50, -M_SQRT3_2} , {0.50, -M_SQRT3_2},
  21713. {1.00, 0.00}
  21714. };
  21715. if( objc != 5 && objc != 6){
  21716. Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy ?flip?");
  21717. return TCL_ERROR;
  21718. }
  21719.  
  21720. if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR;
  21721. if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR;
  21722. if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR;
  21723. if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR;
  21724. if(objc==6) {
  21725. if(Tcl_GetBooleanFromObj(interp,objv[5],&flip)) return TCL_ERROR;
  21726. }
  21727. radx=radx/2.0;
  21728. rady=rady/2.0;
  21729.  
  21730. for(i=0;i<6;i++) {
  21731. if(flip) {
  21732. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i][1]));
  21733. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i][0]));
  21734. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i+1][1]));
  21735. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i+1][0]));
  21736. } else {
  21737. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i][0]));
  21738. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i][1]));
  21739. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i+1][0]));
  21740. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i+1][1]));
  21741. }
  21742. }
  21743.  
  21744. Tcl_SetObjResult(interp, pResult);
  21745. return TCL_OK;
  21746. }
  21747. /* Tcl Proc ::shapes::canvas */
  21748. static int TclCmd_shapes_canvas(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  21749. /*
  21750. ** Apply Matrices
  21751. */
  21752. Tcl_Obj *pResult=Tcl_NewObj();
  21753. int i;
  21754. double zoom;
  21755. double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0};
  21756. double centerx,centery,width,height,angle=0.0;
  21757.  
  21758. if( objc < 6 || objc>7 ){
  21759. Tcl_WrongNumArgs(interp, 1, objv, "zoom centerx centery ?angle?");
  21760. return TCL_ERROR;
  21761. }
  21762. if(Tcl_GetDoubleFromObj(interp,objv[1],&zoom)) return TCL_ERROR;
  21763. if(Tcl_GetDoubleFromObj(interp,objv[2],&centerx)) return TCL_ERROR;
  21764. if(Tcl_GetDoubleFromObj(interp,objv[3],&centery)) return TCL_ERROR;
  21765. if(Tcl_GetDoubleFromObj(interp,objv[2],&width)) return TCL_ERROR;
  21766. if(Tcl_GetDoubleFromObj(interp,objv[3],&height)) return TCL_ERROR;
  21767. if(objc==7) {
  21768. if(Tcl_GetDoubleFromObj(interp,objv[4],&angle)) return TCL_ERROR;
  21769.  
  21770. }
  21771. matA[0]=cos(angle);
  21772. matA[1]=sin(angle);
  21773. matA[2]=-sin(angle);
  21774. matA[3]=cos(angle);
  21775. matA[4]=0.0;
  21776. matA[5]=0.0;
  21777.  
  21778.  
  21779. for(i=6;i<objc;i+=2) {
  21780. double x,y,sx,sy,newx,newy;
  21781. if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR;
  21782. if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR;
  21783.  
  21784. sx=(x/zoom);
  21785. sy=(y/zoom);
  21786. newx=matA[0]*sx+matA[1]*sy+matA[4]+centerx;
  21787. newy=matA[2]*sx+matA[3]*sy+matA[5]+centery;
  21788.  
  21789. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newx));
  21790. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(newy));
  21791. }
  21792. Tcl_SetObjResult(interp, pResult);
  21793. return TCL_OK;
  21794. }
  21795. /* OO Method Plotter actualcoords */
  21796. static int OOMethod_Plotter_actualcoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  21797.  
  21798. /*
  21799. ** tclmethod: PLOTTER actualcoords CANVAS-COORD-LIST
  21800. ** title: Convert from canvas to actual coordinate space
  21801. */
  21802. Plotter *p = GETPLOTTER(thisObject);
  21803. int i, n;
  21804. Tcl_Obj *pResult;
  21805. if( objc!=3 ){
  21806. Tcl_WrongNumArgs(interp, 2, objv, "CANVAS-COORD-LIST");
  21807. return TCL_ERROR;
  21808. }
  21809. if( Tcl_ListObjLength(interp, objv[2], &n) ) return TCL_ERROR;
  21810. if( n%2!=0 ){
  21811. Tcl_AppendResult(interp, "coordinate list must contain a multiple "
  21812. "of 2 values", 0);
  21813. return TCL_ERROR;
  21814. }
  21815.  
  21816. pResult = Tcl_NewObj();
  21817. for(i=0; i<n-1; i+=2){
  21818. double cx, cy;
  21819. Tcl_Obj *pObj;
  21820. VectorXY M;
  21821.  
  21822. Tcl_ListObjIndex(0, objv[2], i, &pObj);
  21823. if( Tcl_GetDoubleFromObj(interp, pObj, &cx) ) break;
  21824. Tcl_ListObjIndex(0, objv[2], i+1, &pObj);
  21825. if( Tcl_GetDoubleFromObj(interp, pObj, &cy) ) break;
  21826. /* Original Formula
  21827. ** ax = cx*p->rZoom - pS->rXShift;
  21828. ** ay = pS->mxY + (pS->mnY-pS->mxY)*(cy-pS->top)/(pS->btm-pS->top);
  21829. */
  21830. M[X_IDX]=Plotter_xCanvasToActual(p,cx);
  21831. M[Y_IDX]=Plotter_yCanvasToActual(p,cy);
  21832.  
  21833. Tcl_ListObjAppendElement(interp, pResult, VectorXY_To_TclObj(M));
  21834. }
  21835. if( i<n-1 ){
  21836. Tcl_DecrRefCount(pResult);
  21837. return TCL_ERROR;
  21838. }
  21839. Tcl_SetObjResult(interp, pResult);
  21840. return TCL_OK;
  21841. }
  21842. /* OO Method Plotter canvascoords */
  21843. static int OOMethod_Plotter_canvascoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  21844.  
  21845. /*
  21846. ** tclmethod: PLOTTER canvascoords VECTOR-LIST ?xvar? ?yvar?
  21847. ** title: Convert from actual (a list of vectors) to canvas coordinate space
  21848. **
  21849. */
  21850. Plotter *p = GETPLOTTER(thisObject);
  21851. int i,n,m;
  21852. Tcl_Obj *pResult=NULL;
  21853. double cx, cy, ax, ay;
  21854. Tcl_Obj *pObj;
  21855. int error=0;
  21856. int singlearg=0;
  21857.  
  21858. if( objc!=3 && objc!=5 ){
  21859. Tcl_WrongNumArgs(interp, 2, objv, "VECTOR-LIST ?xvar yvar?");
  21860. return TCL_ERROR;
  21861. }
  21862. if(objv[2]->typePtr==&matrix_tclobjtype) {
  21863. singlearg=1;
  21864. } else {
  21865. if( Tcl_ListObjLength(interp, objv[2], &n) ) return TCL_ERROR;
  21866. Tcl_ListObjIndex(0, objv[2], 0, &pObj);
  21867. if( Tcl_ListObjLength(interp, pObj, &m) ) return TCL_ERROR;
  21868. if(m==1) {
  21869. singlearg=1;
  21870. }
  21871. }
  21872.  
  21873. if(singlearg) {
  21874. /*
  21875. ** Accept a single vector as an argument
  21876. ** Do this to ensure we don't interpret the
  21877. ** value as a list
  21878. */
  21879. MATOBJ *M;
  21880. if(Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_vectorxy,&M)) return TCL_ERROR;
  21881. if(!M) return TCL_ERROR;
  21882. ax=*(M->matrix+X_IDX);
  21883. ay=*(M->matrix+Y_IDX);
  21884. cx = Plotter_xActualToCanvas(p,ax);
  21885. cy = Plotter_yActualToCanvas(p,ay);
  21886. if(objc==5) {
  21887. Tcl_ObjSetVar2(interp,objv[3],NULL,Tcl_NewDoubleObj(cx),0);
  21888. Tcl_ObjSetVar2(interp,objv[4],NULL,Tcl_NewDoubleObj(cy),0);
  21889. }
  21890. pResult = Tcl_NewObj();
  21891. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(cx));
  21892. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(cy));
  21893. Tcl_SetObjResult(interp, pResult);
  21894. return TCL_OK;
  21895. }
  21896.  
  21897. if(objc != 5) {
  21898. pResult = Tcl_NewObj();
  21899. }
  21900.  
  21901. for(i=0; i<n; i++){
  21902. MATOBJ *M;
  21903. Tcl_ListObjIndex(0, objv[2], i, &pObj);
  21904. if(Odie_GetMatrixFromTclObj(interp,pObj,MATFORM_vectorxy,&M)) return TCL_ERROR;
  21905. ax=*(M->matrix+X_IDX);
  21906. ay=*(M->matrix+Y_IDX);
  21907. cx = Plotter_xActualToCanvas(p,ax);
  21908. cy = Plotter_yActualToCanvas(p,ay);
  21909. if(objc==5) {
  21910. Tcl_ObjSetVar2(interp,objv[3],NULL,Tcl_NewDoubleObj(cx),0);
  21911. Tcl_ObjSetVar2(interp,objv[4],NULL,Tcl_NewDoubleObj(cy),0);
  21912. return TCL_OK;
  21913. } else {
  21914. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(cx));
  21915. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(cy));
  21916. }
  21917. }
  21918. if(error) {
  21919. if(pResult) {
  21920. Tcl_DecrRefCount(pResult);
  21921. }
  21922. return TCL_ERROR;
  21923. }
  21924. if( i<n-3 ){
  21925. Tcl_AppendResult(interp, "Did not reach the end", 0);
  21926. Tcl_DecrRefCount(pResult);
  21927. return TCL_ERROR;
  21928. }
  21929.  
  21930. Tcl_SetObjResult(interp, pResult);
  21931. return TCL_OK;
  21932. }
  21933. /* OO Method Plotter centerset */
  21934. static int OOMethod_Plotter_centerset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  21935.  
  21936. /*
  21937. ** tclmethod: PLOTTER centerset zoom width height
  21938. ** title: Set all settings for plotter in one go
  21939. ** description: Sets the center of the screen based on the width
  21940. ** and height (0,0 = width/2 height/2)
  21941. */
  21942. Plotter *p = GETPLOTTER(thisObject);
  21943. double rZoom,rXOffset,rYOffset;
  21944. if(objc!=5) {
  21945. printf("%d\n",objc);
  21946. Tcl_WrongNumArgs(interp, 2, objv, "ZOOM XOFFSET YOFFSET");
  21947. return TCL_ERROR;
  21948. }
  21949. if( Tcl_GetDoubleFromObj(interp, objv[2], &rZoom) ) return TCL_ERROR;
  21950. p->rZoom = rZoom;
  21951. if( Tcl_GetDoubleFromObj(interp, objv[3], &rXOffset) ) return TCL_ERROR;
  21952. p->rXOffset = -rXOffset/2.0;
  21953. if( Tcl_GetDoubleFromObj(interp, objv[4], &rYOffset) ) return TCL_ERROR;
  21954. p->rYOffset = -rYOffset/2.0;
  21955. return TCL_OK;
  21956. }
  21957. /* OO Method Plotter xoffset */
  21958. static int OOMethod_Plotter_xoffset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  21959.  
  21960. /*
  21961. ** tclmethod: PLOTTER xoffset ?AMT?
  21962. ** title: Change the X-Offset
  21963. */
  21964. Plotter *p = GETPLOTTER(thisObject);
  21965. double rXOffset;
  21966. if( objc!=2 && objc!=3 ){
  21967. Tcl_WrongNumArgs(interp, 2, objv, "?ZOOM?");
  21968. return TCL_ERROR;
  21969. }
  21970. if( objc==3 ){
  21971. if( Tcl_GetDoubleFromObj(interp, objv[2], &rXOffset) ) return TCL_ERROR;
  21972. p->rXOffset = rXOffset;
  21973. }
  21974. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(p->rXOffset));
  21975. return TCL_OK;
  21976. }
  21977. /* OO Method Plotter yoffset */
  21978. static int OOMethod_Plotter_yoffset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  21979.  
  21980. /*
  21981. ** tclmethod: PLOTTER yoffset ?AMT?
  21982. ** title: Change the Y-Offset
  21983. */
  21984. Plotter *p = GETPLOTTER(thisObject);
  21985. double rYOffset;
  21986. if( objc!=2 && objc!=3 ){
  21987. Tcl_WrongNumArgs(interp, 2, objv, "?ZOOM?");
  21988. return TCL_ERROR;
  21989. }
  21990. if( objc==3 ){
  21991. if( Tcl_GetDoubleFromObj(interp, objv[2], &rYOffset) ) return TCL_ERROR;
  21992. p->rYOffset = rYOffset;
  21993. }
  21994. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(p->rYOffset));
  21995. return TCL_OK;
  21996. }
  21997. /* OO Method Plotter zoom */
  21998. static int OOMethod_Plotter_zoom(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  21999.  
  22000. /*
  22001. ** tclmethod: PLOTTER zoom ?ZOOM?
  22002. ** title: Query or change the zoom factor.
  22003. */
  22004. Plotter *p = GETPLOTTER(thisObject);
  22005. Tcl_Obj *pResult;
  22006. if( objc!=2 && objc!=3 ){
  22007. Tcl_WrongNumArgs(interp, 2, objv, "?ZOOM?");
  22008. return TCL_ERROR;
  22009. }
  22010. if( objc==3 ){
  22011. double r;
  22012. if( Tcl_GetDoubleFromObj(interp, objv[2], &r) ) return TCL_ERROR;
  22013. p->rZoom = r;
  22014. }
  22015. pResult = Tcl_NewDoubleObj(p->rZoom);
  22016. Tcl_SetObjResult(interp, pResult);
  22017. return TCL_OK;
  22018. }
  22019. /* OO Method Plotter constructor */
  22020. static int OOMethod_Plotter_constructor(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22021.  
  22022. Plotter *p;
  22023. p = (Plotter *)Odie_Alloc( sizeof(*p) );
  22024. p->rZoom = 1.0;
  22025. p->rXOffset = 0.0;
  22026. p->rYOffset = 0.0;
  22027. Tcl_ObjectSetMetadata(thisObject, &PlotterDataType, (ClientData) p);
  22028. return TCL_OK;
  22029. }
  22030. /* Loader for Plotter */
  22031. static int Plotter_OO_Init(Tcl_Interp *interp) {
  22032. /*
  22033. ** Build the "::odielib::plotter" class
  22034. */
  22035. Tcl_Obj* nameObj; /* Name of a class or method being looked up */
  22036. Tcl_Object curClassObject; /* Tcl_Object representing the current class */
  22037. Tcl_Class curClass; /* Tcl_Class representing the current class */
  22038.  
  22039. /*
  22040. * Find the "::odielib::plotter" class, and attach an 'init' method to it.
  22041. */
  22042.  
  22043. nameObj = Tcl_NewStringObj("::odielib::plotter", -1);
  22044. Tcl_IncrRefCount(nameObj);
  22045. if ((curClassObject = Tcl_GetObjectFromObj(interp, nameObj)) == NULL) {
  22046. Tcl_DecrRefCount(nameObj);
  22047. return TCL_ERROR;
  22048. }
  22049. Tcl_DecrRefCount(nameObj);
  22050. curClass = Tcl_GetObjectAsClass(curClassObject);
  22051. /* Attach the constructor to the class */
  22052. Tcl_ClassSetConstructor(interp, curClass, Tcl_NewMethod(interp, curClass, NULL, 1, &OOMethodType_Plotter_constructor, NULL));
  22053.  
  22054. nameObj=Tcl_NewStringObj("actualcoords",-1);
  22055. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Plotter_actualcoords, (ClientData) NULL);
  22056. Tcl_DecrRefCount(nameObj);
  22057. nameObj=Tcl_NewStringObj("canvascoords",-1);
  22058. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Plotter_canvascoords, (ClientData) NULL);
  22059. Tcl_DecrRefCount(nameObj);
  22060. nameObj=Tcl_NewStringObj("centerset",-1);
  22061. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Plotter_centerset, (ClientData) NULL);
  22062. Tcl_DecrRefCount(nameObj);
  22063. nameObj=Tcl_NewStringObj("xoffset",-1);
  22064. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Plotter_xoffset, (ClientData) NULL);
  22065. Tcl_DecrRefCount(nameObj);
  22066. nameObj=Tcl_NewStringObj("yoffset",-1);
  22067. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Plotter_yoffset, (ClientData) NULL);
  22068. Tcl_DecrRefCount(nameObj);
  22069. nameObj=Tcl_NewStringObj("zoom",-1);
  22070. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Plotter_zoom, (ClientData) NULL);
  22071. Tcl_DecrRefCount(nameObj);
  22072. return TCL_OK;
  22073. }
  22074. /* OO Method Slicer drawline */
  22075. static int OOMethod_Slicer_drawline(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22076.  
  22077. /*
  22078. ** tclmethod: SLICER drawline_dxyz CANVAS PATH TAG TRANSDECK-TAG P-TAG
  22079. ** title: Return TK to draw a line on a canvas
  22080. */
  22081. Slicer *p = GETSLICER(thisObject);
  22082.  
  22083. int i, j=0, totalN, n, len;
  22084. double *xCoord,*yCoord; /* Actual coordinates of line to draw */
  22085. int *deckCoord;
  22086. struct OneSlice **apDeck; /* Array of all decks */
  22087. const char *zKTag=NULL;
  22088. const char *zXTag=NULL;
  22089. const char *zBTag=NULL;
  22090. if( objc < 5 && objc > 7 ){
  22091. Tcl_WrongNumArgs(interp, 2, objv,
  22092. "CANVAS PATH TAG ?TRANSDECK-TAG? ?BEND-TAG?");
  22093. return TCL_ERROR;
  22094. }
  22095. if( Tcl_ListObjLength(interp, objv[3], &n) ) return TCL_ERROR;
  22096.  
  22097. totalN=n+2;
  22098. xCoord = (double *)Odie_Alloc(sizeof(xCoord[0])*totalN);
  22099. yCoord = (double *)Odie_Alloc(sizeof(yCoord[0])*totalN);
  22100. deckCoord = (int *)Odie_Alloc(sizeof(deckCoord[0])*(totalN));
  22101. apDeck = (struct OneSlice **)Odie_Alloc(sizeof(apDeck[0])*(totalN));
  22102.  
  22103. if( xCoord==0 || yCoord == 0 || deckCoord == 0 || apDeck == 0 ) {
  22104. return TCL_ERROR;
  22105. }
  22106.  
  22107. j=0;
  22108. for(i=0; i<n; i++){
  22109. Tcl_Obj *deckObj,*xObj,*yObj;
  22110. Tcl_ListObjIndex(0, objv[3], i, &deckObj);
  22111. if( Tcl_GetIntFromObj(interp, deckObj, &deckCoord[j]) || i>(n-4) ) {
  22112. if(Location_FromTclObj(interp,deckObj,&deckCoord[j],&xCoord[j],&yCoord[j])) {
  22113. goto badRoute;
  22114. }
  22115. } else {
  22116. if(i++ >= n) goto badRoute;
  22117. Tcl_ListObjIndex(0, objv[3], i, &xObj);
  22118. if(i++ >= n) goto badRoute;
  22119. Tcl_ListObjIndex(0, objv[3], i, &yObj);
  22120. i++;
  22121. if( Odie_GetMatrixElementFromObj(interp, xObj, xCoord, j) ) goto badRoute;
  22122. if( Odie_GetMatrixElementFromObj(interp, yObj, yCoord, j) ) goto badRoute;
  22123. }
  22124. if(deckCoord[j]==deckCoord[j-1]) {
  22125. apDeck[j]=apDeck[j-1];
  22126. } else {
  22127. apDeck[j]=Slicer_getDeck_FromInt(p,deckCoord[j]); if(!apDeck[j]) goto badRoute;
  22128. }
  22129. j++;
  22130. }
  22131. zKTag = (const char *)Tcl_GetStringFromObj(objv[4], &len);
  22132. if(objc>=6) {
  22133. zXTag=(const char *)Tcl_GetStringFromObj(objv[5], &len);
  22134. if(len==0) {
  22135. zXTag=NULL;
  22136. }
  22137. }
  22138. if(objc==7) {
  22139. zBTag=(const char *)Tcl_GetStringFromObj(objv[6], &len);
  22140. if(len==0) {
  22141. zBTag=NULL;
  22142. }
  22143. }
  22144.  
  22145. slicer_drawline_do(interp,p,j,deckCoord,xCoord,yCoord,apDeck,objv[2],zKTag,zXTag,zBTag);
  22146. Odie_Free((char *)xCoord);
  22147. Odie_Free((char *)yCoord);
  22148. Odie_Free((char *)deckCoord);
  22149. Odie_Free((char *)apDeck);
  22150. return TCL_OK;
  22151.  
  22152. badRoute:
  22153. Odie_Free((char *)xCoord);
  22154. Odie_Free((char *)yCoord);
  22155. Odie_Free((char *)deckCoord);
  22156. Odie_Free((char *)apDeck);
  22157. return TCL_ERROR;
  22158. }
  22159. /* OO Method Slicer above */
  22160. static int OOMethod_Slicer_above(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22161.  
  22162. /*
  22163. ** tclmethod: SLICER above NAME
  22164. ** title: Return the deck above NAME
  22165. */
  22166. Slicer *p = GETSLICER(thisObject);
  22167. struct OneSlice *pDeck;
  22168. if( objc!=3 && objc!=5 && objc!=6){
  22169. Tcl_WrongNumArgs(interp, 2, objv, "NAME ?x y? ?zoff?");
  22170. return TCL_ERROR;
  22171. }
  22172. if( Slicer_getDeckId(interp,p,objv[2],&pDeck) ) return TCL_ERROR;
  22173. if(objc==3) {
  22174. Tcl_SetObjResult(interp, Tcl_NewIntObj(pDeck->above));
  22175. } else {
  22176. Tcl_Obj *pResult=Tcl_NewObj();
  22177.  
  22178. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewIntObj(pDeck->above));
  22179. Tcl_ListObjAppendElement(interp, pResult, Tcl_DuplicateObj(objv[3]));
  22180. Tcl_ListObjAppendElement(interp, pResult, Tcl_DuplicateObj(objv[4]));
  22181. if(objc==6) {
  22182. Tcl_ListObjAppendElement(interp, pResult, Tcl_DuplicateObj(objv[5]));
  22183. }
  22184. Tcl_SetObjResult(interp, pResult);
  22185. }
  22186. return TCL_OK;
  22187. }
  22188. /* OO Method Slicer below */
  22189. static int OOMethod_Slicer_below(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22190.  
  22191. /*
  22192. ** tclmethod: SLICER below NAME
  22193. ** title: Return the deck below NAME
  22194. */
  22195. Slicer *p = GETSLICER(thisObject);
  22196. struct OneSlice *pDeck;
  22197. if( objc!=3 && objc!=5 && objc!=6){
  22198. Tcl_WrongNumArgs(interp, 2, objv, "NAME ?x y? ?zoff?");
  22199. return TCL_ERROR;
  22200. }
  22201. if( Slicer_getDeckId(interp,p,objv[2],&pDeck) ) return TCL_ERROR;
  22202. if(objc==3) {
  22203. Tcl_SetObjResult(interp, Tcl_NewIntObj(pDeck->below));
  22204. } else {
  22205. Tcl_Obj *pResult=Tcl_NewObj();
  22206.  
  22207. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewIntObj(pDeck->below));
  22208. Tcl_ListObjAppendElement(interp, pResult, Tcl_DuplicateObj(objv[3]));
  22209. Tcl_ListObjAppendElement(interp, pResult, Tcl_DuplicateObj(objv[4]));
  22210. if(objc==6) {
  22211. Tcl_ListObjAppendElement(interp, pResult, Tcl_DuplicateObj(objv[5]));
  22212. }
  22213. Tcl_SetObjResult(interp, pResult);
  22214. }
  22215. return TCL_OK;
  22216. }
  22217. /* OO Method Slicer deckid_to_name */
  22218. static int OOMethod_Slicer_deckid_to_name(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22219.  
  22220. Slicer *p = GETSLICER(thisObject);
  22221. struct OneSlice *pDeck;
  22222. if( objc!=3 ) {
  22223. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  22224. return TCL_ERROR;
  22225. }
  22226. if( Slicer_getDeckId(interp,p,objv[2],&pDeck) ) return TCL_ERROR;
  22227. Tcl_SetObjResult(interp, ODIE_CONSTANT_STRING(pDeck->zName));
  22228. return TCL_OK;
  22229. }
  22230. /* OO Method Slicer deckname_to_id */
  22231. static int OOMethod_Slicer_deckname_to_id(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22232.  
  22233. Slicer *p = GETSLICER(thisObject);
  22234. struct OneSlice *pDeck;
  22235. if( objc!=3 ) {
  22236. Tcl_WrongNumArgs(interp, 2, objv, "NAME");
  22237. return TCL_ERROR;
  22238. }
  22239. if( Slicer_getDeckId(interp,p,objv[2],&pDeck) ) return TCL_ERROR;
  22240. Tcl_SetObjResult(interp, Tcl_NewIntObj(pDeck->did));
  22241. return TCL_OK;
  22242. }
  22243. /* OO Method Slicer bbox_to_location */
  22244. static int OOMethod_Slicer_bbox_to_location(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22245.  
  22246. /*
  22247. ** tclmethod: SLICER bbox_to_midpoint MINX MINY MINZ MAXX MAXY MAXZ
  22248. ** title: Convert from a bounding box to IRM Coordinates of the base
  22249. */
  22250. Slicer *p = GETSLICER(thisObject);
  22251. double x0, y0, z0, x1, y1, dheight;
  22252. Tcl_Obj *pResult;
  22253. struct OneSlice *pS;
  22254. if( p->nSlice<=0 ){
  22255. Tcl_AppendResult(interp, "no slices defined", 0);
  22256. return TCL_ERROR;
  22257. }
  22258. pResult = Tcl_NewObj();
  22259. if (objc!=8) {
  22260. Tcl_WrongNumArgs(interp, 2, objv, "MINX MINY MINZ MAXX MAXY MAXZ");
  22261. return TCL_ERROR;
  22262. }
  22263. if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR;
  22264. if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR;
  22265. if( Tcl_GetDoubleFromObj(interp, objv[4], &z0) ) return TCL_ERROR;
  22266. if( Tcl_GetDoubleFromObj(interp, objv[5], &x1) ) return TCL_ERROR;
  22267. if( Tcl_GetDoubleFromObj(interp, objv[6], &y1) ) return TCL_ERROR;
  22268. pS = Slicer_deckAt(p, x0, z0);
  22269. dheight=z0-Slicer_deckHeight(pS,x0);
  22270. if(dheight<0) {
  22271. dheight=0;
  22272. }
  22273. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pS->did));
  22274. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj((x1-x0)/2+x0));
  22275. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj((y1-y0)/2+y0));
  22276. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(dheight));
  22277.  
  22278. Tcl_SetObjResult(interp, pResult);
  22279. return TCL_OK;
  22280. }
  22281. /* OO Method Slicer bbox_to_midpoint */
  22282. static int OOMethod_Slicer_bbox_to_midpoint(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22283.  
  22284. /*
  22285. ** tclmethod: SLICER bbox_to_midpoint MINX MINY MINZ MAXX MAXY MAXZ
  22286. ** title: Convert from a bounding box to IRM Coordinates of the midpoint
  22287. */
  22288. Slicer *p = GETSLICER(thisObject);
  22289. double x0, y0, z0, x1, y1, z1, dheight;
  22290. Tcl_Obj *pResult;
  22291. struct OneSlice *pS;
  22292. if( p->nSlice<=0 ){
  22293. Tcl_AppendResult(interp, "no slices defined", 0);
  22294. return TCL_ERROR;
  22295. }
  22296. pResult = Tcl_NewObj();
  22297. if (objc!=8) {
  22298. Tcl_WrongNumArgs(interp, 2, objv, "MINX MINY MINZ MAXX MAXY MAXZ");
  22299. return TCL_ERROR;
  22300. }
  22301. if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR;
  22302. if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR;
  22303. if( Tcl_GetDoubleFromObj(interp, objv[4], &z0) ) return TCL_ERROR;
  22304. if( Tcl_GetDoubleFromObj(interp, objv[5], &x1) ) return TCL_ERROR;
  22305. if( Tcl_GetDoubleFromObj(interp, objv[6], &y1) ) return TCL_ERROR;
  22306. if( Tcl_GetDoubleFromObj(interp, objv[7], &z1) ) return TCL_ERROR;
  22307. pS = Slicer_deckAt(p, x0, z0);
  22308. dheight=((z1-z0)/2+z0)-Slicer_deckHeight(pS,x0);
  22309. if (dheight<0) {
  22310. dheight=0;
  22311. }
  22312. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pS->did));
  22313. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj((x1-x0)/2+x0));
  22314. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj((y1-y0)/2+y0));
  22315. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(dheight));
  22316.  
  22317. Tcl_SetObjResult(interp, pResult);
  22318. return TCL_OK;
  22319. }
  22320. /* OO Method Slicer xyz_to_location */
  22321. static int OOMethod_Slicer_xyz_to_location(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22322.  
  22323. /*
  22324. ** tclmethod: SLICER xyz_to_location X Y Z
  22325. ** title: Convert from X Y Z to IRM Coordinates
  22326. **
  22327. ** The ABOVE-DECK parameter, if present, is the height above the deck.
  22328. */
  22329. Slicer *p = GETSLICER(thisObject);
  22330. double x0, y0, z0, dheight;
  22331. Tcl_Obj *pResult;
  22332. struct OneSlice *pS;
  22333. int i;
  22334. if(objc==2) {
  22335. Tcl_SetObjResult(interp, Tcl_NewObj());
  22336. return TCL_OK;
  22337. }
  22338. if( objc < 5 ){
  22339. Tcl_WrongNumArgs(interp, 2, objv, "X Y Z ?x y z?");
  22340. return TCL_ERROR;
  22341. }
  22342. if( p->nSlice<=0 ){
  22343. Tcl_AppendResult(interp, "no slices defined", 0);
  22344. return TCL_ERROR;
  22345. }
  22346. pResult = Tcl_NewObj();
  22347.  
  22348. for(i=2;i<objc;i+=3) {
  22349. if( Tcl_GetDoubleFromObj(interp, objv[i], &x0) ) return TCL_ERROR;
  22350. if( Tcl_GetDoubleFromObj(interp, objv[i+1], &y0) ) return TCL_ERROR;
  22351. if( Tcl_GetDoubleFromObj(interp, objv[i+2], &z0) ) return TCL_ERROR;
  22352. pS = Slicer_deckAt(p, x0, z0);
  22353. dheight=z0-Slicer_deckHeight(pS,x0);
  22354.  
  22355. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pS->did));
  22356. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(x0));
  22357. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(y0));
  22358. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(dheight));
  22359. }
  22360.  
  22361. Tcl_SetObjResult(interp, pResult);
  22362. return TCL_OK;
  22363. }
  22364. /* OO Method Slicer location_to_xyz */
  22365. static int OOMethod_Slicer_location_to_xyz(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22366.  
  22367. Slicer *p = GETSLICER(thisObject);
  22368. int i;
  22369. double x0, y0, z0, dheight;
  22370. Tcl_Obj *pResult;
  22371. struct OneSlice *pS;
  22372. if(objc==2) {
  22373. Tcl_SetObjResult(interp, Tcl_NewObj());
  22374. return TCL_OK;
  22375. }
  22376. if( objc!= 5 && objc < 6 ){
  22377. Tcl_WrongNumArgs(interp, 2, objv, "DECK X Y ?ZOFF? ...");
  22378. return TCL_ERROR;
  22379. }
  22380. if( p->nSlice<=0 ){
  22381. Tcl_AppendResult(interp, "no slices defined", 0);
  22382. return TCL_ERROR;
  22383. }
  22384. if(objc<7) {
  22385. if( Slicer_getDeckId(interp,p,objv[2],&pS) ) return TCL_ERROR;
  22386. if( Tcl_GetDoubleFromObj(interp, objv[3], &x0) ) return TCL_ERROR;
  22387. if( Tcl_GetDoubleFromObj(interp, objv[4], &y0) ) return TCL_ERROR;
  22388. if(objc==6) {
  22389. if( Tcl_GetDoubleFromObj(NULL, objv[5], &dheight) ) {
  22390. dheight=0.0;
  22391. }
  22392. } else {
  22393. dheight=0.0;
  22394. }
  22395. pResult = Tcl_NewObj();
  22396. z0=Slicer_Location_zabs(p,pS,x0,dheight);
  22397. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(x0));
  22398. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(y0));
  22399. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(z0));
  22400. Tcl_SetObjResult(interp, pResult);
  22401. return TCL_OK;
  22402. }
  22403. pResult = Tcl_NewObj();
  22404. for(i=2;i<objc;i+=4) {
  22405. if( Slicer_getDeckId(interp,p,objv[i],&pS) ) return TCL_ERROR;
  22406. if( Tcl_GetDoubleFromObj(interp, objv[i+1], &x0) ) return TCL_ERROR;
  22407. if( Tcl_GetDoubleFromObj(interp, objv[i+2], &y0) ) return TCL_ERROR;
  22408. if( Tcl_GetDoubleFromObj(NULL, objv[i+3], &dheight) ) return TCL_ERROR;
  22409.  
  22410. z0=Slicer_Location_zabs(p,pS,x0,dheight);
  22411. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(x0));
  22412. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(y0));
  22413. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(z0));
  22414. }
  22415. Tcl_SetObjResult(interp, pResult);
  22416. return TCL_OK;
  22417. }
  22418. /* OO Method Slicer location_z */
  22419. static int OOMethod_Slicer_location_z(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22420.  
  22421. Slicer *p = GETSLICER(thisObject);
  22422. double x0, y0, z0, dheight;
  22423. struct OneSlice *pS;
  22424. if( objc!= 5 && objc!=6 ){
  22425. Tcl_WrongNumArgs(interp, 2, objv, "DECK X Y ?ZOFF? ...");
  22426. return TCL_ERROR;
  22427. }
  22428. if( p->nSlice<=0 ){
  22429. Tcl_AppendResult(interp, "no slices defined", 0);
  22430. return TCL_ERROR;
  22431. }
  22432. if( Slicer_getDeckId(interp,p,objv[2],&pS) ) return TCL_ERROR;
  22433. if( Tcl_GetDoubleFromObj(interp, objv[3], &x0) ) return TCL_ERROR;
  22434. if( Tcl_GetDoubleFromObj(interp, objv[4], &y0) ) return TCL_ERROR;
  22435. if(objc==6) {
  22436. if( Tcl_GetDoubleFromObj(NULL, objv[5], &dheight) ) {
  22437. dheight=0.0;
  22438. }
  22439. } else {
  22440. dheight=0.0;
  22441. }
  22442. z0=Slicer_Location_zabs(p,pS,x0,dheight);
  22443. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(z0));
  22444. return TCL_OK;
  22445. }
  22446. /* OO Method Slicer distance */
  22447. static int OOMethod_Slicer_distance(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22448.  
  22449. Slicer *p = GETSLICER(thisObject);
  22450. int d0,d1;
  22451. double x0, y0, z0, zoff0;
  22452. double x1, y1, z1, zoff1;
  22453. double dx,dy,dz,distance;
  22454. struct OneSlice *pS0;
  22455. struct OneSlice *pS1;
  22456. if( objc!= 4 ){
  22457. Tcl_WrongNumArgs(interp, 2, objv, "LOCATION LOCATION");
  22458. return TCL_ERROR;
  22459. }
  22460. if( p->nSlice<=0 ){
  22461. Tcl_AppendResult(interp, "no slices defined", 0);
  22462. return TCL_ERROR;
  22463. }
  22464. if(Location_Base_FromTclObj(interp,objv[2],&d0,&x0,&y0,&zoff0)) return TCL_ERROR;
  22465. if(Location_Base_FromTclObj(interp,objv[3],&d1,&x1,&y1,&zoff1)) return TCL_ERROR;
  22466. pS0=Slicer_getDeck_FromInt(p,d0);
  22467. if(pS0) {
  22468. z0=Slicer_Location_zabs(p,pS0,x0,zoff0);
  22469. } else {
  22470. z0=zoff0;
  22471. }
  22472. pS1=Slicer_getDeck_FromInt(p,d1);
  22473. if(pS1) {
  22474. z1=Slicer_Location_zabs(p,pS1,x1,zoff1);
  22475. } else {
  22476. z1=zoff1;
  22477. }
  22478. dx=x1-x0;
  22479. dy=y1-y0;
  22480. dz=z1-z0;
  22481. distance=sqrt(dx*dx+dy*dy+dz*dz);
  22482. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(distance));
  22483. return TCL_OK;
  22484. }
  22485. /* OO Method Slicer actualcoords */
  22486. static int OOMethod_Slicer_actualcoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22487.  
  22488. /*
  22489. ** tclmethod: SLICER actualcoords CANVAS-COORD-LIST ?ABOVE-DECK?
  22490. ** title: Convert from canvas to actual coordinate space
  22491. **
  22492. ** The ABOVE-DECK parameter, if present, is the height above the deck.
  22493. */
  22494. Slicer *p = GETSLICER(thisObject);
  22495. int i, n;
  22496. double aboveDeck;
  22497. Tcl_Obj *pResult;
  22498. if( objc!=3 && objc!=4 ){
  22499. Tcl_WrongNumArgs(interp, 2, objv, "CANVAS-COORD-LIST ?ABOVE-DECK?");
  22500. return TCL_ERROR;
  22501. }
  22502. if( Tcl_ListObjLength(interp, objv[2], &n) ) return TCL_ERROR;
  22503. if( n%2!=0 ){
  22504. Tcl_AppendResult(interp, "coordinate list must contain a multiple "
  22505. "of 2 values", 0);
  22506. return TCL_ERROR;
  22507. }
  22508. if( objc==4 ){
  22509. if( Tcl_GetDoubleFromObj(interp, objv[3], &aboveDeck) ) return TCL_ERROR;
  22510. }else{
  22511. aboveDeck = 0.0;
  22512. }
  22513. if( p->nSlice<=0 ){
  22514. Tcl_AppendResult(interp, "no slices defined", 0);
  22515. return TCL_ERROR;
  22516. }
  22517. pResult = Tcl_NewObj();
  22518. for(i=0; i<n-1; i+=2){
  22519. double ax, ay;
  22520. double cx, cy;
  22521. Tcl_Obj *pObj;
  22522. int j;
  22523. struct OneSlice *pS;
  22524. Tcl_ListObjIndex(0, objv[2], i, &pObj);
  22525. if( Tcl_GetDoubleFromObj(interp, pObj, &cx) ) break;
  22526. Tcl_ListObjIndex(0, objv[2], i+1, &pObj);
  22527. if( Tcl_GetDoubleFromObj(interp, pObj, &cy) ) break;
  22528. for(j=0; j<p->nSlice-1 && p->a[j].upperbound>cy; j++){}
  22529. pS = &p->a[j];
  22530.  
  22531. /* Original Formula
  22532. ** ax = cx*p->rZoom - pS->rXShift;
  22533. ** ay = pS->mxY + (pS->mnY-pS->mxY)*(cy-pS->top)/(pS->btm-pS->top);
  22534. */
  22535. ax=Slicer_xCanvasToActual(p,pS,cx);
  22536. ay=Slicer_yCanvasToActual(p,pS,cy);
  22537.  
  22538. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pS->did));
  22539. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(round(ax)));
  22540. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(round(ay)));
  22541. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(round(aboveDeck)));
  22542. }
  22543. if( i<n-1 ){
  22544. Tcl_DecrRefCount(pResult);
  22545. return TCL_ERROR;
  22546. }
  22547. Tcl_SetObjResult(interp, pResult);
  22548. return TCL_OK;
  22549. }
  22550. /* OO Method Slicer canvascoords */
  22551. static int OOMethod_Slicer_canvascoords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22552.  
  22553. /*
  22554. ** tclmethod: SLICER canvascoords ACTUAL-COORD-LIST ?xvar? ?yvar?
  22555. ** title: Convert from actual (in DID X Y) to canvas coordinate space
  22556. **
  22557. ** The coordinates are considered to form a line. If the actual
  22558. ** coordinates make a transition from one slice to another, an extra
  22559. ** set of canvas coordinates may be inserted to show the point of
  22560. ** this transition.
  22561. **
  22562. */
  22563. Slicer *p = GETSLICER(thisObject);
  22564. int i, n;
  22565. Tcl_Obj *pResult=NULL;
  22566. double ax, ay;
  22567. double cx, cy;
  22568. Tcl_Obj *pObj;
  22569. struct OneSlice *pS;
  22570. int error=0;
  22571.  
  22572. if( objc!=3 && objc!=5 ){
  22573. Tcl_WrongNumArgs(interp, 2, objv, "ACTUAL-COORD-LIST ?xvar yvar?");
  22574. return TCL_ERROR;
  22575. }
  22576. if( Tcl_ListObjLength(interp, objv[2], &n) ) return TCL_ERROR;
  22577. if(n==3) {
  22578. /* Goose a 3 length to a 4 length */
  22579. n=4;
  22580. }
  22581. if(n<4 || n%4!=0) {
  22582. Tcl_AppendResult(interp, "coordinate list must contain a multiple "
  22583. "of 4 values", 0);
  22584. return TCL_ERROR;
  22585. }
  22586.  
  22587. if( p->nSlice<=0 ){
  22588. Tcl_AppendResult(interp, "no slices defined", 0);
  22589. return TCL_ERROR;
  22590. }
  22591. if(objc != 5) {
  22592. pResult = Tcl_NewObj();
  22593. }
  22594.  
  22595. for(i=0; i<n-3; i+=4){
  22596. Tcl_ListObjIndex(0, objv[2], i+1, &pObj);
  22597. if( Tcl_GetDoubleFromObj(interp, pObj, &ax) ) {
  22598. error=1;
  22599. break;
  22600. }
  22601. Tcl_ListObjIndex(0, objv[2], i+2, &pObj);
  22602. if( Tcl_GetDoubleFromObj(interp, pObj, &ay) ) {
  22603. error=1;
  22604. break;
  22605. }
  22606. Tcl_ListObjIndex(0, objv[2], i, &pObj);
  22607. if( Slicer_getDeckId(interp, p, pObj, &pS) ) {
  22608. error=1;
  22609. break;
  22610. }
  22611.  
  22612. /* Old direct formula
  22613. **
  22614. ** cx = (ax+pS->rXShift)/p->rZoom;
  22615. ** cy = pS->top + (pS->btm-pS->top)*(ay-pS->mxY)/(pS->mnY-pS->mxY);
  22616. */
  22617. cx = Slicer_xActualToCanvas(p,pS,ax);
  22618. cy = Slicer_yActualToCanvas(p,pS,ay);
  22619.  
  22620. if(objc==5) {
  22621. Tcl_ObjSetVar2(interp,objv[3],NULL,Tcl_NewDoubleObj(cx),0);
  22622. Tcl_ObjSetVar2(interp,objv[4],NULL,Tcl_NewDoubleObj(cy),0);
  22623. return TCL_OK;
  22624. } else {
  22625. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(cx));
  22626. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(cy));
  22627. }
  22628. }
  22629. if(error) {
  22630. if(pResult) {
  22631. Tcl_DecrRefCount(pResult);
  22632. }
  22633. return TCL_ERROR;
  22634. }
  22635. if( i<n-3 ){
  22636. Tcl_AppendResult(interp, "Did not reach the end", 0);
  22637. Tcl_DecrRefCount(pResult);
  22638. return TCL_ERROR;
  22639. }
  22640.  
  22641. Tcl_SetObjResult(interp, pResult);
  22642. return TCL_OK;
  22643. }
  22644. /* OO Method Slicer create */
  22645. static int OOMethod_Slicer_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22646.  
  22647. /*
  22648. ** tclmethod: SLICER create DID NAME Z MIN-Y MAX-Y
  22649. ** title: Create a new slice
  22650. */
  22651. Slicer *p = GETSLICER(thisObject);
  22652. double z, mnY, mxY;
  22653. const char *zNameOrig;
  22654. char *zName;
  22655. int did;
  22656. int i, nName;
  22657. if( objc!=7 ){
  22658. Tcl_WrongNumArgs(interp, 2, objv, "DID NAME Z MIN-Y MAX-Y");
  22659. return TCL_ERROR;
  22660. }
  22661. if( Tcl_GetIntFromObj(interp, objv[2], &did) ) return TCL_ERROR;
  22662. zNameOrig = Tcl_GetStringFromObj(objv[3], &nName);
  22663. if( Tcl_GetDoubleFromObj(interp, objv[4], &z) ) return TCL_ERROR;
  22664. if( Tcl_GetDoubleFromObj(interp, objv[5], &mnY) ) return TCL_ERROR;
  22665. if( Tcl_GetDoubleFromObj(interp, objv[6], &mxY) ) return TCL_ERROR;
  22666. if( mnY>=mxY ){
  22667. Tcl_AppendResult(interp, "MIN-Y must be less than MAX-Y", 0);
  22668. return TCL_ERROR;
  22669. }
  22670. zName = Odie_Alloc( nName+1 );
  22671. if( zName==0 ) return TCL_ERROR;
  22672. memcpy(zName, zNameOrig, nName+1);
  22673. for(i=0; i<p->nSlice; i++){
  22674. if( p->a[i].did==did ){
  22675. Tcl_AppendResult(interp, "Deckid for slice ", zName, " is the "
  22676. "same as existing slice ", p->a[i].zName, 0);
  22677. return TCL_ERROR;
  22678. }
  22679. if( p->a[i].z==z ){
  22680. Tcl_AppendResult(interp, "Z coordinate for slice ", zName, " is the "
  22681. "same as existing slice ", p->a[i].zName, 0);
  22682. return TCL_ERROR;
  22683. }
  22684. }
  22685. p->nSlice++;
  22686. p->a = (OneSlice *)Tcl_Realloc((char *)p->a, sizeof(p->a[0])*p->nSlice);
  22687. if( p->a==0 ){
  22688. p->nSlice = 0;
  22689. return TCL_ERROR;
  22690. }
  22691. for(i=p->nSlice-1; i>0 && p->a[i-1].z>z; i--){
  22692. p->a[i] = p->a[i-1];
  22693. p->a[i].idx = i;
  22694. }
  22695. p->a[i].did = did;
  22696. p->a[i].idx = i;
  22697. p->a[i].zName = zName;
  22698. p->a[i].nXZ = 0;
  22699. p->a[i].xz = 0;
  22700. p->a[i].z = z;
  22701. p->a[i].mnY = mnY;
  22702. p->a[i].mxY = mxY;
  22703. p->a[i].rXShift = p->rXOffset*z;
  22704. Slicer_computeTopAndBottom(p);
  22705. return TCL_OK;
  22706. }
  22707. /* OO Method Slicer deck_at_xyz */
  22708. static int OOMethod_Slicer_deck_at_xyz(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22709.  
  22710. /*
  22711. ** tclmethod: SLICER deck X Y Z
  22712. ** title: Return the name of the deck at actual coordinates X,Y,Z
  22713. **
  22714. ** See also: find
  22715. */
  22716. Slicer *p = GETSLICER(thisObject);
  22717. double x0, y0, z0;
  22718. Tcl_Obj *pResult;
  22719. struct OneSlice *pS;
  22720. if( objc!=5 ){
  22721. Tcl_WrongNumArgs(interp, 2, objv, "X Y Z");
  22722. return TCL_ERROR;
  22723. }
  22724. if( p->nSlice<=0 ){
  22725. Tcl_AppendResult(interp, "no slices defined", 0);
  22726. return TCL_ERROR;
  22727. }
  22728. if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR;
  22729. if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR;
  22730. if( Tcl_GetDoubleFromObj(interp, objv[4], &z0) ) return TCL_ERROR;
  22731. pResult = Tcl_NewObj();
  22732. pS = Slicer_deckAt(p, x0, z0);
  22733. pResult = ODIE_CONSTANT_STRING(pS->zName);
  22734. Tcl_SetObjResult(interp, pResult);
  22735. return TCL_OK;
  22736. }
  22737. /* OO Method Slicer deckid_at_xyx */
  22738. static int OOMethod_Slicer_deckid_at_xyx(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22739.  
  22740. /*
  22741. ** tclmethod: SLICER did X Y Z
  22742. ** title: Return the id of the deck at actual coordinates X,Y,Z
  22743. **
  22744. ** See also: find
  22745. */
  22746. Slicer *p = GETSLICER(thisObject);
  22747. double x0, y0, z0;
  22748. Tcl_Obj *pResult;
  22749. struct OneSlice *pS;
  22750. if( objc!=5 ){
  22751. Tcl_WrongNumArgs(interp, 2, objv, "X Y Z");
  22752. return TCL_ERROR;
  22753. }
  22754. if( p->nSlice<=0 ){
  22755. Tcl_AppendResult(interp, "no slices defined", 0);
  22756. return TCL_ERROR;
  22757. }
  22758. if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR;
  22759. if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR;
  22760. if( Tcl_GetDoubleFromObj(interp, objv[4], &z0) ) return TCL_ERROR;
  22761. pResult = Tcl_NewObj();
  22762. pS = Slicer_deckAt(p, x0, z0);
  22763. pResult = Tcl_NewIntObj(pS->did);
  22764. Tcl_SetObjResult(interp, pResult);
  22765. return TCL_OK;
  22766. }
  22767. /* OO Method Slicer delete */
  22768. static int OOMethod_Slicer_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22769.  
  22770. /*
  22771. ** tclmethod: SLICER delete NAME
  22772. ** title: Remove a slice from the slicer
  22773. */
  22774. Slicer *p = GETSLICER(thisObject);
  22775. int i, j;
  22776. const char *zName;
  22777. if( objc!=2 ){
  22778. Tcl_WrongNumArgs(interp, 2, objv, "NAME");
  22779. return TCL_ERROR;
  22780. }
  22781. zName = Tcl_GetStringFromObj(objv[2], 0);
  22782. for(i=0; i<p->nSlice && strcmp(p->a[i].zName,zName)!=0; i++){}
  22783. if( i<p->nSlice ){
  22784. Odie_Free((char *)p->a[i].zName);
  22785. p->nSlice--;
  22786. for(j=i; j<p->nSlice; j++){
  22787. p->a[j] = p->a[j+1];
  22788. }
  22789. Slicer_computeTopAndBottom(p);
  22790. }
  22791. return TCL_OK;
  22792. }
  22793. /* OO Method Slicer makedlist */
  22794. static int OOMethod_Slicer_makedlist(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22795.  
  22796. /*
  22797. ** tclmethod: SLICER makedlist CANVAS ACTUAL-PATH TAG TRANSDECK-TAG P-TAG ?COLOR?
  22798. ** title: Return TK to draw a line on a canvas
  22799. */
  22800. Slicer *p = GETSLICER(thisObject);
  22801. int i, n;
  22802. double *aCoord; /* Actual coordinates of line to draw */
  22803. struct OneSlice **apDeck; /* Array of all decks */
  22804. Tcl_Obj *pVTag; /* The "sNNN" tag added to all line segments */
  22805. const char *zXTag; /* Trans-deck tag (dashed lines) */
  22806. Tcl_Obj *rtnList ; /* List object to return */
  22807. Tcl_Obj *coordList ; /* List of coords to return */
  22808. Tcl_Obj *configList ; /* configuration string to return */
  22809. Tcl_Obj *tmpObj; /* Cheater for filling lists */
  22810.  
  22811. if( objc!=5 && objc!=6 ){
  22812. Tcl_WrongNumArgs(interp, 2, objv,
  22813. "ACTUAL-PATH TAG TRANSDECK-TAG ?COLOR?");
  22814. return TCL_ERROR;
  22815. }
  22816. // slicer makedlist Path TagList Transdeck-TagList ?COLOR?
  22817. // 0 1 2 3 4 5
  22818.  
  22819. zXTag = Tcl_GetStringFromObj(objv[4], 0);
  22820.  
  22821. if( Tcl_ListObjLength(interp, objv[2], &n) ) return TCL_ERROR;
  22822.  
  22823. if( n%3!=0 || n<6 ){
  22824. Tcl_AppendResult(interp, "coordinate list must contain a multiple "
  22825. "of 3 values with a minimum of 6", 0);
  22826. return TCL_ERROR;
  22827. }
  22828.  
  22829. rtnList = Tcl_NewListObj(0, NULL);
  22830.  
  22831. aCoord = (double *)Odie_Alloc( sizeof(aCoord[0])*n + sizeof(apDeck[0])*(n/3) );
  22832. if( aCoord==0 ){
  22833. return TCL_ERROR;
  22834. }
  22835.  
  22836. // Move coords from Tcl objv[3] int "C" aCoord array
  22837.  
  22838. apDeck = (struct OneSlice **)&aCoord[n];
  22839. for(i=0; i<n; i++){
  22840. Tcl_Obj *pObj;
  22841. Tcl_ListObjIndex(0, objv[2], i, &pObj);
  22842. if( Odie_GetMatrixElementFromObj(interp, pObj, aCoord, i) ){
  22843. Odie_Free((char *)aCoord);
  22844. return TCL_ERROR;
  22845. }
  22846. }
  22847. n /= 3;
  22848.  
  22849. for(i=0; i<n; i++){
  22850. double z = aCoord[i*3+2];
  22851. double x = aCoord[i*3];
  22852. apDeck[i] = Slicer_deckAt(p, x, z);
  22853. }
  22854.  
  22855. for(i=1; i<n; i++){
  22856. char zBuf[30];
  22857. double x0, y0, x1, y1, Y0, Y1;
  22858.  
  22859. coordList = Tcl_NewListObj(0, NULL);
  22860. configList = Tcl_NewListObj(0, NULL);
  22861.  
  22862. sprintf(zBuf, "s%d", i);
  22863. pVTag = Tcl_NewStringObj(zBuf, -1);
  22864. if( apDeck[i]!=apDeck[i-1] ) {
  22865.  
  22866. /* Old direct formula
  22867. **
  22868. ** x0=(aCoord[i*3-3]+apDeck[i-1]->rXShift)/p->rZoom;
  22869. ** x1 = (aCoord[i*3]+apDeck[i]->rXShift)/p->rZoom;
  22870. */
  22871. x0 = Slicer_xActualToCanvas(p,apDeck[i-1],aCoord[i*3-3]);
  22872. x1 = Slicer_xActualToCanvas(p,apDeck[i],aCoord[i*3]);
  22873. y0 = Slicer_yActualToCanvas(p,apDeck[i-1], Y0=aCoord[i*3-2]);
  22874. y1 = Slicer_yActualToCanvas(p,apDeck[i], Y1=aCoord[i*3+1]);
  22875. if( zXTag[0]!=0 ){
  22876. Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(x0));
  22877. Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(y0));
  22878. Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(x1));
  22879. Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(y1));
  22880.  
  22881. Tcl_ListObjAppendElement(interp, configList,
  22882. ODIE_CONSTANT_STRING("-tags"));
  22883.  
  22884. tmpObj = Tcl_DuplicateObj(objv[4]);
  22885. Tcl_ListObjAppendElement(interp, tmpObj, pVTag);
  22886. Tcl_ListObjAppendElement(interp, configList, tmpObj);
  22887.  
  22888. }
  22889. } else {
  22890. /* Old direct formula
  22891. **
  22892. ** x0 = (aCoord[i*3-3]+apDeck[i]->rXShift)/p->rZoom;
  22893. ** x1 = (aCoord[i*3]+apDeck[i]->rXShift)/p->rZoom;
  22894. */
  22895. x0 = Slicer_xActualToCanvas(p,apDeck[i],aCoord[i*3-3]);
  22896. x1 = Slicer_xActualToCanvas(p,apDeck[i],aCoord[i*3]);
  22897.  
  22898. y0 = Slicer_yActualToCanvas(p,apDeck[i], aCoord[i*3-2]);
  22899. y1 = Slicer_yActualToCanvas(p,apDeck[i], aCoord[i*3+1]);
  22900.  
  22901. Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(x0));
  22902. Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(y0));
  22903. Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(x1));
  22904. Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(y1));
  22905.  
  22906.  
  22907. Tcl_ListObjAppendElement(interp, configList, ODIE_CONSTANT_STRING("-tags"));
  22908.  
  22909. tmpObj = Tcl_DuplicateObj(objv[3]);
  22910. Tcl_ListObjAppendElement(interp, tmpObj, pVTag);
  22911.  
  22912. Tcl_ListObjAppendElement(interp, configList, tmpObj);
  22913.  
  22914. }
  22915. if( objc>=6 ) {
  22916. Tcl_ListObjAppendElement(interp, configList, ODIE_CONSTANT_STRING("-fill"));
  22917. Tcl_ListObjAppendElement(interp, configList, Tcl_DuplicateObj(objv[5]));
  22918. }
  22919.  
  22920.  
  22921. Tcl_ListObjAppendElement(interp, rtnList, coordList);
  22922. Tcl_ListObjAppendElement(interp, rtnList, configList);
  22923. }
  22924. Odie_Free((char *)aCoord);
  22925.  
  22926. Tcl_SetObjResult(interp, rtnList);
  22927. return TCL_OK;
  22928. }
  22929. /* OO Method Slicer find */
  22930. static int OOMethod_Slicer_find(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22931.  
  22932. /* tclmethod: SLICER find X Y
  22933. ** title: Return the name of the deck at canvas coordinates X,Y
  22934. **
  22935. ** The "deck" command works similarly except that it uses actual
  22936. ** coordinates as inputs.
  22937. */
  22938. Slicer *p = GETSLICER(thisObject);
  22939. int i;
  22940. double x0, y0;
  22941. Tcl_Obj *pResult;
  22942. struct OneSlice *pS;
  22943. if( objc!=4 ){
  22944. Tcl_WrongNumArgs(interp, 2, objv, "X Y");
  22945. return TCL_ERROR;
  22946. }
  22947. if( p->nSlice<=0 ){
  22948. Tcl_AppendResult(interp, "no slices defined", 0);
  22949. return TCL_ERROR;
  22950. }
  22951. if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR;
  22952. if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR;
  22953. pResult = Tcl_NewObj();
  22954. for(i=0; i<p->nSlice-1 && p->a[i].upperbound>y0; i++){}
  22955. pS = &p->a[i];
  22956. pResult = ODIE_CONSTANT_STRING(pS->zName);
  22957. Tcl_SetObjResult(interp, pResult);
  22958. return TCL_OK;
  22959. }
  22960. /* OO Method Slicer finddid */
  22961. static int OOMethod_Slicer_finddid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22962.  
  22963. /*
  22964. ** tclmethod: SLICER finddid X Y
  22965. ** title: Return the name of the deck at canvas coordinates X,Y
  22966. **
  22967. ** The "deck" command works similarly except that it uses actual
  22968. ** coordinates as inputs.
  22969. */
  22970. Slicer *p = GETSLICER(thisObject);
  22971. int i;
  22972. double x0, y0;
  22973. Tcl_Obj *pResult;
  22974. struct OneSlice *pS;
  22975. if( objc!=4 ){
  22976. Tcl_WrongNumArgs(interp, 2, objv, "X Y");
  22977. return TCL_ERROR;
  22978. }
  22979. if( p->nSlice<=0 ){
  22980. Tcl_AppendResult(interp, "no slices defined", 0);
  22981. return TCL_ERROR;
  22982. }
  22983. if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR;
  22984. if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR;
  22985. pResult = Tcl_NewObj();
  22986. for(i=0; i<p->nSlice-1 && p->a[i].upperbound>y0; i++){}
  22987. pS = &p->a[i];
  22988. pResult = Tcl_NewIntObj(pS->did);
  22989. Tcl_SetObjResult(interp, pResult);
  22990. return TCL_OK;
  22991. }
  22992. /* OO Method Slicer flatheight */
  22993. static int OOMethod_Slicer_flatheight(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  22994.  
  22995. /*
  22996. ** tclmethod: SLICER flatheight NAME ?X?
  22997. ** title: Return the flatheight of slice NAME at actual position X
  22998. ** Assuming the deck were flat
  22999. **
  23000. ** See also "headroom".
  23001. */
  23002. Slicer *p = GETSLICER(thisObject);
  23003. struct OneSlice *ppS;
  23004. //double x0;
  23005.  
  23006. if( objc!=3 && objc!=4 ){
  23007. Tcl_WrongNumArgs(interp, 2, objv, "NAME ?X?");
  23008. return TCL_ERROR;
  23009. }
  23010. //if( Tcl_GetDoubleFromObj(interp, objv[3], &x0) ) return TCL_ERROR;
  23011. if( Slicer_getDeckId(interp,p,objv[2],&ppS) ) return TCL_ERROR;
  23012.  
  23013. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(ppS->z));
  23014. return TCL_OK;
  23015. }
  23016. /* OO Method Slicer headroom */
  23017. static int OOMethod_Slicer_headroom(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23018.  
  23019. /*
  23020. ** tclmethod: SLICER headroom NAME X
  23021. ** title: Return the headroom (Z from deck) of slice NAME at actual position X
  23022. **
  23023. ** See also "height"
  23024. */
  23025. Slicer *p = GETSLICER(thisObject);
  23026. double x0;
  23027. struct OneSlice *pDeck, *pAbove;
  23028. if( objc!=4 ){
  23029. Tcl_WrongNumArgs(interp, 2, objv, "NAME X");
  23030. return TCL_ERROR;
  23031. }
  23032. if( Tcl_GetDoubleFromObj(interp, objv[3], &x0) ) return TCL_ERROR;
  23033.  
  23034. if( Slicer_getDeckId(interp,p,objv[2],&pDeck) ) return TCL_ERROR;
  23035. pAbove = Slicer_deckAbove(p, pDeck);
  23036. if( pAbove ){
  23037. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(Slicer_deckHeight(pAbove,x0)-Slicer_deckHeight(pDeck,x0)));
  23038. }else{
  23039. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(p->upper_height));
  23040. }
  23041. return TCL_OK;
  23042. }
  23043. /* OO Method Slicer ceiling */
  23044. static int OOMethod_Slicer_ceiling(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23045.  
  23046. /*
  23047. ** tclmethod: SLICER ceiling NAME X ?DEFAULT?
  23048. ** title: Return the Z (absolute) of the ceiling of slice NAME at actual position X
  23049. **
  23050. ** See also "height"
  23051. */
  23052. Slicer *p = GETSLICER(thisObject);
  23053. double x0;
  23054. struct OneSlice *pDeck, *pAbove;
  23055. if( objc!=4 ){
  23056. Tcl_WrongNumArgs(interp, 2, objv, "NAME X");
  23057. return TCL_ERROR;
  23058. }
  23059. if( Tcl_GetDoubleFromObj(interp, objv[3], &x0) ) return TCL_ERROR;
  23060.  
  23061. if( Slicer_getDeckId(interp,p,objv[2],&pDeck) ) return TCL_ERROR;
  23062. pAbove = Slicer_deckAbove(p, pDeck);
  23063. if( pAbove ){
  23064. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(Slicer_deckHeight(pAbove,x0)));
  23065. }else{
  23066. Tcl_SetObjResult(interp,Tcl_NewDoubleObj(Slicer_deckHeight(pDeck,x0)+p->upper_height));
  23067. }
  23068. return TCL_OK;
  23069. }
  23070. /* OO Method Slicer height */
  23071. static int OOMethod_Slicer_height(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23072.  
  23073. /*
  23074. ** tclmethod: SLICER height NAME X ?zoff?
  23075. ** title: Return the height (absolute) of slice NAME at actual position X
  23076. ** description:
  23077. ** NOTE if the top deck is asked for, and zoff is negative the
  23078. ** system will assume a 2000mm ceiling
  23079. ** See also "headroom".
  23080. */
  23081. Slicer *p = GETSLICER(thisObject);
  23082. struct OneSlice *ppS,*pAbove;
  23083. double x0,zoff=0,zresult=0.0;
  23084. if( objc!=4 && objc!=5 ){
  23085. Tcl_WrongNumArgs(interp, 2, objv, "NAME X ?ZOFF?");
  23086. return TCL_ERROR;
  23087. }
  23088. if( Tcl_GetDoubleFromObj(interp, objv[3], &x0) ) return TCL_ERROR;
  23089. if( Slicer_getDeckId(interp,p,objv[2],&ppS) ) return TCL_ERROR;
  23090. if( objc==5 ) {
  23091. if( Tcl_GetDoubleFromObj(NULL, objv[4], &zoff) ) {
  23092. zoff=0.0;
  23093. }
  23094. }
  23095. if(zoff < 0.0) {
  23096. pAbove = Slicer_deckAbove(p, ppS);
  23097. if(pAbove) {
  23098. zresult=Slicer_deckHeight(pAbove,x0)+zoff;
  23099. } else {
  23100. zresult=Slicer_deckHeight(ppS,x0)+2000+zoff;
  23101. }
  23102. } else {
  23103. zresult=Slicer_deckHeight(ppS,x0)+zoff;
  23104. }
  23105. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(zresult));
  23106. return TCL_OK;
  23107. }
  23108. /* OO Method Slicer deckheight */
  23109. static int OOMethod_Slicer_deckheight(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23110.  
  23111. /*
  23112. ** tclmethod: SLICER deckheight NAME X ?zoff?
  23113. ** title: Return the height (mm from floor) of slice NAME at actual position X
  23114. ** description:
  23115. ** NOTE if the top deck is asked for, and zoff is negative the
  23116. ** system will assume a 2000mm ceiling
  23117. ** See also "headroom".
  23118. */
  23119. Slicer *p = GETSLICER(thisObject);
  23120. double x0, z0, dheight;
  23121. struct OneSlice *pS;
  23122. if( objc!= 4 && objc!=5 ){
  23123. Tcl_WrongNumArgs(interp, 2, objv, "DECK X ?ZOFF?");
  23124. return TCL_ERROR;
  23125. }
  23126. if( p->nSlice<=0 ){
  23127. Tcl_AppendResult(interp, "no slices defined", 0);
  23128. return TCL_ERROR;
  23129. }
  23130. if( Slicer_getDeckId(interp,p,objv[2],&pS) ) return TCL_ERROR;
  23131. if( Tcl_GetDoubleFromObj(interp, objv[3], &x0) ) return TCL_ERROR;
  23132. if(objc==5) {
  23133. if( Tcl_GetDoubleFromObj(NULL, objv[4], &dheight) ) {
  23134. dheight=0.0;
  23135. }
  23136. } else {
  23137. dheight=0.0;
  23138. }
  23139. z0=Location_zdeck(p,pS,x0,dheight);
  23140. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(z0));
  23141. return TCL_OK;
  23142. }
  23143. /* OO Method Slicer info */
  23144. static int OOMethod_Slicer_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23145.  
  23146. /*
  23147. ** tclmethod: SLICER info NAME
  23148. ** title: Return information about a particular slice
  23149. */
  23150. Slicer *p = GETSLICER(thisObject);
  23151. struct OneSlice *ppS;
  23152.  
  23153. if( objc!=3 ){
  23154. Tcl_WrongNumArgs(interp, 2, objv, "NAME|DECKID");
  23155. return TCL_ERROR;
  23156. }
  23157. if( Slicer_getDeckId(interp,p,objv[2],&ppS) ) {
  23158. return TCL_ERROR;
  23159. } else {
  23160. Tcl_Obj *pResult = Tcl_NewObj();
  23161.  
  23162. Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("name"));
  23163. Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING(ppS->zName));
  23164.  
  23165. Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("did"));
  23166. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewIntObj(ppS->did));
  23167.  
  23168.  
  23169. Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("z"));
  23170. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ppS->z));
  23171.  
  23172. Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("miny"));
  23173. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ppS->mnY));
  23174.  
  23175. Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("maxy"));
  23176. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ppS->mxY));
  23177.  
  23178. Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("top"));
  23179. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ppS->top));
  23180.  
  23181. Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("bottom"));
  23182. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ppS->btm));
  23183.  
  23184. Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("above"));
  23185. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ppS->above));
  23186.  
  23187. Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("below"));
  23188. Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ppS->below));
  23189.  
  23190. Tcl_SetObjResult(interp, pResult);
  23191. }
  23192. return TCL_OK;
  23193. }
  23194. /* OO Method Slicer list */
  23195. static int OOMethod_Slicer_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23196.  
  23197. /*
  23198. ** tclmethod: SLICER list
  23199. ** title: List the names of all defined slices in the slicer
  23200. */
  23201. Slicer *p = GETSLICER(thisObject);
  23202. Tcl_Obj *pResult = Tcl_NewObj();
  23203. int i;
  23204. for(i=0; i<p->nSlice; i++){
  23205. Tcl_ListObjAppendElement(0, pResult, ODIE_CONSTANT_STRING(p->a[i].zName));
  23206. }
  23207. Tcl_SetObjResult(interp, pResult);
  23208. return TCL_OK;
  23209. }
  23210. /* OO Method Slicer profile */
  23211. static int OOMethod_Slicer_profile(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23212.  
  23213. /*
  23214. ** tclmethod: SLICER profile DECK ?X Z ...?
  23215. ** title: Create an inboard profile for a deck
  23216. */
  23217. Slicer *p = GETSLICER(thisObject);
  23218. int i, j, min;
  23219. struct OneSlice *pS;
  23220. if( objc<3 || (objc>3 && objc<7) || (objc & 1)==0 ){
  23221. Tcl_WrongNumArgs(interp, 2, objv, "NAME ?X Z X Z...?");
  23222. return TCL_ERROR;
  23223. }
  23224.  
  23225. if(Slicer_getDeckId(interp,p,objv[2],&pS)) {
  23226. return TCL_ERROR;
  23227. }
  23228. if( objc==3 ){
  23229. Tcl_Obj *pResult = Tcl_NewObj();
  23230. for(i=0; i<pS->nXZ; i++){
  23231. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pS->xz[i]));
  23232. }
  23233. Tcl_SetObjResult(interp, pResult);
  23234. }else{
  23235. double *xz;
  23236. if( pS->xz ) Odie_Free((char *)pS->xz);
  23237. pS->nXZ = objc - 3;
  23238. xz = pS->xz = (double *)Odie_Alloc( sizeof(pS->xz[0])*pS->nXZ );
  23239. if( xz==0 ){
  23240. pS->nXZ = 0;
  23241. return TCL_OK;
  23242. }
  23243. for(i=0; i<pS->nXZ; i++){
  23244. if( Odie_GetMatrixElementFromObj(interp, objv[i+3], xz, i) ){
  23245. Odie_Free((char *)xz);
  23246. pS->nXZ = 0;
  23247. pS->xz = 0;
  23248. return TCL_ERROR;
  23249. }
  23250. }
  23251.  
  23252. /* Put the profile in increasing X order. An N**2 sort is used because
  23253. ** it is convenient and the list will usually be short. */
  23254. for(i=0; i<pS->nXZ-2; i+=2){
  23255. for(min=i, j=i+2; j<pS->nXZ; j+=2){
  23256. if( xz[j]<xz[min] ) min = j;
  23257. }
  23258. if( min>i ){
  23259. double t = xz[min];
  23260. xz[min] = xz[i];
  23261. xz[i] = t;
  23262. t = xz[min+1];
  23263. xz[min+1] = xz[i+1];
  23264. xz[i+1] = t;
  23265. }
  23266. }
  23267.  
  23268. /* Remove duplidate X coordinates */
  23269. for(i=j=0; i<pS->nXZ; i+=2){
  23270. if( i<pS->nXZ-2 && xz[i+2]==xz[i] ){
  23271. /* Ignore the duplicate */
  23272. }else{
  23273. xz[j++] = xz[i];
  23274. xz[j++] = xz[i+1];
  23275. }
  23276. }
  23277. pS->nXZ = j;
  23278. if( j<4 ){
  23279. pS->nXZ = 0;
  23280. Odie_Free((char *)pS->xz);
  23281. pS->xz = 0;
  23282. }
  23283. }
  23284. return TCL_OK;
  23285. }
  23286. /* OO Method Slicer xoffset */
  23287. static int OOMethod_Slicer_xoffset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23288.  
  23289. /*
  23290. ** tclmethod: SLICER xoffset ?AMT?
  23291. ** title: Change the X-Offset as a function of deck height
  23292. */
  23293. Slicer *p = GETSLICER(thisObject);
  23294. double rXOffset;
  23295. int i;
  23296. if( objc!=2 && objc!=3 ){
  23297. Tcl_WrongNumArgs(interp, 2, objv, "?XOFFSET?");
  23298. return TCL_ERROR;
  23299. }
  23300. if( objc==3 ){
  23301. if( Tcl_GetDoubleFromObj(interp, objv[2], &rXOffset) ) return TCL_ERROR;
  23302. for(i=0; i<p->nSlice; i++){
  23303. p->a[i].rXShift = rXOffset*p->a[i].z;
  23304. }
  23305. p->rXOffset = rXOffset;
  23306. }
  23307. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(p->rXOffset));
  23308. return TCL_OK;
  23309. }
  23310. /* OO Method Slicer zoom */
  23311. static int OOMethod_Slicer_zoom(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23312.  
  23313. /*
  23314. ** tclmethod: SLICER zoom ?ZOOM?
  23315. ** title: Query or change the zoom factor.
  23316. */
  23317. Slicer *p = GETSLICER(thisObject);
  23318. if( objc!=2 && objc!=3 ){
  23319. Tcl_WrongNumArgs(interp, 2, objv, "?ZOOM?");
  23320. return TCL_ERROR;
  23321. }
  23322. if( objc==3 ){
  23323. double r;
  23324. if( Tcl_GetDoubleFromObj(interp, objv[2], &r) ) return TCL_ERROR;
  23325. p->rZoom = r;
  23326. Slicer_computeTopAndBottom(p);
  23327. }
  23328. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(p->rZoom));
  23329. return TCL_OK;
  23330. }
  23331. /* OO Method Slicer upper_height */
  23332. static int OOMethod_Slicer_upper_height(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23333.  
  23334. /*
  23335. ** tclmethod: SLICER upper_height MM
  23336. ** title: Set the headroom on the top level of the slicer (defaults to 2000)
  23337. */
  23338. Slicer *p = GETSLICER(thisObject);
  23339. if( objc != 2 && objc!=3 ){
  23340. Tcl_WrongNumArgs(interp, 2, objv, "?Z?");
  23341. return TCL_ERROR;
  23342. }
  23343. if( objc==3 ){
  23344. double r;
  23345. if( Tcl_GetDoubleFromObj(interp, objv[2], &r) ) return TCL_ERROR;
  23346. p->upper_height=r;
  23347. }
  23348. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(p->upper_height));
  23349. return TCL_OK;
  23350. }
  23351. /* OO Method Slicer Slicer_Init */
  23352. static int OOMethod_Slicer_Slicer_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23353.  
  23354. Slicer *p;
  23355. p = (Slicer *)Odie_Alloc( sizeof(*p) );
  23356. p->rZoom = 100;
  23357. p->upper_height=2000;
  23358. Tcl_ObjectSetMetadata(thisObject, &SlicerDataType, (ClientData) p);
  23359. return TCL_OK;
  23360. }
  23361. /* Loader for Slicer */
  23362. static int Slicer_OO_Init(Tcl_Interp *interp) {
  23363. /*
  23364. ** Build the "::odielib::slicer" class
  23365. */
  23366. Tcl_Obj* nameObj; /* Name of a class or method being looked up */
  23367. Tcl_Object curClassObject; /* Tcl_Object representing the current class */
  23368. Tcl_Class curClass; /* Tcl_Class representing the current class */
  23369.  
  23370. /*
  23371. * Find the "::odielib::slicer" class, and attach an 'init' method to it.
  23372. */
  23373.  
  23374. nameObj = Tcl_NewStringObj("::odielib::slicer", -1);
  23375. Tcl_IncrRefCount(nameObj);
  23376. if ((curClassObject = Tcl_GetObjectFromObj(interp, nameObj)) == NULL) {
  23377. Tcl_DecrRefCount(nameObj);
  23378. return TCL_ERROR;
  23379. }
  23380. Tcl_DecrRefCount(nameObj);
  23381. curClass = Tcl_GetObjectAsClass(curClassObject);
  23382. nameObj=Tcl_NewStringObj("drawline",-1);
  23383. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_drawline, (ClientData) NULL);
  23384. Tcl_DecrRefCount(nameObj);
  23385. nameObj=Tcl_NewStringObj("above",-1);
  23386. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_above, (ClientData) NULL);
  23387. Tcl_DecrRefCount(nameObj);
  23388. nameObj=Tcl_NewStringObj("below",-1);
  23389. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_below, (ClientData) NULL);
  23390. Tcl_DecrRefCount(nameObj);
  23391. nameObj=Tcl_NewStringObj("deckid_to_name",-1);
  23392. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_deckid_to_name, (ClientData) NULL);
  23393. Tcl_DecrRefCount(nameObj);
  23394. nameObj=Tcl_NewStringObj("deckname_to_id",-1);
  23395. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_deckname_to_id, (ClientData) NULL);
  23396. Tcl_DecrRefCount(nameObj);
  23397. nameObj=Tcl_NewStringObj("bbox_to_location",-1);
  23398. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_bbox_to_location, (ClientData) NULL);
  23399. Tcl_DecrRefCount(nameObj);
  23400. nameObj=Tcl_NewStringObj("bbox_to_midpoint",-1);
  23401. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_bbox_to_midpoint, (ClientData) NULL);
  23402. Tcl_DecrRefCount(nameObj);
  23403. nameObj=Tcl_NewStringObj("xyz_to_location",-1);
  23404. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_xyz_to_location, (ClientData) NULL);
  23405. Tcl_DecrRefCount(nameObj);
  23406. nameObj=Tcl_NewStringObj("location_to_xyz",-1);
  23407. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_location_to_xyz, (ClientData) NULL);
  23408. Tcl_DecrRefCount(nameObj);
  23409. nameObj=Tcl_NewStringObj("location_z",-1);
  23410. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_location_z, (ClientData) NULL);
  23411. Tcl_DecrRefCount(nameObj);
  23412. nameObj=Tcl_NewStringObj("distance",-1);
  23413. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_distance, (ClientData) NULL);
  23414. Tcl_DecrRefCount(nameObj);
  23415. nameObj=Tcl_NewStringObj("actualcoords",-1);
  23416. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_actualcoords, (ClientData) NULL);
  23417. Tcl_DecrRefCount(nameObj);
  23418. nameObj=Tcl_NewStringObj("canvascoords",-1);
  23419. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_canvascoords, (ClientData) NULL);
  23420. Tcl_DecrRefCount(nameObj);
  23421. nameObj=Tcl_NewStringObj("create",-1);
  23422. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_create, (ClientData) NULL);
  23423. Tcl_DecrRefCount(nameObj);
  23424. nameObj=Tcl_NewStringObj("deck_at_xyz",-1);
  23425. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_deck_at_xyz, (ClientData) NULL);
  23426. Tcl_DecrRefCount(nameObj);
  23427. nameObj=Tcl_NewStringObj("deck",-1);
  23428. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_deck_at_xyz, (ClientData) NULL);
  23429. Tcl_DecrRefCount(nameObj);
  23430. nameObj=Tcl_NewStringObj("deckid_at_xyx",-1);
  23431. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_deckid_at_xyx, (ClientData) NULL);
  23432. Tcl_DecrRefCount(nameObj);
  23433. nameObj=Tcl_NewStringObj("did",-1);
  23434. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_deckid_at_xyx, (ClientData) NULL);
  23435. Tcl_DecrRefCount(nameObj);
  23436. nameObj=Tcl_NewStringObj("deckid",-1);
  23437. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_deckid_at_xyx, (ClientData) NULL);
  23438. Tcl_DecrRefCount(nameObj);
  23439. nameObj=Tcl_NewStringObj("delete",-1);
  23440. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_delete, (ClientData) NULL);
  23441. Tcl_DecrRefCount(nameObj);
  23442. nameObj=Tcl_NewStringObj("makedlist",-1);
  23443. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_makedlist, (ClientData) NULL);
  23444. Tcl_DecrRefCount(nameObj);
  23445. nameObj=Tcl_NewStringObj("find",-1);
  23446. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_find, (ClientData) NULL);
  23447. Tcl_DecrRefCount(nameObj);
  23448. nameObj=Tcl_NewStringObj("finddid",-1);
  23449. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_finddid, (ClientData) NULL);
  23450. Tcl_DecrRefCount(nameObj);
  23451. nameObj=Tcl_NewStringObj("flatheight",-1);
  23452. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_flatheight, (ClientData) NULL);
  23453. Tcl_DecrRefCount(nameObj);
  23454. nameObj=Tcl_NewStringObj("headroom",-1);
  23455. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_headroom, (ClientData) NULL);
  23456. Tcl_DecrRefCount(nameObj);
  23457. nameObj=Tcl_NewStringObj("ceiling",-1);
  23458. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_ceiling, (ClientData) NULL);
  23459. Tcl_DecrRefCount(nameObj);
  23460. nameObj=Tcl_NewStringObj("height",-1);
  23461. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_height, (ClientData) NULL);
  23462. Tcl_DecrRefCount(nameObj);
  23463. nameObj=Tcl_NewStringObj("deckheight",-1);
  23464. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_deckheight, (ClientData) NULL);
  23465. Tcl_DecrRefCount(nameObj);
  23466. nameObj=Tcl_NewStringObj("info",-1);
  23467. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_info, (ClientData) NULL);
  23468. Tcl_DecrRefCount(nameObj);
  23469. nameObj=Tcl_NewStringObj("list",-1);
  23470. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_list, (ClientData) NULL);
  23471. Tcl_DecrRefCount(nameObj);
  23472. nameObj=Tcl_NewStringObj("profile",-1);
  23473. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_profile, (ClientData) NULL);
  23474. Tcl_DecrRefCount(nameObj);
  23475. nameObj=Tcl_NewStringObj("xoffset",-1);
  23476. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_xoffset, (ClientData) NULL);
  23477. Tcl_DecrRefCount(nameObj);
  23478. nameObj=Tcl_NewStringObj("zoom",-1);
  23479. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_zoom, (ClientData) NULL);
  23480. Tcl_DecrRefCount(nameObj);
  23481. nameObj=Tcl_NewStringObj("upper_height",-1);
  23482. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_upper_height, (ClientData) NULL);
  23483. Tcl_DecrRefCount(nameObj);
  23484. nameObj=Tcl_NewStringObj("Slicer_Init",-1);
  23485. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Slicer_Slicer_Init, (ClientData) NULL);
  23486. Tcl_DecrRefCount(nameObj);
  23487. return TCL_OK;
  23488. }
  23489. /* OO Method Wallset atvertex */
  23490. static int OOMethod_Wallset_atvertex(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23491.  
  23492. /*
  23493. ** tclmethod: WALLSET atvertex X Y
  23494. ** title: Return a list of wall IDs that connect to vertex X,Y
  23495. */
  23496. Wallset *p = GETWALLSET(thisObject);
  23497. Link *pList;
  23498. double x, y;
  23499. Tcl_Obj *pResult;
  23500. if( objc!=4 ){
  23501. Tcl_WrongNumArgs(interp, 2, objv, "X Y");
  23502. return TCL_ERROR;
  23503. }
  23504. if( Tcl_GetDoubleFromObj(interp, objv[2], &x) ) return TCL_ERROR;
  23505. if( Tcl_GetDoubleFromObj(interp, objv[3], &y) ) return TCL_ERROR;
  23506. pResult = Tcl_NewObj();
  23507. ignoreNone(p);
  23508. pList = segmentsAtVertex(p, x*p->rXZoom, y*p->rYZoom);
  23509. while( pList ){
  23510. Segment *pSeg=pList->pLinkNode;
  23511. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->id));
  23512. pList = pList->pNext;
  23513. }
  23514. Tcl_SetObjResult(interp, pResult);
  23515. return TCL_OK;
  23516. }
  23517. /* OO Method Wallset boundary */
  23518. static int OOMethod_Wallset_boundary(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23519.  
  23520. /*
  23521. ** tclmethod: WALLSET boundary X Y
  23522. ** title: Return indices of segments forming a boundary around X Y
  23523. */
  23524. Wallset *p = GETWALLSET(thisObject);
  23525. Boundary aBound[MX_BOUND];
  23526. int nBound;
  23527. double x, y;
  23528. Tcl_Obj *pResult;
  23529. int i;
  23530. int showDetail = 0;
  23531.  
  23532. if( objc==5 && strcmp(Tcl_GetStringFromObj(objv[2],0),"-detail")==0 ){
  23533. showDetail = 1;
  23534. objc--;
  23535. objv++;
  23536. }
  23537. if( objc!=4 ){
  23538. Tcl_WrongNumArgs(interp, 2, objv, "?-detail? X Y");
  23539. return TCL_ERROR;
  23540. }
  23541. if( Tcl_GetDoubleFromObj(interp, objv[2], &x) ) return TCL_ERROR;
  23542. if( Tcl_GetDoubleFromObj(interp, objv[3], &y) ) return TCL_ERROR;
  23543. nBound = findBoundary(p, x*p->rXZoom, y*p->rYZoom, MX_BOUND, aBound);
  23544. if( nBound>MX_BOUND ) nBound = 0;
  23545. pResult = Tcl_NewObj();
  23546. for(i=0; i<nBound; i++){
  23547. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(aBound[i].pSeg->id));
  23548. if( showDetail ){
  23549. Tcl_ListObjAppendElement(0, pResult,
  23550. ODIE_CONSTANT_STRING(aBound[i].backwards ? "right" : "left"));
  23551. }
  23552. }
  23553. Tcl_SetObjResult(interp, pResult);
  23554. return TCL_OK;
  23555. }
  23556. /* OO Method Wallset closure */
  23557. static int OOMethod_Wallset_closure(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23558.  
  23559. /*
  23560. ** tclmethod: WALLSET closure WALLID BACKWARDS CHECKPRIMARY ?-coords?
  23561. ** title: Return the closure of a wall
  23562. **
  23563. ** The closure is a path of walls going clockwise from the wall given.
  23564. ** The return value is a list consisting of wall IDs alternating with
  23565. ** keywords "left" or "right" indicating which side of the wall applies.
  23566. ** If the CHECKPRIMARY flag is true and the WALLID/BACKWARDS is not the
  23567. ** primary wall id for the closure, then return an empty string. The
  23568. ** primary wall id is the wall id with the lowest id number, or if
  23569. ** two walls in the closure have the same id, then the one that goes
  23570. ** on the right side of the wall.
  23571. */
  23572. Wallset *p = GETWALLSET(thisObject);
  23573. Boundary aBound[MX_BOUND];
  23574. int id;
  23575. int nBound, i, checkPrim;
  23576. Tcl_Obj *pResult;
  23577. int coordsFlag = 0;
  23578. int noerrFlag = 0;
  23579. if( objc!=5 && objc!=6 ){
  23580. Tcl_WrongNumArgs(interp, 2, objv,
  23581. "WALLID BACKWARDS CHECKPRIMARY ?-coords? ?-noerr?");
  23582. return TCL_ERROR;
  23583. }
  23584. if( objc==6 ){
  23585. const char *zOpt = Tcl_GetStringFromObj(objv[5],0);
  23586. if( strcmp(zOpt,"-coords")==0 ){
  23587. coordsFlag = 1;
  23588. }else if( strcmp(zOpt,"-noerr")==0 ){
  23589. noerrFlag = 1;
  23590. }else{
  23591. Tcl_AppendResult(interp, "unknown option: ", zOpt, 0);
  23592. return TCL_ERROR;
  23593. }
  23594. }
  23595. if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR;
  23596. if( (aBound[0].pSeg = findSegment(p, id))==0 ){
  23597. Tcl_AppendResult(interp, "segment ",
  23598. Tcl_GetStringFromObj(objv[2],0), " does not exist", 0);
  23599. return TCL_ERROR;
  23600. }
  23601. if( Tcl_GetBooleanFromObj(interp, objv[3], &aBound[0].backwards) ){
  23602. return TCL_ERROR;
  23603. }
  23604. if( Tcl_GetBooleanFromObj(interp, objv[4], &checkPrim) ){
  23605. return TCL_ERROR;
  23606. }
  23607. ignoreNone(p);
  23608. nBound = completeBoundary(p, checkPrim, MX_BOUND, aBound);
  23609. pResult = Tcl_NewObj();
  23610. if( nBound<0 && noerrFlag ) nBound = -nBound;
  23611. for(i=0; i<nBound; i++){
  23612. if( coordsFlag ){
  23613. double x, y;
  23614. Segment *pSeg = aBound[i].pSeg;
  23615. if( aBound[i].backwards ){
  23616. x = pSeg->to[X_IDX];
  23617. y = pSeg->to[Y_IDX];
  23618. }else{
  23619. x = pSeg->from[X_IDX];
  23620. y = pSeg->from[Y_IDX];
  23621. }
  23622. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(x/p->rXZoom));
  23623. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(y/p->rYZoom));
  23624. }else{
  23625. Tcl_ListObjAppendElement(0, pResult,
  23626. Tcl_NewIntObj(aBound[i].pSeg->id));
  23627. Tcl_ListObjAppendElement(0, pResult,
  23628. ODIE_CONSTANT_STRING(aBound[i].backwards ? "right" : "left"));
  23629. }
  23630. }
  23631. Tcl_SetObjResult(interp, pResult);
  23632. return TCL_OK;
  23633. }
  23634. /* OO Method Wallset closure_polygon */
  23635. static int OOMethod_Wallset_closure_polygon(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23636.  
  23637. /*
  23638. ** tclmethod: WALLSET closure_polygon WALLID BACKWARDS CHECKPRIMARY
  23639. ** title: Return the closure of a wall
  23640. **
  23641. ** The closure is a path of walls going clockwise from the wall given.
  23642. ** The return value is a list consisting of wall IDs alternating with
  23643. ** keywords "left" or "right" indicating which side of the wall applies.
  23644. ** If the CHECKPRIMARY flag is true and the WALLID/BACKWARDS is not the
  23645. ** primary wall id for the closure, then return an empty string. The
  23646. ** primary wall id is the wall id with the lowest id number, or if
  23647. ** two walls in the closure have the same id, then the one that goes
  23648. ** on the right side of the wall.
  23649. */
  23650. Wallset *p = GETWALLSET(thisObject);
  23651. Boundary aBound[MX_BOUND];
  23652. int id;
  23653. int nBound, i, checkPrim;
  23654. Tcl_Obj *pResult;
  23655. int noerrFlag = 0;
  23656. Odie_Polygon *pPolyOut;
  23657.  
  23658. if( objc!=5 && objc!=6 ){
  23659. Tcl_WrongNumArgs(interp, 2, objv,
  23660. "WALLID BACKWARDS CHECKPRIMARY ?-noerr?");
  23661. return TCL_ERROR;
  23662. }
  23663. if( objc==6 ){
  23664. const char *zOpt = Tcl_GetStringFromObj(objv[5],0);
  23665. if( strcmp(zOpt,"-noerr")==0 ){
  23666. noerrFlag = 1;
  23667. }else{
  23668. Tcl_AppendResult(interp, "unknown option: ", zOpt, 0);
  23669. return TCL_ERROR;
  23670. }
  23671. }
  23672. if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR;
  23673. if( (aBound[0].pSeg = findSegment(p, id))==0 ){
  23674. Tcl_AppendResult(interp, "segment ",
  23675. Tcl_GetStringFromObj(objv[2],0), " does not exist", 0);
  23676. return TCL_ERROR;
  23677. }
  23678. if( Tcl_GetBooleanFromObj(interp, objv[3], &aBound[0].backwards) ){
  23679. return TCL_ERROR;
  23680. }
  23681. if( Tcl_GetBooleanFromObj(interp, objv[4], &checkPrim) ){
  23682. return TCL_ERROR;
  23683. }
  23684. ignoreNone(p);
  23685. nBound = completeBoundary(p, checkPrim, MX_BOUND, aBound);
  23686. pResult = Tcl_NewObj();
  23687. if( nBound<0 && noerrFlag ) nBound = -nBound;
  23688. pPolyOut=Odie_FaceXYZ_Create(nBound+1);
  23689. pPolyOut->nVertex=nBound;
  23690. for(i=0; i<nBound; i++){
  23691. Segment *pSeg = aBound[i].pSeg;
  23692. if( aBound[i].backwards ){
  23693. VectorXYZ_Copy(pPolyOut->v[i],pSeg->to);
  23694. }else{
  23695. VectorXYZ_Copy(pPolyOut->v[i],pSeg->from);
  23696. }
  23697. }
  23698. Odie_Polygon_ComputeArea(interp,pPolyOut);
  23699. Tcl_SetObjResult(interp, Odie_Polygon_NewTclObj(pPolyOut));
  23700. return TCL_OK;
  23701. }
  23702. /* OO Method Wallset closure_check */
  23703. static int OOMethod_Wallset_closure_check(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23704.  
  23705. /*
  23706. ** tclmethod: WALLSET closure_check WALLID BACKWARDS
  23707. ** title: Return the closure of a wall
  23708. **
  23709. ** The closure is a path of walls going clockwise from the wall given.
  23710. ** The return value is a list consisting of wall IDs alternating with
  23711. ** keywords "left" or "right" indicating which side of the wall applies.
  23712. ** If the CHECKPRIMARY flag is true and the WALLID/BACKWARDS is not the
  23713. ** primary wall id for the closure, then return an empty string. The
  23714. ** primary wall id is the wall id with the lowest id number, or if
  23715. ** two walls in the closure have the same id, then the one that goes
  23716. ** on the right side of the wall.
  23717. */
  23718. Wallset *p = GETWALLSET(thisObject);
  23719. Boundary aBound[MX_BOUND];
  23720. int id;
  23721. int nBound, i, checkPrim;
  23722. Tcl_Obj *pResult;
  23723. int noerrFlag = 0;
  23724. if( objc!=5){
  23725. Tcl_WrongNumArgs(interp, 2, objv,
  23726. "WALLID BACKWARDS CHECKPRIMARY");
  23727. return TCL_ERROR;
  23728. }
  23729. if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR;
  23730. if( (aBound[0].pSeg = findSegment(p, id))==0 ){
  23731. Tcl_AppendResult(interp, "segment ",
  23732. Tcl_GetStringFromObj(objv[2],0), " does not exist", 0);
  23733. return TCL_ERROR;
  23734. }
  23735. if( Tcl_GetBooleanFromObj(interp, objv[3], &aBound[0].backwards) ){
  23736. return TCL_ERROR;
  23737. }
  23738. if( Tcl_GetBooleanFromObj(interp, objv[4], &checkPrim) ){
  23739. return TCL_ERROR;
  23740. }
  23741. ignoreNone(p);
  23742. nBound = completeBoundary(p, 0, MX_BOUND, aBound);
  23743. pResult = Tcl_NewObj();
  23744. if( nBound<0 && noerrFlag ) nBound = -nBound;
  23745. for(i=0; i<nBound; i++) {
  23746. Tcl_ListObjAppendElement(0, pResult,
  23747. Tcl_NewIntObj(aBound[i].pSeg->id));
  23748. Tcl_ListObjAppendElement(0, pResult,
  23749. Tcl_NewIntObj(aBound[i].backwards));
  23750. if(aBound[i].backwards) {
  23751. Tcl_ListObjAppendElement(0, pResult,
  23752. Tcl_NewIntObj(aBound[i].pSeg->idLC));
  23753. } else {
  23754. Tcl_ListObjAppendElement(0, pResult,
  23755. Tcl_NewIntObj(aBound[i].pSeg->idRC));
  23756. }
  23757. }
  23758. Tcl_SetObjResult(interp, pResult);
  23759. return TCL_OK;
  23760. }
  23761. /* OO Method Wallset comptlist */
  23762. static int OOMethod_Wallset_comptlist(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23763.  
  23764. /*
  23765. ** tclmethod: WALLSET comptlist
  23766. ** title: Return a list of all compartments
  23767. **
  23768. ** A compartment is a closed circuit of walls. This routine returns
  23769. ** a list of all compartments. Each element of the list consists of
  23770. ** the primary wall for the compartment followed by a bounding box
  23771. ** for the compartment.
  23772. */
  23773. Wallset *p = GETWALLSET(thisObject);
  23774. ComptBox *pBox;
  23775. Tcl_Obj *pResult = Tcl_NewObj();
  23776. buildComptBoxCache(p);
  23777. for(pBox=p->pComptBox; pBox; pBox=pBox->pNext){
  23778. Tcl_Obj *pElem = Tcl_NewObj();
  23779. Tcl_ListObjAppendElement(0, pElem,Tcl_NewIntObj(pBox->prim.pSeg->id));
  23780. Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pBox->prim.backwards));
  23781. Tcl_ListObjAppendElement(0, pElem, Tcl_NewDoubleObj(pBox->bbox[BBOX_X0_IDX]/p->rXZoom));
  23782. Tcl_ListObjAppendElement(0, pElem, Tcl_NewDoubleObj(pBox->bbox[BBOX_Y0_IDX]/p->rYZoom));
  23783. Tcl_ListObjAppendElement(0, pElem, Tcl_NewDoubleObj(pBox->bbox[BBOX_X1_IDX]/p->rXZoom));
  23784. Tcl_ListObjAppendElement(0, pElem, Tcl_NewDoubleObj(pBox->bbox[BBOX_Y1_IDX]/p->rYZoom));
  23785. Tcl_ListObjAppendElement(0, pResult, pElem);
  23786. }
  23787. Tcl_SetObjResult(interp, pResult);
  23788. return TCL_OK;
  23789. }
  23790. /* OO Method Wallset corners */
  23791. static int OOMethod_Wallset_corners(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23792.  
  23793. /*
  23794. ** tclmethod: WALLSET corners X Y
  23795. ** title: Return vertices of compartment containing X,Y
  23796. */
  23797. Wallset *p = GETWALLSET(thisObject);
  23798. Boundary aBound[MX_BOUND];
  23799. int nBound, i;
  23800. double x, y;
  23801. Tcl_Obj *pResult;
  23802. if( objc!=4 ){
  23803. Tcl_WrongNumArgs(interp, 2, objv, "X Y");
  23804. return TCL_ERROR;
  23805. }
  23806. if( Tcl_GetDoubleFromObj(interp, objv[2], &x) ) return TCL_ERROR;
  23807. if( Tcl_GetDoubleFromObj(interp, objv[3], &y) ) return TCL_ERROR;
  23808. nBound = findBoundary(p, x*p->rXZoom, y*p->rYZoom, MX_BOUND, aBound);
  23809. if( nBound>MX_BOUND ) nBound = 0;
  23810. pResult = Tcl_NewObj();
  23811. for(i=0; i<nBound; i++){
  23812. Segment *pSeg = aBound[i].pSeg;
  23813. if( aBound[i].backwards ){
  23814. x = pSeg->to[X_IDX];
  23815. y = pSeg->to[Y_IDX];
  23816. }else{
  23817. x = pSeg->from[X_IDX];
  23818. y = pSeg->from[Y_IDX];
  23819. }
  23820. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(x/p->rXZoom));
  23821. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(y/p->rYZoom));
  23822. }
  23823. Tcl_SetObjResult(interp, pResult);
  23824. return TCL_OK;
  23825. }
  23826. /* OO Method Wallset delete */
  23827. static int OOMethod_Wallset_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23828.  
  23829. /*
  23830. ** tclmethod: WALLSET delete ID
  23831. ** title: Delete a single segment of a wall given by ID
  23832. */
  23833. Wallset *p = GETWALLSET(thisObject);
  23834. int id;
  23835. Segment *pSeg;
  23836. if( objc!=3 ){
  23837. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  23838. return TCL_ERROR;
  23839. }
  23840. if( p->busy ){
  23841. Tcl_AppendResult(interp, "cannot \"delete\" from within a \"foreach\"",0);
  23842. return TCL_ERROR;
  23843. }
  23844. if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR;
  23845. if( (pSeg = findSegment(p, id))==0 ){
  23846. Tcl_AppendResult(interp, "segment ",
  23847. Tcl_GetStringFromObj(objv[2],0), " does not exist", 0);
  23848. return TCL_ERROR;
  23849. }
  23850. clearComptBoxCache(p);
  23851. LinkRemove(&pSeg->pAll);
  23852. /* We intentionally do not remove pSeg->pSet because it might not be
  23853. ** a well-formed list */
  23854. LinkRemove(&pSeg->pHash);
  23855. LinkRemove(&pSeg->pFrom);
  23856. LinkRemove(&pSeg->pTo);
  23857. Tcl_Free((char *)pSeg);
  23858. return TCL_OK;
  23859. }
  23860. /* OO Method Wallset firstboundary */
  23861. static int OOMethod_Wallset_firstboundary(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23862.  
  23863. /*
  23864. ** tclmethod: WALLSET firstboundary X Y
  23865. ** title: Find a wall on the boundary of compartment containing X Y
  23866. **
  23867. ** Returns a list of two elements on success or an empty list if no
  23868. ** suitable boundary could be found. The first element is the ID of a
  23869. ** wall that forms part of the boundary for the compartment containing
  23870. ** point X,Y. The second element is TRUE if X,Y is to the right of the
  23871. ** wall and false if it is to the left.
  23872. **
  23873. ** The right/left designation assumes a right-handed coordinate system.
  23874. */
  23875. Wallset *p = GETWALLSET(thisObject);
  23876. int isBack;
  23877. Segment *pSeg;
  23878. double x, y;
  23879. int rc;
  23880. if( objc!=4 ){
  23881. Tcl_WrongNumArgs(interp, 1, objv, "X Y");
  23882. return TCL_ERROR;
  23883. }
  23884. if( Tcl_GetDoubleFromObj(interp, objv[2], &x) ) return TCL_ERROR;
  23885. if( Tcl_GetDoubleFromObj(interp, objv[3], &y) ) return TCL_ERROR;
  23886. ignoreNone(p);
  23887. rc = firstBoundarySegment(p, x*p->rXZoom, y*p->rYZoom, &pSeg, &isBack);
  23888. if( rc==0 ){
  23889. Tcl_Obj *pResult = Tcl_NewObj();
  23890. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->id));
  23891. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(isBack));
  23892. Tcl_SetObjResult(interp, pResult);
  23893. }
  23894. return TCL_OK;
  23895. }
  23896. /* OO Method Wallset foreach */
  23897. static int OOMethod_Wallset_foreach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23898.  
  23899. /*
  23900. ** tclmethod: WALLSET foreach CODE
  23901. ** title: Run CODE for each segment of the wallset
  23902. */
  23903. Wallset *p = GETWALLSET(thisObject);
  23904. Link *pLink;
  23905. int rc = TCL_OK;
  23906. if( objc!=3 ){
  23907. Tcl_WrongNumArgs(interp, 2, objv, "CODE");
  23908. return TCL_ERROR;
  23909. }
  23910. p->busy++;
  23911. for(pLink=p->pAll; pLink && rc==TCL_OK; pLink=pLink->pNext){
  23912. Segment *pSeg = pLink->pLinkNode;
  23913. Tcl_SetVar2Ex(interp, "x0", 0, Tcl_NewDoubleObj(pSeg->from[X_IDX]/p->rXZoom), 0);
  23914. Tcl_SetVar2Ex(interp, "y0", 0, Tcl_NewDoubleObj(pSeg->from[Y_IDX]/p->rYZoom), 0);
  23915. Tcl_SetVar2Ex(interp, "x1", 0, Tcl_NewDoubleObj(pSeg->to[X_IDX]/p->rXZoom), 0);
  23916. Tcl_SetVar2Ex(interp, "y1", 0, Tcl_NewDoubleObj(pSeg->to[Y_IDX]/p->rYZoom), 0);
  23917. Tcl_SetVar2Ex(interp, "id", 0, Tcl_NewIntObj(pSeg->id), 0);
  23918. Tcl_SetVar2Ex(interp, "lc", 0, Tcl_NewIntObj(pSeg->idLC), 0);
  23919. Tcl_SetVar2Ex(interp, "rc", 0, Tcl_NewIntObj(pSeg->idRC), 0);
  23920. Tcl_SetVar2Ex(interp, "virtual", 0, Tcl_NewIntObj(pSeg->isBoundary), 0);
  23921. rc = Tcl_EvalObjEx(interp, objv[2], 0);
  23922. }
  23923. if( rc==TCL_BREAK ) rc = TCL_OK;
  23924. p->busy--;
  23925. return rc;
  23926. }
  23927. /* OO Method Wallset info */
  23928. static int OOMethod_Wallset_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23929.  
  23930. /*
  23931. ** tclmethod: WALLSET info ID
  23932. ** title: Return information about a single wall segment
  23933. */
  23934. Wallset *p = GETWALLSET(thisObject);
  23935. int id;
  23936. Segment *pSeg;
  23937. Tcl_Obj *pResult;
  23938. if( objc!=3 ){
  23939. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  23940. return TCL_ERROR;
  23941. }
  23942. if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR;
  23943. if( (pSeg = findSegment(p, id))==0 ){
  23944. Tcl_AppendResult(interp, "segment ",
  23945. Tcl_GetStringFromObj(objv[2],0), " does not exist", 0);
  23946. return TCL_ERROR;
  23947. }
  23948. pResult = Tcl_NewObj();
  23949. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSeg->from[X_IDX]/p->rXZoom));
  23950. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSeg->from[Y_IDX]/p->rYZoom));
  23951. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSeg->to[X_IDX]/p->rXZoom));
  23952. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSeg->to[Y_IDX]/p->rYZoom));
  23953. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->id));
  23954. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->idLC));
  23955. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->idRC));
  23956. Tcl_SetObjResult(interp, pResult);
  23957. return TCL_OK;
  23958. }
  23959. /* OO Method Wallset rawinfo */
  23960. static int OOMethod_Wallset_rawinfo(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23961.  
  23962. /*
  23963. ** tclmethod: WALLSET info ID
  23964. ** title: Return information about a single wall segment
  23965. */
  23966. Wallset *p = GETWALLSET(thisObject);
  23967. int id;
  23968. Segment *pSeg;
  23969. Tcl_Obj *pResult;
  23970. if( objc!=3 ){
  23971. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  23972. return TCL_ERROR;
  23973. }
  23974. if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR;
  23975. if( (pSeg = findSegment(p, id))==0 ){
  23976. Tcl_AppendResult(interp, "segment ",
  23977. Tcl_GetStringFromObj(objv[2],0), " does not exist", 0);
  23978. return TCL_ERROR;
  23979. }
  23980. pResult = Tcl_NewObj();
  23981. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSeg->from[X_IDX]));
  23982. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSeg->from[Y_IDX]));
  23983. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSeg->to[X_IDX]));
  23984. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSeg->to[Y_IDX]));
  23985. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->id));
  23986. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->idLC));
  23987. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->idRC));
  23988. Tcl_SetObjResult(interp, pResult);
  23989. return TCL_OK;
  23990. }
  23991. /* OO Method Wallset insert */
  23992. static int OOMethod_Wallset_insert(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  23993.  
  23994. /*
  23995. ** tclmethod: WALLSET insert X0 Y0 X1 Y1 ID LC RC VIRTUAL
  23996. ** title: Create a new wall within the wallset
  23997. */
  23998. Wallset *p = GETWALLSET(thisObject);
  23999. int id;
  24000. int h,virtual=0;
  24001. double x0, y0, x1, y1;
  24002. int idLC, idRC;
  24003. Segment *pSeg;
  24004. if( objc!=9 && objc!=10){
  24005. Tcl_WrongNumArgs(interp, 2, objv, "X0 Y0 X1 Y1 ID LC RC ?1|0?");
  24006. return TCL_ERROR;
  24007. }
  24008. if( p->busy ){
  24009. Tcl_AppendResult(interp, "cannot \"insert\" from within a \"foreach\"",0);
  24010. return TCL_ERROR;
  24011. }
  24012. if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR;
  24013. if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR;
  24014. if( Tcl_GetDoubleFromObj(interp, objv[4], &x1) ) return TCL_ERROR;
  24015. if( Tcl_GetDoubleFromObj(interp, objv[5], &y1) ) return TCL_ERROR;
  24016. if( Tcl_GetIntFromObj(interp, objv[6], &id) ) return TCL_ERROR;
  24017. if( Tcl_GetIntFromObj(interp, objv[7], &idLC) ) {
  24018. Tcl_ResetResult(interp);
  24019. idLC=0;
  24020. }
  24021. if( Tcl_GetIntFromObj(interp, objv[8], &idRC) ) {
  24022. Tcl_ResetResult(interp);
  24023. idRC=0;
  24024. }
  24025. if(objc==10) {
  24026. if( Tcl_GetIntFromObj(interp, objv[8], &virtual) ) {
  24027. Tcl_ResetResult(interp);
  24028. virtual=0;
  24029. }
  24030. }
  24031. x0 = roundCoord(x0*p->rXZoom);
  24032. y0 = roundCoord(y0*p->rYZoom);
  24033. x1 = roundCoord(x1*p->rXZoom);
  24034. y1 = roundCoord(y1*p->rYZoom);
  24035. if( findSegment(p, id) ){
  24036. Tcl_AppendResult(interp, "segment ",
  24037. Tcl_GetStringFromObj(objv[6],0), " already exists", 0);
  24038. return TCL_ERROR;
  24039. }
  24040. if( floatCompare(x0,x1)==0 && floatCompare(y0,y1)==0 ){
  24041. /* Tcl_AppendResult(interp, "endpoints must be distinct", 0); */
  24042. /* return TCL_ERROR; */
  24043. return TCL_OK; /* Not an error. Just a no-op. */
  24044. }
  24045. clearComptBoxCache(p);
  24046. pSeg = (Segment *)Odie_Alloc( sizeof(*pSeg) );
  24047. if( pSeg==0 ) return TCL_ERROR;
  24048. pSeg->id = id;
  24049. pSeg->idLC = idLC;
  24050. pSeg->idRC = idRC;
  24051. pSeg->from[X_IDX] = x0;
  24052. pSeg->from[Y_IDX] = y0;
  24053. pSeg->to[X_IDX] = x1;
  24054. pSeg->to[Y_IDX] = y1;
  24055. pSeg->isBoundary=virtual;
  24056.  
  24057. LinkInit(pSeg->pAll, pSeg);
  24058. LinkInit(pSeg->pSet, pSeg);
  24059. LinkInit(pSeg->pHash, pSeg);
  24060. LinkInit(pSeg->pFrom, pSeg);
  24061. LinkInit(pSeg->pTo, pSeg);
  24062. LinkInsert(&p->pAll, &pSeg->pAll);
  24063. h = hashInt(id);
  24064. LinkInsert(&p->hashId[h], &pSeg->pHash);
  24065. h = hashCoord(pSeg->from[X_IDX], pSeg->from[Y_IDX]);
  24066. LinkInsert(&p->hashFrom[h], &pSeg->pFrom);
  24067. h = hashCoord(pSeg->to[X_IDX], pSeg->to[Y_IDX]);
  24068. LinkInsert(&p->hashTo[h], &pSeg->pTo);
  24069. return TCL_OK;
  24070. }
  24071. /* OO Method Wallset primary */
  24072. static int OOMethod_Wallset_primary(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24073.  
  24074. /*
  24075. ** tclmethod: WALLSET primary X Y
  24076. ** title: Return the primary segment of the compartment enclosing X,Y
  24077. **
  24078. ** The primary segment is the segment with the smallest ID. If the
  24079. ** same segment occurs twice on the list (in other words, if the
  24080. ** same compartment is on both sides of a wall), then the right side
  24081. ** (as measured facing the direction of travel from x0,y0 -> x1,y1)
  24082. ** is used.
  24083. */
  24084. Wallset *p = GETWALLSET(thisObject);
  24085. Boundary aBound[MX_BOUND];
  24086. int nBound;
  24087. double x, y;
  24088. int i, sideSmallest;
  24089. int idSmallest;
  24090. Tcl_Obj *pResult;
  24091. if( objc!=4 ){
  24092. Tcl_WrongNumArgs(interp, 2, objv, "X Y");
  24093. return TCL_ERROR;
  24094. }
  24095. if( Tcl_GetDoubleFromObj(interp, objv[2], &x) ) return TCL_ERROR;
  24096. if( Tcl_GetDoubleFromObj(interp, objv[3], &y) ) return TCL_ERROR;
  24097. nBound = findBoundary(p, x*p->rXZoom, y*p->rYZoom, MX_BOUND, aBound);
  24098. if( nBound>0 && nBound<MX_BOUND ){
  24099. idSmallest = aBound[0].pSeg->id;
  24100. sideSmallest = aBound[0].backwards;
  24101. for(i=1; i<nBound; i++){
  24102. if( aBound[i].pSeg->id>idSmallest ) continue;
  24103. if( aBound[i].pSeg->id<idSmallest || !sideSmallest ){
  24104. idSmallest = aBound[i].pSeg->id;
  24105. sideSmallest = aBound[i].backwards;
  24106. }
  24107. }
  24108. pResult = Tcl_NewObj();
  24109. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(idSmallest));
  24110. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(sideSmallest));
  24111. Tcl_SetObjResult(interp, pResult);
  24112. }
  24113. return TCL_OK;
  24114. }
  24115. /* OO Method Wallset intersect */
  24116. static int OOMethod_Wallset_intersect(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24117.  
  24118. /*
  24119. ** tclmethod: WALLSET intersect X0 Y0 X1 Y1
  24120. ** title: Find the intersection of X0,Y0->X1,Y1 with a segment
  24121. **
  24122. ** Scan all segments in the wallset looking for one that intersects with
  24123. ** a line from X0,Y0 to X1,Y1. If the intersection occurs at x0,y0, it
  24124. ** is ignored, but intersections at x1,y1 count. If no such intersection
  24125. ** exists, return the empty string. If there are one or more intersections,
  24126. ** return the ID of the segment and the X and Y coordinates of the nearest
  24127. ** intersection to X0,Y0.
  24128. */
  24129. Wallset *p = GETWALLSET(thisObject);
  24130. double x0,y0,x1,y1;
  24131. double adx, ady;
  24132. Link *pI;
  24133. int id=-1;
  24134. double nx, ny;
  24135. double mindist2 = -1.0;
  24136. if( objc!=6 ){
  24137. Tcl_WrongNumArgs(interp, 2, objv, "X0 Y0 X1 Y1");
  24138. return TCL_ERROR;
  24139. }
  24140. if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR;
  24141. if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR;
  24142. if( Tcl_GetDoubleFromObj(interp, objv[4], &x1) ) return TCL_ERROR;
  24143. if( Tcl_GetDoubleFromObj(interp, objv[5], &y1) ) return TCL_ERROR;
  24144. nx = x0 = roundCoord(x0*p->rXZoom);
  24145. ny = y0 = roundCoord(y0*p->rYZoom);
  24146. x1 = roundCoord(x1*p->rXZoom);
  24147. y1 = roundCoord(y1*p->rYZoom);
  24148. adx = x1-x0;
  24149. ady = y1-y0;
  24150. if( adx==0.0 && ady==0.0 ) return TCL_OK;
  24151. for(pI=p->pAll; pI; pI=pI->pNext){
  24152. double bdx, bdy, denom, num1;
  24153. Segment *pSeg;
  24154. pSeg = pI->pLinkNode;
  24155. bdx = pSeg->to[X_IDX] - pSeg->from[X_IDX];
  24156. bdy = pSeg->to[Y_IDX] - pSeg->from[Y_IDX];
  24157. denom = adx*bdy - ady*bdx;
  24158. num1 = (y0-pSeg->from[Y_IDX])*bdx - (x0-pSeg->from[X_IDX])*bdy;
  24159. if( denom==0.0 ){
  24160. /* The reference line and segment are parallel */
  24161. if( num1==0.0 ){
  24162. /* The reference line and segment are colinear */
  24163. if( Vector2d_SamePoint(x0,y0,pSeg->from[X_IDX],pSeg->from[Y_IDX])
  24164. && adx*bdx<=0.0 && ady*bdy<=0.0 ){
  24165. continue;
  24166. }
  24167. if( Vector2d_SamePoint(x0,y0,pSeg->to[X_IDX],pSeg->to[Y_IDX])
  24168. && adx*bdx>=0.0 && ady*bdy>=0.0 ){
  24169. continue;
  24170. }
  24171. if( between(pSeg->from[Y_IDX],y0,y1) && between(pSeg->from[X_IDX],x0,x1) ){
  24172. double dx, dy, dist2;
  24173. dx = pSeg->from[X_IDX] - x0;
  24174. dy = pSeg->from[Y_IDX] - y0;
  24175. dist2 = dx*dx + dy*dy;
  24176. if( mindist2<0 || mindist2>dist2 ){
  24177. mindist2 = dist2;
  24178. nx = pSeg->from[X_IDX];
  24179. ny = pSeg->from[Y_IDX];
  24180. id = pSeg->id;
  24181. }
  24182. }
  24183. if( between(pSeg->to[Y_IDX],y0,y1) && between(pSeg->to[X_IDX],x0,x1) ){
  24184. double dx, dy, dist2;
  24185. dx = pSeg->to[X_IDX] - x0;
  24186. dy = pSeg->to[Y_IDX] - y0;
  24187. dist2 = dx*dx + dy*dy;
  24188. if( mindist2<0 || mindist2>dist2 ){
  24189. mindist2 = dist2;
  24190. nx = pSeg->to[X_IDX];
  24191. ny = pSeg->to[Y_IDX];
  24192. id = pSeg->id;
  24193. }
  24194. }
  24195. if( between(y0,pSeg->from[Y_IDX],pSeg->to[Y_IDX]) && between(x0,pSeg->from[X_IDX],pSeg->to[X_IDX]) ){
  24196. if( mindist2<0 || mindist2>0.0 ){
  24197. mindist2 = 0.0;
  24198. nx = x0;
  24199. ny = y0;
  24200. id = pSeg->id;
  24201. }
  24202. }
  24203. }
  24204. }else{
  24205. /* The reference line and segment are not parallel */
  24206. double r, s;
  24207. r = num1/denom;
  24208. s = ((y0-pSeg->from[Y_IDX])*adx - (x0-pSeg->from[X_IDX])*ady)/denom;
  24209. if( r>0 && r<=1.0 && s>=0.0 && s<=1.0 ){
  24210. double dx, dy, dist2;
  24211. dx = r*adx;
  24212. dy = r*ady;
  24213. dist2 = dx*dx + dy*dy;
  24214. if( dist2>=OdieGrain && (mindist2<0 || mindist2>dist2) ){
  24215. mindist2 = dist2;
  24216. nx = x0 + dx;
  24217. ny = y0 + dy;
  24218. id = pSeg->id;
  24219. }
  24220. }
  24221. }
  24222. }
  24223. if( mindist2>=0.0 ){
  24224. Tcl_Obj *pResult;
  24225. pResult = Tcl_NewObj();
  24226. nx = roundCoord(nx);
  24227. ny = roundCoord(ny);
  24228. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(nx/p->rXZoom));
  24229. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(ny/p->rYZoom));
  24230. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(id));
  24231. Tcl_SetObjResult(interp, pResult);
  24232. }
  24233. return TCL_OK;
  24234. }
  24235. /* OO Method Wallset left */
  24236. static int OOMethod_Wallset_left(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24237.  
  24238. /*
  24239. ** tclmethod: WALLSET left ID LC
  24240. ** title: Change the left compartment of a line segment
  24241. */
  24242. Wallset *p = GETWALLSET(thisObject);
  24243. int id, idLC;
  24244. Segment *pSeg;
  24245. if( objc!=4 ){
  24246. Tcl_WrongNumArgs(interp, 2, objv, "ID LC");
  24247. return TCL_ERROR;
  24248. }
  24249. if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR;
  24250. if( Tcl_GetIntFromObj(interp, objv[3], &idLC) ) return TCL_ERROR;
  24251. if( (pSeg = findSegment(p, id))==0 ){
  24252. Tcl_AppendResult(interp, "segment ",
  24253. Tcl_GetStringFromObj(objv[2],0), " does not exist", 0);
  24254. return TCL_ERROR;
  24255. }
  24256. pSeg->idLC = idLC;
  24257. return TCL_OK;
  24258. }
  24259. /* OO Method Wallset list */
  24260. static int OOMethod_Wallset_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24261.  
  24262. /*
  24263. ** tclmethod: WALLSET list
  24264. ** title: Return a list of all wall segment identifiers
  24265. */
  24266. Wallset *p = GETWALLSET(thisObject);
  24267. Link *pLink;
  24268. Tcl_Obj *pResult;
  24269. pResult = Tcl_NewObj();
  24270. for(pLink=p->pAll; pLink; pLink=pLink->pNext){
  24271. Segment *pSeg=pLink->pLinkNode;
  24272. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->id));
  24273. }
  24274. Tcl_SetObjResult(interp, pResult);
  24275. return TCL_OK;
  24276. }
  24277. /* OO Method Wallset looseends */
  24278. static int OOMethod_Wallset_looseends(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24279.  
  24280. /*
  24281. ** tclmethod: WALLSET looseends
  24282. ** title: Return a list of walls that are have unconnected ends
  24283. **
  24284. ** For each unconnected end, the list contains four elements:
  24285. ** 1. The wallid
  24286. ** 2. 0 for the "from" end, "1" for the "to" end
  24287. ** 3. The X coordinate of the loose end
  24288. ** 4. The Y coordinate of the loose end
  24289. */
  24290. Wallset *p = GETWALLSET(thisObject);
  24291. Segment *pSeg;
  24292. Link *pAll, *pList;
  24293. Tcl_Obj *pRes = Tcl_NewObj();
  24294. for(pAll=p->pAll; pAll; pAll=pAll->pNext){
  24295. pSeg = pAll->pLinkNode;
  24296. pList = segmentsAtVertex(p, pSeg->from[X_IDX], pSeg->from[Y_IDX]);
  24297. if( LinkCount(pList)==1 ){
  24298. Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(pSeg->id));
  24299. Tcl_ListObjAppendElement(0, pRes, ODIE_INT_ZERO());
  24300. Tcl_ListObjAppendElement(0, pRes, Tcl_NewDoubleObj(pSeg->from[X_IDX]/p->rXZoom));
  24301. Tcl_ListObjAppendElement(0, pRes, Tcl_NewDoubleObj(pSeg->from[Y_IDX]/p->rYZoom));
  24302. }
  24303. pList = segmentsAtVertex(p, pSeg->to[X_IDX], pSeg->to[Y_IDX]);
  24304. if( LinkCount(pList)==1 ){
  24305. Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(pSeg->id));
  24306. Tcl_ListObjAppendElement(0, pRes, ODIE_INT_ONE());
  24307. Tcl_ListObjAppendElement(0, pRes, Tcl_NewDoubleObj(pSeg->to[X_IDX]/p->rXZoom));
  24308. Tcl_ListObjAppendElement(0, pRes, Tcl_NewDoubleObj(pSeg->to[Y_IDX]/p->rYZoom));
  24309. }
  24310. }
  24311. Tcl_SetObjResult(interp, pRes);
  24312. return TCL_OK;
  24313. }
  24314. /* OO Method Wallset nearest */
  24315. static int OOMethod_Wallset_nearest(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24316.  
  24317. /*
  24318. ** tclmethod: WALLSET nearest vertex|point X Y
  24319. ** title: Find the nearest vertex or point to a point in the plan
  24320. */
  24321. Wallset *p = GETWALLSET(thisObject);
  24322. int type;
  24323. double x, y, near_x, near_y;
  24324. static const char *NEAR_strs[] = { "point", "vertex", 0 };
  24325. enum NEAR_enum { NEAR_POINT, NEAR_VERTEX, };
  24326. Link *pLink;
  24327. Tcl_Obj *pResult;
  24328. double dx, dy, dist;
  24329.  
  24330. if( objc!=5 ){
  24331. Tcl_WrongNumArgs(interp, 2, objv, "point|vertex X Y");
  24332. return TCL_ERROR;
  24333. }
  24334. if( Tcl_GetIndexFromObj(interp, objv[2], NEAR_strs, "option", 0, &type) ){
  24335. return TCL_ERROR;
  24336. }
  24337. if( Tcl_GetDoubleFromObj(interp, objv[3], &x) ) return TCL_ERROR;
  24338. if( Tcl_GetDoubleFromObj(interp, objv[4], &y) ) return TCL_ERROR;
  24339. x *= p->rXZoom;
  24340. y *= p->rYZoom;
  24341. ignoreNone(p);
  24342. if( type==NEAR_POINT ){
  24343. pLink = nearestPoint(p, x, y, &near_x, &near_y);
  24344. }else if( type==NEAR_VERTEX ){
  24345. pLink = nearestVertex(p, x, y, &near_x, &near_y);
  24346. }else{
  24347. /* Cannot happen */ return TCL_ERROR;
  24348. }
  24349. if( pLink==0 ) return TCL_OK; /* There are not segments in the wallset */
  24350. pResult = Tcl_NewObj();
  24351. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(near_x/p->rXZoom));
  24352. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(near_y/p->rYZoom));
  24353. dx = x - near_x;
  24354. dy = y - near_y;
  24355. dist = sqrt(dx*dx + dy*dy);
  24356. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(dist/p->rXZoom));
  24357. Tcl_ListObjAppendElement(0, pResult, Tcl_NewObj());
  24358. while( pLink ){
  24359. Segment *pSeg=pLink->pLinkNode;
  24360. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->id));
  24361. pLink = pLink->pNext;
  24362. }
  24363. Tcl_SetObjResult(interp, pResult);
  24364. return TCL_OK;
  24365. }
  24366. /* OO Method Wallset nextcwwall */
  24367. static int OOMethod_Wallset_nextcwwall(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24368.  
  24369. /*
  24370. ** tclmethod: WALLSET nextcwwall X0 Y0 X1 Y1
  24371. ** title: Find a wall on X1,Y1 clockwise from X0,Y0->X1,Y1
  24372. */
  24373. Wallset *p = GETWALLSET(thisObject);
  24374. int isBack;
  24375. Segment *pSeg;
  24376. double x0, y0, x1, y1;
  24377. int rc;
  24378. if( objc!=6 ){
  24379. Tcl_WrongNumArgs(interp, 2, objv, "X0 Y0 X1 Y1");
  24380. return TCL_ERROR;
  24381. }
  24382. if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR;
  24383. if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR;
  24384. if( Tcl_GetDoubleFromObj(interp, objv[4], &x1) ) return TCL_ERROR;
  24385. if( Tcl_GetDoubleFromObj(interp, objv[5], &y1) ) return TCL_ERROR;
  24386. x0 = roundCoord(x0*p->rXZoom);
  24387. y0 = roundCoord(y0*p->rYZoom);
  24388. x1 = roundCoord(x1*p->rXZoom);
  24389. y1 = roundCoord(y1*p->rYZoom);
  24390. rc = nextCwSegment(p, x0, y0, x1, y1, &pSeg, &isBack);
  24391. if( rc==0 ){
  24392. Tcl_Obj *pResult = Tcl_NewObj();
  24393. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->id));
  24394. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(isBack));
  24395. Tcl_SetObjResult(interp, pResult);
  24396. }
  24397. return TCL_OK;
  24398. }
  24399. /* OO Method Wallset right */
  24400. static int OOMethod_Wallset_right(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24401.  
  24402. /*
  24403. ** tclmethod: WALLSET right ID RC
  24404. ** title: Change the right compartment of a line segment
  24405. */
  24406. Wallset *p = GETWALLSET(thisObject);
  24407. int id, idRC;
  24408. Segment *pSeg;
  24409. if( objc!=4 ){
  24410. Tcl_WrongNumArgs(interp, 2, objv, "ID RC");
  24411. return TCL_ERROR;
  24412. }
  24413. if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR;
  24414. if( Tcl_GetIntFromObj(interp, objv[3], &idRC) ) return TCL_ERROR;
  24415. if( (pSeg = findSegment(p, id))==0 ){
  24416. Tcl_AppendResult(interp, "segment ",
  24417. Tcl_GetStringFromObj(objv[2],0), " does not exist", 0);
  24418. return TCL_ERROR;
  24419. }
  24420. pSeg->idRC = idRC;
  24421. return TCL_OK;
  24422. }
  24423. /* OO Method Wallset selfcheck */
  24424. static int OOMethod_Wallset_selfcheck(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24425.  
  24426. /*
  24427. ** tclmethod: WALLSET selfcheck
  24428. ** title: Verify the integrity of internal data structures
  24429. */
  24430. Wallset *p = GETWALLSET(thisObject);
  24431. return selfCheck(interp, p);
  24432. }
  24433. /* OO Method Wallset zoom */
  24434. static int OOMethod_Wallset_zoom(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24435.  
  24436. /*
  24437. ** tclmethod: WALLSET zoom ?ZOOM?
  24438. ** title: Query or change the zoom factor.
  24439. */
  24440. Wallset *p = GETWALLSET(thisObject);
  24441. Tcl_Obj *pResult;
  24442. if( objc!=2 && objc!=3 ){
  24443. Tcl_WrongNumArgs(interp, 2, objv, "?ZOOM?");
  24444. return TCL_ERROR;
  24445. }
  24446. if( objc==3 ){
  24447. double r;
  24448. if( Tcl_GetDoubleFromObj(interp, objv[2], &r) ) return TCL_ERROR;
  24449. if( r==0.0 ){
  24450. Tcl_AppendResult(interp, "zoom must be non-zero", 0);
  24451. return TCL_ERROR;
  24452. }
  24453. p->rYZoom = r;
  24454. p->rXZoom = fabs(r);
  24455. }
  24456. pResult = Tcl_NewDoubleObj(p->rYZoom);
  24457. Tcl_SetObjResult(interp, pResult);
  24458. return TCL_OK;
  24459. }
  24460. /* OO Method Wallset constructor */
  24461. static int OOMethod_Wallset_constructor(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24462.  
  24463. /*
  24464. ** tclcmd: wallset WALLSET
  24465. ** title: Create a new wallset object
  24466. ** This routine runs when the "wallset" command is invoked to create a
  24467. ** new wallset.
  24468. */
  24469. Wallset *p;
  24470. p = (Wallset *)Odie_Alloc( sizeof(*p) );
  24471. p->rXZoom = 100.0;
  24472. p->rYZoom = -100.0;
  24473.  
  24474. Tcl_ObjectSetMetadata(thisObject, &WallsetDataType, (ClientData) p);
  24475. return TCL_OK;
  24476. }
  24477. /* Loader for Wallset */
  24478. static int Wallset_OO_Init(Tcl_Interp *interp) {
  24479. /*
  24480. ** Build the "::odielib::wallset" class
  24481. */
  24482. Tcl_Obj* nameObj; /* Name of a class or method being looked up */
  24483. Tcl_Object curClassObject; /* Tcl_Object representing the current class */
  24484. Tcl_Class curClass; /* Tcl_Class representing the current class */
  24485.  
  24486. /*
  24487. * Find the "::odielib::wallset" class, and attach an 'init' method to it.
  24488. */
  24489.  
  24490. nameObj = Tcl_NewStringObj("::odielib::wallset", -1);
  24491. Tcl_IncrRefCount(nameObj);
  24492. if ((curClassObject = Tcl_GetObjectFromObj(interp, nameObj)) == NULL) {
  24493. Tcl_DecrRefCount(nameObj);
  24494. return TCL_ERROR;
  24495. }
  24496. Tcl_DecrRefCount(nameObj);
  24497. curClass = Tcl_GetObjectAsClass(curClassObject);
  24498. /* Attach the constructor to the class */
  24499. Tcl_ClassSetConstructor(interp, curClass, Tcl_NewMethod(interp, curClass, NULL, 1, &OOMethodType_Wallset_constructor, NULL));
  24500.  
  24501. nameObj=Tcl_NewStringObj("atvertex",-1);
  24502. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_atvertex, (ClientData) NULL);
  24503. Tcl_DecrRefCount(nameObj);
  24504. nameObj=Tcl_NewStringObj("boundary",-1);
  24505. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_boundary, (ClientData) NULL);
  24506. Tcl_DecrRefCount(nameObj);
  24507. nameObj=Tcl_NewStringObj("closure",-1);
  24508. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_closure, (ClientData) NULL);
  24509. Tcl_DecrRefCount(nameObj);
  24510. nameObj=Tcl_NewStringObj("closure_polygon",-1);
  24511. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_closure_polygon, (ClientData) NULL);
  24512. Tcl_DecrRefCount(nameObj);
  24513. nameObj=Tcl_NewStringObj("closure_check",-1);
  24514. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_closure_check, (ClientData) NULL);
  24515. Tcl_DecrRefCount(nameObj);
  24516. nameObj=Tcl_NewStringObj("comptlist",-1);
  24517. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_comptlist, (ClientData) NULL);
  24518. Tcl_DecrRefCount(nameObj);
  24519. nameObj=Tcl_NewStringObj("corners",-1);
  24520. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_corners, (ClientData) NULL);
  24521. Tcl_DecrRefCount(nameObj);
  24522. nameObj=Tcl_NewStringObj("delete",-1);
  24523. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_delete, (ClientData) NULL);
  24524. Tcl_DecrRefCount(nameObj);
  24525. nameObj=Tcl_NewStringObj("firstboundary",-1);
  24526. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_firstboundary, (ClientData) NULL);
  24527. Tcl_DecrRefCount(nameObj);
  24528. nameObj=Tcl_NewStringObj("foreach",-1);
  24529. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_foreach, (ClientData) NULL);
  24530. Tcl_DecrRefCount(nameObj);
  24531. nameObj=Tcl_NewStringObj("info",-1);
  24532. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_info, (ClientData) NULL);
  24533. Tcl_DecrRefCount(nameObj);
  24534. nameObj=Tcl_NewStringObj("rawinfo",-1);
  24535. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_rawinfo, (ClientData) NULL);
  24536. Tcl_DecrRefCount(nameObj);
  24537. nameObj=Tcl_NewStringObj("insert",-1);
  24538. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_insert, (ClientData) NULL);
  24539. Tcl_DecrRefCount(nameObj);
  24540. nameObj=Tcl_NewStringObj("primary",-1);
  24541. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_primary, (ClientData) NULL);
  24542. Tcl_DecrRefCount(nameObj);
  24543. nameObj=Tcl_NewStringObj("intersect",-1);
  24544. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_intersect, (ClientData) NULL);
  24545. Tcl_DecrRefCount(nameObj);
  24546. nameObj=Tcl_NewStringObj("left",-1);
  24547. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_left, (ClientData) NULL);
  24548. Tcl_DecrRefCount(nameObj);
  24549. nameObj=Tcl_NewStringObj("list",-1);
  24550. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_list, (ClientData) NULL);
  24551. Tcl_DecrRefCount(nameObj);
  24552. nameObj=Tcl_NewStringObj("looseends",-1);
  24553. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_looseends, (ClientData) NULL);
  24554. Tcl_DecrRefCount(nameObj);
  24555. nameObj=Tcl_NewStringObj("nearest",-1);
  24556. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_nearest, (ClientData) NULL);
  24557. Tcl_DecrRefCount(nameObj);
  24558. nameObj=Tcl_NewStringObj("nextcwwall",-1);
  24559. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_nextcwwall, (ClientData) NULL);
  24560. Tcl_DecrRefCount(nameObj);
  24561. nameObj=Tcl_NewStringObj("right",-1);
  24562. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_right, (ClientData) NULL);
  24563. Tcl_DecrRefCount(nameObj);
  24564. nameObj=Tcl_NewStringObj("selfcheck",-1);
  24565. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_selfcheck, (ClientData) NULL);
  24566. Tcl_DecrRefCount(nameObj);
  24567. nameObj=Tcl_NewStringObj("zoom",-1);
  24568. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Wallset_zoom, (ClientData) NULL);
  24569. Tcl_DecrRefCount(nameObj);
  24570. return TCL_OK;
  24571. }
  24572. /* OO Method PolygonHull vertex_create */
  24573. static int OOMethod_PolygonHull_vertex_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24574.  
  24575. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  24576. PolygonHullVertex *pVertex;
  24577. VectorXYZ A;
  24578. int vertexid;
  24579. int argidx;
  24580.  
  24581. argidx=Tcl_ObjectContextSkippedArgs(objectContext);
  24582.  
  24583. if( objc!=4 ){
  24584. Tcl_WrongNumArgs(interp, 2, objv, "ID XYZ");
  24585. return TCL_ERROR;
  24586. }
  24587. if( Tcl_GetIntFromObj(interp, objv[2], &vertexid) ) return TCL_ERROR;
  24588. if(vertexid>0) {
  24589. pVertex=PolygonHullVertex_ById(pHull,vertexid);
  24590. if(pVertex) {
  24591. Tcl_AppendResult(interp, "vertex id ",
  24592. Tcl_GetStringFromObj(objv[2],0), " already exists", 0);
  24593. return TCL_ERROR;
  24594. }
  24595. }
  24596. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],A)) return TCL_ERROR;
  24597. pVertex=PolygonHullVertex_ByCoords(pHull,A);
  24598. if(pVertex) {
  24599. Tcl_AppendResult(interp, "vertex already exists at ",
  24600. Tcl_GetStringFromObj(objv[3],0), 0);
  24601. return TCL_ERROR;
  24602. }
  24603. pVertex=PolygonHullVertex_Create(pHull,vertexid,A);
  24604. Tcl_SetObjResult(interp, Tcl_NewIntObj(pVertex->id));
  24605. return TCL_OK;
  24606. }
  24607. /* OO Method PolygonHull vertex_coords */
  24608. static int OOMethod_PolygonHull_vertex_coords(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24609.  
  24610. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  24611. int vertexid;
  24612. PolygonHullVertex *pVertex;
  24613. if( objc!=3 ){
  24614. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  24615. return TCL_ERROR;
  24616. }
  24617. if(Tcl_GetIntFromObj(NULL,objv[2],&vertexid)) return TCL_ERROR;
  24618. /* Handle vertex by id */
  24619. pVertex=PolygonHullVertex_ById(pHull,vertexid);
  24620. if(!pVertex) {
  24621. Tcl_AppendResult(interp, "vertex id ",
  24622. Tcl_GetStringFromObj(objv[2],0), " does not exist", 0);
  24623. return TCL_ERROR;
  24624. }
  24625. Tcl_SetObjResult(interp, VectorXYZ_To_TclObj(pVertex->center));
  24626. return TCL_OK;
  24627. }
  24628. /* OO Method PolygonHull vertex_delete */
  24629. static int OOMethod_PolygonHull_vertex_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24630.  
  24631. /* PolygonHullFace delete ID
  24632. **
  24633. ** Delete a triangle
  24634. */
  24635. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  24636. PolygonHullVertex *pVertex;
  24637. int i;
  24638. if( objc!=3 ){
  24639. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  24640. return TCL_ERROR;
  24641. }
  24642. /*
  24643. if( pHull->busy ){
  24644. Tcl_AppendResult(interp, "cannot \"delete\" from within a \"foreach\"",0);
  24645. return TCL_ERROR;
  24646. }
  24647. */
  24648. for(i=2;i<objc;i++) {
  24649. int vertexid;
  24650. if(Tcl_GetIntFromObj(NULL,objv[i],&vertexid)==TCL_OK) {
  24651. /* Handle vertex by id */
  24652. pVertex=PolygonHullVertex_ById(pHull,vertexid);
  24653. } else {
  24654. VectorXYZ A;
  24655. if(Odie_GetVectorXYZFromTclObj(NULL,objv[i],A)) continue;
  24656. pVertex=PolygonHullVertex_ByCoords(pHull,A);
  24657. }
  24658. if(pVertex) {
  24659. PolygonHullVertex_Remove(pVertex);
  24660. readiHashInsert(&pHull->VertexHash, 0, pVertex->id, 0);
  24661. Odie_Free((char *)pVertex);
  24662. }
  24663. }
  24664. PolygonHull_clearSurfaces(pHull);
  24665. return TCL_OK;
  24666. }
  24667. /* OO Method PolygonHull vertex_idlist */
  24668. static int OOMethod_PolygonHull_vertex_idlist(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24669.  
  24670. /* PolygonHullFace list
  24671. **
  24672. ** Return a list of all triangles currently defined.
  24673. */
  24674. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  24675. Tcl_Obj *pResult;
  24676. HashElem *i;
  24677. pResult = Tcl_NewObj();
  24678. for(i=readiHashFirst(&pHull->VertexHash); i; i=readiHashNext(i)) {
  24679. PolygonHullVertex *p=(PolygonHullVertex *)readiHashData(i);
  24680. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(p->id));
  24681. }
  24682. Tcl_SetObjResult(interp, pResult);
  24683. return TCL_OK;
  24684. }
  24685. /* OO Method PolygonHull vertex_inject */
  24686. static int OOMethod_PolygonHull_vertex_inject(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24687.  
  24688. /* PolygonHullFace inject ID ?
  24689. **
  24690. ** Delete a triangle
  24691. */
  24692. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  24693. PolygonHullVertex *pThisVertex;
  24694. int i;
  24695. int vertexid;
  24696. if( objc<4 ){
  24697. Tcl_WrongNumArgs(interp, 2, objv, "ID FACE ?FACE...?");
  24698. return TCL_ERROR;
  24699. }
  24700. /*
  24701. if( pHull->busy ){
  24702. Tcl_AppendResult(interp, "cannot \"delete\" from within a \"foreach\"",0);
  24703. return TCL_ERROR;
  24704. }
  24705. */
  24706. if(Tcl_GetIntFromObj(NULL,objv[2],&vertexid)==TCL_OK) {
  24707. /* Handle vertex by id */
  24708. pThisVertex=PolygonHullVertex_ById(pHull,vertexid);
  24709. if(!pThisVertex) {
  24710. Tcl_AppendResult(interp, "vertex ", Tcl_GetStringFromObj(objv[3],0), " does not exist", 0);
  24711. return TCL_ERROR;
  24712. }
  24713. } else {
  24714. VectorXYZ A;
  24715. if(Odie_GetVectorXYZFromTclObj(NULL,objv[2],A)) return TCL_ERROR;
  24716. pThisVertex=PolygonHullVertex_ByCoords(pHull,A);
  24717. if(!pThisVertex) {
  24718. pThisVertex=PolygonHullVertex_Create(pHull,-1,A);
  24719. }
  24720. if(!pThisVertex) {
  24721. /* Can't create a vertex from coords */
  24722. Tcl_AppendResult(interp, "Failed to create vertex ", Tcl_GetStringFromObj(objv[3],0), 0);
  24723. return TCL_ERROR;
  24724. }
  24725. }
  24726. for(i=3;i<objc;i++) {
  24727. int faceid;
  24728. const char *err;
  24729. PolygonHullFace *pFace;
  24730. if( Tcl_GetIntFromObj(interp, objv[i], &faceid) ) return TCL_ERROR;
  24731. pFace = PolygonHullFace_ById(pHull,faceid);
  24732. if(!pFace) {
  24733. Tcl_AppendResult(interp, "face ", Tcl_GetStringFromObj(objv[i],0), " does not exist", 0);
  24734. return TCL_ERROR;
  24735. }
  24736. err=PolygonHullFace_VertexInject(pFace,pThisVertex);
  24737. //printf("INJECT %s\n",err);
  24738. PolygonHullFace_Compute(pFace);
  24739. if(err) {
  24740. Tcl_AppendResult(interp, err, " on face ", Tcl_GetStringFromObj(objv[i],0), err, 0);
  24741. return TCL_ERROR;
  24742. }
  24743. }
  24744. PolygonHull_clearSurfaces(pHull);
  24745. return TCL_OK;
  24746. }
  24747. /* OO Method PolygonHull vertex_list */
  24748. static int OOMethod_PolygonHull_vertex_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24749.  
  24750. /* PolygonHullFace list
  24751. **
  24752. ** Return a list of all triangles currently defined.
  24753. */
  24754. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  24755. Tcl_Obj *pResult;
  24756. HashElem *i;
  24757. pResult = Tcl_NewObj();
  24758. for(i=readiHashFirst(&pHull->VertexHash); i; i=readiHashNext(i)) {
  24759. PolygonHullVertex *p=(PolygonHullVertex *)readiHashData(i);
  24760. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(p->center));
  24761. }
  24762. Tcl_SetObjResult(interp, pResult);
  24763. return TCL_OK;
  24764. }
  24765. /* OO Method PolygonHull vertex_at */
  24766. static int OOMethod_PolygonHull_vertex_at(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24767.  
  24768. /* PolygonHullFace list
  24769. **
  24770. ** Return a vertices at x,y,z
  24771. */
  24772. VectorXYZ A;
  24773. int i;
  24774. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  24775. PolygonHullVertex *pVertex;
  24776. Tcl_Obj *pResult;
  24777. pResult = Tcl_NewObj();
  24778. for(i=2;i<objc;i++) {
  24779. if(Odie_GetVectorXYZFromTclObj(interp,objv[i],A)) {
  24780. Tcl_DecrRefCount(pResult);
  24781. Tcl_AppendResult(interp, "could not interpret ", Tcl_GetString(objv[i]), 0);
  24782. return TCL_ERROR;
  24783. }
  24784. pVertex=PolygonHullVertex_ByCoords(pHull,A);
  24785. if(pVertex) {
  24786. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pVertex->id));
  24787. }
  24788. }
  24789. Tcl_SetObjResult(interp, pResult);
  24790. return TCL_OK;
  24791. }
  24792. /* OO Method PolygonHull face_info */
  24793. static int OOMethod_PolygonHull_face_info(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24794.  
  24795. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  24796. int id,i;
  24797. PolygonHullFace *pFace;
  24798. static const char *POLYGONHULLFACE_fields[] = { "id", "nVertex", "wallid", "deckid", "typeid", "is_wall", "is_exterior", "is_virtual", "idLC", "idRC", "center", "normal", "radius", "bbox", 0 };
  24799. enum POLYGONHULLFACE_enum { POLYGONHULLFACE_FIELD_ID, POLYGONHULLFACE_FIELD_NVERTEX, POLYGONHULLFACE_FIELD_WALLID, POLYGONHULLFACE_FIELD_DECKID, POLYGONHULLFACE_FIELD_TYPEID, POLYGONHULLFACE_FIELD_IS_WALL, POLYGONHULLFACE_FIELD_IS_EXTERIOR, POLYGONHULLFACE_FIELD_IS_VIRTUAL, POLYGONHULLFACE_FIELD_IDLC, POLYGONHULLFACE_FIELD_IDRC, POLYGONHULLFACE_FIELD_CENTER, POLYGONHULLFACE_FIELD_NORMAL, POLYGONHULLFACE_FIELD_RADIUS, POLYGONHULLFACE_FIELD_BBOX };
  24800.  
  24801. if(objc<3) {
  24802. Tcl_WrongNumArgs(interp, 2, objv, "ID ?field value...?");
  24803. return TCL_ERROR;
  24804. }
  24805. if( PolygonHull_findFace(interp, pHull, objv[2], &pFace) ) return TCL_ERROR;
  24806. if(!pFace) {
  24807. Tcl_AppendResult(interp, "PolygonHullFace does not exist",0);
  24808. return TCL_ERROR;
  24809. }
  24810. for(i=3;i<objc;i+=2) {
  24811. Tcl_Obj *field,*value;
  24812. int option;
  24813. if((i+1) == objc) break;
  24814. field=objv[i];
  24815. value=objv[i+1];
  24816. if( Tcl_GetIndexFromObj(interp, field, POLYGONHULLFACE_fields, "option", 0, &option) ) return TCL_ERROR;
  24817. switch(option) {
  24818. case POLYGONHULLFACE_FIELD_ID: {
  24819. /* Ignore */
  24820. break; } case POLYGONHULLFACE_FIELD_NVERTEX: {
  24821. /* Ignore */
  24822. break; } case POLYGONHULLFACE_FIELD_WALLID: {
  24823. int temp;
  24824. if(Tcl_GetIntFromObj(interp,value,&temp)) {
  24825. Tcl_AppendResult(interp," while processing wallid",NULL);
  24826. return TCL_ERROR;
  24827. }
  24828. pFace->wallid=temp;
  24829. break; } case POLYGONHULLFACE_FIELD_DECKID: {
  24830. int temp;
  24831. if(Tcl_GetIntFromObj(interp,value,&temp)) {
  24832. Tcl_AppendResult(interp," while processing deckid",NULL);
  24833. return TCL_ERROR;
  24834. }
  24835. pFace->deckid=temp;
  24836. break; } case POLYGONHULLFACE_FIELD_TYPEID: {
  24837. int temp;
  24838. if(Tcl_GetIntFromObj(interp,value,&temp)) {
  24839. Tcl_AppendResult(interp," while processing typeid",NULL);
  24840. return TCL_ERROR;
  24841. }
  24842. pFace->typeid=temp;
  24843. break; } case POLYGONHULLFACE_FIELD_IS_WALL: {
  24844. int temp;
  24845. if(Tcl_GetBooleanFromObj(interp,value,&temp)) {
  24846. Tcl_AppendResult(interp," while processing is_wall",NULL);
  24847. return TCL_ERROR;
  24848. }
  24849. pFace->is_wall=temp;
  24850. break; } case POLYGONHULLFACE_FIELD_IS_EXTERIOR: {
  24851. int temp;
  24852. if(Tcl_GetBooleanFromObj(interp,value,&temp)) {
  24853. Tcl_AppendResult(interp," while processing is_exterior",NULL);
  24854. return TCL_ERROR;
  24855. }
  24856. pFace->is_exterior=temp;
  24857. break; } case POLYGONHULLFACE_FIELD_IS_VIRTUAL: {
  24858. int temp;
  24859. if(Tcl_GetIntFromObj(interp,value,&temp)) {
  24860. Tcl_AppendResult(interp," while processing is_virtual",NULL);
  24861. return TCL_ERROR;
  24862. }
  24863. pFace->is_virtual=temp;
  24864. break; } case POLYGONHULLFACE_FIELD_IDLC: {
  24865. int temp;
  24866. if(Tcl_GetIntFromObj(interp,value,&temp)) {
  24867. Tcl_AppendResult(interp," while processing idLC",NULL);
  24868. return TCL_ERROR;
  24869. }
  24870. pFace->idLC=temp;
  24871. break; } case POLYGONHULLFACE_FIELD_IDRC: {
  24872. int temp;
  24873. if(Tcl_GetIntFromObj(interp,value,&temp)) {
  24874. Tcl_AppendResult(interp," while processing idLC",NULL);
  24875. return TCL_ERROR;
  24876. }
  24877. pFace->idRC=temp;
  24878. break; } case POLYGONHULLFACE_FIELD_CENTER: {
  24879. /* Ignore */
  24880. break; } case POLYGONHULLFACE_FIELD_NORMAL: {
  24881. /* Ignore */
  24882. break; } case POLYGONHULLFACE_FIELD_RADIUS: {
  24883. /* Ignore */
  24884. break; } case POLYGONHULLFACE_FIELD_BBOX: {
  24885. /* Ignore */
  24886. break; } }
  24887. }
  24888.  
  24889. Tcl_SetObjResult(interp, PolygonHullFace_To_Dict(pFace));
  24890. return TCL_OK;
  24891. }
  24892. /* OO Method PolygonHull face_exists */
  24893. static int OOMethod_PolygonHull_face_exists(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24894.  
  24895. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  24896. PolygonHullFace *pFace;
  24897. if(objc<3) {
  24898. Tcl_WrongNumArgs(interp, 2, objv, "ID ?field value...?");
  24899. return TCL_ERROR;
  24900. }
  24901. if( PolygonHull_findFace(interp, pHull, objv[2], &pFace) ) return TCL_ERROR;
  24902. if(!pFace) {
  24903. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  24904. } else {
  24905. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
  24906. }
  24907. return TCL_OK;
  24908. }
  24909. /* OO Method PolygonHull face_active */
  24910. static int OOMethod_PolygonHull_face_active(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24911.  
  24912. /* PolygonHullFace active
  24913. ** PolygonHullFace active all
  24914. ** PolygonHullFace active sphere RADIUS X Y Z
  24915. ** PolygonHullFace active ID ...
  24916. **
  24917. ** This first form returns a list of all active triangles. The
  24918. ** other forms set the active triangle list. The 2nd form sets the
  24919. ** active list to all triangles. This is the default setting. The
  24920. ** 4d form sets the active list to all triangles that intersect a
  24921. ** sphere centered at X,Y,Z with radius RADIUS. The 4th form sets
  24922. ** the active triangles to be just those listed.
  24923. */
  24924. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  24925. PolygonHullFace *p;
  24926. if( objc==2 ){
  24927. Tcl_Obj *pResult = Tcl_NewObj();
  24928. for(p=pHull->pActive; p; p=p->pActive){
  24929. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(p->id));
  24930. }
  24931. Tcl_SetObjResult(interp, pResult);
  24932. }else if( objc>=3 && strcmp(Tcl_GetString(objv[2]),"all")==0 ){
  24933. HashElem *i;
  24934. pHull->pActive = 0;
  24935. for(i=readiHashFirst(&pHull->FaceHash); i; i=readiHashNext(i)) {
  24936. p = readiHashData(i);
  24937. p->pActive = pHull->pActive;
  24938. pHull->pActive = p;
  24939. }
  24940. }else if(strcmp(Tcl_GetString(objv[2]),"sphere")==0 ){
  24941. double radius;
  24942. VectorXYZ center;
  24943. HashElem *i;
  24944.  
  24945. if(objc!=5 && objc!=7) {
  24946. Tcl_WrongNumArgs( interp, 2, objv, "sphere RADIUS XYZ\nOR\nsphere RADIUS X Y Z" );
  24947. return TCL_ERROR;
  24948. }
  24949. if( Tcl_GetDoubleFromObj(interp, objv[3], &radius) ) return TCL_ERROR;
  24950. if(objc==5) {
  24951. if(Odie_GetVectorXYZFromTclObj(interp,objv[1],center)) return TCL_ERROR;
  24952. }
  24953. if(objc==7) {
  24954. if( Odie_GetMatrixElementFromObj(interp, objv[4], center, X_IDX) ) return TCL_ERROR;
  24955. if( Odie_GetMatrixElementFromObj(interp, objv[5], center, Y_IDX) ) return TCL_ERROR;
  24956. if( Odie_GetMatrixElementFromObj(interp, objv[6], center, Z_IDX) ) return TCL_ERROR;
  24957. }
  24958. pHull->pActive = 0;
  24959. for(i=readiHashFirst(&pHull->FaceHash); i; i=readiHashNext(i)) {
  24960. p = readiHashData(i);
  24961. if( VectorXYZ_Distance(center,p->center) - p->radius <= radius ){
  24962. p->pActive = pHull->pActive;
  24963. pHull->pActive = p;
  24964. }
  24965. }
  24966. } else {
  24967. int j;
  24968. HashElem *i;
  24969. pHull->pActive = 0;
  24970. for(i=readiHashFirst(&pHull->FaceHash); i; i=readiHashNext(i)) {
  24971. p = readiHashData(i);
  24972. p->pActive = 0;
  24973. }
  24974. for(j=3; j<objc; j++){
  24975. if( PolygonHull_findFace(interp, pHull, objv[j], &p) ) return TCL_ERROR;
  24976. if( p->pActive ) continue;
  24977. p->pActive = pHull->pActive;
  24978. pHull->pActive = p;
  24979. }
  24980. }
  24981. return TCL_OK;
  24982. }
  24983. /* OO Method PolygonHull face_center */
  24984. static int OOMethod_PolygonHull_face_center(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  24985.  
  24986. /*
  24987. ** PolygonHullFace center ID
  24988. **
  24989. ** The center is really just the average of the three vertices.
  24990. */
  24991. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  24992. PolygonHullFace *p;
  24993. if( objc!=3 ){
  24994. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  24995. return TCL_ERROR;
  24996. }
  24997. if( PolygonHull_findFace(interp, pHull, objv[2], &p) ) return TCL_ERROR;
  24998. Tcl_SetObjResult(interp,VectorXYZ_To_TclObj(p->center));
  24999. return TCL_OK;
  25000. }
  25001. /* OO Method PolygonHull face_polygon */
  25002. static int OOMethod_PolygonHull_face_polygon(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25003.  
  25004. /* PolygonHullFace coords ID
  25005. **
  25006. ** Return the coordinates for a triangle. The return is a list of
  25007. ** 3 lists of XYZ floating point numbers one for each of three vertices.
  25008. */
  25009. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25010. PolygonHullFace *p;
  25011. Odie_FaceXYZ *pPolyOut;
  25012. int i;
  25013. if( objc!=3 ){
  25014. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  25015. return TCL_ERROR;
  25016. }
  25017. if( PolygonHull_findFace(interp, pHull, objv[2], &p) ) return TCL_ERROR;
  25018. pPolyOut=Odie_FaceXYZ_Create(p->nVertex);
  25019. for(i=0; i<p->nVertex; i++){
  25020. VectorXYZ_Copy(pPolyOut->vertex_xyz[i],p->aVertex[i]->center);
  25021. }
  25022. Odie_FaceXYZ_Compute(interp,pPolyOut);
  25023. Tcl_SetObjResult(interp, Odie_FaceXYZ_NewTclObj(pPolyOut));
  25024. return TCL_OK;
  25025. }
  25026. /* OO Method PolygonHull face_vertices */
  25027. static int OOMethod_PolygonHull_face_vertices(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25028.  
  25029. /* PolygonHullFace vertices ID
  25030. **
  25031. ** Return the coordinates for a triangle. The return is a list of
  25032. ** 3 lists of XYZ floating point numbers one for each of three vertices.
  25033. */
  25034. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25035. PolygonHullFace *p;
  25036. Tcl_Obj *pResult;
  25037. int i;
  25038. if( objc!=3 ){
  25039. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  25040. return TCL_ERROR;
  25041. }
  25042. if( PolygonHull_findFace(interp, pHull, objv[2], &p) ) return TCL_ERROR;
  25043. pResult = Tcl_NewObj();
  25044. for(i=0; i<p->nVertex; i++){
  25045. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(p->aVertex[i]->id));
  25046. }
  25047. Tcl_SetObjResult(interp, pResult);
  25048. return TCL_OK;
  25049. }
  25050. /* OO Method PolygonHull face_create */
  25051. static int OOMethod_PolygonHull_face_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25052.  
  25053. /* PolygonHullFace create ID A B C
  25054. **
  25055. ** Create a new 3d triangle. Or if the triangle already exists,
  25056. ** change its coordinates.
  25057. */
  25058. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25059. PolygonHullFace *pFace;
  25060. int id;
  25061. int i;
  25062. if( objc<5 ){
  25063. Tcl_WrongNumArgs(interp, 2, objv, "ID XYZ XYZ XYZ ?XYZ...?");
  25064. return TCL_ERROR;
  25065. }
  25066. if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR;
  25067. if(id>0) {
  25068. pFace=PolygonHullFace_ById(pHull,id);
  25069. if(pFace) {
  25070. Tcl_AppendResult(interp, "face ",
  25071. Tcl_GetStringFromObj(objv[2],0), " already exists", 0);
  25072. return TCL_ERROR;
  25073. }
  25074. if (id>=pHull->FaceNextId) {
  25075. pHull->FaceNextId=id;
  25076. }
  25077. } else {
  25078. pHull->FaceNextId++;
  25079. id=pHull->FaceNextId;
  25080. }
  25081.  
  25082. PolygonHull_clearSurfaces(pHull);
  25083. /* Left off here
  25084. ** Need to develop a tool to pick a vertex by ID or by coordinate
  25085. ** allocate missing vertexes, and link the vertex and face together
  25086. */
  25087. pFace = PolygonHullFace_Create(pHull,id);
  25088. if( pFace==0 ) return TCL_ERROR;
  25089. id=pFace->id;
  25090. for(i=0;i<pFace->nVertex;i++) {
  25091. LinkInit(pFace->pVertex[i], pFace);
  25092. }
  25093. pFace->nVertex=objc-3;
  25094.  
  25095.  
  25096. for(i=0;i<objc-3;i++) {
  25097. int vertexid,idxmode=0;
  25098. VectorXYZ A;
  25099. PolygonHullVertex *pVertex;
  25100. if(Tcl_GetIntFromObj(NULL,objv[i+3],&vertexid)==TCL_OK) {
  25101. /* Handle vertex by id */
  25102. pVertex=PolygonHullVertex_ById(pHull,vertexid);
  25103. idxmode=1;
  25104. } else {
  25105. if(Odie_GetVectorXYZFromTclObj(interp,objv[i+3],A)) {
  25106. Tcl_AppendResult(interp, "could not interpret ", Tcl_GetString(objv[i+3]), 0);
  25107. goto failed;
  25108. }
  25109. pVertex=PolygonHullVertex_ByCoords(pHull,A);
  25110. }
  25111. if(!pVertex) {
  25112. if(idxmode) {
  25113. Tcl_AppendResult(interp, "no such vertex", 0);
  25114. goto failed;
  25115. }
  25116. pVertex=PolygonHullVertex_Create(pHull,-1,A);
  25117. if(!pVertex) {
  25118. /* Can't create a vertex from an integer */
  25119. Tcl_AppendResult(interp, "no such vertex", 0);
  25120. goto failed;
  25121. }
  25122. }
  25123. pVertex->pNextVertex=pFace->pNextVertex;
  25124. pFace->pNextVertex=pVertex;
  25125. }
  25126. PolygonHullFace_Compute(pFace);
  25127. Tcl_SetObjResult(interp,Tcl_NewIntObj(pFace->id));
  25128. return TCL_OK;
  25129. failed:
  25130. PolygonHullFace_Remove(pFace);
  25131. Odie_Free((char *)pFace);
  25132. return TCL_ERROR;
  25133. }
  25134. /* OO Method PolygonHull face_delete */
  25135. static int OOMethod_PolygonHull_face_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25136.  
  25137. /* PolygonHullFace delete ID
  25138. **
  25139. ** Delete a triangle
  25140. */
  25141. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25142. PolygonHullFace *pFace;
  25143. int id;
  25144. if( objc!=3 ){
  25145. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  25146. return TCL_ERROR;
  25147. }
  25148. /*
  25149. if( pHull->busy ){
  25150. Tcl_AppendResult(interp, "cannot \"delete\" from within a \"foreach\"",0);
  25151. return TCL_ERROR;
  25152. }
  25153. */
  25154. if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR;
  25155. pFace = PolygonHullFace_ById(pHull,id);
  25156. if( pFace ){
  25157. PolygonHullFace_Remove(pFace);
  25158. readiHashInsert(&pHull->FaceHash, 0, pFace->id, 0);
  25159. Odie_Free((char *)pFace);
  25160. PolygonHull_clearSurfaces(pHull);
  25161. }
  25162. return TCL_OK;
  25163. }
  25164. /* OO Method PolygonHull face_intersect */
  25165. static int OOMethod_PolygonHull_face_intersect(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25166.  
  25167. /* PolygonHullFace intersect A B ?ID?
  25168. **
  25169. ** Find the point of intersection between triangles and the
  25170. ** line segment between X0,Y0,Z0 and X1,Y1,Z1. If ID is
  25171. ** specified, only that one triangle is checked. If ID is
  25172. ** omitted, then all triangles are checked.
  25173. **
  25174. ** The result is a list which is a multiple of 2 elements in length.
  25175. ** Within each group of 2 elements, the first element is
  25176. ** the ID of the intersecting triangle. The next element is an XYZ vectors
  25177. ** with the coordinates of the point of intersection. The
  25178. ** triangles appear on the least in order of increasing distance
  25179. ** from X0,Y0,Z0.
  25180. */
  25181. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25182. PolygonHullFace *p;
  25183. VectorXYZ start, end;
  25184. double x;
  25185. Tcl_Obj *pResult;
  25186. if( objc!=4 && objc!=5 ){
  25187. Tcl_WrongNumArgs(interp, 2, objv, "A B ?ID?");
  25188. return TCL_ERROR;
  25189. }
  25190. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],start)) return TCL_ERROR;
  25191. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],end)) return TCL_ERROR;
  25192. if( objc==5 ){
  25193. if( PolygonHull_findFace(interp, pHull, objv[4], &p) ) return TCL_ERROR;
  25194. x = PolygonHull_intersectLineSegFace(p, start, end, p->intersect);
  25195. if( x<0.0 ){
  25196. p = 0;
  25197. }else{
  25198. p->pNext = 0;
  25199. }
  25200. }else{
  25201. p = PolygonHullFace_findHits(pHull,start, end);
  25202. }
  25203. if( p ){
  25204. pResult = Tcl_NewObj();
  25205. while( p ){
  25206. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(p->id));
  25207. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(p->intersect));
  25208. p = p->pNext;
  25209. }
  25210. Tcl_SetObjResult(interp, pResult);
  25211. }
  25212. return TCL_OK;
  25213. }
  25214. /* OO Method PolygonHull face_list */
  25215. static int OOMethod_PolygonHull_face_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25216.  
  25217. /* PolygonHullFace list
  25218. **
  25219. ** Return a list of all triangles currently defined.
  25220. */
  25221. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25222. Tcl_Obj *pResult;
  25223. HashElem *i;
  25224. pResult = Tcl_NewObj();
  25225. for(i=readiHashFirst(&pHull->FaceHash); i; i=readiHashNext(i)) {
  25226. PolygonHullFace *pFace=readiHashData(i);
  25227. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pFace->id));
  25228. }
  25229. Tcl_SetObjResult(interp, pResult);
  25230. return TCL_OK;
  25231. }
  25232. /* OO Method PolygonHull face_nearest */
  25233. static int OOMethod_PolygonHull_face_nearest(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25234.  
  25235. /* PolygonHullFace nearest X Y Z ?ID?
  25236. **
  25237. ** Find the triangle that is closest to the point X,Y,Z. Or if
  25238. ** ID is specified, find the point on ID that is closest to X,Y,Z.
  25239. ** Return a list that consists of:
  25240. **
  25241. ** * The ID of the triangle
  25242. ** * The distance from X,Y,Z to the triangle
  25243. ** * The point on the triangle closest to X,Y,Z
  25244. **
  25245. ** The return value is a list of 5 elements. An empty string
  25246. ** is returned if no triangles are defined.
  25247. */
  25248. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25249. PolygonHullFace *p;
  25250. VectorXYZ A,nearest;
  25251. double d;
  25252. Tcl_Obj *pResult;
  25253. if( objc!=3 && objc!=4 ){
  25254. Tcl_WrongNumArgs(interp, 2, objv, "XYZ ?ID?");
  25255. return TCL_ERROR;
  25256. }
  25257. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],A)) return TCL_ERROR;
  25258. if( objc==3 ){
  25259. p = PolygonHullFace_findClosest(pHull, A, nearest, &d);
  25260. } else {
  25261. if( PolygonHull_findFace(interp, pHull, objv[3], &p) ) return TCL_ERROR;
  25262. d = PolygonHull_closestPointOnFace(p, A, nearest);
  25263. }
  25264. if( p ){
  25265. pResult = Tcl_NewObj();
  25266. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(p->id));
  25267. Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(d));
  25268. Tcl_ListObjAppendElement(0, pResult, VectorXYZ_To_TclObj(nearest));
  25269. Tcl_SetObjResult(interp, pResult);
  25270. }
  25271. return TCL_OK;
  25272. }
  25273. /* OO Method PolygonHull face_radius */
  25274. static int OOMethod_PolygonHull_face_radius(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25275.  
  25276. /* PolygonHullFace radius ID
  25277. **
  25278. ** Return a radius for the given triangle.
  25279. ** The radius the maximum distance from the center to any vertex.
  25280. */
  25281. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25282. PolygonHullFace *p;
  25283. if( objc!=3 ){
  25284. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  25285. return TCL_ERROR;
  25286. }
  25287. if( PolygonHull_findFace(interp, pHull, objv[2], &p) ) return TCL_ERROR;
  25288. Tcl_SetObjResult(interp, Tcl_NewDoubleObj(p->radius));
  25289. return TCL_OK;
  25290. }
  25291. /* OO Method PolygonHull face_normal */
  25292. static int OOMethod_PolygonHull_face_normal(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25293.  
  25294. /* PolygonHullFace normal ID
  25295. **
  25296. ** Return a normal vector to the given triangle
  25297. */
  25298. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25299. PolygonHullFace *p;
  25300. if( objc!=3 ){
  25301. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  25302. return TCL_ERROR;
  25303. }
  25304. if( PolygonHull_findFace(interp, pHull, objv[2], &p) ) return TCL_ERROR;
  25305. Tcl_SetObjResult(interp, VectorXYZ_To_TclObj(p->normal));
  25306. return TCL_OK;
  25307. }
  25308. /* OO Method PolygonHull face_side */
  25309. static int OOMethod_PolygonHull_face_side(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25310.  
  25311. /* PolygonHullFace side ID X Y Z
  25312. **
  25313. ** Determine which side of trangle ID the point X,Y,Z is on and return
  25314. ** postive for the front side, negative for the back side or zero
  25315. ** if the point is on the same plane as the triangle.
  25316. **
  25317. ** The front side of a triangle is determined by the right-hand rule
  25318. ** of thumb.
  25319. */
  25320. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25321. VectorXYZ pt;
  25322. PolygonHullFace *p;
  25323. VectorXYZ vec; /* Vector from surface to the point */
  25324. double dp; /* Dot product of vec and norm */
  25325. if( objc!=4 ){
  25326. Tcl_WrongNumArgs(interp, 2, objv, "ID XYZ");
  25327. return TCL_ERROR;
  25328. }
  25329. if(Odie_GetVectorXYZFromTclObj(interp,objv[3],pt)) return TCL_ERROR;
  25330. if( PolygonHull_findFace(interp, pHull, objv[2], &p) ) return TCL_ERROR;
  25331. VectorXYZ_Subtract(vec, pt, p->center);
  25332. dp = VectorXYZ_Dot_Product(vec, p->normal);
  25333. if(dp<=0) {
  25334. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  25335. } else {
  25336. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
  25337. }
  25338. return TCL_OK;
  25339. }
  25340. /* OO Method PolygonHull face_volume */
  25341. static int OOMethod_PolygonHull_face_volume(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25342.  
  25343. /* PolygonHullFace normal ID
  25344. **
  25345. ** Return a normal vector to the given triangle
  25346. */
  25347. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25348. PolygonHullFace *pFace;
  25349. if( objc!=3 && objc !=4 && objc !=5 ){
  25350. Tcl_WrongNumArgs(interp, 2, objv, "ID ?side? ?volumeid?");
  25351. return TCL_ERROR;
  25352. }
  25353. if( PolygonHull_findFace(interp, pHull, objv[2], &pFace) ) return TCL_ERROR;
  25354. if(objc==3) {
  25355. Tcl_Obj *pResult=Tcl_NewObj();
  25356. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pFace->idRC));
  25357. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pFace->idLC));
  25358. Tcl_SetObjResult(interp, pResult);
  25359. return TCL_OK;
  25360. }
  25361. if(objc==4) {
  25362. int side;
  25363. if( Tcl_GetBooleanFromObj(interp,objv[3], &side) ) return TCL_ERROR;
  25364. if(side) {
  25365. Tcl_SetObjResult(interp, Tcl_NewIntObj(pFace->idLC));
  25366. } else {
  25367. Tcl_SetObjResult(interp, Tcl_NewIntObj(pFace->idRC));
  25368. }
  25369. return TCL_OK;
  25370. } else {
  25371. int side;
  25372. PolygonHullVolume *pVolume=NULL;
  25373. int volumeid;
  25374. if( Tcl_GetBooleanFromObj(interp,objv[3], &side) ) return TCL_ERROR;
  25375. if(Tcl_GetIntFromObj(interp,objv[4],&volumeid) ) return TCL_ERROR;
  25376. if(volumeid>0) {
  25377. /* Handle vertex by id */
  25378. pVolume=PolygonHullVolume_ById(pHull,volumeid);
  25379. if(!pVolume) {
  25380. Tcl_AppendResult(interp, "volume id ",
  25381. Tcl_GetStringFromObj(objv[4],0), " does not exist", 0);
  25382. return TCL_ERROR;
  25383. }
  25384. }
  25385. if(side) {
  25386. /* sideLeft */
  25387. pFace->idLC=volumeid;
  25388. } else {
  25389. /* sideRight */
  25390. pFace->idRC=volumeid;
  25391. }
  25392. return TCL_OK;
  25393. }
  25394. return TCL_OK;
  25395. }
  25396. /* OO Method PolygonHull faces_at */
  25397. static int OOMethod_PolygonHull_faces_at(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25398.  
  25399. /* PolygonHullFace list
  25400. **
  25401. ** Return a vertices at x,y,z
  25402. */
  25403. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25404. VectorXYZ A;
  25405. int i;
  25406. Link *pLink;
  25407. PolygonHullVertex *pVertex;
  25408. Tcl_Obj *pResult;
  25409. pResult = Tcl_NewObj();
  25410. for(i=2;i<objc;i++) {
  25411. int vertexid;
  25412. if(Tcl_GetIntFromObj(NULL,objv[i],&vertexid)==TCL_OK) {
  25413. /* Handle vertex by id */
  25414. pVertex=PolygonHullVertex_ById(pHull,vertexid);
  25415. } else {
  25416. if(Odie_GetVectorXYZFromTclObj(interp,objv[i],A)) {
  25417. Tcl_DecrRefCount(pResult);
  25418. Tcl_AppendResult(interp, "could not interpret ", Tcl_GetString(objv[i]), 0);
  25419. return TCL_ERROR;
  25420. }
  25421. pVertex=PolygonHullVertex_ByCoords(pHull,A);
  25422. }
  25423. if(pVertex) {
  25424. for(pLink=pVertex->pHashFace;pLink;pLink=pLink->pNext) {
  25425. PolygonHullFace *pFace=pLink->pLinkNode;
  25426. if(pFace) {
  25427. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pFace->id));
  25428. }
  25429. }
  25430. }
  25431. }
  25432. Tcl_SetObjResult(interp, pResult);
  25433. return TCL_OK;
  25434. }
  25435. /* OO Method PolygonHull face_within */
  25436. static int OOMethod_PolygonHull_face_within(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25437.  
  25438. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25439. VectorXYZ POINT,nearest;
  25440. if( objc!=3 && objc!=4 ){
  25441. Tcl_WrongNumArgs(interp, 2, objv, "A ?ID?");
  25442. return TCL_ERROR;
  25443. }
  25444. if(Odie_GetVectorXYZFromTclObj(interp,objv[2],POINT)) return TCL_ERROR;
  25445. if( objc==4 ){
  25446. PolygonHullFace *pFace;
  25447. double d;
  25448. if( PolygonHull_findFace(interp, pHull, objv[3], &pFace) ) return TCL_ERROR;
  25449. if(!VectorXYZ_AABB_Within(POINT,pFace->bbox)) {
  25450. Tcl_SetObjResult(interp,Tcl_NewIntObj(0));
  25451. } else {
  25452. d = PolygonHull_closestPointOnFace(pFace, POINT, nearest);
  25453. if(d<=Vector_Tolerance) {
  25454. Tcl_SetObjResult(interp,Tcl_NewIntObj(1));
  25455. } else {
  25456. Tcl_SetObjResult(interp,Tcl_NewIntObj(0));
  25457. }
  25458. }
  25459. } else {
  25460. Tcl_Obj *pResult;
  25461. pResult = Tcl_NewObj();
  25462. HashElem *i;
  25463. double d;
  25464. for(i=readiHashFirst(&pHull->FaceHash); i; i=readiHashNext(i)) {
  25465. PolygonHullFace *pFace=readiHashData(i);
  25466. if(!VectorXYZ_AABB_Within(POINT,pFace->bbox)) continue;
  25467. d = PolygonHull_closestPointOnFace(pFace, POINT, nearest);
  25468. if(d<=Vector_Tolerance) {
  25469. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pFace->id));
  25470. }
  25471. }
  25472. Tcl_SetObjResult(interp, pResult);
  25473. }
  25474. return TCL_OK;
  25475. }
  25476. /* OO Method PolygonHull volume_create */
  25477. static int OOMethod_PolygonHull_volume_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25478.  
  25479. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25480. PolygonHullVolume *pVolume=NULL;
  25481. int volumeid;
  25482.  
  25483. if( objc!=3 ){
  25484. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  25485. return TCL_ERROR;
  25486. }
  25487. if( Tcl_GetIntFromObj(interp, objv[2], &volumeid) ) return TCL_ERROR;
  25488. if(volumeid>0) {
  25489. pVolume=PolygonHullVolume_ById(pHull,volumeid);
  25490. if(pVolume) {
  25491. Tcl_AppendResult(interp, "volume id ",
  25492. Tcl_GetStringFromObj(objv[2],0), " already exists", 0);
  25493. return TCL_ERROR;
  25494. }
  25495. }
  25496. pVolume=PolygonHullVolume_Create(pHull,volumeid);
  25497. Tcl_SetObjResult(interp, Tcl_NewIntObj(pVolume->id));
  25498. return TCL_OK;
  25499. }
  25500. /* OO Method PolygonHull volume_delete */
  25501. static int OOMethod_PolygonHull_volume_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25502.  
  25503. /* PolygonHullFace delete ID
  25504. **
  25505. ** Delete a triangle
  25506. */
  25507. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25508. PolygonHullVolume *pVolume=NULL;
  25509. int id;
  25510. if( objc!=3 ){
  25511. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  25512. return TCL_ERROR;
  25513. }
  25514. /*
  25515. if( pHull->busy ){
  25516. Tcl_AppendResult(interp, "cannot \"delete\" from within a \"foreach\"",0);
  25517. return TCL_ERROR;
  25518. }
  25519. */
  25520. if(Tcl_GetIntFromObj(NULL,objv[2],&id)==TCL_OK) {
  25521. /* Handle vertex by id */
  25522. pVolume=PolygonHullVolume_ById(pHull,id);
  25523. }
  25524. if(pVolume) {
  25525. PolygonHullVolume_Unlink(pVolume);
  25526. Odie_Free((char *)pVolume);
  25527. }
  25528. PolygonHull_clearSurfaces(pHull);
  25529. return TCL_OK;
  25530. }
  25531. /* OO Method PolygonHull volume_list */
  25532. static int OOMethod_PolygonHull_volume_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25533.  
  25534. /* volume list
  25535. **
  25536. ** Return a list of all triangles currently defined.
  25537. */
  25538. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25539. Tcl_Obj *pResult;
  25540. HashElem *i;
  25541. pResult = Tcl_NewObj();
  25542. for(i=readiHashFirst(&pHull->VolumeHash); i; i=readiHashNext(i)) {
  25543. PolygonHullVolume *p=(PolygonHullVolume *)readiHashData(i);
  25544. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(p->id));
  25545. }
  25546. Tcl_SetObjResult(interp, pResult);
  25547. return TCL_OK;
  25548. }
  25549. /* OO Method PolygonHull volume_faces */
  25550. static int OOMethod_PolygonHull_volume_faces(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25551.  
  25552. /* volume list
  25553. **
  25554. ** Return a list of all triangles currently defined.
  25555. */
  25556. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25557. int id;
  25558. PolygonHullVolume *pVolume=NULL;
  25559. Tcl_Obj *pResult;
  25560. if( objc!=3 ){
  25561. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  25562. return TCL_ERROR;
  25563. }
  25564. if(Tcl_GetIntFromObj(NULL,objv[2],&id)==TCL_OK) {
  25565. /* Handle vertex by id */
  25566. pVolume=PolygonHullVolume_ById(pHull,id);
  25567. }
  25568. if(!pVolume) {
  25569. Tcl_ResetResult(interp);
  25570. return TCL_OK;
  25571. }
  25572. HashElem *i;
  25573. pResult = Tcl_NewObj();
  25574.  
  25575. for(i=readiHashFirst(&pHull->FaceHash); i; i=readiHashNext(i)) {
  25576. PolygonHullFace *pFace=readiHashData(i);
  25577. if(pFace->idRC==id) {
  25578. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pFace->id));
  25579. Tcl_ListObjAppendElement(0, pResult, Tcl_NewBooleanObj(0));
  25580. }
  25581. if(pFace->idLC==id) {
  25582. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pFace->id));
  25583. Tcl_ListObjAppendElement(0, pResult, Tcl_NewBooleanObj(1));
  25584. }
  25585. }
  25586. Tcl_SetObjResult(interp, pResult);
  25587. return TCL_OK;
  25588. }
  25589. /* OO Method PolygonHull volume_group */
  25590. static int OOMethod_PolygonHull_volume_group(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25591.  
  25592. /* volume list
  25593. **
  25594. ** Return a list of all triangles currently defined.
  25595. */
  25596. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25597. int id;
  25598. PolygonHullVolume *pVolume=NULL;
  25599. Tcl_Obj *pResult;
  25600. pResult = Tcl_NewObj();
  25601. if( objc!=3 && objc!=4 ){
  25602. Tcl_WrongNumArgs(interp, 2, objv, "ID ?groupid?");
  25603. return TCL_ERROR;
  25604. }
  25605. if(Tcl_GetIntFromObj(NULL,objv[2],&id)==TCL_OK) {
  25606. /* Handle vertex by id */
  25607. pVolume=PolygonHullVolume_ById(pHull,id);
  25608. }
  25609. if(!pVolume) {
  25610. Tcl_AppendResult(interp,"Volume does not exist",NULL);
  25611. return TCL_ERROR;
  25612. }
  25613. if(objc==4) {
  25614. int groupid;
  25615. if(Tcl_GetIntFromObj(NULL,objv[3],&groupid)) return TCL_ERROR;
  25616. pVolume->groupid=groupid;
  25617. }
  25618. Tcl_SetObjResult(interp,Tcl_NewIntObj(pVolume->groupid));
  25619. return TCL_OK;
  25620. }
  25621. /* OO Method PolygonHull volume_center */
  25622. static int OOMethod_PolygonHull_volume_center(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25623.  
  25624. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25625. int id;
  25626. PolygonHullVolume *pVolume=NULL;
  25627. VectorXYZ center;
  25628. int nFaces=0;
  25629. if( objc!=3 ){
  25630. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  25631. return TCL_ERROR;
  25632. }
  25633. if(Tcl_GetIntFromObj(NULL,objv[2],&id)==TCL_OK) {
  25634. /* Handle vertex by id */
  25635. pVolume=PolygonHullVolume_ById(pHull,id);
  25636. }
  25637. if(!pVolume) {
  25638. Tcl_AppendResult(interp,"Volume does not exist",NULL);
  25639. return TCL_ERROR;
  25640. }
  25641. HashElem *i;
  25642. VectorXYZ_Zero(center);
  25643. for(i=readiHashFirst(&pHull->FaceHash); i; i=readiHashNext(i)) {
  25644. PolygonHullFace *pFace=readiHashData(i);
  25645. if(!pFace) continue;
  25646. nFaces++;
  25647. if(pFace->idRC==id) {
  25648. center[X_IDX]+=pFace->center[X_IDX];
  25649. center[Y_IDX]+=pFace->center[Y_IDX];
  25650. center[Z_IDX]+=pFace->center[Z_IDX];
  25651. }
  25652. if(pFace->idLC==id) {
  25653. center[X_IDX]-=pFace->center[X_IDX];
  25654. center[Y_IDX]-=pFace->center[Y_IDX];
  25655. center[Z_IDX]-=pFace->center[Z_IDX];
  25656. }
  25657. }
  25658. if(nFaces>0) {
  25659. center[X_IDX]/=nFaces;
  25660. center[Y_IDX]/=nFaces;
  25661. center[Z_IDX]/=nFaces;
  25662. }
  25663. Tcl_SetObjResult(interp, VectorXYZ_To_TclObj(center));
  25664. return TCL_OK;
  25665. }
  25666. /* OO Method PolygonHull reset */
  25667. static int OOMethod_PolygonHull_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25668.  
  25669. /* PolygonHullFace reset
  25670. **
  25671. ** Delete all triangles
  25672. */
  25673. PolygonHull *pHull = GETPOLYGONHULL(thisObject);
  25674. PolygonHull_Reset(pHull);
  25675. return TCL_OK;
  25676. }
  25677. /* OO Method PolygonHull PolygonHull_Init */
  25678. static int OOMethod_PolygonHull_PolygonHull_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  25679.  
  25680. /*
  25681. ** tclcmd: wallset WALLSET
  25682. ** title: Create a new wallset object
  25683. ** This routine runs when the "wallset" command is invoked to create a
  25684. ** new wallset.
  25685. */
  25686. PolygonHull *p;
  25687. p = (PolygonHull *)Odie_Alloc( sizeof(PolygonHull) );
  25688. p->FaceNextId=0;
  25689. p->VertexNextId=0;
  25690. p->VolumeNextId=0;
  25691. readiHashInit(&p->VertexHash,READI_HASH_INT,0);
  25692. readiHashInit(&p->VolumeHash,READI_HASH_INT,0);
  25693. readiHashInit(&p->FaceHash,READI_HASH_INT,0);
  25694.  
  25695. Tcl_ObjectSetMetadata(thisObject, &PolygonHullDataType, (ClientData) p);
  25696. return TCL_OK;
  25697. }
  25698. /* Loader for PolygonHull */
  25699. static int PolygonHull_OO_Init(Tcl_Interp *interp) {
  25700. /*
  25701. ** Build the "::odielib::polygonhull" class
  25702. */
  25703. Tcl_Obj* nameObj; /* Name of a class or method being looked up */
  25704. Tcl_Object curClassObject; /* Tcl_Object representing the current class */
  25705. Tcl_Class curClass; /* Tcl_Class representing the current class */
  25706.  
  25707. /*
  25708. * Find the "::odielib::polygonhull" class, and attach an 'init' method to it.
  25709. */
  25710.  
  25711. nameObj = Tcl_NewStringObj("::odielib::polygonhull", -1);
  25712. Tcl_IncrRefCount(nameObj);
  25713. if ((curClassObject = Tcl_GetObjectFromObj(interp, nameObj)) == NULL) {
  25714. Tcl_DecrRefCount(nameObj);
  25715. return TCL_ERROR;
  25716. }
  25717. Tcl_DecrRefCount(nameObj);
  25718. curClass = Tcl_GetObjectAsClass(curClassObject);
  25719. nameObj=Tcl_NewStringObj("vertex_create",-1);
  25720. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_vertex_create, (ClientData) NULL);
  25721. Tcl_DecrRefCount(nameObj);
  25722. nameObj=Tcl_NewStringObj("vertex_coords",-1);
  25723. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_vertex_coords, (ClientData) NULL);
  25724. Tcl_DecrRefCount(nameObj);
  25725. nameObj=Tcl_NewStringObj("vertex_delete",-1);
  25726. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_vertex_delete, (ClientData) NULL);
  25727. Tcl_DecrRefCount(nameObj);
  25728. nameObj=Tcl_NewStringObj("vertex_idlist",-1);
  25729. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_vertex_idlist, (ClientData) NULL);
  25730. Tcl_DecrRefCount(nameObj);
  25731. nameObj=Tcl_NewStringObj("vertex_inject",-1);
  25732. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_vertex_inject, (ClientData) NULL);
  25733. Tcl_DecrRefCount(nameObj);
  25734. nameObj=Tcl_NewStringObj("vertex_list",-1);
  25735. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_vertex_list, (ClientData) NULL);
  25736. Tcl_DecrRefCount(nameObj);
  25737. nameObj=Tcl_NewStringObj("vertex_at",-1);
  25738. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_vertex_at, (ClientData) NULL);
  25739. Tcl_DecrRefCount(nameObj);
  25740. nameObj=Tcl_NewStringObj("face_info",-1);
  25741. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_info, (ClientData) NULL);
  25742. Tcl_DecrRefCount(nameObj);
  25743. nameObj=Tcl_NewStringObj("face_exists",-1);
  25744. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_exists, (ClientData) NULL);
  25745. Tcl_DecrRefCount(nameObj);
  25746. nameObj=Tcl_NewStringObj("face_active",-1);
  25747. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_active, (ClientData) NULL);
  25748. Tcl_DecrRefCount(nameObj);
  25749. nameObj=Tcl_NewStringObj("face_center",-1);
  25750. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_center, (ClientData) NULL);
  25751. Tcl_DecrRefCount(nameObj);
  25752. nameObj=Tcl_NewStringObj("face_polygon",-1);
  25753. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_polygon, (ClientData) NULL);
  25754. Tcl_DecrRefCount(nameObj);
  25755. nameObj=Tcl_NewStringObj("face_vertices",-1);
  25756. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_vertices, (ClientData) NULL);
  25757. Tcl_DecrRefCount(nameObj);
  25758. nameObj=Tcl_NewStringObj("face_create",-1);
  25759. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_create, (ClientData) NULL);
  25760. Tcl_DecrRefCount(nameObj);
  25761. nameObj=Tcl_NewStringObj("face_delete",-1);
  25762. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_delete, (ClientData) NULL);
  25763. Tcl_DecrRefCount(nameObj);
  25764. nameObj=Tcl_NewStringObj("face_intersect",-1);
  25765. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_intersect, (ClientData) NULL);
  25766. Tcl_DecrRefCount(nameObj);
  25767. nameObj=Tcl_NewStringObj("face_list",-1);
  25768. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_list, (ClientData) NULL);
  25769. Tcl_DecrRefCount(nameObj);
  25770. nameObj=Tcl_NewStringObj("face_nearest",-1);
  25771. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_nearest, (ClientData) NULL);
  25772. Tcl_DecrRefCount(nameObj);
  25773. nameObj=Tcl_NewStringObj("face_radius",-1);
  25774. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_radius, (ClientData) NULL);
  25775. Tcl_DecrRefCount(nameObj);
  25776. nameObj=Tcl_NewStringObj("face_normal",-1);
  25777. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_normal, (ClientData) NULL);
  25778. Tcl_DecrRefCount(nameObj);
  25779. nameObj=Tcl_NewStringObj("face_side",-1);
  25780. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_side, (ClientData) NULL);
  25781. Tcl_DecrRefCount(nameObj);
  25782. nameObj=Tcl_NewStringObj("face_volume",-1);
  25783. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_volume, (ClientData) NULL);
  25784. Tcl_DecrRefCount(nameObj);
  25785. nameObj=Tcl_NewStringObj("faces_at",-1);
  25786. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_faces_at, (ClientData) NULL);
  25787. Tcl_DecrRefCount(nameObj);
  25788. nameObj=Tcl_NewStringObj("face_within",-1);
  25789. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_face_within, (ClientData) NULL);
  25790. Tcl_DecrRefCount(nameObj);
  25791. nameObj=Tcl_NewStringObj("volume_create",-1);
  25792. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_volume_create, (ClientData) NULL);
  25793. Tcl_DecrRefCount(nameObj);
  25794. nameObj=Tcl_NewStringObj("volume_delete",-1);
  25795. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_volume_delete, (ClientData) NULL);
  25796. Tcl_DecrRefCount(nameObj);
  25797. nameObj=Tcl_NewStringObj("volume_list",-1);
  25798. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_volume_list, (ClientData) NULL);
  25799. Tcl_DecrRefCount(nameObj);
  25800. nameObj=Tcl_NewStringObj("volume_faces",-1);
  25801. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_volume_faces, (ClientData) NULL);
  25802. Tcl_DecrRefCount(nameObj);
  25803. nameObj=Tcl_NewStringObj("volume_group",-1);
  25804. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_volume_group, (ClientData) NULL);
  25805. Tcl_DecrRefCount(nameObj);
  25806. nameObj=Tcl_NewStringObj("volume_center",-1);
  25807. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_volume_center, (ClientData) NULL);
  25808. Tcl_DecrRefCount(nameObj);
  25809. nameObj=Tcl_NewStringObj("reset",-1);
  25810. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_reset, (ClientData) NULL);
  25811. Tcl_DecrRefCount(nameObj);
  25812. nameObj=Tcl_NewStringObj("PolygonHull_Init",-1);
  25813. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_PolygonHull_PolygonHull_Init, (ClientData) NULL);
  25814. Tcl_DecrRefCount(nameObj);
  25815. return TCL_OK;
  25816. }
  25817. /* Tcl Proc ::get */
  25818. static int TclCmd_get(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  25819. Tcl_Obj *result;
  25820. if(objc != 2) {
  25821. Tcl_WrongNumArgs(interp, 1, objv, "varname");
  25822. return TCL_ERROR;
  25823. }
  25824. result=Tcl_ObjGetVar2(interp,objv[1],NULL,0);
  25825. if(!result) {
  25826. Tcl_ResetResult(interp);
  25827. result=Odie_LiteralConstantObj(ODIE_STATIC_NULL);
  25828. }
  25829. Tcl_SetObjResult(interp,result);
  25830. return TCL_OK;
  25831. }
  25832. /* Tcl Proc ::list_to_int */
  25833. static int TclCmd_list_to_int(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  25834. int i;
  25835. Tcl_Obj *resultPtr;
  25836. if(objc < 2) {
  25837. Tcl_WrongNumArgs(interp, 1, objv, "element ?element");
  25838. return TCL_ERROR;
  25839. }
  25840. resultPtr=Tcl_NewObj();
  25841. for(i=1;i<objc;i++) {
  25842. Tcl_ListObjAppendElement(interp,resultPtr,Odie_Obj_To_Int(objv[i]));
  25843. }
  25844. Tcl_SetObjResult(interp,resultPtr);
  25845. return TCL_OK;
  25846. }
  25847. /* Tcl Proc ::ladd */
  25848. static int TclCmd_ladd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  25849. /*
  25850. ** topic:
  25851. ** command: ladd
  25852. ** arglist: variable element ...
  25853. ** title: Add all [emph element] arguments to list stored in [emph variable]
  25854. ** description:
  25855. ** If [emph varname] does not exist, an empty list is created. Only one
  25856. ** instance of [emph element] is added per list. If an element is already
  25857. ** in the list, it is not added.
  25858. */
  25859. Tcl_Obj *varPtr,*listObj,*resultPtr;
  25860. int length;
  25861. Tcl_Obj **data;
  25862.  
  25863. if(objc < 2) {
  25864. Tcl_WrongNumArgs(interp, 1, objv, "varname element ...");
  25865. }
  25866. varPtr=Tcl_ObjGetVar2(interp,objv[1],NULL,0);
  25867. if(!varPtr) {
  25868. Tcl_ResetResult(interp);
  25869. varPtr=Tcl_NewObj();
  25870. }
  25871. /*
  25872. ** Make sure we have well formed list
  25873. */
  25874. if(Tcl_ListObjGetElements(interp,varPtr,&length,&data)!=TCL_OK) {
  25875. return TCL_ERROR;
  25876. }
  25877. listObj=Tcl_NewListObj(length,data);
  25878.  
  25879. if(objc>2) {
  25880. if(Tcl_ListObjReplace(interp,listObj,length,0,(objc-2), (objv+2))) {
  25881. return TCL_ERROR;
  25882. }
  25883. }
  25884. resultPtr=Odie_ListObj_Sort(listObj);
  25885. Tcl_ObjSetVar2(interp,objv[1],NULL,resultPtr,0);
  25886. Tcl_SetObjResult(interp,resultPtr);
  25887. return TCL_OK;
  25888. }
  25889. /* Tcl Proc ::ldelete */
  25890. static int TclCmd_ldelete(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  25891. /*
  25892. ** topic:
  25893. ** command: ldelete
  25894. ** arglist: variable element ...
  25895. ** title: Remove all instances of [emph element] from a list stored in [emph variable]
  25896. ** description:
  25897. ** If [emph varname] does not exist, an empty list is created.
  25898. */
  25899. int listLength, idx;
  25900. Tcl_Obj *resultPtr,*listPtr;
  25901. Tcl_Obj **listObjPtrs;
  25902.  
  25903. if (objc < 2) {
  25904. Tcl_WrongNumArgs(interp, 1, objv, "variable element ...");
  25905. return TCL_ERROR;
  25906. }
  25907. listPtr=Tcl_ObjGetVar2(interp,objv[1],NULL,0);
  25908. if(!listPtr) {
  25909. Tcl_ResetResult(interp);
  25910. listPtr=Tcl_NewObj();
  25911. } else {
  25912. listPtr=Tcl_DuplicateObj(listPtr);
  25913. }
  25914.  
  25915. if(Tcl_ListObjGetElements(interp, listPtr, &listLength, &listObjPtrs)) {
  25916. return TCL_ERROR;
  25917. }
  25918.  
  25919. resultPtr=Tcl_NewObj();
  25920. for(idx=0;idx<listLength;idx++) {
  25921. int matchIdx=Odie_Lsearch((objc-2),(Tcl_Obj **)(objv+2),listObjPtrs[idx]);
  25922. if(matchIdx < 0) {
  25923. Tcl_ListObjAppendElement(interp,resultPtr,listObjPtrs[idx]);
  25924. }
  25925. }
  25926. Tcl_DecrRefCount(listPtr);
  25927. Tcl_ObjSetVar2(interp,objv[1],NULL,resultPtr,0);
  25928. Tcl_SetObjResult(interp,resultPtr);
  25929. return TCL_OK;
  25930. }
  25931. /* Tcl Proc ::logicset::union */
  25932. static int TclCmd_logicset_union(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  25933. Tcl_Obj *listObj;
  25934. int i;
  25935. if(objc < 2) {
  25936. Tcl_WrongNumArgs(interp, 1, objv, "varname element ...");
  25937. return TCL_ERROR;
  25938. }
  25939. listObj=Tcl_ObjGetVar2(interp,objv[1],NULL,0);
  25940. if(!listObj) {
  25941. Tcl_ResetResult(interp);
  25942. listObj=Tcl_NewObj();
  25943. } else {
  25944. if(Tcl_IsShared(listObj)) {
  25945. listObj=Tcl_DuplicateObj(listObj);
  25946. }
  25947. }
  25948. for(i=2;i<objc;i++) {
  25949. Logicset_Include(listObj,objv[i]);
  25950. }
  25951. Tcl_ObjSetVar2(interp,objv[1],NULL,listObj,0);
  25952. Tcl_SetObjResult(interp,listObj);
  25953. return TCL_OK;
  25954. }
  25955. /* Tcl Proc ::logicset::create */
  25956. static int TclCmd_logicset_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  25957. Tcl_Obj *stringObj;
  25958. Tcl_DString parse;
  25959. Tcl_DStringInit(&parse);
  25960. if(objc < 2) {
  25961. Tcl_SetObjResult(interp,Tcl_NewObj());
  25962. return TCL_OK;
  25963. }
  25964. int i;
  25965. for(i=1;i<objc;i++) {
  25966. Tcl_DStringAppendElement(&parse,Tcl_GetString(objv[i]));
  25967. }
  25968. int len=Tcl_DStringLength(&parse);
  25969. char *rawvalue=Tcl_DStringValue(&parse);
  25970. Logicset_Sanitize_List(rawvalue,len);
  25971. stringObj=Tcl_NewStringObj(rawvalue,len);
  25972. Tcl_DStringFree(&parse);
  25973.  
  25974. int listLength;
  25975. Tcl_Obj **listObjPtrs;
  25976. if(Tcl_ListObjGetElements(interp, stringObj, &listLength, &listObjPtrs)) {
  25977. return TCL_ERROR;
  25978. }
  25979. Tcl_Obj *listObj=Tcl_NewObj();
  25980. for(i=0;i<listLength;i++) {
  25981. Logicset_Add(listObj,listObjPtrs[i]);
  25982. }
  25983. Tcl_DecrRefCount(stringObj);
  25984. Tcl_SetObjResult(interp,listObj);
  25985. return TCL_OK;
  25986. }
  25987. /* Tcl Proc ::logicset::contains */
  25988. static int TclCmd_logicset_contains(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  25989. int listLength, idx, match=1;
  25990. Tcl_Obj **listObjPtrs;
  25991.  
  25992. if (objc < 2) {
  25993. Tcl_WrongNumArgs(interp, 1, objv, "varlist element ...");
  25994. return TCL_ERROR;
  25995. }
  25996. if(Tcl_ListObjGetElements(interp, objv[1], &listLength, &listObjPtrs)) {
  25997. return TCL_ERROR;
  25998. }
  25999.  
  26000. for(idx=2;idx<objc && match;idx++) {
  26001. int matchIdx=Odie_Lsearch(listLength,listObjPtrs,objv[idx]);
  26002. if(matchIdx < 0) {
  26003. match=0;
  26004. break;
  26005. }
  26006. }
  26007. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(match));
  26008. return TCL_OK;
  26009. }
  26010. /* Tcl Proc ::logicset::empty */
  26011. static int TclCmd_logicset_empty(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26012. int length;
  26013. Tcl_Obj **data;
  26014.  
  26015. if(objc != 2) {
  26016. Tcl_WrongNumArgs(interp, 1, objv, "varlist");
  26017. return TCL_ERROR;
  26018. }
  26019. /*
  26020. ** Make sure we have well formed list
  26021. */
  26022. if(Tcl_ListObjGetElements(interp,objv[1],&length,&data)!=TCL_OK) {
  26023. Tcl_ResetResult(interp);
  26024. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(0));
  26025. return TCL_OK;
  26026. }
  26027. if(length) {
  26028. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(0));
  26029. } else {
  26030. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(1));
  26031. }
  26032. return TCL_OK;
  26033. }
  26034. /* Tcl Proc ::logicset::expr_and */
  26035. static int TclCmd_logicset_expr_and(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26036. if (objc != 3) {
  26037. Tcl_WrongNumArgs(interp, 1, objv, "A B");
  26038. return TCL_ERROR;
  26039. }
  26040. int match=Logicset_EXPR_AND(objv[1],objv[2]);
  26041. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(match));
  26042. return TCL_OK;
  26043. }
  26044. /* Tcl Proc ::logicset::expr_or */
  26045. static int TclCmd_logicset_expr_or(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26046. if (objc != 3) {
  26047. Tcl_WrongNumArgs(interp, 1, objv, "A B");
  26048. return TCL_ERROR;
  26049. }
  26050. int match=Logicset_EXPR_OR(objv[1],objv[2]);
  26051. Tcl_SetObjResult(interp,Tcl_NewBooleanObj(match));
  26052. return TCL_OK;
  26053. }
  26054. /* Tcl Proc ::logicset::product_intersect */
  26055. static int TclCmd_logicset_product_intersect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26056. if (objc != 3) {
  26057. Tcl_WrongNumArgs(interp, 1, objv, "A B");
  26058. return TCL_ERROR;
  26059. }
  26060. Tcl_Obj *product=Logicset_PRODUCT_INTERSECT(objv[1],objv[2]);
  26061. if(product) {
  26062. Tcl_SetObjResult(interp,product);
  26063. } else {
  26064. Tcl_SetObjResult(interp,Tcl_NewObj());
  26065. }
  26066. return TCL_OK;
  26067. }
  26068. /* Tcl Proc ::logicset::product_union */
  26069. static int TclCmd_logicset_product_union(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26070. if (objc != 3) {
  26071. Tcl_WrongNumArgs(interp, 1, objv, "A B");
  26072. return TCL_ERROR;
  26073. }
  26074. Tcl_Obj *product=Logicset_PRODUCT_UNION(objv[1],objv[2]);
  26075. if(product) {
  26076. Tcl_SetObjResult(interp,product);
  26077. } else {
  26078. Tcl_SetObjResult(interp,Tcl_NewObj());
  26079. }
  26080. return TCL_OK;
  26081. }
  26082. /* Tcl Proc ::logicset::product_xor */
  26083. static int TclCmd_logicset_product_xor(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26084. if (objc != 3) {
  26085. Tcl_WrongNumArgs(interp, 1, objv, "A B");
  26086. return TCL_ERROR;
  26087. }
  26088. Tcl_Obj *product=Logicset_PRODUCT_XOR(objv[1],objv[2]);
  26089. if(product) {
  26090. Tcl_SetObjResult(interp,product);
  26091. } else {
  26092. Tcl_SetObjResult(interp,Tcl_NewObj());
  26093. }
  26094. return TCL_OK;
  26095. }
  26096. /* Tcl Proc ::logicset::product_missing */
  26097. static int TclCmd_logicset_product_missing(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26098. if (objc != 3) {
  26099. Tcl_WrongNumArgs(interp, 1, objv, "A B");
  26100. return TCL_ERROR;
  26101. }
  26102. Tcl_Obj *product=Logicset_PRODUCT_MISSING(objv[1],objv[2]);
  26103. if(product) {
  26104. Tcl_SetObjResult(interp,product);
  26105. } else {
  26106. Tcl_SetObjResult(interp,Tcl_NewObj());
  26107. }
  26108. return TCL_OK;
  26109. }
  26110. /* Tcl Proc ::logicset::remove */
  26111. static int TclCmd_logicset_remove(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26112. int listLength, idx;
  26113. Tcl_Obj *resultPtr,*listPtr;
  26114. Tcl_Obj **listObjPtrs;
  26115.  
  26116. if (objc < 2) {
  26117. Tcl_WrongNumArgs(interp, 1, objv, "variable element ...");
  26118. return TCL_ERROR;
  26119. }
  26120. listPtr=Tcl_ObjGetVar2(interp,objv[1],NULL,0);
  26121. if(!listPtr) {
  26122. Tcl_ResetResult(interp);
  26123. listPtr=Tcl_NewObj();
  26124. } else {
  26125. listPtr=Tcl_DuplicateObj(listPtr);
  26126. }
  26127.  
  26128. if(Tcl_ListObjGetElements(interp, listPtr, &listLength, &listObjPtrs)) {
  26129. return TCL_ERROR;
  26130. }
  26131.  
  26132. resultPtr=Tcl_NewObj();
  26133. for(idx=0;idx<listLength;idx++) {
  26134. int matchIdx=Odie_Lsearch((objc-2),(Tcl_Obj **)(objv+2),listObjPtrs[idx]);
  26135. if(matchIdx < 0) {
  26136. Logicset_Add(resultPtr,listObjPtrs[idx]);
  26137. }
  26138. }
  26139. Tcl_ObjSetVar2(interp,objv[1],NULL,resultPtr,0);
  26140. Tcl_SetObjResult(interp,resultPtr);
  26141. return TCL_OK;
  26142. }
  26143. /* Tcl Proc ::literal */
  26144. static int TclCmd_literal(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26145. char *newName;
  26146. Tcl_Obj *result;
  26147.  
  26148. if(objc != 2) {
  26149. Tcl_WrongNumArgs(interp, 1, objv, "string");
  26150. return TCL_ERROR;
  26151. }
  26152. newName=Tcl_GetString(objv[1]);
  26153. result=Odie_LiteralStringObj(newName);
  26154. if (!result) return TCL_ERROR;
  26155. Tcl_SetObjResult(interp,result);
  26156. return TCL_OK;
  26157. }
  26158. /* Tcl Proc ::literal_dump */
  26159. static int TclCmd_literal_dump(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26160. Tcl_HashSearch searchPtr;
  26161. Tcl_HashEntry *i;
  26162. Tcl_Obj *result;
  26163. result=Tcl_NewObj();
  26164. for(i=Tcl_FirstHashEntry(&OdieLiteralStringTable,&searchPtr); i ; i = Tcl_NextHashEntry(&searchPtr)) {
  26165. Tcl_Obj *p = (Tcl_Obj *)Tcl_GetHashValue(i);
  26166. Tcl_ListObjAppendElement(interp,result,p);
  26167. }
  26168. Tcl_SetObjResult(interp,result);
  26169. return TCL_OK;
  26170. }
  26171. /* Tcl Proc ::literal_stats */
  26172. static int TclCmd_literal_stats(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26173. Tcl_Obj *result;
  26174. result=Tcl_NewObj();
  26175. Tcl_ListObjAppendElement(interp,result,Tcl_NewStringObj("literal count:",-1));
  26176. Tcl_ListObjAppendElement(interp,result,Tcl_NewIntObj(nOdieObjString));
  26177. Tcl_ListObjAppendElement(interp,result,Tcl_NewStringObj("hash table count:",-1));
  26178. Tcl_ListObjAppendElement(interp,result,Tcl_NewIntObj(nOdieHashTable));
  26179. Tcl_ListObjAppendElement(interp,result,Tcl_NewStringObj("hash table created:",-1));
  26180. Tcl_ListObjAppendElement(interp,result,Tcl_NewIntObj(nOdieHashTableCreated));
  26181. Tcl_ListObjAppendElement(interp,result,Tcl_NewStringObj("hash table deleted:",-1));
  26182. Tcl_ListObjAppendElement(interp,result,Tcl_NewIntObj(nOdieHashTableDeleted));
  26183. Tcl_ListObjAppendElement(interp,result,Tcl_NewStringObj("dict spec count:",-1));
  26184. Tcl_ListObjAppendElement(interp,result,Tcl_NewIntObj(nOdieDictSpecCount));
  26185. Tcl_ListObjAppendElement(interp,result,Tcl_NewStringObj("dict spec created:",-1));
  26186. Tcl_ListObjAppendElement(interp,result,Tcl_NewIntObj(nOdieDictSpecCreated));
  26187. Tcl_ListObjAppendElement(interp,result,Tcl_NewStringObj("dict spec deleted:",-1));
  26188. Tcl_ListObjAppendElement(interp,result,Tcl_NewIntObj(nOdieDictSpecDeleted));
  26189. Tcl_ListObjAppendElement(interp,result,Tcl_NewStringObj("dict spec shared:",-1));
  26190. Tcl_ListObjAppendElement(interp,result,Tcl_NewIntObj(nOdieDictSpecShared));
  26191. Tcl_ListObjAppendElement(interp,result,Tcl_NewStringObj("dict spec null:",-1));
  26192. Tcl_ListObjAppendElement(interp,result,Tcl_NewIntObj(nOdieDictSpecNull));
  26193. Tcl_ListObjAppendElement(interp,result,Tcl_NewStringObj("dict spec recycled:",-1));
  26194. Tcl_ListObjAppendElement(interp,result,Tcl_NewIntObj(nOdieDictSpecRecycled));
  26195. Tcl_ListObjAppendElement(interp,result,Tcl_NewStringObj("dict spec modified:",-1));
  26196. Tcl_ListObjAppendElement(interp,result,Tcl_NewIntObj(nOdieDictSpecModified));
  26197. Tcl_ListObjAppendElement(interp,result,Tcl_NewStringObj("dict spec accessed:",-1));
  26198. Tcl_ListObjAppendElement(interp,result,Tcl_NewIntObj(nOdieDictSpecAccessed));
  26199. Tcl_SetObjResult(interp,result);
  26200. return TCL_OK;
  26201. }
  26202. /* Tcl Proc ::constant_string */
  26203. static int TclCmd_constant_string(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26204. char *newName;
  26205. Tcl_Obj *result;
  26206.  
  26207. if(objc != 2) {
  26208. Tcl_WrongNumArgs(interp, 1, objv, "string");
  26209. return TCL_ERROR;
  26210. }
  26211. newName=Tcl_GetString(objv[1]);
  26212. result=Odie_LiteralStringObj(newName);
  26213. if (!result) return TCL_ERROR;
  26214. Tcl_SetObjResult(interp,result);
  26215. return TCL_OK;
  26216. }
  26217. /* Tcl Proc ::location::grid_square */
  26218. static int TclCmd_location_grid_square(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26219. double grid;
  26220. double x;
  26221. double y;
  26222. Tcl_Obj *pResult;
  26223. if( objc != 4 ){
  26224. Tcl_WrongNumArgs(interp, 1, objv, "gridsize x y");
  26225. return TCL_ERROR;
  26226. }
  26227. if(Tcl_GetDoubleFromObj(interp,objv[1],&grid)) return TCL_ERROR;
  26228. if(Tcl_GetDoubleFromObj(interp,objv[2],&x)) return TCL_ERROR;
  26229. if(Tcl_GetDoubleFromObj(interp,objv[3],&y)) return TCL_ERROR;
  26230. pResult=Tcl_NewObj();
  26231. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*round(x/grid)));
  26232. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*round(y/grid)));
  26233. Tcl_SetObjResult(interp, pResult);
  26234. return TCL_OK;
  26235. }
  26236. /* Tcl Proc ::location::gridhash_square */
  26237. static int TclCmd_location_gridhash_square(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26238. double x, y;
  26239. int grid,deckid;
  26240. Tcl_WideInt result;
  26241.  
  26242. if( objc != 5 ){
  26243. Tcl_WrongNumArgs(interp, 1, objv, "gridsize deck x y");
  26244. return TCL_ERROR;
  26245. }
  26246. if(Tcl_GetIntFromObj(interp,objv[1],&grid)) return TCL_ERROR;
  26247. if(Tcl_GetIntFromObj(interp,objv[2],&deckid)) return TCL_ERROR;
  26248. if(Tcl_GetDoubleFromObj(interp,objv[3],&x)) return TCL_ERROR;
  26249. if(Tcl_GetDoubleFromObj(interp,objv[4],&y)) return TCL_ERROR;
  26250. result=irm_squaregrid_hash(grid,deckid,(int)x,(int)y);
  26251. Tcl_SetObjResult(interp,Tcl_NewWideIntObj(result));
  26252. return TCL_OK;
  26253. }
  26254. /* Tcl Proc ::location::location_gridhash */
  26255. static int TclCmd_location_location_gridhash(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26256. Irm_Location dest;
  26257. int grid;
  26258. Tcl_WideInt hash;
  26259. Tcl_Obj *pResult;
  26260.  
  26261. if( objc != 3 ){
  26262. Tcl_WrongNumArgs(interp, 1, objv, "gridsize hash");
  26263. return TCL_ERROR;
  26264. }
  26265. if(Tcl_GetIntFromObj(interp,objv[1],&grid)) return TCL_ERROR;
  26266. if(Tcl_GetWideIntFromObj(interp,objv[2],&hash)) return TCL_ERROR;
  26267. irm_gridhash_location(&dest,hash,grid);
  26268.  
  26269. pResult=Tcl_NewObj();
  26270. Tcl_ListObjAppendElement(interp,pResult,Odie_LiteralIntObj(dest.deckid));
  26271. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(dest.x));
  26272. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(dest.y));
  26273. Tcl_SetObjResult(interp, pResult);
  26274.  
  26275. return TCL_OK;
  26276. }
  26277. /* Tcl Proc ::location::grid_hex */
  26278. static int TclCmd_location_grid_hex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26279. double grid, x, y;
  26280. int gx,gy;
  26281. Tcl_Obj *pResult;
  26282.  
  26283. if( objc != 4 ){
  26284. Tcl_WrongNumArgs(interp, 1, objv, "gridsize x y");
  26285. return TCL_ERROR;
  26286. }
  26287. if(Tcl_GetDoubleFromObj(interp,objv[1],&grid)) return TCL_ERROR;
  26288. if(Tcl_GetDoubleFromObj(interp,objv[2],&x)) return TCL_ERROR;
  26289. if(Tcl_GetDoubleFromObj(interp,objv[3],&y)) return TCL_ERROR;
  26290. pResult=Tcl_NewObj();
  26291. gy=(int)round(y/grid);
  26292. if(gy%2==1){
  26293. gx=(int)round((x-grid/2)/grid);
  26294. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*gx+grid/2));
  26295. } else {
  26296. gx=(int)round(x/grid);
  26297. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*gx));
  26298. }
  26299. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*gy));
  26300. Tcl_SetObjResult(interp, pResult);
  26301. return TCL_OK;
  26302. }
  26303. /* Tcl Proc ::location::gridhash_hex */
  26304. static int TclCmd_location_gridhash_hex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26305. double x, y;
  26306. int grid,deckid;
  26307. Tcl_WideInt result;
  26308.  
  26309. if( objc != 5 ){
  26310. Tcl_WrongNumArgs(interp, 1, objv, "gridsize deck x y");
  26311. return TCL_ERROR;
  26312. }
  26313. if(Tcl_GetIntFromObj(interp,objv[1],&grid)) return TCL_ERROR;
  26314. if(Tcl_GetIntFromObj(interp,objv[2],&deckid)) return TCL_ERROR;
  26315. if(Tcl_GetDoubleFromObj(interp,objv[3],&x)) return TCL_ERROR;
  26316. if(Tcl_GetDoubleFromObj(interp,objv[4],&y)) return TCL_ERROR;
  26317. result=irm_hexgrid_hash(grid,deckid,(int)x,(int)y);
  26318. Tcl_SetObjResult(interp,Tcl_NewWideIntObj(result));
  26319. return TCL_OK;
  26320. }
  26321. /* Tcl Proc ::location::gridhash_adjacent */
  26322. static int TclCmd_location_gridhash_adjacent(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26323. Tcl_WideInt hash;
  26324. Tcl_Obj *pResult;
  26325. int x,y;
  26326. int gx,gy,deckid,isHex;
  26327.  
  26328. if( objc != 2 ){
  26329. Tcl_WrongNumArgs(interp, 1, objv, "gridhash");
  26330. return TCL_ERROR;
  26331. }
  26332. if(Tcl_GetWideIntFromObj(interp,objv[1],&hash)) return TCL_ERROR;
  26333. /* decompose */
  26334.  
  26335. irm_gridhash_decompose(hash,&isHex,&deckid,&gx,&gy);
  26336.  
  26337. pResult=Tcl_NewObj();
  26338. if(isHex) {
  26339. /* Each hexagonal tile has 6 adjacent tiles
  26340. ** ##
  26341. ** # #
  26342. ** ##
  26343. */
  26344. Tcl_WideInt tile;
  26345. tile=irm_gridhash_compose(1,deckid,gx+1,gy);
  26346. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewWideIntObj(tile));
  26347. tile=irm_gridhash_compose(1,deckid,gx,gy+1);
  26348. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewWideIntObj(tile));
  26349. tile=irm_gridhash_compose(1,deckid,gx-1,gy+1);
  26350. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewWideIntObj(tile));
  26351. tile=irm_gridhash_compose(1,deckid,gx-1,gy);
  26352. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewWideIntObj(tile));
  26353. tile=irm_gridhash_compose(1,deckid,gx-1,gy-1);
  26354. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewWideIntObj(tile));
  26355. tile=irm_gridhash_compose(1,deckid,gx,gy-1);
  26356. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewWideIntObj(tile));
  26357. } else {
  26358. /* Each square tile has 9 adjacent tiles
  26359. ** ###
  26360. ** # #
  26361. ** ###
  26362. */
  26363. for(x=-1;x<=1;x++) {
  26364. for(y=-1;y<=1;y++) {
  26365. Tcl_WideInt tile;
  26366. if(x==0 && y==0) continue;
  26367. tile=irm_gridhash_compose(0,deckid,gx+x,gy+y);
  26368. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewWideIntObj(tile));
  26369. }
  26370. }
  26371. }
  26372. Tcl_SetObjResult(interp, pResult);
  26373. return TCL_OK;
  26374. }
  26375. /* Tcl Proc ::location::object */
  26376. static int TclCmd_location_object(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26377. int deckid;
  26378. double x,y;
  26379. Tcl_Obj *pResult;
  26380.  
  26381. if( objc != 2 ){
  26382. Tcl_WrongNumArgs(interp, 1, objv, "node");
  26383. return TCL_ERROR;
  26384. }
  26385. if(Location_FromTclObj(interp,objv[1],&deckid,&x,&y)) {
  26386. return TCL_ERROR;
  26387. }
  26388. pResult=Tcl_NewObj();
  26389. Tcl_ListObjAppendElement(interp,pResult,Odie_LiteralIntObj(deckid));
  26390. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(x));
  26391. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(y));
  26392. Tcl_SetObjResult(interp, pResult);
  26393. return TCL_OK;
  26394. }
  26395. /* Tcl Proc ::location::midpoint */
  26396. static int TclCmd_location_midpoint(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26397. int deckid;
  26398. double x,y,z;
  26399. Tcl_Obj *pResult;
  26400. if( objc != 2 ){
  26401. Tcl_WrongNumArgs(interp, 1, objv, "node");
  26402. return TCL_ERROR;
  26403. }
  26404. if(Location_Base_FromTclObj(interp,objv[1],&deckid,&x,&y,&z)) {
  26405. return TCL_ERROR;
  26406. }
  26407. pResult=Tcl_NewObj();
  26408. Tcl_ListObjAppendElement(interp,pResult,Odie_LiteralIntObj(deckid));
  26409. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(x));
  26410. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(y));
  26411. Tcl_ListObjAppendElement(interp,pResult,Tcl_NewIntObj(z));
  26412. Tcl_SetObjResult(interp, pResult);
  26413. return TCL_OK;
  26414. }
  26415. /* Tcl Proc ::location::match */
  26416. static int TclCmd_location_match(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  26417. int a_deckid;
  26418. double a_x,a_y;
  26419. int b_deckid;
  26420. double b_x,b_y;
  26421. double tolerance=1.0;
  26422. int match=1;
  26423.  
  26424. if( objc != 3 && objc != 4 ){
  26425. Tcl_WrongNumArgs(interp, 1, objv, "A B ?tolerance?");
  26426. return TCL_ERROR;
  26427. }
  26428. if(Location_FromTclObj(interp,objv[1],&a_deckid,&a_x,&a_y)) {
  26429. return TCL_ERROR;
  26430. }
  26431. if(Location_FromTclObj(interp,objv[2],&b_deckid,&b_x,&b_y)) {
  26432. return TCL_ERROR;
  26433. }
  26434. if(objc==4) {
  26435. if(Tcl_GetDoubleFromObj(interp,objv[3],&tolerance)) {
  26436. return TCL_ERROR;
  26437. }
  26438. }
  26439. if(a_deckid!=b_deckid) {
  26440. match=0;
  26441. } else {
  26442. double dx,dy;
  26443. dx=fabs(b_x-a_x);
  26444. if(dx > tolerance) {
  26445. match=0;
  26446. } else {
  26447. dy=fabs(b_y-a_y);
  26448. if(dy > tolerance) {
  26449. match=0;
  26450. }
  26451. }
  26452. }
  26453. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(match));
  26454. return TCL_OK;
  26455. }
  26456. /* OO Method Simulator C_Init */
  26457. static int OOMethod_Simulator_C_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26458.  
  26459. Simulator *p;
  26460. p = (Simulator *)Odie_Alloc( sizeof(*p) );
  26461. Tcl_InitHashTable(&p->EntityIdSet, TCL_STRING_KEYS);
  26462. Tcl_InitHashTable(&p->SimTypeIdSet, TCL_ONE_WORD_KEYS);
  26463. Tcl_ObjectSetMetadata(thisObject, &SimulatorDataType, (ClientData) p);
  26464. return TCL_OK;
  26465. }
  26466. /* Loader for Simulator */
  26467. static int Simulator_OO_Init(Tcl_Interp *interp) {
  26468. /*
  26469. ** Build the "::odielib::simulator" class
  26470. */
  26471. Tcl_Obj* nameObj; /* Name of a class or method being looked up */
  26472. Tcl_Object curClassObject; /* Tcl_Object representing the current class */
  26473. Tcl_Class curClass; /* Tcl_Class representing the current class */
  26474.  
  26475. /*
  26476. * Find the "::odielib::simulator" class, and attach an 'init' method to it.
  26477. */
  26478.  
  26479. nameObj = Tcl_NewStringObj("::odielib::simulator", -1);
  26480. Tcl_IncrRefCount(nameObj);
  26481. if ((curClassObject = Tcl_GetObjectFromObj(interp, nameObj)) == NULL) {
  26482. Tcl_DecrRefCount(nameObj);
  26483. return TCL_ERROR;
  26484. }
  26485. Tcl_DecrRefCount(nameObj);
  26486. curClass = Tcl_GetObjectAsClass(curClassObject);
  26487. nameObj=Tcl_NewStringObj("C_Init",-1);
  26488. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_Simulator_C_Init, (ClientData) NULL);
  26489. Tcl_DecrRefCount(nameObj);
  26490. return TCL_OK;
  26491. }
  26492. /* OO Method OOEntity C_Init */
  26493. static int OOMethod_OOEntity_C_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26494.  
  26495. Simulator *p;
  26496. Tcl_Object masterObject;
  26497. if(objc!=3) {
  26498. Tcl_WrongNumArgs(interp, 2, objv, "SIMULATOR_OBJECT");
  26499. return TCL_ERROR;
  26500. }
  26501. masterObject=Tcl_GetObjectFromObj(interp,objv[2]);
  26502. if(masterObject==NULL) {
  26503. return TCL_ERROR;
  26504. }
  26505. p=GETSIMULATOR(masterObject);
  26506. Tcl_ObjectSetMetadata(thisObject, &SimulatorDataType, (ClientData) p);
  26507. return TCL_OK;
  26508. }
  26509. /* OO Method OOEntity create */
  26510. static int OOMethod_OOEntity_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26511.  
  26512. Entity *p;
  26513. Entity *pType=NULL;
  26514. const char *zName;
  26515.  
  26516. if( objc!=3 && objc!=4 && objc != 5){
  26517. Tcl_WrongNumArgs(interp, 2, objv, "NAME ?typeid?");
  26518. return TCL_ERROR;
  26519. }
  26520. CurrentSim=GETSIMULATOR(thisObject);
  26521. zName = Tcl_GetString(objv[2]);
  26522. p=Entity_ByName(zName,1);
  26523.  
  26524. if(objc > 4) {
  26525. if( SimType_FromTclObj(interp, objv[3], &pType) ) return TCL_ERROR;
  26526. p->pType=pType;
  26527. }
  26528.  
  26529. return TCL_OK;
  26530. }
  26531. /* OO Method OOEntity attach_to */
  26532. static int OOMethod_OOEntity_attach_to(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26533.  
  26534. Entity *pNat;
  26535. if( objc!=3 && objc!=4 ){
  26536. Tcl_WrongNumArgs(interp, 2, objv, "ID NODEID");
  26537. return TCL_ERROR;
  26538. }
  26539. CurrentSim=GETSIMULATOR(thisObject);
  26540. if( Entity_FromTclObj(interp, objv[2], &pNat) ) return TCL_ERROR;
  26541. #ifdef build_IRM
  26542. if(objc==3) {
  26543. Tcl_Obj *pResult=NULL;
  26544. if(pNat->attached_to) {
  26545. switch (pNat->attached_type) {
  26546. case CSTRUCT_crew: {
  26547. pResult=Crew_PublicId(pNat->attached_to);
  26548. break;
  26549. }
  26550. case CSTRUCT_entity: {
  26551. pResult=Entity_Identify(pNat->attached_to);
  26552. break;
  26553. }
  26554. case CSTRUCT_portal: {
  26555. pResult=Portal_PublicId(pNat->attached_to);
  26556. break;
  26557. }
  26558. case CSTRUCT_simnode: {
  26559. pResult=SimNode_PublicId(pNat->attached_to);
  26560. break;
  26561. }
  26562. }
  26563. }
  26564. if(pResult) {
  26565. Tcl_SetObjResult(interp,pResult);
  26566. }
  26567. return TCL_OK;
  26568. }
  26569. #endif
  26570. return Entity_StructAttachLocation(interp,pNat,objv[2]);
  26571. }
  26572. /* OO Method OOEntity compartment */
  26573. static int OOMethod_OOEntity_compartment(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26574.  
  26575. Entity *p;
  26576.  
  26577. if( objc!=3 && objc!=4){
  26578. Tcl_WrongNumArgs(interp, 2, objv, "NODEID ?COMPTID?");
  26579. return TCL_ERROR;
  26580. }
  26581. CurrentSim=GETSIMULATOR(thisObject);
  26582. if( Entity_FromTclObj(interp, objv[2], &p) ) {
  26583. Tcl_ResetResult(interp);
  26584. return TCL_OK;
  26585. }
  26586. /* Compartments report themselves */
  26587. if(p->public_class=='c') {
  26588. Tcl_SetObjResult(interp,Entity_Identify(p));
  26589. return TCL_OK;
  26590. }
  26591. if(objc==3) {
  26592. p->comptPtr=Entity_IdentifyCompartment(objv[3]);
  26593. }
  26594. #ifdef build_IRM
  26595. if(!p->comptPtr) {
  26596. Irm_Location temp;
  26597. int cid=0;
  26598. Entity_StructLocation(&temp,p);
  26599. cid=Compartment_At_Location(&temp);
  26600. p->comptPtr=Entity_ById('c',cid,0);
  26601. }
  26602. #endif
  26603. if(p->comptPtr) {
  26604. Tcl_SetObjResult(interp,Entity_Identify(p->comptPtr));
  26605. } else {
  26606. Tcl_SetObjResult(interp,Odie_LiteralIntObj(0));
  26607. }
  26608. return TCL_OK;
  26609. }
  26610. /* OO Method OOEntity comptid */
  26611. static int OOMethod_OOEntity_comptid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26612.  
  26613. Entity *p;
  26614.  
  26615. if( objc!=3 && objc!=4){
  26616. Tcl_WrongNumArgs(interp, 2, objv, "NODEID ?COMPTID?");
  26617. return TCL_ERROR;
  26618. }
  26619. CurrentSim=GETSIMULATOR(thisObject);
  26620. if( Entity_FromTclObj(interp, objv[2], &p) ) {
  26621. Tcl_ResetResult(interp);
  26622. return TCL_OK;
  26623. }
  26624. if(objc==4) {
  26625. p->comptPtr=Entity_IdentifyCompartment(objv[3]);
  26626. }
  26627. if(p->comptPtr) {
  26628. Tcl_SetObjResult(interp,Entity_Identify(p->comptPtr));
  26629. } else {
  26630. Tcl_SetObjResult(interp,Odie_LiteralIntObj(0));
  26631. }
  26632. return TCL_OK;
  26633. }
  26634. /* OO Method OOEntity count */
  26635. static int OOMethod_OOEntity_count(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26636.  
  26637. Tcl_HashSearch search;
  26638. Tcl_HashEntry *i;
  26639. int matchStruct[ENTITY_SEARCH_NCOUNT];
  26640. int domatch=0;
  26641. int result=0;
  26642. CurrentSim=GETSIMULATOR(thisObject);
  26643. if(objc==3) {
  26644. domatch=1;
  26645. if(Entity_BuildMatch(interp,objv[2],matchStruct) != TCL_OK) {
  26646. return TCL_ERROR;
  26647. }
  26648. }
  26649. for(i=Entity_First(CurrentSim,&search); i ; i = Tcl_NextHashEntry(&search)) {
  26650. Entity *p = (Entity*)Tcl_GetHashValue(i);
  26651. if(domatch) {
  26652. if(!Entity_StructMatches(p,matchStruct)) continue;
  26653. }
  26654. result++;
  26655. }
  26656. Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
  26657. return TCL_OK;
  26658. }
  26659. /* OO Method OOEntity deckid */
  26660. static int OOMethod_OOEntity_deckid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26661.  
  26662. Entity *pNat;
  26663. Irm_Location temp;
  26664.  
  26665. if( objc!=3 ){
  26666. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  26667. return TCL_ERROR;
  26668. }
  26669. CurrentSim=GETSIMULATOR(thisObject);
  26670. if( Entity_FromTclObj(interp, objv[2], &pNat) ) return TCL_ERROR;
  26671. Entity_StructLocation(&temp,pNat);
  26672. Tcl_SetObjResult(interp,Odie_LiteralIntObj(temp.deckid));
  26673. return TCL_OK;
  26674. }
  26675. /* OO Method OOEntity delete */
  26676. static int OOMethod_OOEntity_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26677.  
  26678. Entity *p;
  26679.  
  26680. if( objc!=3 ){
  26681. Tcl_WrongNumArgs(interp, 2, objv, "NAME");
  26682. return TCL_ERROR;
  26683. }
  26684. CurrentSim=GETSIMULATOR(thisObject);
  26685. if( Entity_FromTclObj(interp, objv[2], &p) ) {
  26686. Tcl_ResetResult(interp);
  26687. return TCL_OK;
  26688. }
  26689. if(p) {
  26690. Entity_Unlink(p);
  26691. Entity_Delete(p);
  26692. }
  26693. return TCL_OK;
  26694. }
  26695. /* OO Method OOEntity drawn_reset */
  26696. static int OOMethod_OOEntity_drawn_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26697.  
  26698. Tcl_HashSearch search;
  26699. Tcl_HashEntry *i;
  26700. CurrentSim=GETSIMULATOR(thisObject);
  26701. i = Entity_First(CurrentSim,&search);
  26702. while( i ){
  26703. Entity *p = (Entity*)Tcl_GetHashValue(i);
  26704. p->public_drawn=0;
  26705. i = Tcl_NextHashEntry(&search);
  26706. }
  26707. return TCL_OK;
  26708. }
  26709. /* OO Method OOEntity exists */
  26710. static int OOMethod_OOEntity_exists(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26711.  
  26712. Entity *p;
  26713. if( objc!=3 ){
  26714. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  26715. return TCL_ERROR;
  26716. }
  26717. CurrentSim=GETSIMULATOR(thisObject);
  26718. if( Entity_FromTclObj(interp, objv[2], &p) ) {
  26719. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  26720. } else {
  26721. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
  26722. }
  26723. return TCL_OK;
  26724. }
  26725. /* OO Method OOEntity for */
  26726. static int OOMethod_OOEntity_for(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26727.  
  26728. Tcl_HashSearch *searchPtr;
  26729. Tcl_HashEntry *i;
  26730. int searchresult=TCL_OK;
  26731. Tcl_Obj **varv;
  26732. int varc;
  26733.  
  26734. Tcl_Obj *keyvar;
  26735. Tcl_Obj *infovar=NULL;
  26736. Tcl_Obj *body,*matchvalues=NULL;
  26737. int matchStruct[ENTITY_SEARCH_NCOUNT];
  26738.  
  26739. if( objc != 4 && objc != 5 ){
  26740. Tcl_WrongNumArgs(interp, 2, objv, "{keyvar ?valvar?} ?matchlist? body");
  26741. return TCL_ERROR;
  26742. }
  26743. if (Tcl_ListObjGetElements(interp, objv[2], &varc, &varv) != TCL_OK) {
  26744. return TCL_ERROR;
  26745. }
  26746. if(varc==0) {
  26747. keyvar=Odie_LiteralStringObj("id");
  26748. } else {
  26749. keyvar=varv[0];
  26750. }
  26751. Tcl_IncrRefCount(keyvar);
  26752. if(varc>1) {
  26753. infovar=varv[1];
  26754. Tcl_IncrRefCount(infovar);
  26755. } else {
  26756. infovar=NULL;
  26757. }
  26758.  
  26759. if(objc==4) {
  26760. body=objv[3];
  26761. } else {
  26762. matchvalues=objv[3];
  26763. body=objv[4];
  26764. }
  26765. if(Entity_BuildMatch(interp,matchvalues,matchStruct) != TCL_OK) {
  26766. return TCL_ERROR;
  26767. }
  26768. CurrentSim=GETSIMULATOR(thisObject);
  26769. searchresult=TCL_OK;
  26770. searchPtr=(Tcl_HashSearch *)Odie_Alloc(sizeof(Tcl_HashSearch));
  26771. for(i=Entity_First(CurrentSim,searchPtr); i ; i = Tcl_NextHashEntry(searchPtr)) {
  26772. Entity *p = (Entity*)Tcl_GetHashValue(i);
  26773. if(matchvalues) {
  26774. if(!Entity_StructMatches(p,matchStruct)) continue;
  26775. }
  26776. Tcl_ObjSetVar2(interp, keyvar, (Tcl_Obj *)NULL, Entity_Identify(p), 0);
  26777. if(infovar) {
  26778. Tcl_ObjSetVar2(interp, infovar, (Tcl_Obj *)NULL, Entity_StructToDict(interp,p,1), 0);
  26779. }
  26780. searchresult=Tcl_EvalObjEx(interp,body,0);
  26781. if (searchresult !=TCL_OK && searchresult!=TCL_CONTINUE) {
  26782. break;
  26783. }
  26784. }
  26785. Tcl_DecrRefCount(keyvar);
  26786. if(infovar) {
  26787. Tcl_DecrRefCount(infovar);
  26788. }
  26789. Odie_Free((char *)searchPtr);
  26790. return searchresult;
  26791. }
  26792. /* OO Method OOEntity foreach */
  26793. static int OOMethod_OOEntity_foreach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26794.  
  26795. Tcl_HashSearch *searchPtr;
  26796. Tcl_HashEntry *i;
  26797. int searchresult=TCL_OK;
  26798. Tcl_Obj *body,*matchvalues=NULL;
  26799. int matchStruct[ENTITY_SEARCH_NCOUNT];
  26800.  
  26801. if( objc != 3 && objc != 4){
  26802. Tcl_WrongNumArgs(interp, 2, objv, "?matchlist? body");
  26803. return TCL_ERROR;
  26804. }
  26805. CurrentSim=GETSIMULATOR(thisObject);
  26806. if(objc==3) {
  26807. body=objv[2];
  26808. } else {
  26809. matchvalues=objv[2];
  26810. body=objv[3];
  26811. }
  26812. if(Entity_BuildMatch(interp,matchvalues,matchStruct) != TCL_OK) {
  26813. return TCL_ERROR;
  26814. }
  26815.  
  26816. searchPtr=(Tcl_HashSearch *)Odie_Alloc(sizeof(Tcl_HashSearch));
  26817. for(i=Entity_First(CurrentSim,searchPtr); i ; i = Tcl_NextHashEntry(searchPtr)) {
  26818. Entity *p = (Entity*)Tcl_GetHashValue(i);
  26819. if(matchvalues) {
  26820. if(!Entity_StructMatches(p,matchStruct)) continue;
  26821. }
  26822. searchresult=Entity_nodeeval(interp,p,body,0);
  26823. if (searchresult !=TCL_OK && searchresult!=TCL_CONTINUE) {
  26824. Odie_Free((char *)searchPtr);
  26825. return searchresult;
  26826. }
  26827. }
  26828. Odie_Free((char *)searchPtr);
  26829. return TCL_OK;
  26830. }
  26831. /* OO Method OOEntity groupid */
  26832. static int OOMethod_OOEntity_groupid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26833.  
  26834. Entity *p;
  26835. Roid groupid=0;
  26836. if( objc!=3 && objc != 4 ){
  26837. Tcl_WrongNumArgs(interp, 2, objv, "ID ?groupid?");
  26838. return TCL_ERROR;
  26839. }
  26840. CurrentSim=GETSIMULATOR(thisObject);
  26841. if( Entity_FromTclObj(interp, objv[2], &p) ) {
  26842. Tcl_ResetResult(interp);
  26843. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  26844. return TCL_OK;
  26845. }
  26846. if(objc==4) {
  26847. if(Irm_GetRoidFromObj(interp,objv[2],&groupid)) {
  26848. return TCL_ERROR;
  26849. }
  26850. Entity_StructSetGroup(p,groupid);
  26851. }
  26852. groupid=Entity_StructGetGroup(p);
  26853. if(groupid>0) {
  26854. Tcl_SetObjResult(interp, Irm_NewRoidObj(groupid));
  26855. } else {
  26856. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  26857. }
  26858. return TCL_OK;
  26859. }
  26860. /* OO Method OOEntity groups_recalculate */
  26861. static int OOMethod_OOEntity_groups_recalculate(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26862.  
  26863. Tcl_HashSearch search;
  26864. Tcl_HashEntry *i;
  26865. CurrentSim=GETSIMULATOR(thisObject);
  26866. i = Entity_First(CurrentSim,&search);
  26867. while( i ){
  26868. Entity *p = (Entity*)Tcl_GetHashValue(i);
  26869. p->gType=NULL;
  26870. i = Tcl_NextHashEntry(&search);
  26871. }
  26872. return TCL_OK;
  26873. }
  26874. /* OO Method OOEntity hidden_inherit */
  26875. static int OOMethod_OOEntity_hidden_inherit(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26876.  
  26877. Tcl_HashSearch search;
  26878. Tcl_HashEntry *i;
  26879. CurrentSim=GETSIMULATOR(thisObject);
  26880. i = Entity_First(CurrentSim,&search);
  26881. while( i ){
  26882. Entity *p = (Entity*)Tcl_GetHashValue(i);
  26883. if(p->pType) {
  26884. if(p->pType->public_hidden) {
  26885. p->public_hidden=1;
  26886. } else {
  26887. p->public_hidden=0;
  26888. }
  26889. }
  26890. i = Tcl_NextHashEntry(&search);
  26891. }
  26892. return TCL_OK;
  26893. }
  26894. /* OO Method OOEntity list */
  26895. static int OOMethod_OOEntity_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26896.  
  26897. Tcl_Obj *pResult = Tcl_NewObj();
  26898. Tcl_HashSearch search;
  26899. Tcl_HashEntry *i;
  26900. int matchStruct[ENTITY_SEARCH_NCOUNT];
  26901. int domatch=0;
  26902. CurrentSim=GETSIMULATOR(thisObject);
  26903.  
  26904. if(objc==3) {
  26905. domatch=1;
  26906. if(Entity_BuildMatch(interp,objv[2],matchStruct) != TCL_OK) {
  26907. return TCL_ERROR;
  26908. }
  26909. }
  26910. for(i=Entity_First(CurrentSim,&search); i ; i = Tcl_NextHashEntry(&search)) {
  26911. Entity *p = (Entity*)Tcl_GetHashValue(i);
  26912. if(domatch) {
  26913. if(!Entity_StructMatches(p,matchStruct)) continue;
  26914. }
  26915. Tcl_ListObjAppendElement(interp, pResult, Entity_Identify(p));
  26916. }
  26917. Tcl_SetObjResult(interp, pResult);
  26918. return TCL_OK;
  26919. }
  26920. /* OO Method OOEntity location */
  26921. static int OOMethod_OOEntity_location(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26922.  
  26923. Entity *p;
  26924. if( objc!=3 && objc!=4 && objc!=6 && objc!=7){
  26925. Tcl_WrongNumArgs(interp, 2, objv, "ID ?D X Y ?ZOFF??");
  26926. return TCL_ERROR;
  26927. }
  26928. CurrentSim=GETSIMULATOR(thisObject);
  26929. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  26930. if( objc==3 ){
  26931. Tcl_Obj *pResult = Tcl_NewObj();
  26932. Irm_Location temp;
  26933. Entity_StructLocation(&temp,p);
  26934. Tcl_ListObjAppendElement(0, pResult, Odie_LiteralIntObj(temp.deckid));
  26935. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(temp.x));
  26936. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(temp.y));
  26937. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(temp.zoff));
  26938. Tcl_SetObjResult(interp, pResult);
  26939. } else if( objc==4 ) {
  26940. double x, y;
  26941. int did;
  26942. if( Location_FromTclObj(interp,objv[3],&did,&x,&y) ) {
  26943. return TCL_ERROR;
  26944. }
  26945. p->x = (long)x;
  26946. p->y = (long)y;
  26947. p->deckid = did;
  26948. p->zoff=0;
  26949. Entity_Node_ApplyLocation(p);
  26950. } else {
  26951. double x, y, zoff;
  26952. int did;
  26953. if( Tcl_GetIntFromObj(interp, objv[3], &did) ) return TCL_ERROR;
  26954. if( Tcl_GetDoubleFromObj(interp, objv[4], &x) ) return TCL_ERROR;
  26955. if( Tcl_GetDoubleFromObj(interp, objv[5], &y) ) return TCL_ERROR;
  26956. p->attached_to=NULL;
  26957. p->attached_type=0;
  26958. p->x = (long)x;
  26959. p->y = (long)y;
  26960. p->deckid = did;
  26961. if(objc==7) {
  26962. if( Tcl_GetDoubleFromObj(interp, objv[6], &zoff) ) {
  26963. Tcl_ResetResult(interp);
  26964. zoff=0;
  26965. }
  26966. p->zoff=(int)zoff;
  26967. }
  26968. Entity_Node_ApplyLocation(p);
  26969. }
  26970. return TCL_OK;
  26971. }
  26972. /* OO Method OOEntity midpoint */
  26973. static int OOMethod_OOEntity_midpoint(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26974.  
  26975. CurrentSim=GETSIMULATOR(thisObject);
  26976. local_interp=interp;
  26977. Entity *p;
  26978. Irm_Location temp;
  26979. int height;
  26980.  
  26981. if( objc!=3){
  26982. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  26983. return TCL_ERROR;
  26984. }
  26985. Tcl_Obj *pResult = Tcl_NewObj();
  26986.  
  26987. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  26988. Entity_StructLocation(&temp,p);
  26989. height=Entity_StructSizeZ(p);
  26990. Tcl_ListObjAppendElement(0, pResult, Odie_LiteralIntObj(temp.deckid));
  26991. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(temp.x));
  26992. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(temp.y));
  26993. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(temp.zoff+height/2));
  26994. Tcl_SetObjResult(interp, pResult);
  26995. return TCL_OK;
  26996. }
  26997. /* OO Method OOEntity nodeget */
  26998. static int OOMethod_OOEntity_nodeget(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  26999.  
  27000. CurrentSim=GETSIMULATOR(thisObject);
  27001.  
  27002. local_interp=interp;
  27003. Entity *p;
  27004. if( objc!=3 && objc != 4){
  27005. Tcl_WrongNumArgs(interp, 2, objv, "ID ?field?");
  27006. return TCL_ERROR;
  27007. }
  27008. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  27009.  
  27010. if(objc==4) {
  27011. Tcl_Obj *result;
  27012. int offset=-1,err,type;
  27013. err=Entity_StructValueOffset(interp, objv[3], &offset,&type);
  27014. if(err == TCL_OK ) {
  27015. result=Entity_StructGet(p,offset);
  27016. Tcl_SetObjResult(interp,result);
  27017. return TCL_OK;
  27018. }
  27019. /* Pull the value from extended dict */
  27020. result=Entity_SpecHashGet(p,objv[3],ODIE_NULL_EMPTY);
  27021. Tcl_SetObjResult(interp,result);
  27022. } else {
  27023. Tcl_SetObjResult(interp,Entity_StructToDict(interp,p,1));
  27024. }
  27025. return TCL_OK;
  27026. }
  27027. /* OO Method OOEntity nodeput */
  27028. static int OOMethod_OOEntity_nodeput(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27029.  
  27030. CurrentSim=GETSIMULATOR(thisObject);
  27031.  
  27032. local_interp=interp;
  27033. Entity *p;
  27034. Tcl_DictSearch search;
  27035. Tcl_Obj *key, *value, *objPtr;
  27036. int done;
  27037. int offset,type,err=TCL_OK;
  27038.  
  27039. if( objc!=4 ){
  27040. Tcl_WrongNumArgs(interp, 2, objv, "ID infoDict");
  27041. return TCL_ERROR;
  27042. }
  27043.  
  27044. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  27045. objPtr=objv[3];
  27046. if (Tcl_DictObjFirst(interp, objPtr, &search,
  27047. &key, &value, &done) != TCL_OK) {
  27048. return TCL_ERROR;
  27049. }
  27050. for (; !done ; Tcl_DictObjNext(&search, &key, &value, &done)) {
  27051. if( Entity_StructValueOffset(interp, key, &offset, &type) == TCL_OK ) {
  27052. err=Entity_StructSet(interp,p,offset,value);
  27053. if(err != TCL_OK) {
  27054. break;
  27055. }
  27056. } else {
  27057. Entity_SpecHashPut(p,key,value);
  27058. Tcl_SetObjResult(interp, value);
  27059. }
  27060. }
  27061. Tcl_DictObjDone(&search);
  27062. if(err==TCL_OK) {
  27063. Entity_ApplySettings(p);
  27064. }
  27065. return err;
  27066. }
  27067. /* OO Method OOEntity nodewith */
  27068. static int OOMethod_OOEntity_nodewith(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27069.  
  27070. CurrentSim=GETSIMULATOR(thisObject);
  27071.  
  27072. local_interp=interp;
  27073. Entity *p;
  27074. if( objc != 4){
  27075. Tcl_WrongNumArgs(interp, 2, objv, "ID body");
  27076. return TCL_ERROR;
  27077. }
  27078. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  27079. return Entity_nodeeval(interp,p,objv[3],1);
  27080. }
  27081. /* OO Method OOEntity normalize */
  27082. static int OOMethod_OOEntity_normalize(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27083.  
  27084. CurrentSim=GETSIMULATOR(thisObject);
  27085.  
  27086. local_interp=interp;
  27087. Entity *p;
  27088. if( objc!=3 ){
  27089. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  27090. return TCL_ERROR;
  27091. }
  27092. if( Entity_FromTclObj(interp, objv[2], &p) ) {
  27093. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  27094. } else {
  27095. Tcl_SetObjResult(interp, Entity_Identify(p));
  27096. }
  27097. return TCL_OK;
  27098. }
  27099. /* OO Method OOEntity orientation */
  27100. static int OOMethod_OOEntity_orientation(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27101.  
  27102. CurrentSim=GETSIMULATOR(thisObject);
  27103.  
  27104. local_interp=interp;
  27105. Entity *p;
  27106. if( objc!=3 && objc!=5 && objc!=6){
  27107. Tcl_WrongNumArgs(interp, 1, objv, "ID ?nx ny nz?");
  27108. return TCL_ERROR;
  27109. }
  27110. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  27111. if( objc>3 ){
  27112. double nx,ny,nz;
  27113. if( Tcl_GetDoubleFromObj(interp, objv[3], &nx) ) return TCL_ERROR;
  27114. if( Tcl_GetDoubleFromObj(interp, objv[4], &ny) ) return TCL_ERROR;
  27115. p->nx =(int)nx;
  27116. p->ny =(int)ny;
  27117. p->nz = 0;
  27118. if(objc==6) {
  27119. if( Tcl_GetDoubleFromObj(interp, objv[4], &nz) ) return TCL_ERROR;
  27120. p->nz =(int)nz;
  27121. }
  27122. }
  27123. Tcl_Obj *pResult = Tcl_NewObj();
  27124. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(p->nx));
  27125. Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(p->ny));
  27126. Tcl_SetObjResult(interp, pResult);
  27127.  
  27128. return TCL_OK;
  27129. }
  27130. /* OO Method OOEntity redraw */
  27131. static int OOMethod_OOEntity_redraw(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27132.  
  27133. CurrentSim=GETSIMULATOR(thisObject);
  27134.  
  27135. local_interp=interp;
  27136. Entity *p;
  27137. if( objc!=3 ) {
  27138. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  27139. return TCL_ERROR;
  27140. }
  27141. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  27142. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(p->public_redraw));
  27143. p->public_redraw=0;
  27144. return TCL_OK;
  27145. }
  27146. /* OO Method OOEntity reset */
  27147. static int OOMethod_OOEntity_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27148.  
  27149. CurrentSim=GETSIMULATOR(thisObject);
  27150.  
  27151. local_interp=interp;
  27152. Simulator_Reset(CurrentSim);
  27153. Entity_Module_Free(CurrentSim);
  27154. Entity_Module_Init(CurrentSim);
  27155. Simulator_Init(CurrentSim);
  27156. Tcl_ResetResult(interp);
  27157. return TCL_OK;
  27158. }
  27159. /* OO Method OOEntity setting */
  27160. static int OOMethod_OOEntity_setting(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27161.  
  27162. CurrentSim=GETSIMULATOR(thisObject);
  27163.  
  27164. local_interp=interp;
  27165. int offset,type,rcode;
  27166. /* If given a new value, act like a stylized set */
  27167. Entity *p;
  27168.  
  27169. if( objc!=4 && objc!=5 ){
  27170. Tcl_WrongNumArgs(interp, 2, objv, "ID FIELD ?VALUE?");
  27171. return TCL_ERROR;
  27172. }
  27173. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  27174.  
  27175. if(objc == 5) {
  27176. if( Entity_StructValueOffset(interp, objv[3], &offset, &type) == TCL_OK ) {
  27177. rcode=Entity_StructSet(interp,p,offset,objv[4]);
  27178. return rcode;
  27179. }
  27180. rcode=Entity_SetFromObj(interp,p,objv[3],objv[4]);
  27181. return rcode;
  27182. } else {
  27183. Tcl_Obj *result;
  27184. int offset=-1,err,type;
  27185. err=Entity_StructValueOffset(interp, objv[3], &offset,&type);
  27186. if(err == TCL_OK ) {
  27187. result=Entity_StructGet(p,offset);
  27188. Tcl_SetObjResult(interp,result);
  27189. return TCL_OK;
  27190. }
  27191. /* Pull the value from extended dict */
  27192. result=Entity_ExportField(p->pType,p->infoDict,Tcl_GetString(objv[3]),ODIE_NULL_ZERO);
  27193. Tcl_SetObjResult(interp,result);
  27194. return TCL_OK;
  27195. }
  27196. }
  27197. /* OO Method OOEntity spec_get */
  27198. static int OOMethod_OOEntity_spec_get(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27199.  
  27200. CurrentSim=GETSIMULATOR(thisObject);
  27201.  
  27202. local_interp=interp;
  27203. Entity *p;
  27204. Tcl_Obj *pResult=NULL;
  27205. if( objc!=3 && objc != 4){
  27206. Tcl_WrongNumArgs(interp, 2, objv, "ID ?field?");
  27207. return TCL_ERROR;
  27208. }
  27209. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  27210.  
  27211. if(objc==4) {
  27212. /* Pull the value from extended dict */
  27213. pResult=Entity_SpecHashGet(p,objv[3],ODIE_NULL_EMPTY);
  27214. } else {
  27215. pResult=Entity_GetDict(p->pType,p->infoDict);
  27216. }
  27217. if(pResult) {
  27218. Tcl_SetObjResult(interp,pResult);
  27219. }
  27220. return TCL_OK;
  27221. }
  27222. /* OO Method OOEntity spec_put */
  27223. static int OOMethod_OOEntity_spec_put(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27224.  
  27225. CurrentSim=GETSIMULATOR(thisObject);
  27226.  
  27227. local_interp=interp;
  27228. Entity *p;
  27229. Tcl_DictSearch search;
  27230. Tcl_Obj *key, *value, *objPtr;
  27231. int done;
  27232.  
  27233. if( objc!=4 ){
  27234. Tcl_WrongNumArgs(interp, 2, objv, "ID infoDict");
  27235. return TCL_ERROR;
  27236. }
  27237.  
  27238. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  27239. objPtr=objv[3];
  27240. if (Tcl_DictObjFirst(interp, objPtr, &search,
  27241. &key, &value, &done) != TCL_OK) {
  27242. return TCL_ERROR;
  27243. }
  27244. for (; !done ; Tcl_DictObjNext(&search, &key, &value, &done)) {
  27245. Entity_SpecHashPut(p,key,value);
  27246. Tcl_SetObjResult(interp, value);
  27247. }
  27248. Tcl_DictObjDone(&search);
  27249. return TCL_OK;
  27250. }
  27251. /* OO Method OOEntity spec_replace */
  27252. static int OOMethod_OOEntity_spec_replace(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27253.  
  27254. CurrentSim=GETSIMULATOR(thisObject);
  27255.  
  27256. local_interp=interp;
  27257. Entity *p;
  27258. Tcl_DictSearch search;
  27259. Tcl_Obj *key, *value, *objPtr;
  27260. int done;
  27261.  
  27262. if( objc!=4 ){
  27263. Tcl_WrongNumArgs(interp, 2, objv, "ID infoDict");
  27264. return TCL_ERROR;
  27265. }
  27266.  
  27267. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  27268.  
  27269. objPtr=objv[3];
  27270. if (Tcl_DictObjFirst(interp, objPtr, &search,
  27271. &key, &value, &done) != TCL_OK) {
  27272. return TCL_ERROR;
  27273. }
  27274. Entity_SpecHashClear(p);
  27275. for (; !done ; Tcl_DictObjNext(&search, &key, &value, &done)) {
  27276. Entity_SpecHashPut(p,key,value);
  27277. Tcl_SetObjResult(interp, value);
  27278. }
  27279. Tcl_DictObjDone(&search);
  27280. return TCL_OK;
  27281. }
  27282. /* OO Method OOEntity struct_get */
  27283. static int OOMethod_OOEntity_struct_get(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27284.  
  27285. CurrentSim=GETSIMULATOR(thisObject);
  27286.  
  27287. local_interp=interp;
  27288. Entity *p;
  27289. if( objc!=3 && objc != 4){
  27290. Tcl_WrongNumArgs(interp, 2, objv, "ID ?field?");
  27291. return TCL_ERROR;
  27292. }
  27293. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  27294.  
  27295. if(objc==4) {
  27296. Tcl_Obj *result;
  27297. int offset=-1,err,type;
  27298. err=Entity_StructValueOffset(interp, objv[3], &offset,&type);
  27299. if(err == TCL_OK ) {
  27300. result=Entity_StructGet(p,offset);
  27301. Tcl_SetObjResult(interp,result);
  27302. return TCL_OK;
  27303. }
  27304. return TCL_ERROR;
  27305. } else {
  27306. Tcl_SetObjResult(interp,Entity_StructToDict(interp,p,0));
  27307. }
  27308. return TCL_OK;
  27309. }
  27310. /* OO Method OOEntity struct_put */
  27311. static int OOMethod_OOEntity_struct_put(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27312.  
  27313. CurrentSim=GETSIMULATOR(thisObject);
  27314.  
  27315. local_interp=interp;
  27316. Entity *p;
  27317. Tcl_DictSearch search;
  27318. int done;
  27319. int offset,type,err=TCL_OK;
  27320.  
  27321. if( objc!=4 && objc!=5 ){
  27322. Tcl_WrongNumArgs(interp, 2, objv, "ID infoDict");
  27323. return TCL_ERROR;
  27324. }
  27325.  
  27326. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  27327. if(objc==5) {
  27328. if( Entity_StructValueOffset(interp, objv[3], &offset, &type) == TCL_OK ) {
  27329. err=Entity_StructSet(interp,p,offset,objv[4]);
  27330. if(err != TCL_OK) {
  27331. return TCL_ERROR;
  27332. }
  27333. } else {
  27334. return TCL_ERROR;
  27335. }
  27336. } else {
  27337. Tcl_Obj *key, *value;
  27338. Tcl_Obj *objPtr=objv[3];
  27339. if (Tcl_DictObjFirst(interp, objPtr, &search,
  27340. &key, &value, &done) != TCL_OK) {
  27341. return TCL_ERROR;
  27342. }
  27343. for (; !done ; Tcl_DictObjNext(&search, &key, &value, &done)) {
  27344. if( Entity_StructValueOffset(interp, key, &offset, &type) == TCL_OK ) {
  27345. err=Entity_StructSet(interp,p,offset,value);
  27346. if(err != TCL_OK) {
  27347. break;
  27348. }
  27349. } else {
  27350. return TCL_ERROR;
  27351. }
  27352. }
  27353. Tcl_DictObjDone(&search);
  27354. }
  27355. if(err==TCL_OK) {
  27356. Entity_ApplySettings(p);
  27357. }
  27358. return err;
  27359. }
  27360. /* OO Method OOEntity type */
  27361. static int OOMethod_OOEntity_type(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27362.  
  27363. CurrentSim=GETSIMULATOR(thisObject);
  27364.  
  27365. local_interp=interp;
  27366. Entity *p;
  27367. Entity *pType;
  27368. if( objc != 3 && objc != 4 ){
  27369. Tcl_WrongNumArgs(interp, 2, objv, "NODEID field");
  27370. return TCL_ERROR;
  27371. }
  27372. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  27373. pType=Entity_StructGetType(p);
  27374. if(!pType) {
  27375. if(objc==3) {
  27376. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  27377. }
  27378. return TCL_OK;
  27379. }
  27380. if(objc==3) {
  27381. Tcl_SetObjResult(interp, SimType_Identify(pType));
  27382. }
  27383. if(objc==4) {
  27384. Tcl_Obj *pResult;
  27385. pResult=Entity_ExportField(pType,NULL,Tcl_GetString(objv[3]),ODIE_NULL_EMPTY);
  27386. Tcl_SetObjResult(interp,pResult);
  27387. }
  27388. return TCL_OK;
  27389. }
  27390. /* OO Method OOEntity typeid */
  27391. static int OOMethod_OOEntity_typeid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27392.  
  27393. CurrentSim=GETSIMULATOR(thisObject);
  27394.  
  27395. local_interp=interp;
  27396. Entity *p;
  27397. Entity *pType;
  27398. if( objc!=3 && objc != 4 ){
  27399. Tcl_WrongNumArgs(interp, 2, objv, "ID ?typeid?");
  27400. return TCL_ERROR;
  27401. }
  27402. if( Entity_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  27403. if(objc==4) {
  27404. if( SimType_FromTclObj(interp, objv[3], &pType) ) {
  27405. /* Translate a ZERO length list to null */
  27406. int len;
  27407. if(Tcl_ListObjLength(NULL,objv[3],&len)) {
  27408. return TCL_ERROR;
  27409. }
  27410. if(len) {
  27411. int intval;
  27412. if(Tcl_GetIntFromObj(NULL,objv[3],&intval)==TCL_ERROR) {
  27413. return TCL_ERROR;
  27414. }
  27415. if(intval>0) {
  27416. return TCL_ERROR;
  27417. }
  27418. }
  27419. Tcl_ResetResult(interp);
  27420. pType=NULL;
  27421. }
  27422. Entity_StructSetType(p,pType);
  27423. /* Reset the group pointer so it's recalculated */
  27424. Entity_StructSetGroup(p,-1);
  27425. }
  27426. pType=Entity_StructGetType(p);
  27427. if(pType) {
  27428. Tcl_SetObjResult(interp, SimType_Identify(pType));
  27429. } else {
  27430. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  27431. }
  27432. return TCL_OK;
  27433. }
  27434. /* OO Method OOEntity visible */
  27435. static int OOMethod_OOEntity_visible(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27436.  
  27437. CurrentSim=GETSIMULATOR(thisObject);
  27438.  
  27439. local_interp=interp;
  27440. Entity *p;
  27441. if( objc != 2 && objc!=3 && objc!=4 ){
  27442. Tcl_WrongNumArgs(interp, 2, objv, "?ID? ?VALUE?");
  27443. return TCL_ERROR;
  27444. }
  27445. if(objc==2) {
  27446. /*
  27447. ** If zero arguments return a list of all nodes with the
  27448. ** visible flag set
  27449. */
  27450. Tcl_Obj *pResult;
  27451. Tcl_HashSearch search;
  27452. Tcl_HashEntry *i;
  27453. i = Entity_First(CurrentSim,&search);
  27454. pResult = Tcl_NewObj();
  27455. while( i ){
  27456. Entity *p = (Entity*)Tcl_GetHashValue(i);
  27457. if(p->public_visible) {
  27458. Tcl_ListObjAppendElement(0, pResult, Entity_Identify(p));
  27459. }
  27460. i = Tcl_NextHashEntry(&search);
  27461. }
  27462. Tcl_SetObjResult(interp, pResult);
  27463. return TCL_OK;
  27464. }
  27465. if(objc==3) {
  27466. /*
  27467. ** With one argument, query the visible flag
  27468. ** of a specific node
  27469. */
  27470. if( Entity_FromTclObj(interp, objv[2], &p) ) {
  27471. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  27472. return TCL_OK;
  27473. }
  27474. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(p->public_visible));
  27475. return TCL_OK;
  27476. }
  27477. /*
  27478. ** With two arguments, set a list of nodes given in
  27479. ** argument 1 to the new status argument 2
  27480. */
  27481. if( objc==4 ){
  27482. int i,n,value;
  27483. Tcl_Obj *element;
  27484. if(Tcl_ListObjLength(interp,objv[2],&n)) return TCL_ERROR;
  27485. if(Tcl_GetBooleanFromObj(interp, objv[3], &value)) return TCL_ERROR;
  27486.  
  27487. for(i=0;i<n;i++) {
  27488. if(Tcl_ListObjIndex(interp, objv[2], i, &element)) return TCL_ERROR;
  27489. if(Entity_FromTclObj(interp, element, &p)) continue;
  27490. p->public_visible=value;
  27491. }
  27492. }
  27493. return TCL_OK;
  27494. }
  27495. /* OO Method OOEntity visible_filter */
  27496. static int OOMethod_OOEntity_visible_filter(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27497.  
  27498. CurrentSim=GETSIMULATOR(thisObject);
  27499.  
  27500. local_interp=interp;
  27501. Tcl_HashSearch search;
  27502. Tcl_HashEntry *i;
  27503. i = Entity_First(CurrentSim,&search);
  27504. while( i ){
  27505. Entity *p = (Entity*)Tcl_GetHashValue(i);
  27506. if(p->pType) {
  27507. if(!p->pType->public_visible) {
  27508. p->public_visible=0;
  27509. }
  27510. }
  27511. i = Tcl_NextHashEntry(&search);
  27512. }
  27513. return TCL_OK;
  27514. }
  27515. /* OO Method OOEntity visible_hidden_subtract */
  27516. static int OOMethod_OOEntity_visible_hidden_subtract(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27517.  
  27518. CurrentSim=GETSIMULATOR(thisObject);
  27519.  
  27520. local_interp=interp;
  27521. Tcl_HashSearch search;
  27522. Tcl_HashEntry *i;
  27523. i = Entity_First(CurrentSim,&search);
  27524. while( i ){
  27525. Entity *p = (Entity*)Tcl_GetHashValue(i);
  27526. if(p->public_hidden==0) {
  27527. p->public_visible=0;
  27528. }
  27529. i = Tcl_NextHashEntry(&search);
  27530. }
  27531. return TCL_OK;
  27532. }
  27533. /* OO Method OOEntity visible_inherit */
  27534. static int OOMethod_OOEntity_visible_inherit(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27535.  
  27536. CurrentSim=GETSIMULATOR(thisObject);
  27537.  
  27538. local_interp=interp;
  27539. Tcl_HashSearch search;
  27540. Tcl_HashEntry *i;
  27541.  
  27542. i = Entity_First(CurrentSim,&search);
  27543. while( i ){
  27544. Entity *p = (Entity*)Tcl_GetHashValue(i);
  27545. if(p->pType) {
  27546. if(p->pType->public_hidden) {
  27547. p->public_hidden=1;
  27548. p->public_visible=0;
  27549. } else {
  27550. if(p->pType->public_visible) {
  27551. p->public_visible=1;
  27552. }
  27553. p->public_hidden=0;
  27554. }
  27555. }
  27556. i = Tcl_NextHashEntry(&search);
  27557. }
  27558. return TCL_OK;
  27559. }
  27560. /* OO Method OOEntity visible_reset */
  27561. static int OOMethod_OOEntity_visible_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27562.  
  27563. CurrentSim=GETSIMULATOR(thisObject);
  27564.  
  27565. local_interp=interp;
  27566. Tcl_HashSearch search;
  27567. Tcl_HashEntry *i;
  27568. i = SimType_First(CurrentSim,&search);
  27569. while( i ){
  27570. Entity *p = (Entity*)Tcl_GetHashValue(i);
  27571. p->public_visible=0;
  27572. p->public_trace=0;
  27573. p->public_hidden=0;
  27574. i = Tcl_NextHashEntry(&search);
  27575. }
  27576. i = Entity_First(CurrentSim,&search);
  27577. while( i ){
  27578. Entity *p = (Entity*)Tcl_GetHashValue(i);
  27579. p->public_visible=0;
  27580. p->public_trace=0;
  27581. p->public_hidden=0;
  27582. i = Tcl_NextHashEntry(&search);
  27583. }
  27584. return TCL_OK;
  27585. }
  27586. /* OO Method OOEntity visible_tree */
  27587. static int OOMethod_OOEntity_visible_tree(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27588.  
  27589. CurrentSim=GETSIMULATOR(thisObject);
  27590.  
  27591. local_interp=interp;
  27592. Tcl_HashSearch search;
  27593. Tcl_HashEntry *i;
  27594. /*
  27595. ** Rebuild the visible and active flags
  27596. ** in simtypes
  27597. */
  27598.  
  27599. i = SimType_First(CurrentSim,&search);
  27600. while( i ){
  27601. Entity *p = (Entity*)Tcl_GetHashValue(i);
  27602. p->public_visible=0;
  27603. p->public_trace=0;
  27604. p->public_hidden=0;
  27605. i = Tcl_NextHashEntry(&search);
  27606. }
  27607. i = Entity_First(CurrentSim,&search);
  27608. while( i ){
  27609. Entity *p = (Entity*)Tcl_GetHashValue(i);
  27610. p->public_visible=0;
  27611. p->public_trace=0;
  27612. p->public_hidden=0;
  27613. i = Tcl_NextHashEntry(&search);
  27614. }
  27615.  
  27616. i = SimType_First(CurrentSim,&search);
  27617. while( i ){
  27618. Entity *p = (Entity*)Tcl_GetHashValue(i);
  27619. int code=SimType_Walk_Parent(p);
  27620. if(code > 0) {
  27621. p->public_visible=1;
  27622. } else if (code < 0) {
  27623. p->public_visible=0;
  27624. p->public_hidden=1;
  27625. }
  27626. i = Tcl_NextHashEntry(&search);
  27627. }
  27628. i = Entity_First(CurrentSim,&search);
  27629. while( i ){
  27630. Entity *p = (Entity*)Tcl_GetHashValue(i);
  27631. int code=SimType_Walk_Parent(p->pType);
  27632. if(code==1) {
  27633. p->public_visible=1;
  27634. } else if (code < 0) {
  27635. p->public_visible=0;
  27636. p->public_hidden=1;
  27637. }
  27638. i = Tcl_NextHashEntry(&search);
  27639. }
  27640. return TCL_OK;
  27641. }
  27642. /* OO Method OOEntity witheach */
  27643. static int OOMethod_OOEntity_witheach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27644.  
  27645. CurrentSim=GETSIMULATOR(thisObject);
  27646.  
  27647. local_interp=interp;
  27648. Tcl_HashSearch *searchPtr;
  27649. Tcl_HashEntry *i;
  27650. int searchresult=TCL_OK;
  27651. Tcl_Obj *body,*matchvalues=NULL;
  27652. int matchStruct[ENTITY_SEARCH_NCOUNT];
  27653.  
  27654. if( objc != 3 && objc != 4){
  27655. Tcl_WrongNumArgs(interp, 2, objv, "?matchlist? body");
  27656. return TCL_ERROR;
  27657. }
  27658. if(objc==3) {
  27659. body=objv[2];
  27660. } else {
  27661. matchvalues=objv[2];
  27662. body=objv[3];
  27663. }
  27664. if(Entity_BuildMatch(interp,matchvalues,matchStruct) != TCL_OK) {
  27665. return TCL_ERROR;
  27666. }
  27667.  
  27668. searchPtr=(Tcl_HashSearch *)Odie_Alloc(sizeof(Tcl_HashSearch));
  27669. for(i=Entity_First(CurrentSim,searchPtr); i ; i = Tcl_NextHashEntry(searchPtr)) {
  27670. Entity *p = (Entity*)Tcl_GetHashValue(i);
  27671. if(matchvalues) {
  27672. if(!Entity_StructMatches(p,matchStruct)) continue;
  27673. }
  27674. searchresult=Entity_nodeeval(interp,p,body,1);
  27675. if (searchresult !=TCL_OK && searchresult!=TCL_CONTINUE) {
  27676. Odie_Free((char *)searchPtr);
  27677. return searchresult;
  27678. }
  27679. }
  27680. Odie_Free((char *)searchPtr);
  27681. return TCL_OK;
  27682. }
  27683. /* Loader for OOEntity */
  27684. static int OOEntity_OO_Init(Tcl_Interp *interp) {
  27685. /*
  27686. ** Build the "::odielib::entity" class
  27687. */
  27688. Tcl_Obj* nameObj; /* Name of a class or method being looked up */
  27689. Tcl_Object curClassObject; /* Tcl_Object representing the current class */
  27690. Tcl_Class curClass; /* Tcl_Class representing the current class */
  27691.  
  27692. /*
  27693. * Find the "::odielib::entity" class, and attach an 'init' method to it.
  27694. */
  27695.  
  27696. nameObj = Tcl_NewStringObj("::odielib::entity", -1);
  27697. Tcl_IncrRefCount(nameObj);
  27698. if ((curClassObject = Tcl_GetObjectFromObj(interp, nameObj)) == NULL) {
  27699. Tcl_DecrRefCount(nameObj);
  27700. return TCL_ERROR;
  27701. }
  27702. Tcl_DecrRefCount(nameObj);
  27703. curClass = Tcl_GetObjectAsClass(curClassObject);
  27704. nameObj=Tcl_NewStringObj("C_Init",-1);
  27705. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_C_Init, (ClientData) NULL);
  27706. Tcl_DecrRefCount(nameObj);
  27707. nameObj=Tcl_NewStringObj("create",-1);
  27708. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_create, (ClientData) NULL);
  27709. Tcl_DecrRefCount(nameObj);
  27710. nameObj=Tcl_NewStringObj("add",-1);
  27711. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_create, (ClientData) NULL);
  27712. Tcl_DecrRefCount(nameObj);
  27713. nameObj=Tcl_NewStringObj("attach_to",-1);
  27714. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_attach_to, (ClientData) NULL);
  27715. Tcl_DecrRefCount(nameObj);
  27716. nameObj=Tcl_NewStringObj("compartment",-1);
  27717. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_compartment, (ClientData) NULL);
  27718. Tcl_DecrRefCount(nameObj);
  27719. nameObj=Tcl_NewStringObj("comptid",-1);
  27720. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_comptid, (ClientData) NULL);
  27721. Tcl_DecrRefCount(nameObj);
  27722. nameObj=Tcl_NewStringObj("count",-1);
  27723. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_count, (ClientData) NULL);
  27724. Tcl_DecrRefCount(nameObj);
  27725. nameObj=Tcl_NewStringObj("deckid",-1);
  27726. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_deckid, (ClientData) NULL);
  27727. Tcl_DecrRefCount(nameObj);
  27728. nameObj=Tcl_NewStringObj("delete",-1);
  27729. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_delete, (ClientData) NULL);
  27730. Tcl_DecrRefCount(nameObj);
  27731. nameObj=Tcl_NewStringObj("drawn_reset",-1);
  27732. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_drawn_reset, (ClientData) NULL);
  27733. Tcl_DecrRefCount(nameObj);
  27734. nameObj=Tcl_NewStringObj("exists",-1);
  27735. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_exists, (ClientData) NULL);
  27736. Tcl_DecrRefCount(nameObj);
  27737. nameObj=Tcl_NewStringObj("for",-1);
  27738. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_for, (ClientData) NULL);
  27739. Tcl_DecrRefCount(nameObj);
  27740. nameObj=Tcl_NewStringObj("foreach",-1);
  27741. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_foreach, (ClientData) NULL);
  27742. Tcl_DecrRefCount(nameObj);
  27743. nameObj=Tcl_NewStringObj("groupid",-1);
  27744. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_groupid, (ClientData) NULL);
  27745. Tcl_DecrRefCount(nameObj);
  27746. nameObj=Tcl_NewStringObj("groups_recalculate",-1);
  27747. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_groups_recalculate, (ClientData) NULL);
  27748. Tcl_DecrRefCount(nameObj);
  27749. nameObj=Tcl_NewStringObj("hidden_inherit",-1);
  27750. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_hidden_inherit, (ClientData) NULL);
  27751. Tcl_DecrRefCount(nameObj);
  27752. nameObj=Tcl_NewStringObj("list",-1);
  27753. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_list, (ClientData) NULL);
  27754. Tcl_DecrRefCount(nameObj);
  27755. nameObj=Tcl_NewStringObj("location",-1);
  27756. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_location, (ClientData) NULL);
  27757. Tcl_DecrRefCount(nameObj);
  27758. nameObj=Tcl_NewStringObj("midpoint",-1);
  27759. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_midpoint, (ClientData) NULL);
  27760. Tcl_DecrRefCount(nameObj);
  27761. nameObj=Tcl_NewStringObj("nodeget",-1);
  27762. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_nodeget, (ClientData) NULL);
  27763. Tcl_DecrRefCount(nameObj);
  27764. nameObj=Tcl_NewStringObj("nodeput",-1);
  27765. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_nodeput, (ClientData) NULL);
  27766. Tcl_DecrRefCount(nameObj);
  27767. nameObj=Tcl_NewStringObj("nodewith",-1);
  27768. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_nodewith, (ClientData) NULL);
  27769. Tcl_DecrRefCount(nameObj);
  27770. nameObj=Tcl_NewStringObj("normalize",-1);
  27771. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_normalize, (ClientData) NULL);
  27772. Tcl_DecrRefCount(nameObj);
  27773. nameObj=Tcl_NewStringObj("orientation",-1);
  27774. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_orientation, (ClientData) NULL);
  27775. Tcl_DecrRefCount(nameObj);
  27776. nameObj=Tcl_NewStringObj("redraw",-1);
  27777. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_redraw, (ClientData) NULL);
  27778. Tcl_DecrRefCount(nameObj);
  27779. nameObj=Tcl_NewStringObj("reset",-1);
  27780. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_reset, (ClientData) NULL);
  27781. Tcl_DecrRefCount(nameObj);
  27782. nameObj=Tcl_NewStringObj("setting",-1);
  27783. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_setting, (ClientData) NULL);
  27784. Tcl_DecrRefCount(nameObj);
  27785. nameObj=Tcl_NewStringObj("spec_get",-1);
  27786. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_spec_get, (ClientData) NULL);
  27787. Tcl_DecrRefCount(nameObj);
  27788. nameObj=Tcl_NewStringObj("spec_put",-1);
  27789. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_spec_put, (ClientData) NULL);
  27790. Tcl_DecrRefCount(nameObj);
  27791. nameObj=Tcl_NewStringObj("spec_replace",-1);
  27792. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_spec_replace, (ClientData) NULL);
  27793. Tcl_DecrRefCount(nameObj);
  27794. nameObj=Tcl_NewStringObj("struct_get",-1);
  27795. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_struct_get, (ClientData) NULL);
  27796. Tcl_DecrRefCount(nameObj);
  27797. nameObj=Tcl_NewStringObj("struct_put",-1);
  27798. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_struct_put, (ClientData) NULL);
  27799. Tcl_DecrRefCount(nameObj);
  27800. nameObj=Tcl_NewStringObj("type",-1);
  27801. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_type, (ClientData) NULL);
  27802. Tcl_DecrRefCount(nameObj);
  27803. nameObj=Tcl_NewStringObj("typeid",-1);
  27804. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_typeid, (ClientData) NULL);
  27805. Tcl_DecrRefCount(nameObj);
  27806. nameObj=Tcl_NewStringObj("visible",-1);
  27807. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_visible, (ClientData) NULL);
  27808. Tcl_DecrRefCount(nameObj);
  27809. nameObj=Tcl_NewStringObj("visible_filter",-1);
  27810. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_visible_filter, (ClientData) NULL);
  27811. Tcl_DecrRefCount(nameObj);
  27812. nameObj=Tcl_NewStringObj("visible_hidden_subtract",-1);
  27813. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_visible_hidden_subtract, (ClientData) NULL);
  27814. Tcl_DecrRefCount(nameObj);
  27815. nameObj=Tcl_NewStringObj("visible_inherit",-1);
  27816. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_visible_inherit, (ClientData) NULL);
  27817. Tcl_DecrRefCount(nameObj);
  27818. nameObj=Tcl_NewStringObj("visible_reset",-1);
  27819. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_visible_reset, (ClientData) NULL);
  27820. Tcl_DecrRefCount(nameObj);
  27821. nameObj=Tcl_NewStringObj("visible_tree",-1);
  27822. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_visible_tree, (ClientData) NULL);
  27823. Tcl_DecrRefCount(nameObj);
  27824. nameObj=Tcl_NewStringObj("witheach",-1);
  27825. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_OOEntity_witheach, (ClientData) NULL);
  27826. Tcl_DecrRefCount(nameObj);
  27827. return TCL_OK;
  27828. }
  27829. /* OO Method SimType C_Init */
  27830. static int OOMethod_SimType_C_Init(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27831.  
  27832. Simulator *p;
  27833. Tcl_Object masterObject;
  27834. if(objc!=3) {
  27835. Tcl_WrongNumArgs(interp, 2, objv, "SIMULATOR_OBJECT");
  27836. return TCL_ERROR;
  27837. }
  27838. masterObject=Tcl_GetObjectFromObj(interp,objv[2]);
  27839. if(masterObject==NULL) {
  27840. return TCL_ERROR;
  27841. }
  27842. p=GETSIMULATOR(masterObject);
  27843. Tcl_ObjectSetMetadata(thisObject, &SimulatorDataType, (ClientData) p);
  27844. return TCL_OK;
  27845. }
  27846. /* OO Method SimType children */
  27847. static int OOMethod_SimType_children(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27848.  
  27849. Tcl_Obj *pResult = Tcl_NewObj();
  27850. Tcl_HashSearch search;
  27851. Tcl_HashEntry *i;
  27852. Roid id;
  27853. if( objc!=3 ) {
  27854. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  27855. }
  27856. if(Irm_GetRoidFromObj(interp,objv[2],&id)) return TCL_ERROR;
  27857. CurrentSim=GETSIMULATOR(thisObject);
  27858. i = SimType_First(CurrentSim,&search);
  27859. while( i ){
  27860. Entity *p = (Entity*)Tcl_GetHashValue(i);
  27861. int match=0;
  27862. if(!id && !p->public_parent) {
  27863. match=1;
  27864. }
  27865. if(p->public_parent) {
  27866. if(p->public_parent == id) {
  27867. match=1;
  27868. }
  27869. }
  27870. if(match) {
  27871. Tcl_Obj *namevalue=Entity_GetField(NULL,p->infoDict,"name");
  27872. if(!namevalue) {
  27873. namevalue=Irm_NewRoidObj(p->id);
  27874. }
  27875. Tcl_ListObjAppendElement(0, pResult, namevalue);
  27876. Tcl_ListObjAppendElement(0, pResult, Irm_NewRoidObj(p->id));
  27877. }
  27878. i = Tcl_NextHashEntry(&search);
  27879. }
  27880. Tcl_SetObjResult(interp, pResult);
  27881. return TCL_OK;
  27882. }
  27883. /* OO Method SimType count */
  27884. static int OOMethod_SimType_count(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27885.  
  27886. Tcl_HashSearch search;
  27887. Tcl_HashEntry *i;
  27888. int matchStruct[ENTITY_SEARCH_NCOUNT];
  27889. int domatch=0;
  27890. int result=0;
  27891. CurrentSim=GETSIMULATOR(thisObject);
  27892.  
  27893. if(objc>2) {
  27894. domatch=1;
  27895. if(Entity_BuildMatch(interp,objv[2],matchStruct) != TCL_OK) {
  27896. return TCL_ERROR;
  27897. }
  27898. }
  27899. for(i=SimType_First(CurrentSim,&search); i ; i = Tcl_NextHashEntry(&search)) {
  27900. Entity *p = (Entity*)Tcl_GetHashValue(i);
  27901. if(domatch) {
  27902. if(!Entity_StructMatches(p,matchStruct)) continue;
  27903. }
  27904. result++;
  27905. }
  27906. Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
  27907. return TCL_OK;
  27908. }
  27909. /* OO Method SimType create */
  27910. static int OOMethod_SimType_create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27911.  
  27912. Entity *pType;
  27913. Roid id;
  27914. if( objc!=3 ){
  27915. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  27916. return TCL_ERROR;
  27917. }
  27918. if( Irm_GetRoidFromObj(interp, objv[2], &id) ) return TCL_ERROR;
  27919. CurrentSim=GETSIMULATOR(thisObject);
  27920. pType = SimType_ById(id, 1);
  27921. Tcl_SetObjResult(interp, Irm_NewRoidObj(pType->id));
  27922. return TCL_OK;
  27923. }
  27924. /* OO Method SimType delete */
  27925. static int OOMethod_SimType_delete(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27926.  
  27927. Roid id;
  27928. Entity *p;
  27929.  
  27930. if( objc!=3 ){
  27931. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  27932. return TCL_ERROR;
  27933. }
  27934. if( Irm_GetRoidFromObj(interp, objv[2], &id) ) return TCL_ERROR;
  27935. CurrentSim=GETSIMULATOR(thisObject);
  27936. p=SimType_ById(id,0);
  27937. if(p==0 ){
  27938. return TCL_OK;
  27939. }
  27940. SimType_Unlink(p);
  27941. Entity_StructFree(p);
  27942. Odie_Free((char *)p);
  27943. return TCL_OK;
  27944. }
  27945. /* OO Method SimType exists */
  27946. static int OOMethod_SimType_exists(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27947.  
  27948. Entity *pType;
  27949. Roid id;
  27950. if( objc!=3 ){
  27951. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  27952. return TCL_ERROR;
  27953. }
  27954. CurrentSim=GETSIMULATOR(thisObject);
  27955.  
  27956. if( Irm_GetRoidFromObj(interp, objv[2], &id) ) {
  27957. Tcl_ResetResult(interp);
  27958. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  27959. return TCL_OK;
  27960. }
  27961. pType = SimType_ById(id, 0);
  27962. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(pType > 0));
  27963. return TCL_OK;
  27964. }
  27965. /* OO Method SimType for */
  27966. static int OOMethod_SimType_for(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  27967.  
  27968. Tcl_HashSearch *searchPtr;
  27969. Tcl_HashEntry *i;
  27970. int searchresult=TCL_OK;
  27971.  
  27972. Tcl_Obj *keyvar;
  27973. Tcl_Obj *infovar=NULL;
  27974. Tcl_Obj *body;
  27975.  
  27976. if( objc != 4 && objc != 5){
  27977. Tcl_WrongNumArgs(interp, 2, objv, "keyvar ?valvar? body");
  27978. return TCL_ERROR;
  27979. }
  27980. CurrentSim=GETSIMULATOR(thisObject);
  27981.  
  27982. keyvar=objv[2];
  27983. if (objc == 5) {
  27984. infovar=objv[3];
  27985. body=objv[4];
  27986. } else {
  27987. body=objv[4];
  27988. }
  27989. Tcl_IncrRefCount(keyvar);
  27990. Tcl_IncrRefCount(body);
  27991. if(infovar) {
  27992. Tcl_IncrRefCount(infovar);
  27993. }
  27994. searchresult=TCL_OK;
  27995. searchPtr=(Tcl_HashSearch *)Odie_Alloc(sizeof(Tcl_HashSearch));
  27996. for(i=SimType_First(CurrentSim,searchPtr); i ; i = Tcl_NextHashEntry(searchPtr)) {
  27997. Entity *p = (Entity *)Tcl_GetHashValue(i);
  27998. Tcl_ObjSetVar2(interp, keyvar, (Tcl_Obj *)NULL, SimType_Identify(p), 0);
  27999. if(infovar) {
  28000. Tcl_ObjSetVar2(interp, infovar, (Tcl_Obj *)NULL, Entity_StructToDict(interp,p,1), 0);
  28001. }
  28002. searchresult=Tcl_EvalObjEx(interp,body,0);
  28003. if (searchresult !=TCL_OK && searchresult!=TCL_CONTINUE) {
  28004. break;
  28005. }
  28006. }
  28007. Tcl_DecrRefCount(keyvar);
  28008. if(infovar) {
  28009. Tcl_DecrRefCount(infovar);
  28010. }
  28011. Tcl_DecrRefCount(body);
  28012. Odie_Free((char *)searchPtr);
  28013. return searchresult;
  28014. }
  28015. /* OO Method SimType foreach */
  28016. static int OOMethod_SimType_foreach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28017.  
  28018. Tcl_HashSearch *searchPtr;
  28019. Tcl_HashEntry *i;
  28020. int searchresult=TCL_OK;
  28021. Tcl_Obj *body,*matchvalues=NULL;
  28022. int matchStruct[ENTITY_SEARCH_NCOUNT];
  28023. CurrentSim=GETSIMULATOR(thisObject);
  28024.  
  28025. if( objc != 3 && objc != 4){
  28026. Tcl_WrongNumArgs(interp, 2, objv, "?matchlist? body");
  28027. return TCL_ERROR;
  28028. }
  28029. if(objc==3) {
  28030. body=objv[2];
  28031. } else {
  28032. matchvalues=objv[2];
  28033. body=objv[3];
  28034. }
  28035. if(Entity_BuildMatch(interp,matchvalues,matchStruct) != TCL_OK) {
  28036. return TCL_ERROR;
  28037. }
  28038.  
  28039. searchPtr=(Tcl_HashSearch *)Odie_Alloc(sizeof(Tcl_HashSearch));
  28040. for(i=SimType_First(CurrentSim,searchPtr); i ; i = Tcl_NextHashEntry(searchPtr)) {
  28041. Entity *p = (Entity*)Tcl_GetHashValue(i);
  28042. if(matchvalues) {
  28043. if(!Entity_StructMatches(p,matchStruct)) continue;
  28044. }
  28045. searchresult=Entity_nodeeval(interp,p,body,0);
  28046. if (searchresult !=TCL_OK && searchresult!=TCL_CONTINUE) {
  28047. Odie_Free((char *)searchPtr);
  28048. return searchresult;
  28049. }
  28050. }
  28051. Odie_Free((char *)searchPtr);
  28052. return TCL_OK;
  28053. }
  28054. /* OO Method SimType groupid */
  28055. static int OOMethod_SimType_groupid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28056.  
  28057. CurrentSim=GETSIMULATOR(thisObject);
  28058. Entity *p;
  28059. Roid groupid=0;
  28060. if( objc!=3 && objc != 4 ){
  28061. Tcl_WrongNumArgs(interp, 2, objv, "ID ?groupid?");
  28062. return TCL_ERROR;
  28063. }
  28064. if( SimType_FromTclObj(interp, objv[2], &p) ) {
  28065. Tcl_ResetResult(interp);
  28066. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  28067. return TCL_OK;
  28068. }
  28069. if(objc==4) {
  28070. if(Irm_GetRoidFromObj(interp,objv[3],&groupid)) {
  28071. return TCL_ERROR;
  28072. }
  28073. SimType_StructSetGroup(p,groupid);
  28074. }
  28075. groupid=SimType_StructGetGroup(p);
  28076. if(groupid>0) {
  28077. Tcl_SetObjResult(interp, Irm_NewRoidObj(groupid));
  28078. } else {
  28079. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  28080. }
  28081. return TCL_OK;
  28082. }
  28083. /* OO Method SimType list */
  28084. static int OOMethod_SimType_list(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28085.  
  28086. CurrentSim=GETSIMULATOR(thisObject);
  28087. Tcl_Obj *pResult = Tcl_NewObj();
  28088. Tcl_HashSearch search;
  28089. Tcl_HashEntry *i;
  28090. int matchStruct[ENTITY_SEARCH_NCOUNT];
  28091. int domatch=0;
  28092.  
  28093. if(objc==3) {
  28094. domatch=1;
  28095. if(Entity_BuildMatch(interp,objv[2],matchStruct) != TCL_OK) {
  28096. return TCL_ERROR;
  28097. }
  28098. }
  28099. for(i=SimType_First(CurrentSim,&search); i ; i = Tcl_NextHashEntry(&search)) {
  28100. Entity *p = (Entity*)Tcl_GetHashValue(i);
  28101. if(domatch) {
  28102. if(!Entity_StructMatches(p,matchStruct)) continue;
  28103. }
  28104. Tcl_ListObjAppendElement(interp, pResult, SimType_Identify(p));
  28105. }
  28106. Tcl_SetObjResult(interp, pResult);
  28107. return TCL_OK;
  28108. }
  28109. /* OO Method SimType nodeget */
  28110. static int OOMethod_SimType_nodeget(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28111.  
  28112. CurrentSim=GETSIMULATOR(thisObject);
  28113. Entity *p;
  28114. if( objc!=3 && objc != 4){
  28115. Tcl_WrongNumArgs(interp, 2, objv, "ID ?field?");
  28116. return TCL_ERROR;
  28117. }
  28118. if( SimType_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  28119.  
  28120. if(objc==4) {
  28121. Tcl_Obj *result;
  28122. int offset=-1,err,type;
  28123. err=Entity_StructValueOffset(interp, objv[3], &offset,&type);
  28124. if(err == TCL_OK ) {
  28125. result=Entity_StructGet(p,offset);
  28126. Tcl_SetObjResult(interp,result);
  28127. return TCL_OK;
  28128. }
  28129. /* Pull the value from extended dict */
  28130. result=Entity_SpecHashGet(p,objv[3],ODIE_NULL_EMPTY);
  28131. Tcl_SetObjResult(interp,result);
  28132. } else {
  28133. Tcl_SetObjResult(interp,Entity_StructToDict(interp,p,1));
  28134. }
  28135. return TCL_OK;
  28136. }
  28137. /* OO Method SimType nodeput */
  28138. static int OOMethod_SimType_nodeput(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28139.  
  28140. CurrentSim=GETSIMULATOR(thisObject);
  28141. Entity *p;
  28142. Tcl_DictSearch search;
  28143. Tcl_Obj *key, *value, *objPtr;
  28144. int done;
  28145. int offset,type,err=TCL_OK;
  28146.  
  28147. if( objc!=4 ){
  28148. Tcl_WrongNumArgs(interp, 2, objv, "ID infoDict");
  28149. return TCL_ERROR;
  28150. }
  28151.  
  28152. if( SimType_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  28153. objPtr=objv[3];
  28154. if (Tcl_DictObjFirst(interp, objPtr, &search,
  28155. &key, &value, &done) != TCL_OK) {
  28156. return TCL_ERROR;
  28157. }
  28158. for (; !done ; Tcl_DictObjNext(&search, &key, &value, &done)) {
  28159. if( Entity_StructValueOffset(interp, key, &offset, &type) == TCL_OK ) {
  28160. err=Entity_StructSet(interp,p,offset,value);
  28161. if(err != TCL_OK) {
  28162. break;
  28163. }
  28164. } else {
  28165. Entity_SpecHashPut(p,key,value);
  28166. Tcl_SetObjResult(interp, value);
  28167. }
  28168. }
  28169. Tcl_DictObjDone(&search);
  28170. if(err==TCL_OK) {
  28171. SimType_ApplySettings(p);
  28172. }
  28173. return err;
  28174. }
  28175. /* OO Method SimType nodewith */
  28176. static int OOMethod_SimType_nodewith(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28177.  
  28178. CurrentSim=GETSIMULATOR(thisObject);
  28179. Entity *p;
  28180. if( objc != 4){
  28181. Tcl_WrongNumArgs(interp, 2, objv, "ID body");
  28182. return TCL_ERROR;
  28183. }
  28184. if( SimType_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  28185. return SimType_nodeeval(interp,p,objv[3],1);
  28186. }
  28187. /* OO Method SimType normalize */
  28188. static int OOMethod_SimType_normalize(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28189.  
  28190. CurrentSim=GETSIMULATOR(thisObject);
  28191. Entity *p;
  28192. if( objc!=3 ){
  28193. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  28194. return TCL_ERROR;
  28195. }
  28196. if( SimType_FromTclObj(interp, objv[2], &p) ) {
  28197. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  28198. } else {
  28199. Tcl_SetObjResult(interp, SimType_Identify(p));
  28200. }
  28201. return TCL_OK;
  28202. }
  28203. /* OO Method SimType parent */
  28204. static int OOMethod_SimType_parent(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28205.  
  28206. CurrentSim=GETSIMULATOR(thisObject);
  28207. Entity *p;
  28208.  
  28209. if( objc!=3){
  28210. Tcl_WrongNumArgs(interp, 2, objv, "ID");
  28211. return TCL_ERROR;
  28212. }
  28213. if( SimType_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  28214. Tcl_SetObjResult(interp, Irm_NewRoidObj(p->public_parent));
  28215. return TCL_OK;
  28216. }
  28217. /* OO Method SimType setting */
  28218. static int OOMethod_SimType_setting(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28219.  
  28220. CurrentSim=GETSIMULATOR(thisObject);
  28221. int offset,type,rcode;
  28222. /* If given a new value, act like a stylized set */
  28223. Entity *p;
  28224.  
  28225. if( objc!=4 && objc!=5 ){
  28226. Tcl_WrongNumArgs(interp, 2, objv, "ID FIELD ?VALUE?");
  28227. return TCL_ERROR;
  28228. }
  28229. if( SimType_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  28230.  
  28231. if(objc == 5) {
  28232. if( Entity_StructValueOffset(interp, objv[3], &offset, &type) == TCL_OK ) {
  28233. rcode=Entity_StructSet(interp,p,offset,objv[4]);
  28234. return rcode;
  28235. }
  28236. rcode=Entity_SetFromObj(interp,p,objv[3],objv[4]);
  28237. return rcode;
  28238. } else {
  28239. Tcl_Obj *result;
  28240. int offset=-1,err,type;
  28241. err=Entity_StructValueOffset(interp, objv[3], &offset,&type);
  28242. if(err == TCL_OK ) {
  28243. result=Entity_StructGet(p,offset);
  28244. Tcl_SetObjResult(interp,result);
  28245. return TCL_OK;
  28246. }
  28247. /* Pull the value from extended dict */
  28248. result=Entity_ExportField(p->pType,p->infoDict,Tcl_GetString(objv[3]),ODIE_NULL_ZERO);
  28249. Tcl_SetObjResult(interp,result);
  28250. return TCL_OK;
  28251. }
  28252. }
  28253. /* OO Method SimType spec_get */
  28254. static int OOMethod_SimType_spec_get(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28255.  
  28256. CurrentSim=GETSIMULATOR(thisObject);
  28257. Entity *p;
  28258. Tcl_Obj *pResult=NULL;
  28259. if( objc!=3 && objc != 4){
  28260. Tcl_WrongNumArgs(interp, 2, objv, "ID ?field?");
  28261. return TCL_ERROR;
  28262. }
  28263. if( SimType_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  28264. if(objc==3) {
  28265. /* Pull the value from extended dict */
  28266. pResult=Entity_SpecHashGet(p,objv[3],ODIE_NULL_EMPTY);
  28267. } else {
  28268. pResult=Entity_GetDict(p->pType,p->infoDict);
  28269. }
  28270. if(pResult) {
  28271. Tcl_SetObjResult(interp,pResult);
  28272. }
  28273. return TCL_OK;
  28274. }
  28275. /* OO Method SimType spec_put */
  28276. static int OOMethod_SimType_spec_put(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28277.  
  28278. CurrentSim=GETSIMULATOR(thisObject);
  28279. Entity *p;
  28280. Tcl_DictSearch search;
  28281. Tcl_Obj *key, *value, *objPtr;
  28282. int done;
  28283.  
  28284. if( objc!=4 ){
  28285. Tcl_WrongNumArgs(interp, 2, objv, "ID infoDict");
  28286. return TCL_ERROR;
  28287. }
  28288.  
  28289. if( SimType_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  28290. objPtr=objv[3];
  28291. if (Tcl_DictObjFirst(interp, objPtr, &search,
  28292. &key, &value, &done) != TCL_OK) {
  28293. return TCL_ERROR;
  28294. }
  28295. for (; !done ; Tcl_DictObjNext(&search, &key, &value, &done)) {
  28296. Entity_SpecHashPut(p,key,value);
  28297. Tcl_SetObjResult(interp, value);
  28298. }
  28299. Tcl_DictObjDone(&search);
  28300. return TCL_OK;
  28301. }
  28302. /* OO Method SimType spec_replace */
  28303. static int OOMethod_SimType_spec_replace(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28304.  
  28305. CurrentSim=GETSIMULATOR(thisObject);
  28306. Entity *p;
  28307. Tcl_DictSearch search;
  28308. Tcl_Obj *key, *value, *objPtr;
  28309. int done;
  28310.  
  28311. if( objc!=4 ){
  28312. Tcl_WrongNumArgs(interp, 2, objv, "ID infoDict");
  28313. return TCL_ERROR;
  28314. }
  28315.  
  28316. if( SimType_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  28317.  
  28318. objPtr=objv[3];
  28319. if (Tcl_DictObjFirst(interp, objPtr, &search,
  28320. &key, &value, &done) != TCL_OK) {
  28321. return TCL_ERROR;
  28322. }
  28323. Entity_SpecHashClear(p);
  28324. for (; !done ; Tcl_DictObjNext(&search, &key, &value, &done)) {
  28325. Entity_SpecHashPut(p,key,value);
  28326. Tcl_SetObjResult(interp, value);
  28327. }
  28328. Tcl_DictObjDone(&search);
  28329. return TCL_OK;
  28330. }
  28331. /* OO Method SimType struct_get */
  28332. static int OOMethod_SimType_struct_get(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28333.  
  28334. CurrentSim=GETSIMULATOR(thisObject);
  28335. Entity *p;
  28336. if( objc!=3 && objc != 4){
  28337. Tcl_WrongNumArgs(interp, 2, objv, "ID ?field?");
  28338. return TCL_ERROR;
  28339. }
  28340. if( SimType_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  28341.  
  28342. if(objc==4) {
  28343. Tcl_Obj *result;
  28344. int offset=-1,err,type;
  28345. err=Entity_StructValueOffset(interp, objv[3], &offset,&type);
  28346. if(err == TCL_OK ) {
  28347. result=Entity_StructGet(p,offset);
  28348. Tcl_SetObjResult(interp,result);
  28349. return TCL_OK;
  28350. }
  28351. return TCL_ERROR;
  28352. } else {
  28353. Tcl_SetObjResult(interp,Entity_StructToDict(interp,p,0));
  28354. }
  28355. return TCL_OK;
  28356. }
  28357. /* OO Method SimType struct_put */
  28358. static int OOMethod_SimType_struct_put(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28359.  
  28360. CurrentSim=GETSIMULATOR(thisObject);
  28361. Entity *p;
  28362. Tcl_DictSearch search;
  28363. int done;
  28364. int offset,type,err=TCL_OK;
  28365.  
  28366. if( objc!=4 && objc!=5 ){
  28367. Tcl_WrongNumArgs(interp, 2, objv, "ID infoDict");
  28368. return TCL_ERROR;
  28369. }
  28370.  
  28371. if( SimType_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  28372. if(objc==5) {
  28373. if( Entity_StructValueOffset(interp, objv[3], &offset, &type) == TCL_OK ) {
  28374. err=Entity_StructSet(interp,p,offset,objv[4]);
  28375. if(err != TCL_OK) {
  28376. return TCL_ERROR;
  28377. }
  28378. } else {
  28379. return TCL_ERROR;
  28380. }
  28381. } else {
  28382. Tcl_Obj *key, *value;
  28383. Tcl_Obj *objPtr=objv[3];
  28384. if (Tcl_DictObjFirst(interp, objPtr, &search,
  28385. &key, &value, &done) != TCL_OK) {
  28386. return TCL_ERROR;
  28387. }
  28388. for (; !done ; Tcl_DictObjNext(&search, &key, &value, &done)) {
  28389. if( Entity_StructValueOffset(interp, key, &offset, &type) == TCL_OK ) {
  28390. err=Entity_StructSet(interp,p,offset,value);
  28391. if(err != TCL_OK) {
  28392. break;
  28393. }
  28394. } else {
  28395. return TCL_ERROR;
  28396. }
  28397. }
  28398. Tcl_DictObjDone(&search);
  28399. }
  28400. if(err==TCL_OK) {
  28401. SimType_ApplySettings(p);
  28402. }
  28403. return err;
  28404. }
  28405. /* OO Method SimType type */
  28406. static int OOMethod_SimType_type(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28407.  
  28408. CurrentSim=GETSIMULATOR(thisObject);
  28409. Entity *p;
  28410. Entity *pType;
  28411. if( objc != 3 && objc != 4 ){
  28412. Tcl_WrongNumArgs(interp, 2, objv, "NODEID field");
  28413. return TCL_ERROR;
  28414. }
  28415. if( SimType_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  28416. pType=SimType_StructGetType(p);
  28417. if(!pType) {
  28418. if(objc==3) {
  28419. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  28420. }
  28421. return TCL_OK;
  28422. }
  28423. if(objc==3) {
  28424. Tcl_SetObjResult(interp, SimType_Identify(pType));
  28425. }
  28426. if(objc==4) {
  28427. Tcl_Obj *pResult;
  28428. pResult=Entity_ExportField(pType,NULL,Tcl_GetString(objv[3]),ODIE_NULL_EMPTY);
  28429. Tcl_SetObjResult(interp,pResult);
  28430. }
  28431. return TCL_OK;
  28432. }
  28433. /* OO Method SimType typeid */
  28434. static int OOMethod_SimType_typeid(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28435.  
  28436. CurrentSim=GETSIMULATOR(thisObject);
  28437. Entity *p;
  28438. Entity *pType;
  28439. if( objc!=3 && objc != 4 ){
  28440. Tcl_WrongNumArgs(interp, 2, objv, "ID ?typeid?");
  28441. return TCL_ERROR;
  28442. }
  28443. if( SimType_FromTclObj(interp, objv[2], &p) ) return TCL_ERROR;
  28444. if(objc==3) {
  28445. if( SimType_FromTclObj(interp, objv[3], &pType) ) {
  28446. /* Translate a ZERO length list to null */
  28447. int len;
  28448. if(Tcl_ListObjLength(NULL,objv[3],&len)) {
  28449. return TCL_ERROR;
  28450. }
  28451. if(len) {
  28452. int intval;
  28453. if(Tcl_GetIntFromObj(NULL,objv[3],&intval)==TCL_ERROR) {
  28454. return TCL_ERROR;
  28455. }
  28456. if(intval>0) {
  28457. return TCL_ERROR;
  28458. }
  28459. }
  28460. Tcl_ResetResult(interp);
  28461. pType=NULL;
  28462. }
  28463. SimType_StructSetType(p,pType);
  28464. /* Reset the group pointer so it's recalculated */
  28465. SimType_StructSetGroup(p,-1);
  28466. }
  28467. pType=SimType_StructGetType(p);
  28468. if(pType) {
  28469. Tcl_SetObjResult(interp, SimType_Identify(pType));
  28470. } else {
  28471. Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
  28472. }
  28473. return TCL_OK;
  28474. }
  28475. /* OO Method SimType visible_reset */
  28476. static int OOMethod_SimType_visible_reset(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28477.  
  28478. CurrentSim=GETSIMULATOR(thisObject);
  28479. Tcl_HashSearch *searchPtr;
  28480. Tcl_HashEntry *i;
  28481. searchPtr=(Tcl_HashSearch *)Odie_Alloc(sizeof(Tcl_HashSearch));
  28482. for(i=SimType_First(CurrentSim,searchPtr); i ; i = Tcl_NextHashEntry(searchPtr)) {
  28483. Entity *p = (Entity*)Tcl_GetHashValue(i);
  28484. p->public_visible=0;
  28485. p->public_hidden=0;
  28486. p->public_active=0;
  28487. p->public_oncount=0;
  28488. p->public_drawn=0;
  28489. }
  28490. Odie_Free((char *)searchPtr);
  28491. return TCL_OK;
  28492. }
  28493. /* OO Method SimType witheach */
  28494. static int OOMethod_SimType_witheach(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv) {Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
  28495.  
  28496. CurrentSim=GETSIMULATOR(thisObject);
  28497.  
  28498. Tcl_HashSearch *searchPtr;
  28499. Tcl_HashEntry *i;
  28500. int searchresult=TCL_OK;
  28501. Tcl_Obj *body,*matchvalues=NULL;
  28502. int matchStruct[ENTITY_SEARCH_NCOUNT];
  28503.  
  28504. if( objc != 3 && objc != 4){
  28505. Tcl_WrongNumArgs(interp, 2, objv, "?matchlist? body");
  28506. return TCL_ERROR;
  28507. }
  28508. if(objc==3) {
  28509. body=objv[2];
  28510. } else {
  28511. matchvalues=objv[2];
  28512. body=objv[3];
  28513. }
  28514. if(Entity_BuildMatch(interp,matchvalues,matchStruct) != TCL_OK) {
  28515. return TCL_ERROR;
  28516. }
  28517.  
  28518. searchPtr=(Tcl_HashSearch *)Odie_Alloc(sizeof(Tcl_HashSearch));
  28519. for(i=SimType_First(CurrentSim,searchPtr); i ; i = Tcl_NextHashEntry(searchPtr)) {
  28520. Entity *p = (Entity*)Tcl_GetHashValue(i);
  28521. if(matchvalues) {
  28522. if(!Entity_StructMatches(p,matchStruct)) continue;
  28523. }
  28524. searchresult=Entity_nodeeval(interp,p,body,1);
  28525. if (searchresult !=TCL_OK && searchresult!=TCL_CONTINUE) {
  28526. Odie_Free((char *)searchPtr);
  28527. return searchresult;
  28528. }
  28529. }
  28530. Odie_Free((char *)searchPtr);
  28531. return TCL_OK;
  28532. }
  28533. /* Loader for SimType */
  28534. static int SimType_OO_Init(Tcl_Interp *interp) {
  28535. /*
  28536. ** Build the "::odielib::simtype" class
  28537. */
  28538. Tcl_Obj* nameObj; /* Name of a class or method being looked up */
  28539. Tcl_Object curClassObject; /* Tcl_Object representing the current class */
  28540. Tcl_Class curClass; /* Tcl_Class representing the current class */
  28541.  
  28542. /*
  28543. * Find the "::odielib::simtype" class, and attach an 'init' method to it.
  28544. */
  28545.  
  28546. nameObj = Tcl_NewStringObj("::odielib::simtype", -1);
  28547. Tcl_IncrRefCount(nameObj);
  28548. if ((curClassObject = Tcl_GetObjectFromObj(interp, nameObj)) == NULL) {
  28549. Tcl_DecrRefCount(nameObj);
  28550. return TCL_ERROR;
  28551. }
  28552. Tcl_DecrRefCount(nameObj);
  28553. curClass = Tcl_GetObjectAsClass(curClassObject);
  28554. nameObj=Tcl_NewStringObj("C_Init",-1);
  28555. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_C_Init, (ClientData) NULL);
  28556. Tcl_DecrRefCount(nameObj);
  28557. nameObj=Tcl_NewStringObj("children",-1);
  28558. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_children, (ClientData) NULL);
  28559. Tcl_DecrRefCount(nameObj);
  28560. nameObj=Tcl_NewStringObj("count",-1);
  28561. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_count, (ClientData) NULL);
  28562. Tcl_DecrRefCount(nameObj);
  28563. nameObj=Tcl_NewStringObj("create",-1);
  28564. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_create, (ClientData) NULL);
  28565. Tcl_DecrRefCount(nameObj);
  28566. nameObj=Tcl_NewStringObj("delete",-1);
  28567. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_delete, (ClientData) NULL);
  28568. Tcl_DecrRefCount(nameObj);
  28569. nameObj=Tcl_NewStringObj("exists",-1);
  28570. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_exists, (ClientData) NULL);
  28571. Tcl_DecrRefCount(nameObj);
  28572. nameObj=Tcl_NewStringObj("for",-1);
  28573. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_for, (ClientData) NULL);
  28574. Tcl_DecrRefCount(nameObj);
  28575. nameObj=Tcl_NewStringObj("foreach",-1);
  28576. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_foreach, (ClientData) NULL);
  28577. Tcl_DecrRefCount(nameObj);
  28578. nameObj=Tcl_NewStringObj("groupid",-1);
  28579. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_groupid, (ClientData) NULL);
  28580. Tcl_DecrRefCount(nameObj);
  28581. nameObj=Tcl_NewStringObj("list",-1);
  28582. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_list, (ClientData) NULL);
  28583. Tcl_DecrRefCount(nameObj);
  28584. nameObj=Tcl_NewStringObj("nodeget",-1);
  28585. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_nodeget, (ClientData) NULL);
  28586. Tcl_DecrRefCount(nameObj);
  28587. nameObj=Tcl_NewStringObj("nodeput",-1);
  28588. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_nodeput, (ClientData) NULL);
  28589. Tcl_DecrRefCount(nameObj);
  28590. nameObj=Tcl_NewStringObj("nodewith",-1);
  28591. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_nodewith, (ClientData) NULL);
  28592. Tcl_DecrRefCount(nameObj);
  28593. nameObj=Tcl_NewStringObj("normalize",-1);
  28594. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_normalize, (ClientData) NULL);
  28595. Tcl_DecrRefCount(nameObj);
  28596. nameObj=Tcl_NewStringObj("parent",-1);
  28597. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_parent, (ClientData) NULL);
  28598. Tcl_DecrRefCount(nameObj);
  28599. nameObj=Tcl_NewStringObj("setting",-1);
  28600. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_setting, (ClientData) NULL);
  28601. Tcl_DecrRefCount(nameObj);
  28602. nameObj=Tcl_NewStringObj("spec_get",-1);
  28603. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_spec_get, (ClientData) NULL);
  28604. Tcl_DecrRefCount(nameObj);
  28605. nameObj=Tcl_NewStringObj("spec_put",-1);
  28606. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_spec_put, (ClientData) NULL);
  28607. Tcl_DecrRefCount(nameObj);
  28608. nameObj=Tcl_NewStringObj("spec_replace",-1);
  28609. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_spec_replace, (ClientData) NULL);
  28610. Tcl_DecrRefCount(nameObj);
  28611. nameObj=Tcl_NewStringObj("struct_get",-1);
  28612. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_struct_get, (ClientData) NULL);
  28613. Tcl_DecrRefCount(nameObj);
  28614. nameObj=Tcl_NewStringObj("struct_put",-1);
  28615. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_struct_put, (ClientData) NULL);
  28616. Tcl_DecrRefCount(nameObj);
  28617. nameObj=Tcl_NewStringObj("type",-1);
  28618. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_type, (ClientData) NULL);
  28619. Tcl_DecrRefCount(nameObj);
  28620. nameObj=Tcl_NewStringObj("typeid",-1);
  28621. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_typeid, (ClientData) NULL);
  28622. Tcl_DecrRefCount(nameObj);
  28623. nameObj=Tcl_NewStringObj("visible_reset",-1);
  28624. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_visible_reset, (ClientData) NULL);
  28625. Tcl_DecrRefCount(nameObj);
  28626. nameObj=Tcl_NewStringObj("witheach",-1);
  28627. Tcl_NewMethod(interp, curClass, nameObj, 1, &OOMethodType_SimType_witheach, (ClientData) NULL);
  28628. Tcl_DecrRefCount(nameObj);
  28629. return TCL_OK;
  28630. }
  28631. /* END generate-cfile-tclapi */
  28632.  
  28633. extern int DLLEXPORT Odielibc_Init( Tcl_Interp *interp ) {
  28634. /* Initialise the stubs tables. */
  28635. #ifdef USE_TCL_STUBS
  28636. if (Tcl_InitStubs(interp, "8.6", 0)==NULL) return TCL_ERROR;
  28637. if (TclOOInitializeStubs(interp, "1.0") == NULL) return TCL_ERROR;
  28638. #endif
  28639. if(interp) {
  28640. if(Tcl_Eval(interp,
  28641. "\n" \
  28642. "# BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygon.tcl\n" \
  28643. "namespace eval ::polygon {}\n" \
  28644. "###\n" \
  28645. "# Decompose a concave polygon into a set of convex polygons\n" \
  28646. "###\n" \
  28647. "proc ::polygon::convex_decompose POLY {\n" \
  28648. " if {[is_convex $POLY]} {\n" \
  28649. " return [list $POLY]\n" \
  28650. " }\n" \
  28651. " set SEGMENTS [::odielib::segset new]\n" \
  28652. " $SEGMENTS polygon_add 1 $POLY\n" \
  28653. " $SEGMENTS make_convex\n" \
  28654. " set result [$SEGMENTS polygons]\n" \
  28655. " $SEGMENTS destroy\n" \
  28656. " return $result\n" \
  28657. "}\n" \
  28658. "\n" \
  28659. "proc ::polygon::set_union args {\n" \
  28660. " set SEGMENTS [::odielib::segset new]\n" \
  28661. " set polycount 0\n" \
  28662. " foreach poly $args {\n" \
  28663. " incr polycount\n" \
  28664. " set POLYGONS($polycount) $poly\n" \
  28665. " $SEGMENTS polygon_add $polycount $POLYGONS($polycount)\n" \
  28666. " }\n" \
  28667. " set cleanup [$SEGMENTS cleanup]\n" \
  28668. " set cleanup [$SEGMENTS cleanup]\n" \
  28669. " set connections {}\n" \
  28670. " set newseg {}\n" \
  28671. " for {set i 1} {$i <= $polycount} {incr i} {\n" \
  28672. " set COORDS [coords $POLYGONS($i)]\n" \
  28673. " for {set j 1} {$j <= $polycount} {incr j} {\n" \
  28674. " if {$i==$j} continue\n" \
  28675. " foreach vertex $COORDS {\n" \
  28676. " if {$vertex in $connections} continue\n" \
  28677. " set within [within $vertex $POLYGONS($j)]\n" \
  28678. " if {$within>0} {\n" \
  28679. " set connection [$SEGMENTS edge_connection $vertex $j]\n" \
  28680. " if {![::vector::is_null $connection]} {\n" \
  28681. " lappend newseg $vertex $connection\n" \
  28682. " lappend connections $vertex\n" \
  28683. " }\n" \
  28684. " }\n" \
  28685. " }\n" \
  28686. " }\n" \
  28687. " }\n" \
  28688. " foreach {v c} $newseg {\n" \
  28689. " $SEGMENTS segment_add_virtual $v $c\n" \
  28690. " }\n" \
  28691. " $SEGMENTS make_convex\n" \
  28692. " set result [$SEGMENTS polygons]\n" \
  28693. " $SEGMENTS destroy\n" \
  28694. " return $result\n" \
  28695. "}\n" \
  28696. "\n" \
  28697. "proc ::polygon::set_intersection {UNION args} {\n" \
  28698. " set result {}\n" \
  28699. " set id 0\n" \
  28700. " set result {}\n" \
  28701. " foreach poly $UNION {\n" \
  28702. " set match 1\n" \
  28703. " set center [center $poly]\n" \
  28704. " foreach ipoly $args {\n" \
  28705. " if {[within {*}[::vectorxy::flatten $center] $ipoly]<0} {\n" \
  28706. " set match 0\n" \
  28707. " break\n" \
  28708. " }\n" \
  28709. " }\n" \
  28710. " if {$match} {\n" \
  28711. " lappend result $poly\n" \
  28712. " }\n" \
  28713. " }\n" \
  28714. " return $result\n" \
  28715. "}\n" \
  28716. "\n" \
  28717. "proc ::polygon::set_difference {UNION args} {\n" \
  28718. " set result {}\n" \
  28719. " set id 0\n" \
  28720. " set result {}\n" \
  28721. " foreach poly $UNION {\n" \
  28722. " set match 1\n" \
  28723. " set center [center $poly]\n" \
  28724. " foreach ipoly $args {\n" \
  28725. " if {[within {*}[vectorxy::flatten $center] $ipoly]>=0} {\n" \
  28726. " set match 0\n" \
  28727. " break\n" \
  28728. " }\n" \
  28729. " }\n" \
  28730. " if {$match} {\n" \
  28731. " lappend result $poly\n" \
  28732. " }\n" \
  28733. " }\n" \
  28734. " return $result\n" \
  28735. "}\n" \
  28736. "\n" \
  28737. "proc ::polygon::within_concave {A POLY} {\n" \
  28738. " if {[is_convex $POLY]} {\n" \
  28739. " return [within {*}[vectorxy::flatten $A] $POLY]\n" \
  28740. " }\n" \
  28741. " set polylist [convex_decompose $POLY]\n" \
  28742. " return [within {*}[vectorxy::flatten $A] {*}$polylist]\n" \
  28743. "}\n" \
  28744. "# END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygon.tcl\n" \
  28745. "# BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygonxyz.tcl\n" \
  28746. "namespace eval ::polygonxyz {}\n" \
  28747. "###\n" \
  28748. "# Decompose a concave polygon into a set of convex polygons\n" \
  28749. "###\n" \
  28750. "proc ::polygonxyz::convex_decompose POLY {\n" \
  28751. " if {[is_convex $POLY]} {\n" \
  28752. " return [list $POLY]\n" \
  28753. " }\n" \
  28754. " set SEGMENTS [::odielib::segset new]\n" \
  28755. " $SEGMENTS uv_transform polygon $POLY\n" \
  28756. " $SEGMENTS polygon_add 1 $POLY\n" \
  28757. " $SEGMENTS make_convex\n" \
  28758. " set result [$SEGMENTS polygons]\n" \
  28759. " $SEGMENTS destroy\n" \
  28760. " return $result\n" \
  28761. "}\n" \
  28762. "\n" \
  28763. "proc ::polygonxyz::set_union args {\n" \
  28764. " set SEGMENTS [::odielib::segset new]\n" \
  28765. " $SEGMENTS uv_transform polygon [lindex $args 0]\n" \
  28766. " set polycount 0\n" \
  28767. " foreach poly $args {\n" \
  28768. " incr polycount\n" \
  28769. " set POLYGONS($polycount) $poly\n" \
  28770. " $SEGMENTS polygon_add $polycount $POLYGONS($polycount)\n" \
  28771. " }\n" \
  28772. " set cleanup [$SEGMENTS cleanup]\n" \
  28773. " set cleanup [$SEGMENTS cleanup]\n" \
  28774. " set connections {}\n" \
  28775. " set newseg {}\n" \
  28776. " for {set i 1} {$i <= $polycount} {incr i} {\n" \
  28777. " set COORDS [coords $POLYGONS($i)]\n" \
  28778. " for {set j 1} {$j <= $polycount} {incr j} {\n" \
  28779. " if {$i==$j} continue\n" \
  28780. " foreach vertex $COORDS {\n" \
  28781. " if {$vertex in $connections} continue\n" \
  28782. " set within [within $vertex $POLYGONS($j)]\n" \
  28783. " if {$within>0} {\n" \
  28784. " set connection [$SEGMENTS edge_connection $vertex $j]\n" \
  28785. " if {![::vector::is_null $connection]} {\n" \
  28786. " lappend newseg $vertex $connection\n" \
  28787. " lappend connections $vertex\n" \
  28788. " }\n" \
  28789. " }\n" \
  28790. " }\n" \
  28791. " }\n" \
  28792. " }\n" \
  28793. " foreach {v c} $newseg {\n" \
  28794. " $SEGMENTS segment_add_virtual $v $c\n" \
  28795. " }\n" \
  28796. " $SEGMENTS make_convex\n" \
  28797. " set result [$SEGMENTS polygons]\n" \
  28798. " $SEGMENTS destroy\n" \
  28799. " return $result\n" \
  28800. "}\n" \
  28801. "\n" \
  28802. "proc ::polygonxyz::set_intersection {UNION args} {\n" \
  28803. " set result {}\n" \
  28804. " set id 0\n" \
  28805. " set result {}\n" \
  28806. " foreach poly $UNION {\n" \
  28807. " set match 1\n" \
  28808. " set center [center $poly]\n" \
  28809. " foreach ipoly $args {\n" \
  28810. " if {[within $center $ipoly]<0} {\n" \
  28811. " set match 0\n" \
  28812. " break\n" \
  28813. " }\n" \
  28814. " }\n" \
  28815. " if {$match} {\n" \
  28816. " lappend result $poly\n" \
  28817. " }\n" \
  28818. " }\n" \
  28819. " return $result\n" \
  28820. "}\n" \
  28821. "\n" \
  28822. "proc ::polygonxyz::set_difference {UNION args} {\n" \
  28823. " set result {}\n" \
  28824. " set id 0\n" \
  28825. " set result {}\n" \
  28826. " foreach poly $UNION {\n" \
  28827. " set match 1\n" \
  28828. " set center [center $poly]\n" \
  28829. " foreach ipoly $args {\n" \
  28830. " if {[within $center $ipoly]>=0} {\n" \
  28831. " set match 0\n" \
  28832. " break\n" \
  28833. " }\n" \
  28834. " }\n" \
  28835. " if {$match} {\n" \
  28836. " lappend result $poly\n" \
  28837. " }\n" \
  28838. " }\n" \
  28839. " return $result\n" \
  28840. "}\n" \
  28841. "\n" \
  28842. "proc ::polygonxyz::within_concave {A POLY} {\n" \
  28843. " if {[is_convex $POLY]} {\n" \
  28844. " return [within $A $POLY]\n" \
  28845. " }\n" \
  28846. " set polylist [convex_decompose $POLY]\n" \
  28847. " return [within_set $A {*}$polylist]\n" \
  28848. "}\n" \
  28849. "# END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygonxyz.tcl\n" \
  28850. "# BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/segset.tcl\n" \
  28851. "if {[info command ::odielib::segset] eq {}} {\n" \
  28852. "::oo::class create ::odielib::segset {\n" \
  28853. " constructor {} {\n" \
  28854. " my SegmentSet_Init\n" \
  28855. " }\n" \
  28856. "\n" \
  28857. " method fix_coincident {} {\n" \
  28858. " set fixes 0\n" \
  28859. " for {set count 0} {$count < 1000} {incr count} {\n" \
  28860. " my modified 0\n" \
  28861. " foreach problem [my check_coincident] {\n" \
  28862. " my vertex_add [dict get $problem intercept1:] [dict get $problem intercept2:]\n" \
  28863. " }\n" \
  28864. " if {![my modified]} break\n" \
  28865. " incr fixes\n" \
  28866. " }\n" \
  28867. " return $fixes\n" \
  28868. " }\n" \
  28869. "\n" \
  28870. " # Break up oblique angles\n" \
  28871. " method make_convex {} {\n" \
  28872. " set newseg 0\n" \
  28873. " my fix_coincident\n" \
  28874. " for {set count 0} {$count < 128} {incr count} {\n" \
  28875. " my modified 0\n" \
  28876. " foreach {vertex connection} [my check_oblique] {\n" \
  28877. " set c [my segment_add_virtual $vertex $connection]\n" \
  28878. " incr newseg $c\n" \
  28879. " }\n" \
  28880. " if {![my modified]} break\n" \
  28881. " }\n" \
  28882. " return $newseg\n" \
  28883. " }\n" \
  28884. "}\n" \
  28885. "}\n" \
  28886. "# END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/segset.tcl\n" \
  28887. "# BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/plotter.tcl\n" \
  28888. "if {[info command ::odielib::plotter] eq {}} {\n" \
  28889. "::oo::class create ::odielib::plotter {\n" \
  28890. "}\n" \
  28891. "}\n" \
  28892. "proc ::plotter name {\n" \
  28893. " ::odielib::plotter create $name\n" \
  28894. "}\n" \
  28895. "# END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/plotter.tcl\n" \
  28896. "# BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/slicer.tcl\n" \
  28897. "if {[info command ::odielib::slicer] eq {}} {\n" \
  28898. "::oo::class create ::odielib::slicer {\n" \
  28899. " superclass ::odielib::plotter\n" \
  28900. "\n" \
  28901. " constructor {} {\n" \
  28902. " my Slicer_Init\n" \
  28903. " }\n" \
  28904. "}\n" \
  28905. "}\n" \
  28906. "\n" \
  28907. "proc ::slicer name {\n" \
  28908. " ::odielib::slicer create $name\n" \
  28909. " return $name\n" \
  28910. "}\n" \
  28911. "# END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/slicer.tcl\n" \
  28912. "# BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/wallset.tcl\n" \
  28913. "if {[info command ::odielib::wallset] eq {}} {\n" \
  28914. "::oo::class create ::odielib::wallset {\n" \
  28915. "}\n" \
  28916. "}\n" \
  28917. "\n" \
  28918. "proc ::wallset name {\n" \
  28919. " return [::odielib::wallset create $name]\n" \
  28920. "}\n" \
  28921. "# END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/wallset.tcl\n" \
  28922. "# BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/faceset.tcl\n" \
  28923. "if {[info command ::odielib::polygonhull] eq {}} {\n" \
  28924. "::oo::class create ::odielib::polygonhull {\n" \
  28925. " constructor {} {\n" \
  28926. " my PolygonHull_Init\n" \
  28927. " }\n" \
  28928. "\n" \
  28929. " method SimplifyStep {} {\n" \
  28930. " puts [list SimplifyStep]\n" \
  28931. " set vol_list [my volume_list]\n" \
  28932. " foreach vid $vol_list {\n" \
  28933. " if {$vid<=0} continue\n" \
  28934. " set volume_center($vid) [my volume_center $vid]\n" \
  28935. " }\n" \
  28936. " set changes 0\n" \
  28937. " set face_list [lsort -integer [my face_list]]\n" \
  28938. " set face_mod {}\n" \
  28939. " foreach id $face_list {\n" \
  28940. " set facepolygon($id) [my face_polygon $id]\n" \
  28941. " set facesides($id) [my face_volume $id]\n" \
  28942. " }\n" \
  28943. " ###\n" \
  28944. " # WHY IS THIS AN INFINITE LOOP?!?!?\n" \
  28945. " ###\n" \
  28946. " foreach i $face_list {\n" \
  28947. " foreach j $face_list {\n" \
  28948. " #if {$j>=$i} continue\n" \
  28949. " if {![::polygon::coplaner $facepolygon($i) $facepolygon($j)]} continue\n" \
  28950. "\n" \
  28951. " set union [::polygon::union $facepolygon($i) $facepolygon($j)]\n" \
  28952. " set intersect [::polygon::intersection $union $facepolygon($i) $facepolygon($j)]\n" \
  28953. " if {![llength $intersect]} continue\n" \
  28954. " incr changes\n" \
  28955. " lappend face_mod $i $j\n" \
  28956. " my face_delete $i\n" \
  28957. " my face_delete $j\n" \
  28958. " set vola [lindex $facesides($i) 1]\n" \
  28959. " set volb [lindex $facesides($j) 1]\n" \
  28960. " foreach poly $intersect {\n" \
  28961. " set id [my face_create $i {*}[::polygon::coords $poly]]\n" \
  28962. " if {$vola>0} {\n" \
  28963. " set sidea [my face_side $id $volume_center($vola)]\n" \
  28964. " my face_volume $id $sidea $vola\n" \
  28965. " }\n" \
  28966. " if {$volb>0} {\n" \
  28967. " set sideb [my face_side $id $volume_center($volb)]\n" \
  28968. " my face_volume $id $sideb $volb\n" \
  28969. " }\n" \
  28970. " }\n" \
  28971. " foreach poly [::polygon::clip $union $facepolygon($i) $facepolygon($j)] {\n" \
  28972. " set id [my face_create -1 {*}[::polygon::coords $poly]]\n" \
  28973. " if {$vola>0} {\n" \
  28974. " set side [my face_side $id $volume_center($vola)]\n" \
  28975. " my face_volume $id $side $vola\n" \
  28976. " }\n" \
  28977. " }\n" \
  28978. " foreach poly [::polygon::clip $union $facepolygon($j) $facepolygon($i)] {\n" \
  28979. " set id [my face_create -1 {*}[::polygon::coords $poly]]\n" \
  28980. " if {$volb>0} {\n" \
  28981. " set side [my face_side $id $volume_center($volb)]\n" \
  28982. " my face_volume $id $side $volb\n" \
  28983. " }\n" \
  28984. " }\n" \
  28985. " return 1\n" \
  28986. " }\n" \
  28987. " }\n" \
  28988. " return $changes\n" \
  28989. " }\n" \
  28990. "\n" \
  28991. " method simplify {} {\n" \
  28992. " puts [list [self] simplify]\n" \
  28993. " set changes 1\n" \
  28994. " set count 0\n" \
  28995. " while {$changes>0} {\n" \
  28996. " if {[incr count]>1000} {\n" \
  28997. " error \"Infinite loop\"\n" \
  28998. " }\n" \
  28999. " set changes [my SimplifyStep]\n" \
  29000. " puts [list [self] simplify $count $changes]\n" \
  29001. " }\n" \
  29002. " }\n" \
  29003. "}\n" \
  29004. "}\n" \
  29005. "# END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/faceset.tcl\n" \
  29006. "# BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simulator.tcl\n" \
  29007. "if {[info command ::odielib::simulator] eq {}} {\n" \
  29008. "::oo::class create ::odielib::simulator {\n" \
  29009. " constructor {} {\n" \
  29010. " my C_Init\n" \
  29011. " }\n" \
  29012. "}\n" \
  29013. "}\n" \
  29014. "if {[info command ::odielib::entity] eq {}} {\n" \
  29015. "::oo::class create ::odielib::entity {\n" \
  29016. " constructor {simulatorObj} {\n" \
  29017. " my C_Init $simulatorObj\n" \
  29018. " }\n" \
  29019. "}\n" \
  29020. "}\n" \
  29021. "if {[info command ::odielib::simtype] eq {}} {\n" \
  29022. "::oo::class create ::odielib::simtype {\n" \
  29023. " constructor {simulatorObj} {\n" \
  29024. " my C_Init $simulatorObj\n" \
  29025. " }\n" \
  29026. "}\n" \
  29027. "}\n" \
  29028. "# END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simulator.tcl\n" \
  29029. "\n" )) return TCL_ERROR;
  29030. }
  29031. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/odieutil/md5.c */
  29032. if(Md5_Init(interp)!=TCL_OK) return TCL_ERROR;
  29033. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/odieutil/md5.c */
  29034. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/odieutil/tclextra.c */
  29035. if(TclExtra_Init(interp)!=TCL_OK) return TCL_ERROR;
  29036. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/odieutil/tclextra.c */
  29037. if(Rc4_Init(interp)) return TCL_ERROR;
  29038. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/odiemath/odiemath.tcl */
  29039. {
  29040. Tcl_Namespace *modPtr;
  29041. modPtr=Tcl_FindNamespace(interp,"::odiemath",NULL,TCL_NAMESPACE_ONLY);
  29042. if(!modPtr) {
  29043. modPtr = Tcl_CreateNamespace(interp, "::odiemath", NULL, NULL);
  29044. }
  29045. }
  29046. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::const",-1),Tcl_NewStringObj("1_pi",-1),Tcl_NewDoubleObj(M_1_PI),TCL_GLOBAL_ONLY);
  29047. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::M_1_PI",-1),NULL,Tcl_NewDoubleObj(M_1_PI),TCL_GLOBAL_ONLY);
  29048. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::const",-1),Tcl_NewStringObj("2_pi",-1),Tcl_NewDoubleObj(M_2_PI),TCL_GLOBAL_ONLY);
  29049. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::M_2_PI",-1),NULL,Tcl_NewDoubleObj(M_2_PI),TCL_GLOBAL_ONLY);
  29050. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::const",-1),Tcl_NewStringObj("2_sqrtpi",-1),Tcl_NewDoubleObj(M_2_SQRTPI),TCL_GLOBAL_ONLY);
  29051. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::M_2_SQRTPI",-1),NULL,Tcl_NewDoubleObj(M_2_SQRTPI),TCL_GLOBAL_ONLY);
  29052. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::const",-1),Tcl_NewStringObj("e",-1),Tcl_NewDoubleObj(M_E),TCL_GLOBAL_ONLY);
  29053. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::M_E",-1),NULL,Tcl_NewDoubleObj(M_E),TCL_GLOBAL_ONLY);
  29054. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::const",-1),Tcl_NewStringObj("ln2",-1),Tcl_NewDoubleObj(M_LN2),TCL_GLOBAL_ONLY);
  29055. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::M_LN2",-1),NULL,Tcl_NewDoubleObj(M_LN2),TCL_GLOBAL_ONLY);
  29056. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::const",-1),Tcl_NewStringObj("ln10",-1),Tcl_NewDoubleObj(M_LN10),TCL_GLOBAL_ONLY);
  29057. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::M_LN10",-1),NULL,Tcl_NewDoubleObj(M_LN10),TCL_GLOBAL_ONLY);
  29058. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::const",-1),Tcl_NewStringObj("log2e",-1),Tcl_NewDoubleObj(M_LOG2E),TCL_GLOBAL_ONLY);
  29059. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::M_LOG2E",-1),NULL,Tcl_NewDoubleObj(M_LOG2E),TCL_GLOBAL_ONLY);
  29060. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::const",-1),Tcl_NewStringObj("log10e",-1),Tcl_NewDoubleObj(M_LOG10E),TCL_GLOBAL_ONLY);
  29061. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::M_LOG10E",-1),NULL,Tcl_NewDoubleObj(M_LOG10E),TCL_GLOBAL_ONLY);
  29062. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::const",-1),Tcl_NewStringObj("pi",-1),Tcl_NewDoubleObj(M_PI),TCL_GLOBAL_ONLY);
  29063. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::M_PI",-1),NULL,Tcl_NewDoubleObj(M_PI),TCL_GLOBAL_ONLY);
  29064. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::const",-1),Tcl_NewStringObj("pi_2",-1),Tcl_NewDoubleObj(M_PI_2),TCL_GLOBAL_ONLY);
  29065. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::M_PI_2",-1),NULL,Tcl_NewDoubleObj(M_PI_2),TCL_GLOBAL_ONLY);
  29066. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::const",-1),Tcl_NewStringObj("pi_4",-1),Tcl_NewDoubleObj(M_PI_4),TCL_GLOBAL_ONLY);
  29067. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::M_PI_4",-1),NULL,Tcl_NewDoubleObj(M_PI_4),TCL_GLOBAL_ONLY);
  29068. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::const",-1),Tcl_NewStringObj("sqrt1_2",-1),Tcl_NewDoubleObj(M_SQRT1_2),TCL_GLOBAL_ONLY);
  29069. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::M_SQRT1_2",-1),NULL,Tcl_NewDoubleObj(M_SQRT1_2),TCL_GLOBAL_ONLY);
  29070. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::const",-1),Tcl_NewStringObj("sqrt2",-1),Tcl_NewDoubleObj(M_SQRT2),TCL_GLOBAL_ONLY);
  29071. Tcl_ObjSetVar2(interp,Tcl_NewStringObj("::odiemath::M_SQRT2",-1),NULL,Tcl_NewDoubleObj(M_SQRT2),TCL_GLOBAL_ONLY);
  29072. Tcl_CreateObjCommand(interp,"::odiemath::distance",(Tcl_ObjCmdProc *)TclCmd_odiemath_distance,NULL,NULL);
  29073. Tcl_CreateObjCommand(interp,"::odiemath::dist3d",(Tcl_ObjCmdProc *)TclCmd_odiemath_dist3d,NULL,NULL);
  29074. Tcl_CreateObjCommand(interp,"::odiemath::grid_hex",(Tcl_ObjCmdProc *)TclCmd_odiemath_grid_hex,NULL,NULL);
  29075. Tcl_CreateObjCommand(interp,"::odiemath::grid_round",(Tcl_ObjCmdProc *)TclCmd_odiemath_grid_round,NULL,NULL);
  29076. Tcl_CreateObjCommand(interp,"::odiemath::grid_square",(Tcl_ObjCmdProc *)TclCmd_odiemath_grid_square,NULL,NULL);
  29077. Tcl_CreateObjCommand(interp,"::odiemath::list_round",(Tcl_ObjCmdProc *)TclCmd_odiemath_list_round,NULL,NULL);
  29078. Tcl_CreateObjCommand(interp,"::odiemath::list_to_int",(Tcl_ObjCmdProc *)TclCmd_odiemath_list_to_int,NULL,NULL);
  29079. Tcl_CreateObjCommand(interp,"::odiemath::matrix_rotate_angle",(Tcl_ObjCmdProc *)TclCmd_odiemath_matrix_rotate_angle,NULL,NULL);
  29080. Tcl_CreateObjCommand(interp,"::odiemath::matrix_rotate_normal",(Tcl_ObjCmdProc *)TclCmd_odiemath_matrix_rotate_normal,NULL,NULL);
  29081. Tcl_CreateObjCommand(interp,"::odiemath::normal",(Tcl_ObjCmdProc *)TclCmd_odiemath_normal,NULL,NULL);
  29082. Tcl_CreateObjCommand(interp,"::odiemath::perpendicular",(Tcl_ObjCmdProc *)TclCmd_odiemath_perpendicular,NULL,NULL);
  29083. Tcl_CreateObjCommand(interp,"::odiemath::normal_2d",(Tcl_ObjCmdProc *)TclCmd_odiemath_normal_2d,NULL,NULL);
  29084. Tcl_CreateObjCommand(interp,"::odiemath::parallel_segment",(Tcl_ObjCmdProc *)TclCmd_odiemath_parallel_segment,NULL,NULL);
  29085. Tcl_CreateObjCommand(interp,"::odiemath::vector_length",(Tcl_ObjCmdProc *)TclCmd_odiemath_vector_length,NULL,NULL);
  29086. Tcl_CreateObjCommand(interp,"::odiemath::vector_rotate_and_size",(Tcl_ObjCmdProc *)TclCmd_odiemath_vector_rotate_and_size,NULL,NULL);
  29087. Tcl_CreateObjCommand(interp,"::odiemath::vector_scale",(Tcl_ObjCmdProc *)TclCmd_odiemath_vector_scale,NULL,NULL);
  29088. Tcl_CreateObjCommand(interp,"::odiemath::vector_translate_and_zoom",(Tcl_ObjCmdProc *)TclCmd_odiemath_vector_translate_and_zoom,NULL,NULL);
  29089. Tcl_CreateObjCommand(interp,"::odiemath::grid",(Tcl_ObjCmdProc *)TclCmd_odiemath_grid,NULL,NULL);
  29090. Tcl_CreateObjCommand(interp,"::odiemath::tolerance",(Tcl_ObjCmdProc *)TclCmd_odiemath_tolerance,NULL,NULL);
  29091. {
  29092. Tcl_Namespace *modPtr;
  29093. modPtr=Tcl_FindNamespace(interp,"::odiemath",NULL,TCL_NAMESPACE_ONLY);
  29094. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29095. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29096. }
  29097. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/odiemath/odiemath.tcl */
  29098. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/aabb.tcl */
  29099. Tcl_CreateObjCommand(interp,"::odie::aabb::create",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_create,NULL,NULL);
  29100. Tcl_CreateObjCommand(interp,"::vectorxyz::bbox_overlap_two_vectors",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_create,NULL,NULL);
  29101. Tcl_CreateObjCommand(interp,"::odie::aabb::overlap_two_vectors",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_overlap_two_vectors,NULL,NULL);
  29102. Tcl_CreateObjCommand(interp,"::vectorxyz::bbox_overlap_two_vectors",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_overlap_two_vectors,NULL,NULL);
  29103. Tcl_CreateObjCommand(interp,"::odie::aabb::measure",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_measure,NULL,NULL);
  29104. Tcl_CreateObjCommand(interp,"::vectorxyz::bbox_measure",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_measure,NULL,NULL);
  29105. Tcl_CreateObjCommand(interp,"::odie::aabb::faces",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_faces,NULL,NULL);
  29106. Tcl_CreateObjCommand(interp,"::odie::aabb::from_vectorxyz",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_from_vectorxyz,NULL,NULL);
  29107. Tcl_CreateObjCommand(interp,"::vectorxyz::to_aabb",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_from_vectorxyz,NULL,NULL);
  29108. Tcl_CreateObjCommand(interp,"::odie::aabb::from_line",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_from_line,NULL,NULL);
  29109. Tcl_CreateObjCommand(interp,"::vectorxyz::aabb_line",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_from_line,NULL,NULL);
  29110. Tcl_CreateObjCommand(interp,"::odie::aabb::from_center_size",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_from_center_size,NULL,NULL);
  29111. Tcl_CreateObjCommand(interp,"::vectorxyz::aabb_center_size",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_from_center_size,NULL,NULL);
  29112. Tcl_CreateObjCommand(interp,"::odie::aabb::intersect",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_intersect,NULL,NULL);
  29113. Tcl_CreateObjCommand(interp,"::vectorxyz::aabb_intersect",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_intersect,NULL,NULL);
  29114. Tcl_CreateObjCommand(interp,"::odie::aabb::within",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_within,NULL,NULL);
  29115. Tcl_CreateObjCommand(interp,"::vectorxyz::within_aabb",(Tcl_ObjCmdProc *)TclCmd_odie_aabb_within,NULL,NULL);
  29116. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/aabb.tcl */
  29117. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/affine2d.tcl */
  29118. {
  29119. Tcl_Namespace *modPtr;
  29120. modPtr=Tcl_FindNamespace(interp,"::affine2d",NULL,TCL_NAMESPACE_ONLY);
  29121. if(!modPtr) {
  29122. modPtr = Tcl_CreateNamespace(interp, "::affine2d", NULL, NULL);
  29123. }
  29124. }
  29125. Tcl_CreateObjCommand(interp,"::affine2d::apply",(Tcl_ObjCmdProc *)TclCmd_affine2d_apply,NULL,NULL);
  29126. Tcl_CreateObjCommand(interp,"::affine2d::combine",(Tcl_ObjCmdProc *)TclCmd_affine2d_combine,NULL,NULL);
  29127. Tcl_CreateObjCommand(interp,"::odiemath::affine_combine",(Tcl_ObjCmdProc *)TclCmd_affine2d_combine,NULL,NULL);
  29128. Tcl_CreateObjCommand(interp,"::affine2d::rotation_from_angle",(Tcl_ObjCmdProc *)TclCmd_affine2d_rotation_from_angle,NULL,NULL);
  29129. Tcl_CreateObjCommand(interp,"::affine2d::rotation_from_normal",(Tcl_ObjCmdProc *)TclCmd_affine2d_rotation_from_normal,NULL,NULL);
  29130. {
  29131. Tcl_Namespace *modPtr;
  29132. modPtr=Tcl_FindNamespace(interp,"::affine2d",NULL,TCL_NAMESPACE_ONLY);
  29133. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29134. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29135. }
  29136. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/affine2d.tcl */
  29137. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/affine3d.tcl */
  29138. {
  29139. Tcl_Namespace *modPtr;
  29140. modPtr=Tcl_FindNamespace(interp,"::affine4x4",NULL,TCL_NAMESPACE_ONLY);
  29141. if(!modPtr) {
  29142. modPtr = Tcl_CreateNamespace(interp, "::affine4x4", NULL, NULL);
  29143. }
  29144. }
  29145. Tcl_CreateObjCommand(interp,"::affine4x4::compare",(Tcl_ObjCmdProc *)TclCmd_affine4x4_compare,NULL,NULL);
  29146. Tcl_CreateObjCommand(interp,"::affine4x4::identity",(Tcl_ObjCmdProc *)TclCmd_affine4x4_identity,NULL,NULL);
  29147. Tcl_CreateObjCommand(interp,"::affine4x4::translation",(Tcl_ObjCmdProc *)TclCmd_affine4x4_translation,NULL,NULL);
  29148. Tcl_CreateObjCommand(interp,"::affine4x4::scale",(Tcl_ObjCmdProc *)TclCmd_affine4x4_scale,NULL,NULL);
  29149. Tcl_CreateObjCommand(interp,"::affine4x4::rotate_nutation",(Tcl_ObjCmdProc *)TclCmd_affine4x4_rotate_nutation,NULL,NULL);
  29150. Tcl_CreateObjCommand(interp,"::affine4x4::rotate_x",(Tcl_ObjCmdProc *)TclCmd_affine4x4_rotate_nutation,NULL,NULL);
  29151. Tcl_CreateObjCommand(interp,"::affine4x4::rotate_pitch",(Tcl_ObjCmdProc *)TclCmd_affine4x4_rotate_nutation,NULL,NULL);
  29152. Tcl_CreateObjCommand(interp,"::affine4x4::rotate_precession",(Tcl_ObjCmdProc *)TclCmd_affine4x4_rotate_precession,NULL,NULL);
  29153. Tcl_CreateObjCommand(interp,"::affine4x4::rotate_y",(Tcl_ObjCmdProc *)TclCmd_affine4x4_rotate_precession,NULL,NULL);
  29154. Tcl_CreateObjCommand(interp,"::affine4x4::rotate_yaw",(Tcl_ObjCmdProc *)TclCmd_affine4x4_rotate_precession,NULL,NULL);
  29155. Tcl_CreateObjCommand(interp,"::affine4x4::rotate_spin",(Tcl_ObjCmdProc *)TclCmd_affine4x4_rotate_spin,NULL,NULL);
  29156. Tcl_CreateObjCommand(interp,"::affine4x4::rotate_z",(Tcl_ObjCmdProc *)TclCmd_affine4x4_rotate_spin,NULL,NULL);
  29157. Tcl_CreateObjCommand(interp,"::affine4x4::rotate_roll",(Tcl_ObjCmdProc *)TclCmd_affine4x4_rotate_spin,NULL,NULL);
  29158. Tcl_CreateObjCommand(interp,"::affine4x4::from_euler",(Tcl_ObjCmdProc *)TclCmd_affine4x4_from_euler,NULL,NULL);
  29159. Tcl_CreateObjCommand(interp,"::affine4x4::multiply",(Tcl_ObjCmdProc *)TclCmd_affine4x4_multiply,NULL,NULL);
  29160. Tcl_CreateObjCommand(interp,"::affine4x4::X",(Tcl_ObjCmdProc *)TclCmd_affine4x4_multiply,NULL,NULL);
  29161. Tcl_CreateObjCommand(interp,"::affine4x4::multiply_inplace",(Tcl_ObjCmdProc *)TclCmd_affine4x4_multiply_inplace,NULL,NULL);
  29162. Tcl_CreateObjCommand(interp,"::affine4x4::X=",(Tcl_ObjCmdProc *)TclCmd_affine4x4_multiply_inplace,NULL,NULL);
  29163. Tcl_CreateObjCommand(interp,"::affine4x4::inverse",(Tcl_ObjCmdProc *)TclCmd_affine4x4_inverse,NULL,NULL);
  29164. Tcl_CreateObjCommand(interp,"::affine4x4::from_normal",(Tcl_ObjCmdProc *)TclCmd_affine4x4_from_normal,NULL,NULL);
  29165. {
  29166. Tcl_Namespace *modPtr;
  29167. modPtr=Tcl_FindNamespace(interp,"::affine4x4",NULL,TCL_NAMESPACE_ONLY);
  29168. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29169. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29170. }
  29171. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/affine3d.tcl */
  29172. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/bbox.tcl */
  29173. Tcl_CreateObjCommand(interp,"::odie::bbox::create",(Tcl_ObjCmdProc *)TclCmd_odie_bbox_create,NULL,NULL);
  29174. Tcl_CreateObjCommand(interp,":vectorxy::bbox_create",(Tcl_ObjCmdProc *)TclCmd_odie_bbox_create,NULL,NULL);
  29175. Tcl_CreateObjCommand(interp,"::odie::bbox::measure",(Tcl_ObjCmdProc *)TclCmd_odie_bbox_measure,NULL,NULL);
  29176. Tcl_CreateObjCommand(interp,"::vectorxy::bbox_measure",(Tcl_ObjCmdProc *)TclCmd_odie_bbox_measure,NULL,NULL);
  29177. Tcl_CreateObjCommand(interp,"::odie::bbox::elements",(Tcl_ObjCmdProc *)TclCmd_odie_bbox_elements,NULL,NULL);
  29178. Tcl_CreateObjCommand(interp,"::vectorxy::bbox_elements",(Tcl_ObjCmdProc *)TclCmd_odie_bbox_elements,NULL,NULL);
  29179. Tcl_CreateObjCommand(interp,"::odie::bbox::intersect",(Tcl_ObjCmdProc *)TclCmd_odie_bbox_intersect,NULL,NULL);
  29180. Tcl_CreateObjCommand(interp,"::vectorxy::bbox_intersect",(Tcl_ObjCmdProc *)TclCmd_odie_bbox_intersect,NULL,NULL);
  29181. Tcl_CreateObjCommand(interp,"::odie::bbox::within",(Tcl_ObjCmdProc *)TclCmd_odie_bbox_within,NULL,NULL);
  29182. Tcl_CreateObjCommand(interp,"::vectorxy::bbox_within",(Tcl_ObjCmdProc *)TclCmd_odie_bbox_within,NULL,NULL);
  29183. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/bbox.tcl */
  29184. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/quaternion.tcl */
  29185. Tcl_CreateObjCommand(interp,"::quaternion::add",(Tcl_ObjCmdProc *)TclCmd_quaternion_add,NULL,NULL);
  29186. Tcl_CreateObjCommand(interp,"::quaternion::+",(Tcl_ObjCmdProc *)TclCmd_quaternion_add,NULL,NULL);
  29187. Tcl_CreateObjCommand(interp,"::quaternion::subtract",(Tcl_ObjCmdProc *)TclCmd_quaternion_subtract,NULL,NULL);
  29188. Tcl_CreateObjCommand(interp,"::quaternion::-",(Tcl_ObjCmdProc *)TclCmd_quaternion_subtract,NULL,NULL);
  29189. Tcl_CreateObjCommand(interp,"::quaternion::multiply",(Tcl_ObjCmdProc *)TclCmd_quaternion_multiply,NULL,NULL);
  29190. Tcl_CreateObjCommand(interp,"::quaternion::*",(Tcl_ObjCmdProc *)TclCmd_quaternion_multiply,NULL,NULL);
  29191. Tcl_CreateObjCommand(interp,"::quaternion::divide",(Tcl_ObjCmdProc *)TclCmd_quaternion_divide,NULL,NULL);
  29192. Tcl_CreateObjCommand(interp,"::quaternion::/",(Tcl_ObjCmdProc *)TclCmd_quaternion_divide,NULL,NULL);
  29193. Tcl_CreateObjCommand(interp,"::quaternion::square_root",(Tcl_ObjCmdProc *)TclCmd_quaternion_square_root,NULL,NULL);
  29194. Tcl_CreateObjCommand(interp,"::quaternion::sqrt",(Tcl_ObjCmdProc *)TclCmd_quaternion_square_root,NULL,NULL);
  29195. Tcl_CreateObjCommand(interp,"::quaternion::square",(Tcl_ObjCmdProc *)TclCmd_quaternion_square,NULL,NULL);
  29196. Tcl_CreateObjCommand(interp,"::quaternion::^2",(Tcl_ObjCmdProc *)TclCmd_quaternion_square,NULL,NULL);
  29197. Tcl_CreateObjCommand(interp,"::quaternion::from_euler",(Tcl_ObjCmdProc *)TclCmd_quaternion_from_euler,NULL,NULL);
  29198. Tcl_CreateObjCommand(interp,"::vectorxyz::rotate_by_quaternion",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_rotate_by_quaternion,NULL,NULL);
  29199. Tcl_CreateObjCommand(interp,"::quaternion::to_euler",(Tcl_ObjCmdProc *)TclCmd_quaternion_to_euler,NULL,NULL);
  29200. Tcl_CreateObjCommand(interp,"::quaternion::from_normal",(Tcl_ObjCmdProc *)TclCmd_quaternion_from_normal,NULL,NULL);
  29201. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/quaternion.tcl */
  29202. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector.tcl */
  29203. {
  29204. Tcl_Namespace *modPtr;
  29205. modPtr=Tcl_FindNamespace(interp,"::vector",NULL,TCL_NAMESPACE_ONLY);
  29206. if(!modPtr) {
  29207. modPtr = Tcl_CreateNamespace(interp, "::vector", NULL, NULL);
  29208. }
  29209. }
  29210. Tcl_CreateObjCommand(interp,"::odie::tolerance",(Tcl_ObjCmdProc *)TclCmd_odie_tolerance,NULL,NULL);
  29211. Tcl_CreateObjCommand(interp,"::vector::tolerance",(Tcl_ObjCmdProc *)TclCmd_odie_tolerance,NULL,NULL);
  29212. Tcl_CreateObjCommand(interp,"::odie::vector::to_list",(Tcl_ObjCmdProc *)TclCmd_odie_vector_to_list,NULL,NULL);
  29213. Tcl_CreateObjCommand(interp,"::vector::to_list",(Tcl_ObjCmdProc *)TclCmd_odie_vector_to_list,NULL,NULL);
  29214. Tcl_CreateObjCommand(interp,"::odie::vector::index",(Tcl_ObjCmdProc *)TclCmd_odie_vector_index,NULL,NULL);
  29215. Tcl_CreateObjCommand(interp,"::vector::index",(Tcl_ObjCmdProc *)TclCmd_odie_vector_index,NULL,NULL);
  29216. Tcl_CreateObjCommand(interp,"::odie::vector::add",(Tcl_ObjCmdProc *)TclCmd_odie_vector_add,NULL,NULL);
  29217. Tcl_CreateObjCommand(interp,"::vector::add",(Tcl_ObjCmdProc *)TclCmd_odie_vector_add,NULL,NULL);
  29218. Tcl_CreateObjCommand(interp,"::odie::vector::is_null",(Tcl_ObjCmdProc *)TclCmd_odie_vector_is_null,NULL,NULL);
  29219. Tcl_CreateObjCommand(interp,"::vector::is_null",(Tcl_ObjCmdProc *)TclCmd_odie_vector_is_null,NULL,NULL);
  29220. Tcl_CreateObjCommand(interp,"::vectorxy::is_null",(Tcl_ObjCmdProc *)TclCmd_odie_vector_is_null,NULL,NULL);
  29221. Tcl_CreateObjCommand(interp,"::vectorxyz::is_null",(Tcl_ObjCmdProc *)TclCmd_odie_vector_is_null,NULL,NULL);
  29222. Tcl_CreateObjCommand(interp,"::odie::vector::subtract",(Tcl_ObjCmdProc *)TclCmd_odie_vector_subtract,NULL,NULL);
  29223. Tcl_CreateObjCommand(interp,"::vector::subtract",(Tcl_ObjCmdProc *)TclCmd_odie_vector_subtract,NULL,NULL);
  29224. Tcl_CreateObjCommand(interp,"::odie::vector::midpoint",(Tcl_ObjCmdProc *)TclCmd_odie_vector_midpoint,NULL,NULL);
  29225. Tcl_CreateObjCommand(interp,"::vector::midpoint",(Tcl_ObjCmdProc *)TclCmd_odie_vector_midpoint,NULL,NULL);
  29226. Tcl_CreateObjCommand(interp,"::odie::vector::reciprocal",(Tcl_ObjCmdProc *)TclCmd_odie_vector_reciprocal,NULL,NULL);
  29227. Tcl_CreateObjCommand(interp,"::vector::reciprocal",(Tcl_ObjCmdProc *)TclCmd_odie_vector_reciprocal,NULL,NULL);
  29228. Tcl_CreateObjCommand(interp,"::odie::vector::dot_product",(Tcl_ObjCmdProc *)TclCmd_odie_vector_dot_product,NULL,NULL);
  29229. Tcl_CreateObjCommand(interp,"::vector::dot_product",(Tcl_ObjCmdProc *)TclCmd_odie_vector_dot_product,NULL,NULL);
  29230. Tcl_CreateObjCommand(interp,"::odie::vector::to_matrix",(Tcl_ObjCmdProc *)TclCmd_odie_vector_to_matrix,NULL,NULL);
  29231. Tcl_CreateObjCommand(interp,"::vector::to_matrix",(Tcl_ObjCmdProc *)TclCmd_odie_vector_to_matrix,NULL,NULL);
  29232. Tcl_CreateObjCommand(interp,"::odie::vector::to_fuzzy",(Tcl_ObjCmdProc *)TclCmd_odie_vector_to_fuzzy,NULL,NULL);
  29233. Tcl_CreateObjCommand(interp,"::vector::to_fuzzy",(Tcl_ObjCmdProc *)TclCmd_odie_vector_to_fuzzy,NULL,NULL);
  29234. Tcl_CreateObjCommand(interp,"::odie::vector::scale",(Tcl_ObjCmdProc *)TclCmd_odie_vector_scale,NULL,NULL);
  29235. Tcl_CreateObjCommand(interp,"::vector::scale",(Tcl_ObjCmdProc *)TclCmd_odie_vector_scale,NULL,NULL);
  29236. Tcl_CreateObjCommand(interp,"::odie::vector::length",(Tcl_ObjCmdProc *)TclCmd_odie_vector_length,NULL,NULL);
  29237. Tcl_CreateObjCommand(interp,"::vector::length",(Tcl_ObjCmdProc *)TclCmd_odie_vector_length,NULL,NULL);
  29238. Tcl_CreateObjCommand(interp,"::odie::vector::length_squared",(Tcl_ObjCmdProc *)TclCmd_odie_vector_length_squared,NULL,NULL);
  29239. Tcl_CreateObjCommand(interp,"::vector::length_squared",(Tcl_ObjCmdProc *)TclCmd_odie_vector_length_squared,NULL,NULL);
  29240. Tcl_CreateObjCommand(interp,"::odie::grid",(Tcl_ObjCmdProc *)TclCmd_odie_grid,NULL,NULL);
  29241. Tcl_CreateObjCommand(interp,"::odie::gridvar",(Tcl_ObjCmdProc *)TclCmd_odie_gridvar,NULL,NULL);
  29242. {
  29243. Tcl_Namespace *modPtr;
  29244. modPtr=Tcl_FindNamespace(interp,"::vector",NULL,TCL_NAMESPACE_ONLY);
  29245. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29246. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29247. }
  29248. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector.tcl */
  29249. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector2d.tcl */
  29250. {
  29251. Tcl_Namespace *modPtr;
  29252. modPtr=Tcl_FindNamespace(interp,"::vector2d",NULL,TCL_NAMESPACE_ONLY);
  29253. if(!modPtr) {
  29254. modPtr = Tcl_CreateNamespace(interp, "::vector2d", NULL, NULL);
  29255. }
  29256. }
  29257. Tcl_CreateObjCommand(interp,"::vector2d::compare",(Tcl_ObjCmdProc *)TclCmd_vector2d_compare,NULL,NULL);
  29258. Tcl_CreateObjCommand(interp,"::vector2d::=",(Tcl_ObjCmdProc *)TclCmd_vector2d_compare,NULL,NULL);
  29259. Tcl_CreateObjCommand(interp,"::vector2d::add",(Tcl_ObjCmdProc *)TclCmd_vector2d_add,NULL,NULL);
  29260. Tcl_CreateObjCommand(interp,"::vector2d::+",(Tcl_ObjCmdProc *)TclCmd_vector2d_add,NULL,NULL);
  29261. Tcl_CreateObjCommand(interp,"::vector2d::subtract",(Tcl_ObjCmdProc *)TclCmd_vector2d_subtract,NULL,NULL);
  29262. Tcl_CreateObjCommand(interp,"::vector2d::-",(Tcl_ObjCmdProc *)TclCmd_vector2d_subtract,NULL,NULL);
  29263. Tcl_CreateObjCommand(interp,"::vector2d::midpoint",(Tcl_ObjCmdProc *)TclCmd_vector2d_midpoint,NULL,NULL);
  29264. Tcl_CreateObjCommand(interp,"::vector2d::-",(Tcl_ObjCmdProc *)TclCmd_vector2d_midpoint,NULL,NULL);
  29265. Tcl_CreateObjCommand(interp,"::vector2d::affine_apply",(Tcl_ObjCmdProc *)TclCmd_vector2d_affine_apply,NULL,NULL);
  29266. Tcl_CreateObjCommand(interp,"::odiemath::affine_apply",(Tcl_ObjCmdProc *)TclCmd_vector2d_affine_apply,NULL,NULL);
  29267. Tcl_CreateObjCommand(interp,"::vector2d::angle",(Tcl_ObjCmdProc *)TclCmd_vector2d_angle,NULL,NULL);
  29268. Tcl_CreateObjCommand(interp,"::vector2d::distance",(Tcl_ObjCmdProc *)TclCmd_vector2d_distance,NULL,NULL);
  29269. Tcl_CreateObjCommand(interp,"::odiemath::dist2d",(Tcl_ObjCmdProc *)TclCmd_vector2d_distance,NULL,NULL);
  29270. Tcl_CreateObjCommand(interp,"::vector2d::dotproduct",(Tcl_ObjCmdProc *)TclCmd_vector2d_dotproduct,NULL,NULL);
  29271. Tcl_CreateObjCommand(interp,"::vector2d::.",(Tcl_ObjCmdProc *)TclCmd_vector2d_dotproduct,NULL,NULL);
  29272. Tcl_CreateObjCommand(interp,"::vector2d::crossproduct",(Tcl_ObjCmdProc *)TclCmd_vector2d_crossproduct,NULL,NULL);
  29273. Tcl_CreateObjCommand(interp,"::vector2d::x",(Tcl_ObjCmdProc *)TclCmd_vector2d_crossproduct,NULL,NULL);
  29274. Tcl_CreateObjCommand(interp,"::vector2d::rightof",(Tcl_ObjCmdProc *)TclCmd_vector2d_rightof,NULL,NULL);
  29275. Tcl_CreateObjCommand(interp,"::vector2d::rotate_and_size",(Tcl_ObjCmdProc *)TclCmd_vector2d_rotate_and_size,NULL,NULL);
  29276. Tcl_CreateObjCommand(interp,"::vector2d::scale",(Tcl_ObjCmdProc *)TclCmd_vector2d_scale,NULL,NULL);
  29277. Tcl_CreateObjCommand(interp,"::vector2d::translate_and_zoom",(Tcl_ObjCmdProc *)TclCmd_vector2d_translate_and_zoom,NULL,NULL);
  29278. Tcl_CreateObjCommand(interp,"::vector2d::point_on_segment",(Tcl_ObjCmdProc *)TclCmd_vector2d_point_on_segment,NULL,NULL);
  29279. Tcl_CreateObjCommand(interp,"::odiemath::point_on_segment",(Tcl_ObjCmdProc *)TclCmd_vector2d_point_on_segment,NULL,NULL);
  29280. Tcl_CreateObjCommand(interp,"::vector2d::line_circle_intersect",(Tcl_ObjCmdProc *)TclCmd_vector2d_line_circle_intersect,NULL,NULL);
  29281. Tcl_CreateObjCommand(interp,"::odiemath::line_circle_intersect",(Tcl_ObjCmdProc *)TclCmd_vector2d_line_circle_intersect,NULL,NULL);
  29282. Tcl_CreateObjCommand(interp,"::vector2d::line_intersect",(Tcl_ObjCmdProc *)TclCmd_vector2d_line_intersect,NULL,NULL);
  29283. Tcl_CreateObjCommand(interp,"::odiemath::line_intersect",(Tcl_ObjCmdProc *)TclCmd_vector2d_line_intersect,NULL,NULL);
  29284. Tcl_CreateObjCommand(interp,"::vector2d::line_overlap",(Tcl_ObjCmdProc *)TclCmd_vector2d_line_overlap,NULL,NULL);
  29285. Tcl_CreateObjCommand(interp,"::odiemath::line_overlap",(Tcl_ObjCmdProc *)TclCmd_vector2d_line_overlap,NULL,NULL);
  29286. Tcl_CreateObjCommand(interp,"::vector2d::colinear",(Tcl_ObjCmdProc *)TclCmd_vector2d_colinear,NULL,NULL);
  29287. Tcl_CreateObjCommand(interp,"::odiemath::colinear",(Tcl_ObjCmdProc *)TclCmd_vector2d_colinear,NULL,NULL);
  29288. {
  29289. Tcl_Namespace *modPtr;
  29290. modPtr=Tcl_FindNamespace(interp,"::vector2d",NULL,TCL_NAMESPACE_ONLY);
  29291. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29292. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29293. }
  29294. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector2d.tcl */
  29295. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector3d.tcl */
  29296. {
  29297. Tcl_Namespace *modPtr;
  29298. modPtr=Tcl_FindNamespace(interp,"::vector3d",NULL,TCL_NAMESPACE_ONLY);
  29299. if(!modPtr) {
  29300. modPtr = Tcl_CreateNamespace(interp, "::vector3d", NULL, NULL);
  29301. }
  29302. }
  29303. Tcl_CreateObjCommand(interp,"::vector3d::compare",(Tcl_ObjCmdProc *)TclCmd_vector3d_compare,NULL,NULL);
  29304. Tcl_CreateObjCommand(interp,"::vector3d::=",(Tcl_ObjCmdProc *)TclCmd_vector3d_compare,NULL,NULL);
  29305. Tcl_CreateObjCommand(interp,"::vector3d::add",(Tcl_ObjCmdProc *)TclCmd_vector3d_add,NULL,NULL);
  29306. Tcl_CreateObjCommand(interp,"::vector3d::+",(Tcl_ObjCmdProc *)TclCmd_vector3d_add,NULL,NULL);
  29307. Tcl_CreateObjCommand(interp,"::vector3d::subtract",(Tcl_ObjCmdProc *)TclCmd_vector3d_subtract,NULL,NULL);
  29308. Tcl_CreateObjCommand(interp,"::vector3d::-",(Tcl_ObjCmdProc *)TclCmd_vector3d_subtract,NULL,NULL);
  29309. Tcl_CreateObjCommand(interp,"::vector3d::orthagonal",(Tcl_ObjCmdProc *)TclCmd_vector3d_orthagonal,NULL,NULL);
  29310. Tcl_CreateObjCommand(interp,"::vector3d::distance",(Tcl_ObjCmdProc *)TclCmd_vector3d_distance,NULL,NULL);
  29311. Tcl_CreateObjCommand(interp,"::vector3d::distanceSq",(Tcl_ObjCmdProc *)TclCmd_vector3d_distanceSq,NULL,NULL);
  29312. {
  29313. Tcl_Namespace *modPtr;
  29314. modPtr=Tcl_FindNamespace(interp,"::vector3d",NULL,TCL_NAMESPACE_ONLY);
  29315. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29316. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29317. }
  29318. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vector3d.tcl */
  29319. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorn.tcl */
  29320. {
  29321. Tcl_Namespace *modPtr;
  29322. modPtr=Tcl_FindNamespace(interp,"::vectorN",NULL,TCL_NAMESPACE_ONLY);
  29323. if(!modPtr) {
  29324. modPtr = Tcl_CreateNamespace(interp, "::vectorN", NULL, NULL);
  29325. }
  29326. }
  29327. Tcl_CreateObjCommand(interp,"::vectorN::length",(Tcl_ObjCmdProc *)TclCmd_vectorN_length,NULL,NULL);
  29328. Tcl_CreateObjCommand(interp,"::vectorN::distance",(Tcl_ObjCmdProc *)TclCmd_vectorN_distance,NULL,NULL);
  29329. Tcl_CreateObjCommand(interp,"::tcl::mathfunc::distance",(Tcl_ObjCmdProc *)TclCmd_vectorN_distance,NULL,NULL);
  29330. Tcl_CreateObjCommand(interp,"::vectorN::scale",(Tcl_ObjCmdProc *)TclCmd_vectorN_scale,NULL,NULL);
  29331. Tcl_CreateObjCommand(interp,"::vectorN::scalevar",(Tcl_ObjCmdProc *)TclCmd_vectorN_scalevar,NULL,NULL);
  29332. {
  29333. Tcl_Namespace *modPtr;
  29334. modPtr=Tcl_FindNamespace(interp,"::vectorN",NULL,TCL_NAMESPACE_ONLY);
  29335. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29336. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29337. }
  29338. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorn.tcl */
  29339. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorxy.tcl */
  29340. {
  29341. Tcl_Namespace *modPtr;
  29342. modPtr=Tcl_FindNamespace(interp,"::vectorxy",NULL,TCL_NAMESPACE_ONLY);
  29343. if(!modPtr) {
  29344. modPtr = Tcl_CreateNamespace(interp, "::vectorxy", NULL, NULL);
  29345. }
  29346. }
  29347. Tcl_CreateObjCommand(interp,"::vectorxy::compare",(Tcl_ObjCmdProc *)TclCmd_vectorxy_compare,NULL,NULL);
  29348. Tcl_CreateObjCommand(interp,"::vectorxy::=",(Tcl_ObjCmdProc *)TclCmd_vectorxy_compare,NULL,NULL);
  29349. Tcl_CreateObjCommand(interp,"::vectorxy::add",(Tcl_ObjCmdProc *)TclCmd_vectorxy_add,NULL,NULL);
  29350. Tcl_CreateObjCommand(interp,"::vectorxy::+",(Tcl_ObjCmdProc *)TclCmd_vectorxy_add,NULL,NULL);
  29351. Tcl_CreateObjCommand(interp,"::vectorxy::subtract",(Tcl_ObjCmdProc *)TclCmd_vectorxy_subtract,NULL,NULL);
  29352. Tcl_CreateObjCommand(interp,"::vectorxy::-",(Tcl_ObjCmdProc *)TclCmd_vectorxy_subtract,NULL,NULL);
  29353. Tcl_CreateObjCommand(interp,"::vectorxy::midpoint",(Tcl_ObjCmdProc *)TclCmd_vectorxy_midpoint,NULL,NULL);
  29354. Tcl_CreateObjCommand(interp,"::vectorxy::-",(Tcl_ObjCmdProc *)TclCmd_vectorxy_midpoint,NULL,NULL);
  29355. Tcl_CreateObjCommand(interp,"::vectorxy::add_stream",(Tcl_ObjCmdProc *)TclCmd_vectorxy_add_stream,NULL,NULL);
  29356. Tcl_CreateObjCommand(interp,"::vectorxy::angle",(Tcl_ObjCmdProc *)TclCmd_vectorxy_angle,NULL,NULL);
  29357. Tcl_CreateObjCommand(interp,"::vectorxy::create",(Tcl_ObjCmdProc *)TclCmd_vectorxy_create,NULL,NULL);
  29358. Tcl_CreateObjCommand(interp,"::vectorxy::toint",(Tcl_ObjCmdProc *)TclCmd_vectorxy_toint,NULL,NULL);
  29359. Tcl_CreateObjCommand(interp,"::vectorxy::crossproduct",(Tcl_ObjCmdProc *)TclCmd_vectorxy_crossproduct,NULL,NULL);
  29360. Tcl_CreateObjCommand(interp,"::vectorxy::x",(Tcl_ObjCmdProc *)TclCmd_vectorxy_crossproduct,NULL,NULL);
  29361. Tcl_CreateObjCommand(interp,"::vectorxy::distance",(Tcl_ObjCmdProc *)TclCmd_vectorxy_distance,NULL,NULL);
  29362. Tcl_CreateObjCommand(interp,"::vectorxy::length",(Tcl_ObjCmdProc *)TclCmd_vectorxy_length,NULL,NULL);
  29363. Tcl_CreateObjCommand(interp,"::vectorxy::normalize",(Tcl_ObjCmdProc *)TclCmd_vectorxy_normalize,NULL,NULL);
  29364. Tcl_CreateObjCommand(interp,"::vectorxy::dotproduct",(Tcl_ObjCmdProc *)TclCmd_vectorxy_dotproduct,NULL,NULL);
  29365. Tcl_CreateObjCommand(interp,"::vectorxy::.",(Tcl_ObjCmdProc *)TclCmd_vectorxy_dotproduct,NULL,NULL);
  29366. Tcl_CreateObjCommand(interp,"::vectorxy::rightof",(Tcl_ObjCmdProc *)TclCmd_vectorxy_rightof,NULL,NULL);
  29367. Tcl_CreateObjCommand(interp,"::vectorxy::rotate_and_size",(Tcl_ObjCmdProc *)TclCmd_vectorxy_rotate_and_size,NULL,NULL);
  29368. Tcl_CreateObjCommand(interp,"::vectorxy::scale",(Tcl_ObjCmdProc *)TclCmd_vectorxy_scale,NULL,NULL);
  29369. Tcl_CreateObjCommand(interp,"::vectorxy::translate_and_zoom",(Tcl_ObjCmdProc *)TclCmd_vectorxy_translate_and_zoom,NULL,NULL);
  29370. Tcl_CreateObjCommand(interp,"::vectorxy::flatten",(Tcl_ObjCmdProc *)TclCmd_vectorxy_flatten,NULL,NULL);
  29371. {
  29372. Tcl_Namespace *modPtr;
  29373. modPtr=Tcl_FindNamespace(interp,"::vectorxy",NULL,TCL_NAMESPACE_ONLY);
  29374. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29375. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29376. }
  29377. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorxy.tcl */
  29378. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorxyz.tcl */
  29379. {
  29380. Tcl_Namespace *modPtr;
  29381. modPtr=Tcl_FindNamespace(interp,"::vectorxyz",NULL,TCL_NAMESPACE_ONLY);
  29382. if(!modPtr) {
  29383. modPtr = Tcl_CreateNamespace(interp, "::vectorxyz", NULL, NULL);
  29384. }
  29385. }
  29386. Tcl_CreateObjCommand(interp,"::vectorxyz::scale",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_scale,NULL,NULL);
  29387. Tcl_CreateObjCommand(interp,"::vectorxyz::zero",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_zero,NULL,NULL);
  29388. Tcl_CreateObjCommand(interp,"::vectorxyz::compare",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_compare,NULL,NULL);
  29389. Tcl_CreateObjCommand(interp,"::vectorxyz::=",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_compare,NULL,NULL);
  29390. Tcl_CreateObjCommand(interp,"::vectorxyz::polygon_normal_compare",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_polygon_normal_compare,NULL,NULL);
  29391. Tcl_CreateObjCommand(interp,"::vectorxyz::create",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_create,NULL,NULL);
  29392. Tcl_CreateObjCommand(interp,"::vectorxyz::toint",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_toint,NULL,NULL);
  29393. Tcl_CreateObjCommand(interp,"::vectorxyz::add",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_add,NULL,NULL);
  29394. Tcl_CreateObjCommand(interp,"::vectorxyz::+",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_add,NULL,NULL);
  29395. Tcl_CreateObjCommand(interp,"::vectorxyz::add_inplace",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_add_inplace,NULL,NULL);
  29396. Tcl_CreateObjCommand(interp,"::vectorxyz::++",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_add_inplace,NULL,NULL);
  29397. Tcl_CreateObjCommand(interp,"::vectorxyz::orthagonal",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_orthagonal,NULL,NULL);
  29398. Tcl_CreateObjCommand(interp,"::vectorxyz::subtract",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_subtract,NULL,NULL);
  29399. Tcl_CreateObjCommand(interp,"::vectorxyz::-",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_subtract,NULL,NULL);
  29400. Tcl_CreateObjCommand(interp,"::vectorxyz::midpoint",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_midpoint,NULL,NULL);
  29401. Tcl_CreateObjCommand(interp,"::vectorxyz::cross_product",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_cross_product,NULL,NULL);
  29402. Tcl_CreateObjCommand(interp,"::vectorxyz::x",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_cross_product,NULL,NULL);
  29403. Tcl_CreateObjCommand(interp,"::vectorxyz::dot_product",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_dot_product,NULL,NULL);
  29404. Tcl_CreateObjCommand(interp,"::vectorxyz::.",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_dot_product,NULL,NULL);
  29405. Tcl_CreateObjCommand(interp,"::vectorxyz::transform",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_transform,NULL,NULL);
  29406. Tcl_CreateObjCommand(interp,"::vectorxyz::length",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_length,NULL,NULL);
  29407. Tcl_CreateObjCommand(interp,"::vectorxyz::mangitude",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_length,NULL,NULL);
  29408. Tcl_CreateObjCommand(interp,"::tcl::mathfunc::xyz_length",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_length,NULL,NULL);
  29409. Tcl_CreateObjCommand(interp,"::vectorxyz::distance",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_distance,NULL,NULL);
  29410. Tcl_CreateObjCommand(interp,"::tcl::mathfunc::xyz_distance",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_distance,NULL,NULL);
  29411. Tcl_CreateObjCommand(interp,"::vectorxyz::distanceSq",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_distanceSq,NULL,NULL);
  29412. Tcl_CreateObjCommand(interp,"::tcl::mathfunc::xyz_distance_sq",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_distanceSq,NULL,NULL);
  29413. Tcl_CreateObjCommand(interp,"::vectorxyz::length_inv_sqr",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_length_inv_sqr,NULL,NULL);
  29414. Tcl_CreateObjCommand(interp,"::vectorxyz::mangitude_inv_sqr",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_length_inv_sqr,NULL,NULL);
  29415. Tcl_CreateObjCommand(interp,"::tcl::mathfunc::xyz_mag_inv_sq",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_length_inv_sqr,NULL,NULL);
  29416. Tcl_CreateObjCommand(interp,"::vectorxyz::normalize",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_normalize,NULL,NULL);
  29417. Tcl_CreateObjCommand(interp,"::vectorxyz::point_on_segment",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_point_on_segment,NULL,NULL);
  29418. Tcl_CreateObjCommand(interp,"::vectorxyz::point_on_segment_x",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_point_on_segment_x,NULL,NULL);
  29419. Tcl_CreateObjCommand(interp,"::vectorxyz::axis_of_normal",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_axis_of_normal,NULL,NULL);
  29420. Tcl_CreateObjCommand(interp,"::vectorxyz::bend_direction",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_bend_direction,NULL,NULL);
  29421. Tcl_CreateObjCommand(interp,"::vectorxyz::rightof",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_bend_direction,NULL,NULL);
  29422. Tcl_CreateObjCommand(interp,"::vectorxyz::angle_three_points",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_angle_three_points,NULL,NULL);
  29423. Tcl_CreateObjCommand(interp,"::vectorxyz::colinear",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_colinear,NULL,NULL);
  29424. Tcl_CreateObjCommand(interp,"::vectorxyz::coplaner",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_coplaner,NULL,NULL);
  29425. Tcl_CreateObjCommand(interp,"::vectorxyz::linelinecoincident_int",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_linelinecoincident_int,NULL,NULL);
  29426. Tcl_CreateObjCommand(interp,"::vectorxyz::linelinecoincident",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_linelinecoincident,NULL,NULL);
  29427. Tcl_CreateObjCommand(interp,"::vectorxyz::linelineintersect",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_linelineintersect,NULL,NULL);
  29428. Tcl_CreateObjCommand(interp,"::vectorxyz::linelineintersect_distance",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_linelineintersect_distance,NULL,NULL);
  29429. Tcl_CreateObjCommand(interp,"::vectorxyz::sizeof",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_sizeof,NULL,NULL);
  29430. Tcl_CreateObjCommand(interp,"::vectorxyz::closest_point_on_segment",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_closest_point_on_segment,NULL,NULL);
  29431. Tcl_CreateObjCommand(interp,"::vectorxyz::point_in_triangle",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_point_in_triangle,NULL,NULL);
  29432. Tcl_CreateObjCommand(interp,"::vectorxyz::triangle_line_intersect",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_triangle_line_intersect,NULL,NULL);
  29433. Tcl_CreateObjCommand(interp,"::vectorxyz::line_sphere_intersect_length",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_line_sphere_intersect_length,NULL,NULL);
  29434. Tcl_CreateObjCommand(interp,"::odiemath::line_sphere_intersect_length",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_line_sphere_intersect_length,NULL,NULL);
  29435. Tcl_CreateObjCommand(interp,"::vectorxyz::line_sphere_intersect_area",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_line_sphere_intersect_area,NULL,NULL);
  29436. Tcl_CreateObjCommand(interp,"::odiemath::line_sphere_intersect_area",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_line_sphere_intersect_area,NULL,NULL);
  29437. Tcl_CreateObjCommand(interp,"::vectorxyz::line_sphere_intersect",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_line_sphere_intersect,NULL,NULL);
  29438. Tcl_CreateObjCommand(interp,"::odiemath::line_sphere_intersect",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_line_sphere_intersect,NULL,NULL);
  29439. Tcl_CreateObjCommand(interp,"::vectorxyz::polygon_normal",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_polygon_normal,NULL,NULL);
  29440. Tcl_CreateObjCommand(interp,"::vectorxyz::polygon_center",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_polygon_center,NULL,NULL);
  29441. Tcl_CreateObjCommand(interp,"::vectorxyz::flatten",(Tcl_ObjCmdProc *)TclCmd_vectorxyz_flatten,NULL,NULL);
  29442. {
  29443. Tcl_Namespace *modPtr;
  29444. modPtr=Tcl_FindNamespace(interp,"::vectorxyz",NULL,TCL_NAMESPACE_ONLY);
  29445. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29446. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29447. }
  29448. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/vectorxyz.tcl */
  29449. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/affine/cmatrixforms.tcl */
  29450. {
  29451. Tcl_Namespace *modPtr;
  29452. modPtr=Tcl_FindNamespace(interp,"::matrix",NULL,TCL_NAMESPACE_ONLY);
  29453. if(!modPtr) {
  29454. modPtr = Tcl_CreateNamespace(interp, "::matrix", NULL, NULL);
  29455. }
  29456. }
  29457. Tcl_CreateObjCommand(interp,"::matrix::to_aabb_xyz",(Tcl_ObjCmdProc *)TclCmd_matrix_to_aabb_xyz,NULL,NULL);
  29458. Tcl_CreateObjCommand(interp,"::matrix::to_affine",(Tcl_ObjCmdProc *)TclCmd_matrix_to_affine,NULL,NULL);
  29459. Tcl_CreateObjCommand(interp,"::matrix::to_bbox_xy",(Tcl_ObjCmdProc *)TclCmd_matrix_to_bbox_xy,NULL,NULL);
  29460. Tcl_CreateObjCommand(interp,"::matrix::to_cylindrical",(Tcl_ObjCmdProc *)TclCmd_matrix_to_cylindrical,NULL,NULL);
  29461. Tcl_CreateObjCommand(interp,"::matrix::to_euler",(Tcl_ObjCmdProc *)TclCmd_matrix_to_euler,NULL,NULL);
  29462. Tcl_CreateObjCommand(interp,"::matrix::to_heading",(Tcl_ObjCmdProc *)TclCmd_matrix_to_heading,NULL,NULL);
  29463. Tcl_CreateObjCommand(interp,"::matrix::to_mat2",(Tcl_ObjCmdProc *)TclCmd_matrix_to_mat2,NULL,NULL);
  29464. Tcl_CreateObjCommand(interp,"::matrix::to_mat3",(Tcl_ObjCmdProc *)TclCmd_matrix_to_mat3,NULL,NULL);
  29465. Tcl_CreateObjCommand(interp,"::matrix::to_mat4",(Tcl_ObjCmdProc *)TclCmd_matrix_to_mat4,NULL,NULL);
  29466. Tcl_CreateObjCommand(interp,"::matrix::to_null",(Tcl_ObjCmdProc *)TclCmd_matrix_to_null,NULL,NULL);
  29467. Tcl_CreateObjCommand(interp,"::matrix::to_polar",(Tcl_ObjCmdProc *)TclCmd_matrix_to_polar,NULL,NULL);
  29468. Tcl_CreateObjCommand(interp,"::matrix::to_quaternion",(Tcl_ObjCmdProc *)TclCmd_matrix_to_quaternion,NULL,NULL);
  29469. Tcl_CreateObjCommand(interp,"::matrix::to_scaler",(Tcl_ObjCmdProc *)TclCmd_matrix_to_scaler,NULL,NULL);
  29470. Tcl_CreateObjCommand(interp,"::matrix::to_spherical",(Tcl_ObjCmdProc *)TclCmd_matrix_to_spherical,NULL,NULL);
  29471. Tcl_CreateObjCommand(interp,"::matrix::to_unknown",(Tcl_ObjCmdProc *)TclCmd_matrix_to_unknown,NULL,NULL);
  29472. Tcl_CreateObjCommand(interp,"::matrix::to_vector_xy",(Tcl_ObjCmdProc *)TclCmd_matrix_to_vector_xy,NULL,NULL);
  29473. Tcl_CreateObjCommand(interp,"::matrix::to_vector_xyz",(Tcl_ObjCmdProc *)TclCmd_matrix_to_vector_xyz,NULL,NULL);
  29474. Tcl_CreateObjCommand(interp,"::matrix::to_vector_xyzw",(Tcl_ObjCmdProc *)TclCmd_matrix_to_vector_xyzw,NULL,NULL);
  29475. {
  29476. Tcl_Namespace *modPtr;
  29477. modPtr=Tcl_FindNamespace(interp,"::matrix",NULL,TCL_NAMESPACE_ONLY);
  29478. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29479. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29480. }
  29481. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/affine/cmatrixforms.tcl */
  29482. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/fuzzy/fuzzy.tcl */
  29483. Tcl_CreateObjCommand(interp,"::tcl::mathfunc::to_fuzzy",(Tcl_ObjCmdProc *)TclCmd_tcl_mathfunc_to_fuzzy,NULL,NULL);
  29484. Tcl_CreateObjCommand(interp,"::odiemath::double_to_fuzzy",(Tcl_ObjCmdProc *)TclCmd_tcl_mathfunc_to_fuzzy,NULL,NULL);
  29485. Tcl_CreateObjCommand(interp,"::tcl::mathfunc::fuzzy_abs",(Tcl_ObjCmdProc *)TclCmd_tcl_mathfunc_fuzzy_abs,NULL,NULL);
  29486. Tcl_CreateObjCommand(interp,"::odiemath::fuzzy_abs",(Tcl_ObjCmdProc *)TclCmd_tcl_mathfunc_fuzzy_abs,NULL,NULL);
  29487. Tcl_CreateObjCommand(interp,"::tcl::mathfunc::fuzzy_compare",(Tcl_ObjCmdProc *)TclCmd_tcl_mathfunc_fuzzy_compare,NULL,NULL);
  29488. Tcl_CreateObjCommand(interp,"::odiemath::fuzzy_compare",(Tcl_ObjCmdProc *)TclCmd_tcl_mathfunc_fuzzy_compare,NULL,NULL);
  29489. Tcl_CreateObjCommand(interp,"::tcl::mathfunc::fuzzy_is_zero",(Tcl_ObjCmdProc *)TclCmd_tcl_mathfunc_fuzzy_is_zero,NULL,NULL);
  29490. Tcl_CreateObjCommand(interp,"::odiemath::fuzzy_is_zero",(Tcl_ObjCmdProc *)TclCmd_tcl_mathfunc_fuzzy_is_zero,NULL,NULL);
  29491. Tcl_CreateObjCommand(interp,"::tcl::mathfunc::fuzzy_gt_zero",(Tcl_ObjCmdProc *)TclCmd_tcl_mathfunc_fuzzy_gt_zero,NULL,NULL);
  29492. Tcl_CreateObjCommand(interp,"::odiemath::fuzzy_gt_zero",(Tcl_ObjCmdProc *)TclCmd_tcl_mathfunc_fuzzy_gt_zero,NULL,NULL);
  29493. Tcl_CreateObjCommand(interp,"::tcl::mathfunc::fuzzy_epsilon",(Tcl_ObjCmdProc *)TclCmd_tcl_mathfunc_fuzzy_epsilon,NULL,NULL);
  29494. Tcl_CreateObjCommand(interp,"::odiemath::fuzzy_epsilon",(Tcl_ObjCmdProc *)TclCmd_tcl_mathfunc_fuzzy_epsilon,NULL,NULL);
  29495. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/fuzzy/fuzzy.tcl */
  29496. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/triangulate.tcl */
  29497. Tcl_CreateObjCommand(interp, "convex_subpolygons", convexSubpolyCmd, 0, 0);
  29498. Tcl_CreateObjCommand(interp, "convex_subpolygons_new", convexNewSubpolyCmd, 0, 0);
  29499. Tcl_CreateObjCommand(interp,"::triag_test_rightof",(Tcl_ObjCmdProc *)TclCmd_triag_test_rightof,NULL,NULL);
  29500. Tcl_CreateObjCommand(interp,"::triag_test_dotprod",(Tcl_ObjCmdProc *)TclCmd_triag_test_dotprod,NULL,NULL);
  29501. Tcl_CreateObjCommand(interp,"::triag_test_angle",(Tcl_ObjCmdProc *)TclCmd_triag_test_angle,NULL,NULL);
  29502. Tcl_CreateObjCommand(interp,"::triag_test_ideal",(Tcl_ObjCmdProc *)TclCmd_triag_test_ideal,NULL,NULL);
  29503. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/triangulate.tcl */
  29504. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygon.tcl */
  29505. {
  29506. Tcl_Namespace *modPtr;
  29507. modPtr=Tcl_FindNamespace(interp,"::polygon",NULL,TCL_NAMESPACE_ONLY);
  29508. if(!modPtr) {
  29509. modPtr = Tcl_CreateNamespace(interp, "::polygon", NULL, NULL);
  29510. }
  29511. }
  29512. Tcl_CreateObjCommand(interp,"::polygon::create",(Tcl_ObjCmdProc *)TclCmd_polygon_create,NULL,NULL);
  29513. Tcl_CreateObjCommand(interp,"::polygon::compare",(Tcl_ObjCmdProc *)TclCmd_polygon_compare,NULL,NULL);
  29514. Tcl_CreateObjCommand(interp,"::polygon::simplify",(Tcl_ObjCmdProc *)TclCmd_polygon_simplify,NULL,NULL);
  29515. Tcl_CreateObjCommand(interp,"::polygon::area",(Tcl_ObjCmdProc *)TclCmd_polygon_area,NULL,NULL);
  29516. Tcl_CreateObjCommand(interp,"::polygon::bbox",(Tcl_ObjCmdProc *)TclCmd_polygon_bbox,NULL,NULL);
  29517. Tcl_CreateObjCommand(interp,"::polygon::info",(Tcl_ObjCmdProc *)TclCmd_polygon_info,NULL,NULL);
  29518. Tcl_CreateObjCommand(interp,"::polygon::intersect",(Tcl_ObjCmdProc *)TclCmd_polygon_intersect,NULL,NULL);
  29519. Tcl_CreateObjCommand(interp,"::polygon::within",(Tcl_ObjCmdProc *)TclCmd_polygon_within,NULL,NULL);
  29520. Tcl_CreateObjCommand(interp,"::polygon::center",(Tcl_ObjCmdProc *)TclCmd_polygon_center,NULL,NULL);
  29521. Tcl_CreateObjCommand(interp,"::polygon::canvascoords",(Tcl_ObjCmdProc *)TclCmd_polygon_canvascoords,NULL,NULL);
  29522. Tcl_CreateObjCommand(interp,"::polygon::coords",(Tcl_ObjCmdProc *)TclCmd_polygon_coords,NULL,NULL);
  29523. Tcl_CreateObjCommand(interp,"::polygon::xycoords",(Tcl_ObjCmdProc *)TclCmd_polygon_xycoords,NULL,NULL);
  29524. Tcl_CreateObjCommand(interp,"::polygon::edges",(Tcl_ObjCmdProc *)TclCmd_polygon_edges,NULL,NULL);
  29525. Tcl_CreateObjCommand(interp,"::polygon::bend",(Tcl_ObjCmdProc *)TclCmd_polygon_bend,NULL,NULL);
  29526. Tcl_CreateObjCommand(interp,"::polygon::is_convex",(Tcl_ObjCmdProc *)TclCmd_polygon_is_convex,NULL,NULL);
  29527. Tcl_CreateObjCommand(interp,"::polygon::segments",(Tcl_ObjCmdProc *)TclCmd_polygon_segments,NULL,NULL);
  29528. Tcl_CreateObjCommand(interp,"::polygon::rectangle",(Tcl_ObjCmdProc *)TclCmd_polygon_rectangle,NULL,NULL);
  29529. Tcl_CreateObjCommand(interp,"::polygon::vector_place",(Tcl_ObjCmdProc *)TclCmd_polygon_vector_place,NULL,NULL);
  29530. Tcl_CreateObjCommand(interp,"::polygon::hexagon",(Tcl_ObjCmdProc *)TclCmd_polygon_hexagon,NULL,NULL);
  29531. Tcl_CreateObjCommand(interp,"::polygon::poly_place",(Tcl_ObjCmdProc *)TclCmd_polygon_poly_place,NULL,NULL);
  29532. Tcl_CreateObjCommand(interp,"::polygon::drawobj_orientation",(Tcl_ObjCmdProc *)TclCmd_polygon_drawobj_orientation,NULL,NULL);
  29533. Tcl_CreateObjCommand(interp,"::polygon::corners",(Tcl_ObjCmdProc *)TclCmd_polygon_corners,NULL,NULL);
  29534. Tcl_CreateObjCommand(interp,"::polygon::hexgrid_location",(Tcl_ObjCmdProc *)TclCmd_polygon_hexgrid_location,NULL,NULL);
  29535. Tcl_CreateObjCommand(interp,"::polygon::hexgrid_create",(Tcl_ObjCmdProc *)TclCmd_polygon_hexgrid_create,NULL,NULL);
  29536. Tcl_CreateObjCommand(interp,"::polygon::squaregrid_create",(Tcl_ObjCmdProc *)TclCmd_polygon_squaregrid_create,NULL,NULL);
  29537. {
  29538. Tcl_Namespace *modPtr;
  29539. modPtr=Tcl_FindNamespace(interp,"::polygon",NULL,TCL_NAMESPACE_ONLY);
  29540. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29541. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29542. }
  29543. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygon.tcl */
  29544. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygonxyz.tcl */
  29545. {
  29546. Tcl_Namespace *modPtr;
  29547. modPtr=Tcl_FindNamespace(interp,"::polygonxyz",NULL,TCL_NAMESPACE_ONLY);
  29548. if(!modPtr) {
  29549. modPtr = Tcl_CreateNamespace(interp, "::polygonxyz", NULL, NULL);
  29550. }
  29551. }
  29552. Tcl_CreateObjCommand(interp,"::polygonxyz::info",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_info,NULL,NULL);
  29553. Tcl_CreateObjCommand(interp,"::polygonxyz::create",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_create,NULL,NULL);
  29554. Tcl_CreateObjCommand(interp,"::polygonxyz::createxy",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_createxy,NULL,NULL);
  29555. Tcl_CreateObjCommand(interp,"::polygonxyz::simplify",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_simplify,NULL,NULL);
  29556. Tcl_CreateObjCommand(interp,"::polygonxyz::id",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_id,NULL,NULL);
  29557. Tcl_CreateObjCommand(interp,"::polygonxyz::area",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_area,NULL,NULL);
  29558. Tcl_CreateObjCommand(interp,"::polygonxyz::bbox",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_bbox,NULL,NULL);
  29559. Tcl_CreateObjCommand(interp,"::polygonxyz::bend",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_bend,NULL,NULL);
  29560. Tcl_CreateObjCommand(interp,"::polygonxyz::center",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_center,NULL,NULL);
  29561. Tcl_CreateObjCommand(interp,"::polygonxyz::is_2d",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_is_2d,NULL,NULL);
  29562. Tcl_CreateObjCommand(interp,"::polygonxyz::is_convex",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_is_convex,NULL,NULL);
  29563. Tcl_CreateObjCommand(interp,"::polygonxyz::normal",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_normal,NULL,NULL);
  29564. Tcl_CreateObjCommand(interp,"::polygonxyz::nVertex",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_nVertex,NULL,NULL);
  29565. Tcl_CreateObjCommand(interp,"::polygonxyz::radius",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_radius,NULL,NULL);
  29566. Tcl_CreateObjCommand(interp,"::polygonxyz::rotation",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_rotation,NULL,NULL);
  29567. Tcl_CreateObjCommand(interp,"::polygonxyz::rotation_inv",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_rotation_inv,NULL,NULL);
  29568. Tcl_CreateObjCommand(interp,"::polygonxyz::axis_of_normal",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_axis_of_normal,NULL,NULL);
  29569. Tcl_CreateObjCommand(interp,"::polygonxyz::canvascoords",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_canvascoords,NULL,NULL);
  29570. Tcl_CreateObjCommand(interp,"::polygonxyz::coords",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_coords,NULL,NULL);
  29571. Tcl_CreateObjCommand(interp,"::polygonxyz::intcoordsxy",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_intcoordsxy,NULL,NULL);
  29572. Tcl_CreateObjCommand(interp,"::polygonxyz::intcoords",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_intcoords,NULL,NULL);
  29573. Tcl_CreateObjCommand(interp,"::polygonxyz::edges",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_edges,NULL,NULL);
  29574. Tcl_CreateObjCommand(interp,"::polygonxyz::triangles",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_triangles,NULL,NULL);
  29575. Tcl_CreateObjCommand(interp,"::polygonxyz::uvcoords",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_uvcoords,NULL,NULL);
  29576. Tcl_CreateObjCommand(interp,"::polygonxyz::xycoords",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_xycoords,NULL,NULL);
  29577. Tcl_CreateObjCommand(interp,"::polygonxyz::compare",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_compare,NULL,NULL);
  29578. Tcl_CreateObjCommand(interp,"::polygonxyz::coplaner",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_coplaner,NULL,NULL);
  29579. Tcl_CreateObjCommand(interp,"::polygonxyz::flipped",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_flipped,NULL,NULL);
  29580. Tcl_CreateObjCommand(interp,"::polygonxyz::side",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_side,NULL,NULL);
  29581. Tcl_CreateObjCommand(interp,"::polygonxyz::intersect_test",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_intersect_test,NULL,NULL);
  29582. Tcl_CreateObjCommand(interp,"::polygonxyz::intersect_test_uv",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_intersect_test_uv,NULL,NULL);
  29583. Tcl_CreateObjCommand(interp,"::polygonxyz::intersect",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_intersect,NULL,NULL);
  29584. Tcl_CreateObjCommand(interp,"::polygonxyz::intersect_uv",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_intersect_uv,NULL,NULL);
  29585. Tcl_CreateObjCommand(interp,"::polygonxyz::points_within",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_points_within,NULL,NULL);
  29586. Tcl_CreateObjCommand(interp,"::polygonxyz::within",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_within,NULL,NULL);
  29587. Tcl_CreateObjCommand(interp,"::polygonxyz::within_set",(Tcl_ObjCmdProc *)TclCmd_polygonxyz_within_set,NULL,NULL);
  29588. {
  29589. Tcl_Namespace *modPtr;
  29590. modPtr=Tcl_FindNamespace(interp,"::polygonxyz",NULL,TCL_NAMESPACE_ONLY);
  29591. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29592. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29593. }
  29594. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/polygonxyz.tcl */
  29595. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/segset.tcl */
  29596. {
  29597. Tcl_Namespace *modPtr;
  29598. modPtr=Tcl_FindNamespace(interp,"::segset",NULL,TCL_NAMESPACE_ONLY);
  29599. if(!modPtr) {
  29600. modPtr = Tcl_CreateNamespace(interp, "::segset", NULL, NULL);
  29601. }
  29602. }
  29603. if (SegmentSet_OO_Init(interp) != TCL_OK) return TCL_ERROR;
  29604. {
  29605. Tcl_Namespace *modPtr;
  29606. modPtr=Tcl_FindNamespace(interp,"::segset",NULL,TCL_NAMESPACE_ONLY);
  29607. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29608. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29609. }
  29610. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/segset.tcl */
  29611. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/shapes.tcl */
  29612. {
  29613. Tcl_Namespace *modPtr;
  29614. modPtr=Tcl_FindNamespace(interp,"::shapes",NULL,TCL_NAMESPACE_ONLY);
  29615. if(!modPtr) {
  29616. modPtr = Tcl_CreateNamespace(interp, "::shapes", NULL, NULL);
  29617. }
  29618. }
  29619. Tcl_CreateObjCommand(interp,"::shapes::corners",(Tcl_ObjCmdProc *)TclCmd_shapes_corners,NULL,NULL);
  29620. Tcl_CreateObjCommand(interp,"::shapes::drawobj_orientation",(Tcl_ObjCmdProc *)TclCmd_shapes_drawobj_orientation,NULL,NULL);
  29621. Tcl_CreateObjCommand(interp,"::shapes::poly_hex",(Tcl_ObjCmdProc *)TclCmd_shapes_poly_hex,NULL,NULL);
  29622. Tcl_CreateObjCommand(interp,"::shapes::poly_place",(Tcl_ObjCmdProc *)TclCmd_shapes_poly_place,NULL,NULL);
  29623. Tcl_CreateObjCommand(interp,"::shapes::polygon_to_vectors",(Tcl_ObjCmdProc *)TclCmd_shapes_polygon_to_vectors,NULL,NULL);
  29624. Tcl_CreateObjCommand(interp,"::shapes::rectangle_as_polygon",(Tcl_ObjCmdProc *)TclCmd_shapes_rectangle_as_polygon,NULL,NULL);
  29625. Tcl_CreateObjCommand(interp,"::shapes::rectangle_as_vectors",(Tcl_ObjCmdProc *)TclCmd_shapes_rectangle_as_vectors,NULL,NULL);
  29626. Tcl_CreateObjCommand(interp,"::shapes::vector_place",(Tcl_ObjCmdProc *)TclCmd_shapes_vector_place,NULL,NULL);
  29627. Tcl_CreateObjCommand(interp,"::shapes::hexagon",(Tcl_ObjCmdProc *)TclCmd_shapes_hexagon,NULL,NULL);
  29628. Tcl_CreateObjCommand(interp,"::shapes::canvas",(Tcl_ObjCmdProc *)TclCmd_shapes_canvas,NULL,NULL);
  29629. {
  29630. Tcl_Namespace *modPtr;
  29631. modPtr=Tcl_FindNamespace(interp,"::shapes",NULL,TCL_NAMESPACE_ONLY);
  29632. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29633. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29634. }
  29635. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/shapes.tcl */
  29636. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/plotter.tcl */
  29637. if (Plotter_OO_Init(interp) != TCL_OK) return TCL_ERROR;
  29638. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/plotter.tcl */
  29639. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/slicer.tcl */
  29640. if (Slicer_OO_Init(interp) != TCL_OK) return TCL_ERROR;
  29641. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/slicer.tcl */
  29642. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/wallset.tcl */
  29643. if (Wallset_OO_Init(interp) != TCL_OK) return TCL_ERROR;
  29644. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/wallset.tcl */
  29645. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/faceset.tcl */
  29646. if (PolygonHull_OO_Init(interp) != TCL_OK) return TCL_ERROR;
  29647. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/geometry/faceset.tcl */
  29648. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/listcmd/listcmd.tcl */
  29649. Tcl_CreateObjCommand(interp,"::get",(Tcl_ObjCmdProc *)TclCmd_get,NULL,NULL);
  29650. Tcl_CreateObjCommand(interp,"::list_to_int",(Tcl_ObjCmdProc *)TclCmd_list_to_int,NULL,NULL);
  29651. Tcl_CreateObjCommand(interp,"::ladd",(Tcl_ObjCmdProc *)TclCmd_ladd,NULL,NULL);
  29652. Tcl_CreateObjCommand(interp,"::ldelete",(Tcl_ObjCmdProc *)TclCmd_ldelete,NULL,NULL);
  29653. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/listcmd/listcmd.tcl */
  29654. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/logicset/logicset.tcl */
  29655. {
  29656. Tcl_Namespace *modPtr;
  29657. modPtr=Tcl_FindNamespace(interp,"::logicset",NULL,TCL_NAMESPACE_ONLY);
  29658. if(!modPtr) {
  29659. modPtr = Tcl_CreateNamespace(interp, "::logicset", NULL, NULL);
  29660. }
  29661. }
  29662. Tcl_CreateObjCommand(interp,"::logicset::union",(Tcl_ObjCmdProc *)TclCmd_logicset_union,NULL,NULL);
  29663. Tcl_CreateObjCommand(interp,"::logicset::add",(Tcl_ObjCmdProc *)TclCmd_logicset_union,NULL,NULL);
  29664. Tcl_CreateObjCommand(interp,"::logicset::create",(Tcl_ObjCmdProc *)TclCmd_logicset_create,NULL,NULL);
  29665. Tcl_CreateObjCommand(interp,"::logicset::contains",(Tcl_ObjCmdProc *)TclCmd_logicset_contains,NULL,NULL);
  29666. Tcl_CreateObjCommand(interp,"::logicset::empty",(Tcl_ObjCmdProc *)TclCmd_logicset_empty,NULL,NULL);
  29667. Tcl_CreateObjCommand(interp,"::logicset::expr_and",(Tcl_ObjCmdProc *)TclCmd_logicset_expr_and,NULL,NULL);
  29668. Tcl_CreateObjCommand(interp,"::logicset::expr_or",(Tcl_ObjCmdProc *)TclCmd_logicset_expr_or,NULL,NULL);
  29669. Tcl_CreateObjCommand(interp,"::logicset::product_intersect",(Tcl_ObjCmdProc *)TclCmd_logicset_product_intersect,NULL,NULL);
  29670. Tcl_CreateObjCommand(interp,"::logicset::product_union",(Tcl_ObjCmdProc *)TclCmd_logicset_product_union,NULL,NULL);
  29671. Tcl_CreateObjCommand(interp,"::logicset::product_xor",(Tcl_ObjCmdProc *)TclCmd_logicset_product_xor,NULL,NULL);
  29672. Tcl_CreateObjCommand(interp,"::logicset::product_missing",(Tcl_ObjCmdProc *)TclCmd_logicset_product_missing,NULL,NULL);
  29673. Tcl_CreateObjCommand(interp,"::logicset::remove",(Tcl_ObjCmdProc *)TclCmd_logicset_remove,NULL,NULL);
  29674. {
  29675. Tcl_Namespace *modPtr;
  29676. modPtr=Tcl_FindNamespace(interp,"::logicset",NULL,TCL_NAMESPACE_ONLY);
  29677. Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
  29678. Tcl_Export(interp, modPtr, "[a-z]*", 1);
  29679. }
  29680. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/logicset/logicset.tcl */
  29681. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/literal/literal.tcl */
  29682. static int constant_once = 1;
  29683. if( constant_once ){
  29684. int i;
  29685. constant_once = 0;
  29686. Tcl_InitHashTable(&OdieLiteralStringTable,TCL_STRING_KEYS);
  29687.  
  29688. OdieStatic[ODIE_STATIC_NULL]=Tcl_NewObj();
  29689. Tcl_IncrRefCount(OdieStatic[ODIE_STATIC_NULL]);
  29690. Odie_constant_inject(OdieStatic[ODIE_STATIC_NULL]);
  29691.  
  29692. OdieStatic[ODIE_STATIC_ZERO] = Tcl_NewBooleanObj(0);
  29693. Tcl_IncrRefCount(OdieStatic[ODIE_STATIC_ZERO]);
  29694. Odie_constant_inject(OdieStatic[ODIE_STATIC_ZERO]);
  29695.  
  29696. OdieStatic[ODIE_STATIC_ONE] = Tcl_NewBooleanObj(1);
  29697. Tcl_IncrRefCount(OdieStatic[ODIE_STATIC_ONE]);
  29698. Odie_constant_inject(OdieStatic[ODIE_STATIC_ONE]);
  29699.  
  29700. for(i=2;i<10;i++) {
  29701. int idx=ODIE_STATIC_ZERO+i;
  29702. OdieStatic[idx] = Tcl_NewIntObj(i);
  29703. Tcl_IncrRefCount(OdieStatic[idx]);
  29704. Odie_constant_inject(OdieStatic[idx]);
  29705. }
  29706.  
  29707. OdieStatic[ODIE_STATIC_FZERO] = Tcl_NewDoubleObj(0.0);
  29708. Tcl_IncrRefCount(OdieStatic[ODIE_STATIC_FZERO]);
  29709. Odie_constant_inject(OdieStatic[ODIE_STATIC_FZERO]);
  29710.  
  29711. OdieStatic[ODIE_STATIC_NEG1] = Tcl_NewIntObj(-1);
  29712. Tcl_IncrRefCount(OdieStatic[ODIE_STATIC_NEG1]);
  29713. Odie_constant_inject(OdieStatic[ODIE_STATIC_NEG1]);
  29714. }
  29715. Tcl_CreateObjCommand(interp,"::literal",(Tcl_ObjCmdProc *)TclCmd_literal,NULL,NULL);
  29716. Tcl_CreateObjCommand(interp,"::literal_dump",(Tcl_ObjCmdProc *)TclCmd_literal_dump,NULL,NULL);
  29717. Tcl_CreateObjCommand(interp,"::literal_stats",(Tcl_ObjCmdProc *)TclCmd_literal_stats,NULL,NULL);
  29718. Tcl_CreateObjCommand(interp,"::constant_string",(Tcl_ObjCmdProc *)TclCmd_constant_string,NULL,NULL);
  29719. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/literal/literal.tcl */
  29720. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/location.tcl */
  29721. Tcl_CreateObjCommand(interp,"::location::grid_square",(Tcl_ObjCmdProc *)TclCmd_location_grid_square,NULL,NULL);
  29722. Tcl_CreateObjCommand(interp,"::location::gridhash_square",(Tcl_ObjCmdProc *)TclCmd_location_gridhash_square,NULL,NULL);
  29723. Tcl_CreateObjCommand(interp,"::location::location_gridhash",(Tcl_ObjCmdProc *)TclCmd_location_location_gridhash,NULL,NULL);
  29724. Tcl_CreateObjCommand(interp,"::location::grid_hex",(Tcl_ObjCmdProc *)TclCmd_location_grid_hex,NULL,NULL);
  29725. Tcl_CreateObjCommand(interp,"::location::gridhash_hex",(Tcl_ObjCmdProc *)TclCmd_location_gridhash_hex,NULL,NULL);
  29726. Tcl_CreateObjCommand(interp,"::location::gridhash_adjacent",(Tcl_ObjCmdProc *)TclCmd_location_gridhash_adjacent,NULL,NULL);
  29727. Tcl_CreateObjCommand(interp,"::location::object",(Tcl_ObjCmdProc *)TclCmd_location_object,NULL,NULL);
  29728. Tcl_CreateObjCommand(interp,"::location::midpoint",(Tcl_ObjCmdProc *)TclCmd_location_midpoint,NULL,NULL);
  29729. Tcl_CreateObjCommand(interp,"::location::match",(Tcl_ObjCmdProc *)TclCmd_location_match,NULL,NULL);
  29730. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/location.tcl */
  29731. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simulator.tcl */
  29732. if (Simulator_OO_Init(interp) != TCL_OK) return TCL_ERROR;
  29733. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simulator.tcl */
  29734. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/entity.tcl */
  29735. if (OOEntity_OO_Init(interp) != TCL_OK) return TCL_ERROR;
  29736. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/entity.tcl */
  29737. /* BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simtype.tcl */
  29738. if (SimType_OO_Init(interp) != TCL_OK) return TCL_ERROR;
  29739. /* END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simtype.tcl */
  29740. if(interp) {
  29741. if(Tcl_Eval(interp,
  29742. "\n" \
  29743. "# BEGIN /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simulator.tcl\n" \
  29744. "if {[info command ::simulator] eq {}} {\n" \
  29745. " ::odielib::simulator create ::simulator\n" \
  29746. "}\n" \
  29747. "if {[info command ::entity] eq {}} {\n" \
  29748. " ::odielib::entity create ::entity ::simulator\n" \
  29749. "}\n" \
  29750. "if {[info command ::simtype] eq {}} {\n" \
  29751. " ::odielib::simtype create ::simtype ::simulator\n" \
  29752. "}\n" \
  29753. "# END /Users/seandeelywoods/build/odie/odielib/cmodules/typespec/simulator.tcl\n" \
  29754. "\n" )) return TCL_ERROR;
  29755. }
  29756. if (Tcl_PkgProvide(interp, "odielibc" , "2.3" )) return TCL_ERROR;
  29757. return TCL_OK;
  29758. }
  29759.