bn_tcl.c

Go to the documentation of this file.
00001 /*                        B N _ T C L . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1995-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 /** \addtogroup bntcl */
00022 /*@{*/
00023 /** @file bn_tcl.c
00024  * @brief
00025  *  Tcl interfaces to all the LIBBN math routines.
00026  *
00027  *  @author
00028  *      Glenn Durfee
00029  *
00030  *  @par Source
00031  *      The U. S. Army Research Laboratory
00032  *@n    Aberdeen Proving Ground, Maryland  21005-5068  USA
00033  */
00034 
00035 
00036 #ifndef lint
00037 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/libbn/bn_tcl.c,v 14.21 2006/09/07 01:19:17 lbutler Exp $ (ARL)";
00038 #endif
00039 
00040 #include "common.h"
00041 
00042 #include <stdlib.h>
00043 #include <stdio.h>
00044 #include <math.h>
00045 #ifdef HAVE_STRING_H
00046 #  include <string.h>
00047 #else
00048 #  include <strings.h>
00049 #endif
00050 
00051 #include "tcl.h"
00052 
00053 #include "machine.h"
00054 #include "bu.h"
00055 #include "vmath.h"
00056 #include "bn.h"
00057 
00058 /* Support routines for the math functions */
00059 
00060 /* XXX Really need a decode_array function that uses atof(),
00061  * XXX so that junk like leading { and commas between inputs
00062  * XXX don't spoil the conversion.
00063  */
00064 
00065 int
00066 bn_decode_mat(fastf_t *m, const char *str)
00067 {
00068         if( strcmp( str, "I" ) == 0 )  {
00069                 MAT_IDN( m );
00070                 return 16;
00071         }
00072         if( *str == '{' )  str++;
00073 
00074         return sscanf(str,
00075             "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
00076             &m[0], &m[1], &m[2], &m[3], &m[4], &m[5], &m[6], &m[7],
00077             &m[8], &m[9], &m[10], &m[11], &m[12], &m[13], &m[14], &m[15]);
00078 }
00079 
00080 int
00081 bn_decode_quat(fastf_t *q, const char *str)
00082 {
00083         if( *str == '{' )  str++;
00084         return sscanf(str, "%lf %lf %lf %lf", &q[0], &q[1], &q[2], &q[3]);
00085 }
00086 
00087 int
00088 bn_decode_vect(fastf_t *v, const char *str)
00089 {
00090         if( *str == '{' )  str++;
00091         return sscanf(str, "%lf %lf %lf", &v[0], &v[1], &v[2]);
00092 }
00093 
00094 int
00095 bn_decode_hvect(fastf_t *v, const char *str)
00096 {
00097         if( *str == '{' )  str++;
00098         return sscanf(str, "%lf %lf %lf %lf", &v[0], &v[1], &v[2], &v[3]);
00099 }
00100 
00101 void
00102 bn_encode_mat(struct bu_vls *vp, const mat_t m)
00103 {
00104         if( m == NULL )  {
00105                 bu_vls_putc(vp, 'I');
00106                 return;
00107         }
00108 
00109         bu_vls_printf(vp, "%g %g %g %g  %g %g %g %g  %g %g %g %g  %g %g %g %g",
00110             m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7],
00111             m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15]);
00112 }
00113 
00114 void
00115 bn_encode_quat(struct bu_vls *vp, const mat_t q)
00116 {
00117         bu_vls_printf(vp, "%g %g %g %g", V4ARGS(q));
00118 }
00119 
00120 void
00121 bn_encode_vect(struct bu_vls *vp, const mat_t v)
00122 {
00123         bu_vls_printf(vp, "%g %g %g", V3ARGS(v));
00124 }
00125 
00126 void
00127 bn_encode_hvect(struct bu_vls *vp, const mat_t v)
00128 {
00129         bu_vls_printf(vp, "%g %g %g %g", V4ARGS(v));
00130 }
00131 
00132 void
00133 bn_quat_distance_wrapper(double *dp, mat_t q1, mat_t q2)
00134 {
00135         *dp = quat_distance(q1, q2);
00136 }
00137 
00138 void
00139 bn_mat_scale_about_pt_wrapper(int *statusp, mat_t mat, const point_t pt, const double scale)
00140 {
00141         *statusp = bn_mat_scale_about_pt(mat, pt, scale);
00142 }
00143 
00144 static void
00145 bn_mat4x3pnt(fastf_t *o, mat_t m, point_t i)
00146 {
00147         MAT4X3PNT(o, m, i);
00148 }
00149 
00150 static void
00151 bn_mat4x3vec(fastf_t *o, mat_t m, vect_t i)
00152 {
00153         MAT4X3VEC(o, m, i);
00154 }
00155 
00156 static void
00157 bn_hdivide(fastf_t *o, const mat_t i)
00158 {
00159         HDIVIDE(o, i);
00160 }
00161 
00162 static void
00163 bn_vjoin1(fastf_t *o, const point_t pnt, double scale, const vect_t dir)
00164 {
00165         VJOIN1( o, pnt, scale, dir );
00166 }
00167 
00168 
00169 static void bn_vblend(mat_t a, fastf_t b, mat_t c, fastf_t d, mat_t e)
00170 {
00171         VBLEND2( a, b, c, d, e );
00172 }
00173 
00174 /**
00175  *                      B N _ M A T H _ C M D
00176  *@brief
00177  * Tcl wrappers for the math functions.
00178  *
00179  * This is where you should put clauses, in the below "if" statement, to add
00180  * Tcl support for the LIBBN math routines.
00181  */
00182 
00183 int
00184 bn_math_cmd(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
00185 {
00186         void (*math_func)();
00187         struct bu_vls result;
00188 
00189         math_func = (void (*)())clientData; /* object-to-function cast */
00190         bu_vls_init(&result);
00191 
00192         if (math_func == bn_mat_mul) {
00193                 mat_t o, a, b;
00194                 if (argc < 3 || bn_decode_mat(a, argv[1]) < 16 ||
00195                     bn_decode_mat(b, argv[2]) < 16) {
00196                         bu_vls_printf(&result, "usage: %s matA matB", argv[0]);
00197                         goto error;
00198                 }
00199                 bn_mat_mul(o, a, b);
00200                 bn_encode_mat(&result, o);
00201         } else if (math_func == bn_mat_inv || math_func == bn_mat_trn) {
00202                 mat_t o, a;
00203 
00204                 if (argc < 2 || bn_decode_mat(a, argv[1]) < 16) {
00205                         bu_vls_printf(&result, "usage: %s mat", argv[0]);
00206                         goto error;
00207                 }
00208                 (*math_func)(o, a);
00209                 bn_encode_mat(&result, o);
00210         } else if (math_func == bn_matXvec) {
00211                 mat_t m;
00212                 hvect_t i, o;
00213                 if (argc < 3 || bn_decode_mat(m, argv[1]) < 16 ||
00214                     bn_decode_hvect(i, argv[2]) < 4) {
00215                         bu_vls_printf(&result, "usage: %s mat hvect", argv[0]);
00216                         goto error;
00217                 }
00218                 bn_matXvec(o, m, i);
00219                 bn_encode_hvect(&result, o);
00220         } else if (math_func == bn_mat4x3pnt) {
00221                 mat_t m;
00222                 point_t i, o;
00223                 if (argc < 3 || bn_decode_mat(m, argv[1]) < 16 ||
00224                     bn_decode_vect(i, argv[2]) < 3) {
00225                         bu_vls_printf(&result, "usage: %s mat point", argv[0]);
00226                         goto error;
00227                 }
00228                 bn_mat4x3pnt(o, m, i);
00229                 bn_encode_vect(&result, o);
00230         } else if (math_func == bn_mat4x3vec) {
00231                 mat_t m;
00232                 vect_t i, o;
00233                 if (argc < 3 || bn_decode_mat(m, argv[1]) < 16 ||
00234                     bn_decode_vect(i, argv[2]) < 3) {
00235                         bu_vls_printf(&result, "usage: %s mat vect", argv[0]);
00236                         goto error;
00237                 }
00238                 bn_mat4x3vec(o, m, i);
00239                 bn_encode_vect(&result, o);
00240         } else if (math_func == bn_hdivide) {
00241                 hvect_t i;
00242                 vect_t o;
00243                 if (argc < 2 || bn_decode_hvect(i, argv[1]) < 4) {
00244                         bu_vls_printf(&result, "usage: %s hvect", argv[0]);
00245                         goto error;
00246                 }
00247                 bn_hdivide(o, i);
00248                 bn_encode_vect(&result, o);
00249         } else if (math_func == bn_vjoin1) {
00250                 point_t o;
00251                 point_t b, d;
00252                 fastf_t c;
00253 
00254                 if (argc < 4) {
00255                         bu_vls_printf(&result, "usage: %s pnt scale dir", argv[0]);
00256                         goto error;
00257                 }
00258                 if( bn_decode_vect(b, argv[1]) < 3) goto error;
00259                 if (Tcl_GetDouble(interp, argv[2], &c) != TCL_OK) goto error;
00260                 if( bn_decode_vect(d, argv[3]) < 3) goto error;
00261 
00262                 VJOIN1( o, b, c, d );   /* bn_vjoin1( o, b, c, d ) */
00263                 bn_encode_vect(&result, o);
00264 
00265         } else if ( math_func == bn_vblend) {
00266                 point_t a, c, e;
00267                 fastf_t b, d;
00268 
00269                 if( argc < 5 ) {
00270                         bu_vls_printf(&result, "usage: %s scale pnt scale pnt", argv[0]);
00271                         goto error;
00272                 }
00273 
00274                 if( Tcl_GetDouble(interp, argv[1], &b) != TCL_OK) goto error;
00275                 if( bn_decode_vect( c, argv[2] ) < 3) goto error;
00276                 if( Tcl_GetDouble(interp, argv[3], &d) != TCL_OK) goto error;
00277                 if( bn_decode_vect( e, argv[4] ) < 3) goto error;
00278 
00279                 VBLEND2( a, b, c, d, e )
00280                 bn_encode_vect( &result, a );
00281 
00282         } else if (math_func == bn_mat_ae) {
00283                 mat_t o;
00284                 double az, el;
00285 
00286                 if (argc < 3) {
00287                         bu_vls_printf(&result, "usage: %s azimuth elevation", argv[0]);
00288                         goto error;
00289                 }
00290                 if (Tcl_GetDouble(interp, argv[1], &az) != TCL_OK) goto error;
00291                 if (Tcl_GetDouble(interp, argv[2], &el) != TCL_OK) goto error;
00292 
00293                 bn_mat_ae(o, (fastf_t)az, (fastf_t)el);
00294                 bn_encode_mat(&result, o);
00295         } else if (math_func == bn_ae_vec) {
00296                 fastf_t az, el;
00297                 vect_t v;
00298 
00299                 if (argc < 2 || bn_decode_vect(v, argv[1]) < 3) {
00300                         bu_vls_printf(&result, "usage: %s vect", argv[0]);
00301                         goto error;
00302                 }
00303 
00304                 bn_ae_vec(&az, &el, v);
00305                 bu_vls_printf(&result, "%g %g", az, el);
00306         } else if (math_func == bn_aet_vec) {
00307                 fastf_t az, el, twist, accuracy;
00308                 vect_t vec_ae, vec_twist;
00309 
00310                 if (argc < 4 || bn_decode_vect(vec_ae, argv[1]) < 3 ||
00311                     bn_decode_vect(vec_twist, argv[2]) < 3 ||
00312                     sscanf(argv[3], "%lf", &accuracy) < 1) {
00313                   bu_vls_printf(&result, "usage: %s vec_ae vec_twist accuracy",
00314                                 argv[0]);
00315                   goto error;
00316                 }
00317 
00318                 bn_aet_vec(&az, &el, &twist, vec_ae, vec_twist, accuracy);
00319                 bu_vls_printf(&result, "%g %g %g", az, el, twist);
00320         } else if (math_func == bn_mat_angles) {
00321                 mat_t o;
00322                 double alpha, beta, ggamma;
00323 
00324                 if (argc < 4) {
00325                         bu_vls_printf(&result, "usage: %s alpha beta gamma", argv[0]);
00326                         goto error;
00327                 }
00328                 if (Tcl_GetDouble(interp, argv[1], &alpha) != TCL_OK)  goto error;
00329                 if (Tcl_GetDouble(interp, argv[2], &beta) != TCL_OK)   goto error;
00330                 if (Tcl_GetDouble(interp, argv[3], &ggamma) != TCL_OK) goto error;
00331 
00332                 bn_mat_angles(o, alpha, beta, ggamma);
00333                 bn_encode_mat(&result, o);
00334         } else if (math_func == bn_eigen2x2) {
00335                 fastf_t val1, val2;
00336                 vect_t vec1, vec2;
00337                 double a, b, c;
00338 
00339                 if (argc < 4) {
00340                         bu_vls_printf(&result, "usage: %s a b c", argv[0]);
00341                         goto error;
00342                 }
00343                 if (Tcl_GetDouble(interp, argv[1], &a) != TCL_OK) goto error;
00344                 if (Tcl_GetDouble(interp, argv[2], &c) != TCL_OK) goto error;
00345                 if (Tcl_GetDouble(interp, argv[3], &b) != TCL_OK) goto error;
00346 
00347                 bn_eigen2x2(&val1, &val2, vec1, vec2, (fastf_t)a, (fastf_t)b,
00348                     (fastf_t)c);
00349                 bu_vls_printf(&result, "%g %g {%g %g %g} {%g %g %g}", val1, val2,
00350                     V3ARGS(vec1), V3ARGS(vec2));
00351         } else if (math_func == bn_mat_fromto) {
00352                 mat_t o;
00353                 vect_t from, to;
00354 
00355                 if (argc < 3 || bn_decode_vect(from, argv[1]) < 3 ||
00356                     bn_decode_vect(to, argv[2]) < 3) {
00357                         bu_vls_printf(&result, "usage: %s vecFrom vecTo", argv[0]);
00358                         goto error;
00359                 }
00360                 bn_mat_fromto(o, from, to);
00361                 bn_encode_mat(&result, o);
00362         } else if (math_func == bn_mat_xrot || math_func == bn_mat_yrot ||
00363             math_func == bn_mat_zrot) {
00364                 mat_t o;
00365                 double s, c;
00366                 if (argc < 3) {
00367                         bu_vls_printf(&result, "usage: %s sinAngle cosAngle", argv[0]);
00368                         goto error;
00369                 }
00370                 if (Tcl_GetDouble(interp, argv[1], &s) != TCL_OK) goto error;
00371                 if (Tcl_GetDouble(interp, argv[2], &c) != TCL_OK) goto error;
00372 
00373                 (*math_func)(o, s, c);
00374                 bn_encode_mat(&result, o);
00375         } else if (math_func == bn_mat_lookat) {
00376                 mat_t o;
00377                 vect_t dir;
00378                 int yflip;
00379                 if (argc < 3 || bn_decode_vect(dir, argv[1]) < 3) {
00380                         bu_vls_printf(&result, "usage: %s dir yflip", argv[0]);
00381                         goto error;
00382                 }
00383                 if (Tcl_GetBoolean(interp, argv[2], &yflip) != TCL_OK) goto error;
00384 
00385                 bn_mat_lookat(o, dir, yflip);
00386                 bn_encode_mat(&result, o);
00387         } else if (math_func == bn_vec_ortho || math_func == bn_vec_perp) {
00388                 vect_t ov, vec;
00389 
00390                 if (argc < 2 || bn_decode_vect(vec, argv[1]) < 3) {
00391                         bu_vls_printf(&result, "usage: %s vec", argv[0]);
00392                         goto error;
00393                 }
00394 
00395                 (*math_func)(ov, vec);
00396                 bn_encode_vect(&result, ov);
00397         } else if (math_func == bn_mat_scale_about_pt_wrapper) {
00398                 mat_t o;
00399                 vect_t v;
00400                 double scale;
00401                 int status;
00402 
00403                 if (argc < 3 || bn_decode_vect(v, argv[1]) < 3) {
00404                         bu_vls_printf(&result, "usage: %s pt scale", argv[0]);
00405                         goto error;
00406                 }
00407                 if (Tcl_GetDouble(interp, argv[2], &scale) != TCL_OK) goto error;
00408 
00409                 bn_mat_scale_about_pt_wrapper(&status, o, v, scale);
00410                 if (status != 0) {
00411                         bu_vls_printf(&result, "error performing calculation");
00412                         goto error;
00413                 }
00414                 bn_encode_mat(&result, o);
00415         } else if (math_func == bn_mat_xform_about_pt) {
00416                 mat_t o, xform;
00417                 vect_t v;
00418 
00419                 if (argc < 3 || bn_decode_mat(xform, argv[1]) < 16 ||
00420                     bn_decode_vect(v, argv[2]) < 3) {
00421                         bu_vls_printf(&result, "usage: %s xform pt", argv[0]);
00422                         goto error;
00423                 }
00424 
00425                 bn_mat_xform_about_pt(o, xform, v);
00426                 bn_encode_mat(&result, o);
00427         } else if (math_func == bn_mat_arb_rot) {
00428                 mat_t o;
00429                 point_t pt;
00430                 vect_t dir;
00431                 double angle;
00432 
00433                 if (argc < 4 || bn_decode_vect(pt, argv[1]) < 3 ||
00434                     bn_decode_vect(dir, argv[2]) < 3) {
00435                         bu_vls_printf(&result, "usage: %s pt dir angle", argv[0]);
00436                         goto error;
00437                 }
00438                 if (Tcl_GetDouble(interp, argv[3], &angle) != TCL_OK)
00439                         return TCL_ERROR;
00440 
00441                 bn_mat_arb_rot(o, pt, dir, (fastf_t)angle);
00442                 bn_encode_mat(&result, o);
00443         } else if (math_func == quat_mat2quat) {
00444                 mat_t mat;
00445                 quat_t quat;
00446 
00447                 if (argc < 2 || bn_decode_mat(mat, argv[1]) < 16) {
00448                         bu_vls_printf(&result, "usage: %s mat", argv[0]);
00449                         goto error;
00450                 }
00451 
00452                 quat_mat2quat(quat, mat);
00453                 bn_encode_quat(&result, quat);
00454         } else if (math_func == quat_quat2mat) {
00455                 mat_t mat;
00456                 quat_t quat;
00457 
00458                 if (argc < 2 || bn_decode_quat(quat, argv[1]) < 4) {
00459                         bu_vls_printf(&result, "usage: %s quat", argv[0]);
00460                         goto error;
00461                 }
00462 
00463                 quat_quat2mat(mat, quat);
00464                 bn_encode_mat(&result, mat);
00465         } else if (math_func == bn_quat_distance_wrapper) {
00466                 quat_t q1, q2;
00467                 double d;
00468 
00469                 if (argc < 3 || bn_decode_quat(q1, argv[1]) < 4 ||
00470                     bn_decode_quat(q2, argv[2]) < 4) {
00471                         bu_vls_printf(&result, "usage: %s quatA quatB", argv[0]);
00472                         goto error;
00473                 }
00474 
00475                 bn_quat_distance_wrapper(&d, q1, q2);
00476                 bu_vls_printf(&result, "%g", d);
00477         } else if (math_func == quat_double || math_func == quat_bisect ||
00478             math_func == quat_make_nearest) {
00479                 quat_t oqot, q1, q2;
00480 
00481                 if (argc < 3 || bn_decode_quat(q1, argv[1]) < 4 ||
00482                     bn_decode_quat(q2, argv[2]) < 4) {
00483                         bu_vls_printf(&result, "usage: %s quatA quatB", argv[0]);
00484                         goto error;
00485                 }
00486 
00487                 (*math_func)(oqot, q1, q2);
00488                 bn_encode_quat(&result, oqot);
00489         } else if (math_func == quat_slerp) {
00490                 quat_t oq, q1, q2;
00491                 double d;
00492 
00493                 if (argc < 4 || bn_decode_quat(q1, argv[1]) < 4 ||
00494                     bn_decode_quat(q2, argv[2]) < 4) {
00495                         bu_vls_printf(&result, "usage: %s quat1 quat2 factor", argv[0]);
00496                         goto error;
00497                 }
00498                 if (Tcl_GetDouble(interp, argv[3], &d) != TCL_OK) goto error;
00499 
00500                 quat_slerp(oq, q1, q2, d);
00501                 bn_encode_quat(&result, oq);
00502         } else if (math_func == quat_sberp) {
00503                 quat_t oq, q1, qa, qb, q2;
00504                 double d;
00505 
00506                 if (argc < 6 || bn_decode_quat(q1, argv[1]) < 4 ||
00507                     bn_decode_quat(qa, argv[2]) < 4 || bn_decode_quat(qb, argv[3]) < 4 ||
00508                     bn_decode_quat(q2, argv[4]) < 4) {
00509                         bu_vls_printf(&result, "usage: %s quat1 quatA quatB quat2 factor",
00510                             argv[0]);
00511                         goto error;
00512                 }
00513                 if (Tcl_GetDouble(interp, argv[5], &d) != TCL_OK) goto error;
00514 
00515                 quat_sberp(oq, q1, qa, qb, q2, d);
00516                 bn_encode_quat(&result, oq);
00517         } else if (math_func == quat_exp || math_func == quat_log) {
00518                 quat_t qout, qin;
00519 
00520                 if (argc < 2 || bn_decode_quat(qin, argv[1]) < 4) {
00521                         bu_vls_printf(&result, "usage: %s quat", argv[0]);
00522                         goto error;
00523                 }
00524 
00525                 (*math_func)(qout, qin);
00526                 bn_encode_quat(&result, qout);
00527         } else if (math_func == (void (*)())bn_isect_line3_line3) {
00528             double t, u;
00529             point_t pt, a;
00530             vect_t dir, c;
00531             int i;
00532             const static struct bn_tol tol = {
00533                 BN_TOL_MAGIC, 0.005, 0.005*0.005, 1e-6, 1-1e-6
00534             };
00535             if (argc != 5) {
00536                 bu_vls_printf(&result, 
00537                       "Usage: bn_isect_line3_line3 pt dir pt dir (%d args specified)",
00538                               argc-1);
00539                 goto error;
00540             }
00541 
00542             if (bn_decode_vect(pt, argv[1]) < 3) {
00543                 bu_vls_printf(&result, "bn_isect_line3_line3 no pt: %s\n", argv[0]);
00544                 goto error;
00545             }
00546             if (bn_decode_vect(dir, argv[2]) < 3) {
00547                 bu_vls_printf(&result, "bn_isect_line3_line3 no dir: %s\n", argv[0]);
00548                 goto error;
00549             }
00550             if (bn_decode_vect(a, argv[3]) < 3) {
00551                 bu_vls_printf(&result, "bn_isect_line3_line3 no a pt: %s\n", argv[0]);
00552                 goto error;
00553             }
00554             if (bn_decode_vect(c, argv[4]) < 3) {
00555                 bu_vls_printf(&result, "bn_isect_line3_line3 no c dir: %s\n", argv[0]);
00556                 goto error;
00557             }
00558             i = bn_isect_line3_line3(&t, &u, pt, dir, a, c, &tol);
00559             if (i != 1) {
00560                 bu_vls_printf(&result, "bn_isect_line3_line3 no intersection: %s\n", argv[0]);
00561                 goto error;
00562             }
00563 
00564             VJOIN1(a, pt, t, dir);
00565             bn_encode_vect(&result, a);
00566 
00567         } else if (math_func == (void (*)())bn_isect_line2_line2) {
00568             double dist[2];
00569             point_t pt, a;
00570             vect_t dir, c;
00571             int i;
00572             const static struct bn_tol tol = {
00573                 BN_TOL_MAGIC, 0.005, 0.005*0.005, 1e-6, 1-1e-6
00574             };
00575 
00576             if (argc != 5) {
00577                 bu_vls_printf(&result, 
00578                       "Usage: bn_isect_line2_line2 pt dir pt dir (%d args specified)",
00579                               argc-1);
00580                 goto error;
00581             }
00582 
00583             /* i = bn_isect_line2_line2 {0 0} {1 0} {1 1} {0 -1} */
00584 
00585             VSETALL(pt, 0.0);
00586             VSETALL(dir, 0.0);
00587             VSETALL(a, 0.0);
00588             VSETALL(c, 0.0);
00589 
00590             if (bn_decode_vect(pt, argv[1]) < 2) {
00591                 bu_vls_printf(&result, "bn_isect_line2_line2 no pt: %s\n", argv[0]);
00592                 goto error;
00593             }
00594             if (bn_decode_vect(dir, argv[2]) < 2) {
00595                 bu_vls_printf(&result, "bn_isect_line2_line2 no dir: %s\n", argv[0]);
00596                 goto error;
00597             }
00598             if (bn_decode_vect(a, argv[3]) < 2) {
00599                 bu_vls_printf(&result, "bn_isect_line2_line2 no a pt: %s\n", argv[0]);
00600                 goto error;
00601             }
00602             if (bn_decode_vect(c, argv[4]) < 2) {
00603                 bu_vls_printf(&result, "bn_isect_line2_line2 no c dir: %s\n", argv[0]);
00604                 goto error;
00605             }
00606             i = bn_isect_line2_line2(dist, pt, dir, a, c, &tol);
00607             if (i != 1) {
00608                 bu_vls_printf(&result, "bn_isect_line2_line2 no intersection: %s\n", argv[0]);
00609                 goto error;
00610             }
00611 
00612             VJOIN1(a, pt, dist[0], dir);
00613             bu_vls_printf(&result, "%g %g", a[0], a[1]);
00614 
00615         } else {
00616                 bu_vls_printf(&result, "libbn/bn_tcl.c: math function %s not supported yet\n", argv[0]);
00617                 goto error;
00618         }
00619 
00620         Tcl_AppendResult(interp, bu_vls_addr(&result), (char *)NULL);
00621         bu_vls_free(&result);
00622         return TCL_OK;
00623 
00624 error:
00625         Tcl_AppendResult(interp, bu_vls_addr(&result), (char *)NULL);
00626         bu_vls_free(&result);
00627         return TCL_ERROR;
00628 }
00629 
00630 static struct math_func_link {
00631         char *name;
00632         void (*func)();
00633 } math_funcs[] = {
00634     {"bn_isect_line2_line2",    (void (*)())bn_isect_line2_line2},
00635     {"bn_isect_line3_line3",    (void (*)())bn_isect_line3_line3},
00636         {"mat_mul",            bn_mat_mul},
00637         {"mat_inv",            bn_mat_inv},
00638         {"mat_trn",            bn_mat_trn},
00639         {"matXvec",            bn_matXvec},
00640         {"mat4x3vec",          bn_mat4x3vec},
00641         {"mat4x3pnt",          bn_mat4x3pnt},
00642         {"hdivide",            bn_hdivide},
00643         {"vjoin1",            bn_vjoin1},
00644         {"vblend",              bn_vblend},
00645         {"mat_ae",             bn_mat_ae},
00646         {"mat_ae_vec",         bn_ae_vec},
00647         {"mat_aet_vec",        bn_aet_vec},
00648         {"mat_angles",         bn_mat_angles},
00649         {"mat_eigen2x2",       bn_eigen2x2},
00650         {"mat_fromto",         bn_mat_fromto},
00651         {"mat_xrot",           bn_mat_xrot},
00652         {"mat_yrot",           bn_mat_yrot},
00653         {"mat_zrot",           bn_mat_zrot},
00654         {"mat_lookat",         bn_mat_lookat},
00655         {"mat_vec_ortho",      bn_vec_ortho},
00656         {"mat_vec_perp",       bn_vec_perp},
00657         {"mat_scale_about_pt", bn_mat_scale_about_pt_wrapper},
00658         {"mat_xform_about_pt", bn_mat_xform_about_pt},
00659         {"mat_arb_rot",        bn_mat_arb_rot},
00660         {"quat_mat2quat",      quat_mat2quat},
00661         {"quat_quat2mat",      quat_quat2mat},
00662         {"quat_distance",      bn_quat_distance_wrapper},
00663         {"quat_double",        quat_double},
00664         {"quat_bisect",        quat_bisect},
00665         {"quat_slerp",         quat_slerp},
00666         {"quat_sberp",         quat_sberp},
00667         {"quat_make_nearest",  quat_make_nearest},
00668         {"quat_exp",           quat_exp},
00669         {"quat_log",           quat_log},
00670         {0, 0}
00671 };
00672 
00673 int
00674 bn_cmd_noise_perlin(ClientData clientData,
00675                   Tcl_Interp *interp,
00676                   int argc,
00677                   char **argv)
00678 {
00679         point_t pt;
00680         double  v;
00681 
00682         if (argc != 4) {
00683                 Tcl_AppendResult(interp, "wrong # args: should be \"",
00684                                  argv[0], " X Y Z \"",
00685                                  NULL);
00686                 return TCL_ERROR;
00687         }
00688 
00689         pt[X] = atof(argv[1]);
00690         pt[Y] = atof(argv[2]);
00691         pt[Z] = atof(argv[3]);
00692 
00693         v = bn_noise_perlin( pt );
00694         sprintf(interp->result, "%g", v );
00695 
00696         return TCL_OK;
00697 }
00698 
00699 /*
00700  *  usage: bn_noise_fbm X Y Z h_val lacunarity octaves
00701  *
00702  */
00703 int
00704 bn_cmd_noise(ClientData clientData,
00705                  Tcl_Interp *interp,
00706                  int argc,
00707                  char **argv)
00708 {
00709         point_t pt;
00710         double h_val;
00711         double lacunarity;
00712         double octaves;
00713         double val;
00714 
00715         if (argc != 7) {
00716                 Tcl_AppendResult(interp, "wrong # args: should be \"",
00717                                  argv[0], " X Y Z h_val lacunarity octaves\"",
00718                                  NULL);
00719                 return TCL_ERROR;
00720         }
00721 
00722         pt[0] = atof(argv[1]);
00723         pt[1] = atof(argv[2]);
00724         pt[2] = atof(argv[3]);
00725 
00726         h_val = atof(argv[4]);
00727         lacunarity = atof(argv[5]);
00728         octaves = atof(argv[6]);
00729 
00730 
00731         if (!strcmp("bn_noise_turb", argv[0])) {
00732                 val = bn_noise_turb(pt, h_val, lacunarity, octaves);
00733 
00734                 sprintf(interp->result, "%g", val );
00735         } else  if (!strcmp("bn_noise_fbm", argv[0])) {
00736                 val = bn_noise_fbm(pt, h_val, lacunarity, octaves);
00737                 sprintf(interp->result, "%g", val );
00738         } else {
00739                 Tcl_AppendResult(interp, "Unknown noise type \"",
00740                                  argv[0], "\"",  NULL);
00741                 return TCL_ERROR;
00742         }
00743         return TCL_OK;
00744 }
00745 
00746 
00747 /**
00748  * @brief
00749  *      usage: noise_slice xdim ydim inv h_val lac octaves dX dY dZ sX [sY sZ]
00750  *
00751  *      The idea here is to get a whole slice of noise at once, thereby
00752  *      avoiding the overhead of doing this in Tcl.
00753  */
00754 int
00755 bn_cmd_noise_slice(ClientData clientData,
00756                   Tcl_Interp *interp,
00757                   int argc,
00758                   char **argv)
00759 {
00760         double h_val;
00761         double lacunarity;
00762         double octaves;
00763 
00764         vect_t delta;   /* translation to noise space */
00765         vect_t scale;   /* scale to noise space */
00766         unsigned xdim;  /* # samples X direction */
00767         unsigned ydim;  /* # samples Y direction */
00768         unsigned xval, yval;
00769 #define NOISE_FBM 0
00770 #define NOISE_TURB 1
00771 
00772         int noise_type = NOISE_FBM;
00773         double val;
00774         point_t pt;
00775 
00776         if (argc != 7) {
00777                 Tcl_AppendResult(interp, "wrong # args: should be \"",
00778                                  argv[0], " Xdim Ydim Zval h_val lacunarity octaves\"",
00779                                  NULL);
00780                 return TCL_ERROR;
00781         }
00782 
00783         xdim = atoi(argv[0]);
00784         ydim = atoi(argv[1]);
00785         VSETALL(delta, 0.0);
00786         VSETALL(scale, 1.);
00787         pt[Z] = delta[Z] = atof(argv[2]);
00788         h_val = atof(argv[3]);
00789         lacunarity = atof(argv[4]);
00790         octaves = atof(argv[5]);
00791 
00792         switch (noise_type) {
00793         case NOISE_FBM:
00794                 for (yval = 0 ; yval < ydim ; yval++) {
00795 
00796                     pt[Y] = yval * scale[Y] + delta[Y];
00797 
00798                     for (xval = 0 ; xval < xdim ; xval++) {
00799                         pt[X] = xval * scale[X] + delta[X];
00800 
00801                         val = bn_noise_fbm(pt, h_val, lacunarity, octaves);
00802 
00803                     }
00804                 }
00805                 break;
00806         case NOISE_TURB:
00807                 for (yval = 0 ; yval < ydim ; yval++) {
00808 
00809                     pt[Y] = yval * scale[Y] + delta[Y];
00810 
00811                     for (xval = 0 ; xval < xdim ; xval++) {
00812                         pt[X] = xval * scale[X] + delta[X];
00813 
00814                         val = bn_noise_turb(pt, h_val, lacunarity, octaves);
00815 
00816                     }
00817                 }
00818                 break;
00819         }
00820 
00821 
00822         pt[0] = atof(argv[1]);
00823         pt[1] = atof(argv[2]);
00824         pt[2] = atof(argv[3]);
00825 
00826         h_val = atof(argv[4]);
00827         lacunarity = atof(argv[5]);
00828         octaves = atof(argv[6]);
00829 
00830 
00831         if (!strcmp("bn_noise_turb", argv[0])) {
00832                 val = bn_noise_turb(pt, h_val, lacunarity, octaves);
00833 
00834                 sprintf(interp->result, "%g", val );
00835         } else  if (!strcmp("bn_noise_fbm", argv[0])) {
00836                 val = bn_noise_fbm(pt, h_val, lacunarity, octaves);
00837                 sprintf(interp->result, "%g", val );
00838         } else {
00839                 Tcl_AppendResult(interp, "Unknown noise type \"",
00840                                  argv[0], "\"",  NULL);
00841                 return TCL_ERROR;
00842         }
00843         return TCL_OK;
00844 }
00845 
00846 
00847 int
00848 bn_cmd_random(ClientData clientData,
00849                   Tcl_Interp *interp,
00850                   int argc,
00851                   char **argv)
00852 {
00853         int val;
00854         const char *str;
00855         double rnd;
00856         char buf[32];
00857 
00858         if (argc != 2) {
00859                 Tcl_AppendResult(interp, "Wrong # args:  Should be \"",
00860                                  argv[0], " varname\"", NULL);
00861                 return TCL_ERROR;
00862         }
00863 
00864         if (! (str=Tcl_GetVar(interp, argv[1], 0))) {
00865                 Tcl_AppendResult(interp, "Error getting variable ",
00866                                  argv[1], NULL);
00867                 return TCL_ERROR;
00868         }
00869         val = atoi(str);
00870 
00871         if (val < 0) val = 0;
00872 
00873         rnd = BN_RANDOM(val);
00874 
00875         sprintf(buf, "%d", val);
00876 
00877         if (!Tcl_SetVar(interp, argv[1], buf, 0)) {
00878                 Tcl_AppendResult(interp, "Error setting variable ",
00879                                  argv[1], NULL);
00880                 return TCL_ERROR;
00881         }
00882 
00883         sprintf(buf, "%g", rnd);
00884         Tcl_AppendResult(interp, buf, NULL);
00885         return TCL_OK;
00886 }
00887 
00888 /**
00889  *                      B N _ M A T _ P R I N T
00890  */
00891 void
00892 bn_tcl_mat_print(Tcl_Interp             *interp,
00893                  const char             *title,
00894                  const mat_t            m)
00895 {
00896         char            obuf[1024];     /* sprintf may be non-PARALLEL */
00897 
00898         bn_mat_print_guts(title, m, obuf);
00899         Tcl_AppendResult(interp, obuf, "\n", (char *)NULL);
00900 }
00901 
00902 /**
00903  *                      B N _ T C L _ S E T U P
00904  *@brief
00905  *  Add all the supported Tcl interfaces to LIBBN routines to
00906  *  the list of commands known by the given interpreter.
00907  */
00908 void
00909 bn_tcl_setup(Tcl_Interp *interp)
00910 {
00911         struct math_func_link *mp;
00912 
00913         for (mp = math_funcs; mp->name != NULL; mp++) {
00914                 (void)Tcl_CreateCommand(interp, mp->name,
00915                     (Tcl_CmdProc *)bn_math_cmd,
00916                     (ClientData)mp->func, /* Function-to-Object pointer cast */
00917                     (Tcl_CmdDeleteProc *)NULL);
00918         }
00919 
00920         (void)Tcl_CreateCommand(interp, "bn_noise_perlin",
00921                 (Tcl_CmdProc *)bn_cmd_noise_perlin, (ClientData)NULL,
00922                 (Tcl_CmdDeleteProc *)NULL);
00923 
00924         (void)Tcl_CreateCommand(interp, "bn_noise_turb",
00925                 (Tcl_CmdProc *)bn_cmd_noise, (ClientData)NULL,
00926                 (Tcl_CmdDeleteProc *)NULL);
00927 
00928         (void)Tcl_CreateCommand(interp, "bn_noise_fbm",
00929                 (Tcl_CmdProc *)bn_cmd_noise, (ClientData)NULL,
00930                 (Tcl_CmdDeleteProc *)NULL);
00931 
00932         (void)Tcl_CreateCommand(interp, "bn_noise_slice",
00933                 (Tcl_CmdProc *)bn_cmd_noise_slice, (ClientData)NULL,
00934                 (Tcl_CmdDeleteProc *)NULL);
00935 
00936         (void)Tcl_CreateCommand(interp, "bn_random",
00937                 (Tcl_CmdProc *)bn_cmd_random, (ClientData)NULL,
00938                 (Tcl_CmdDeleteProc *)NULL);
00939 
00940 
00941         Tcl_SetVar(interp, "bn_version", (char *)bn_version+5, TCL_GLOBAL_ONLY);
00942 }
00943 
00944 /**
00945  *                      B N _ I N I T
00946  *@brief
00947  *  Allows LIBBN to be dynamically loade to a vanilla tclsh/wish with
00948  *  "load /usr/brlcad/lib/libbn.so"
00949  *
00950  *  The name of this function is specified by TCL.
00951  */
00952 int
00953 #ifdef BRLCAD_DEBUG
00954 Bn_d_Init(Tcl_Interp *interp)
00955 #else
00956 Bn_Init(Tcl_Interp *interp)
00957 #endif
00958 {
00959         bn_tcl_setup(interp);
00960         return TCL_OK;
00961 }
00962 
00963 
00964 double bn_noise_fbm(point_t point,double h_val,double lacunarity,double octaves);
00965 double bn_noise_turb(point_t point,double h_val,double lacunarity,double octaves);
00966 /*@}*/
00967 /*
00968  * Local Variables:
00969  * mode: C
00970  * tab-width: 8
00971  * c-basic-offset: 4
00972  * indent-tabs-mode: t
00973  * End:
00974  * ex: shiftwidth=4 tabstop=8
00975  */

Generated on Mon Sep 18 01:24:47 2006 for BRL-CAD by  doxygen 1.4.6