32 #define VMD_PI 3.14159265358979323846
33 #define VMD_TWOPI (2.0 * VMD_PI)
34 #define DEGTORAD(a) (a*VMD_PI/180.0)
35 #define RADTODEG(a) (a*180.0/VMD_PI)
44 static int obj_vecadd(ClientData, Tcl_Interp *interp,
int argc,
45 Tcl_Obj *
const objv[]) {
47 Tcl_WrongNumArgs(interp, 1, objv, (
char *)
"vec1 vec2 ?vec3? ?vec4? ...");
52 if (Tcl_ListObjGetElements(interp, objv[1], &num, &data) != TCL_OK) {
55 double *sum =
new double[num];
57 for (i=0; i<num; i++) {
58 if (Tcl_GetDoubleFromObj(interp, data[i], sum+i) != TCL_OK) {
65 for (
int term=2; term < argc; term++) {
66 if (Tcl_ListObjGetElements(interp, objv[term], &num2, &data) != TCL_OK) {
71 Tcl_SetResult(interp, (
char *)
"vecadd: two vectors don't have the same size", TCL_STATIC);
75 for (i=0; i<num; i++) {
77 if (Tcl_GetDoubleFromObj(interp, data[i], &df) != TCL_OK) {
87 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
88 for (i=0; i<num; i++) {
89 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(sum[i]));
91 Tcl_SetObjResult(interp, tcl_result);
100 static int obj_vecsub(ClientData, Tcl_Interp *interp,
int argc, Tcl_Obj *
const objv[])
103 Tcl_WrongNumArgs(interp, 1, objv, (
char *)
"?x? ?y?");
107 Tcl_Obj **data1, **data2;
108 if (Tcl_ListObjGetElements(interp, objv[1], &num1, &data1) != TCL_OK)
110 if (Tcl_ListObjGetElements(interp, objv[2], &num2, &data2) != TCL_OK)
114 Tcl_SetResult(interp, (
char *)
"vecsub: two vectors don't have the same size", TCL_STATIC);
118 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
119 for (
int i=0; i<num1; i++) {
121 if (Tcl_GetDoubleFromObj(interp, data1[i], &d1) != TCL_OK) {
122 Tcl_SetResult(interp, (
char *)
"vecsub: non-numeric in first argument", TCL_STATIC);
125 if (Tcl_GetDoubleFromObj(interp, data2[i], &d2) != TCL_OK) {
126 Tcl_SetResult(interp, (
char *)
"vecsub: non-numeric in second argument", TCL_STATIC);
129 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(d1-d2));
131 Tcl_SetObjResult(interp, tcl_result);
140 Tcl_Obj *
const objv[]) {
142 Tcl_WrongNumArgs(interp, 1, objv, (
char *)
"?c? ?v?");
147 Tcl_Obj **data1, **data2;
148 if (Tcl_ListObjGetElements(interp, objv[1], &num1, &data1) != TCL_OK) {
151 if (Tcl_ListObjGetElements(interp, objv[2], &num2, &data2) != TCL_OK) {
154 if (num1 == 0 || num2 == 0) {
155 Tcl_SetResult(interp, (
char *)
"vecscale: parameters must have data", TCL_STATIC);
157 }
else if (num1 != 1 && num2 != 1) {
158 Tcl_SetResult(interp, (
char *)
"vecscale: one parameter must be a scalar value", TCL_STATIC);
163 Tcl_Obj *scalarobj, **vector;
165 scalarobj = data1[0];
169 scalarobj = data2[0];
175 if (Tcl_GetDoubleFromObj(interp, scalarobj, &scalar) != TCL_OK)
178 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
179 for (
int i=0; i<num; i++) {
181 if (Tcl_GetDoubleFromObj(interp, vector[i], &val) != TCL_OK) {
182 Tcl_SetResult(interp, (
char *)
"vecscale: non-numeric in vector", TCL_STATIC);
186 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(val));
188 Tcl_SetObjResult(interp, tcl_result);
198 Tcl_Obj *s,
double *mat)
202 if (Tcl_ListObjGetElements(interp, s, &num_rows, &data_rows) != TCL_OK) {
203 char tmpstring[1024];
204 sprintf(tmpstring,
"%s: badly formed matrix", fctn);
205 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE);
209 char tmpstring[1024];
210 sprintf(tmpstring,
"%s: need a 4x4 matrix", fctn);
211 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE);
215 Tcl_Obj **data_row[4];
216 if (Tcl_ListObjGetElements(interp, data_rows[0], num_row+0, data_row+0) != TCL_OK ||
218 Tcl_ListObjGetElements(interp, data_rows[1], num_row+1, data_row+1) != TCL_OK ||
220 Tcl_ListObjGetElements(interp, data_rows[2], num_row+2, data_row+2) != TCL_OK ||
222 Tcl_ListObjGetElements(interp, data_rows[3], num_row+3, data_row+3) != TCL_OK ||
224 Tcl_AppendResult(interp, fctn,
": poorly formed matrix", NULL);
228 for (
int i=0; i<4; i++) {
229 for (
int j=0; j<4; j++) {
231 if (Tcl_GetDoubleFromObj(interp, data_row[i][j], &tmp) != TCL_OK) {
232 char tmpstring[1024];
233 sprintf(tmpstring,
"%s: non-numeric in matrix", fctn);
234 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE);
237 mat[4*j+i] = (double) tmp;
245 int tcl_get_vector(
const char *s,
double *val, Tcl_Interp *interp)
249 if (Tcl_SplitList(interp, s, &num, &pos) != TCL_OK) {
250 Tcl_SetResult(interp, (
char *)
"need three data elements for a vector",
255 Tcl_SetResult(interp, (
char *)
"need three numbers for a vector", TCL_STATIC);
259 if (Tcl_GetDouble(interp, pos[0], a+0) != TCL_OK ||
260 Tcl_GetDouble(interp, pos[1], a+1) != TCL_OK ||
261 Tcl_GetDouble(interp, pos[2], a+2) != TCL_OK) {
262 ckfree((
char *) pos);
265 val[0] = (double) a[0];
266 val[1] = (double) a[1];
267 val[2] = (double) a[2];
268 ckfree((
char *) pos);
275 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
276 for (
int i=0; i<4; i++) {
277 Tcl_Obj *m = Tcl_NewListObj(0, NULL);
278 for (
int j=0; j<4; j++)
279 Tcl_ListObjAppendElement(interp, m, Tcl_NewDoubleObj(mat[4*j+i]));
280 Tcl_ListObjAppendElement(interp, tcl_result, m);
282 Tcl_SetObjResult(interp, tcl_result);
289 Tcl_Obj *
const objv[])
292 Tcl_WrongNumArgs(interp, 1, objv, (
char *)
"?matrix? ?vector?");
299 Tcl_GetStringFromObj(objv[0],NULL), interp, objv[1], mat) != TCL_OK) {
306 if (Tcl_ListObjGetElements(interp, objv[2], &vec_size, &vec) != TCL_OK)
309 if (vec_size != 3 && vec_size != 4) {
310 Tcl_SetResult(interp, (
char *)
"vectrans: vector must be of size 3 or 4",
317 for (
int i=0; i<vec_size; i++) {
319 if (Tcl_GetDoubleFromObj(interp, vec[i], &tmp) != TCL_OK) {
320 Tcl_SetResult(interp, (
char *)
"vectrans: non-numeric in vector", TCL_STATIC);
323 opoint[i] = (double)tmp;
328 npoint[0]=opoint[0]*mat[0]+opoint[1]*mat[4]+opoint[2]*mat[8]+opoint[3]*mat[12]
330 npoint[1]=opoint[0]*mat[1]+opoint[1]*mat[5]+opoint[2]*mat[9]+opoint[3]*mat[13]
332 npoint[2]=opoint[0]*mat[2]+opoint[1]*mat[6]+opoint[2]*mat[10]+opoint[3]*mat[14
334 npoint[3]=opoint[0]*mat[3]+opoint[1]*mat[7]+opoint[2]*mat[11]+opoint[3]*mat[15
339 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
340 for (
int i=0; i<vec_size; i++)
341 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(npoint[i]));
342 Tcl_SetObjResult(interp, tcl_result);
352 Tcl_Obj *
const objv[]) {
355 Tcl_WrongNumArgs(interp, 1, objv, (
char *)
"mx my ?m1? ?m2? ...");
360 if (
tcl_get_matrix(
"transmult: ", interp, objv[1], mult) != TCL_OK) {
366 if (
tcl_get_matrix(
"transmult: ", interp, objv[i], pre) != TCL_OK) {
371 for (
int k=0; k<4; k++) {
376 for (
int j=0; j<4; j++) {
377 mult[4*j+k] = pre[4*j]*tmp[0] + pre[4*j+1]*tmp[1] +
378 pre[4*j+2]*tmp[2] + pre[4*j+3]*tmp[3];
388 Tcl_Obj *
const objv[]) {
390 Tcl_WrongNumArgs(interp, 1, objv, (
char *)
"?vector?");
396 if (Tcl_ListObjGetElements(interp, objv[1], &num, &data) != TCL_OK)
399 Tcl_AppendResult(interp,
"transvec: vector must have three elements",NULL);
403 if (Tcl_GetDoubleFromObj(interp, data[0], &x) != TCL_OK ||
404 Tcl_GetDoubleFromObj(interp, data[1], &y) != TCL_OK ||
405 Tcl_GetDoubleFromObj(interp, data[2], &z) != TCL_OK) {
406 Tcl_SetResult(interp, (
char *)
"transvec: non-numeric in vector", TCL_STATIC);
410 mat.
transvec((
double) x,(
double) y,(
double) z);
416 Tcl_Obj *
const objv[]) {
418 Tcl_WrongNumArgs(interp, 1, objv, (
char *)
"?vector?");
424 if (Tcl_ListObjGetElements(interp, objv[1], &num, &data) != TCL_OK)
427 Tcl_AppendResult(interp,
"transvecinv: vector must have three elements",NULL);
431 if (Tcl_GetDoubleFromObj(interp, data[0], &x) != TCL_OK ||
432 Tcl_GetDoubleFromObj(interp, data[1], &y) != TCL_OK ||
433 Tcl_GetDoubleFromObj(interp, data[2], &z) != TCL_OK) {
434 Tcl_SetResult(interp, (
char *)
"transvecinv: non-numeric in vector", TCL_STATIC);
449 Tcl_Obj *
const objv[]) {
450 if (argc != 3 && argc != 4) {
451 Tcl_WrongNumArgs(interp, 1, objv, (
char *)
"axis amount [deg|rad|pi]");
458 if (Tcl_ListObjGetElements(interp, objv[1], &num, &data) != TCL_OK)
461 Tcl_AppendResult(interp,
"transabout: vector must have three elements",NULL);
465 if (Tcl_GetDoubleFromObj(interp, data[0], &x) != TCL_OK ||
466 Tcl_GetDoubleFromObj(interp, data[1], &y) != TCL_OK ||
467 Tcl_GetDoubleFromObj(interp, data[2], &z) != TCL_OK) {
468 Tcl_SetResult(interp, (
char *)
"transabout: non-numeric in vector", TCL_STATIC);
474 if (Tcl_GetDoubleFromObj(interp, objv[2], &amount) != TCL_OK) {
475 Tcl_SetResult(interp, (
char *)
"transabout: non-numeric angle", TCL_STATIC);
481 if (!strcmp(Tcl_GetStringFromObj(objv[3], NULL),
"deg")) {
483 }
else if (!strcmp(Tcl_GetStringFromObj(objv[3], NULL),
"rad")) {
485 }
else if (!strcmp(Tcl_GetStringFromObj(objv[3], NULL),
"pi")) {
488 Tcl_AppendResult(interp,
"transabout: unit must be deg|rad|pi",NULL);
497 axis[0] = (double) x;
498 axis[1] = (double) y;
499 axis[2] = (double) z;
507 static int obj_veclength(ClientData, Tcl_Interp *interp,
int argc, Tcl_Obj *
const objv[]) {
510 Tcl_WrongNumArgs(interp, 1, objv, (
char *)
"?vector?");
516 if (Tcl_ListObjGetElements(interp, objv[1], &num, &data) != TCL_OK)
520 for (
int i=0; i<num; i++) {
522 if (Tcl_GetDoubleFromObj(interp, data[i], &tmp) != TCL_OK) {
523 Tcl_SetResult(interp, (
char *)
"veclength: non-numeric in vector", TCL_STATIC);
530 length = sqrt(length);
531 Tcl_Obj *tcl_result = Tcl_GetObjResult(interp);
532 Tcl_SetDoubleObj(tcl_result, length);
541 if (Tcl_ListObjGetElements(interp, objv[1], &num, &data) != TCL_OK)
544 double *list = (
double*) malloc(num*
sizeof(
double));
548 for (
int i=0; i<num; i++) {
550 if (Tcl_GetDoubleFromObj(interp, data[i], &tmp) != TCL_OK) {
551 Tcl_SetResult(interp, (
char *)
"veclength: non-numeric in vector", TCL_STATIC);
564 static int obj_vecsum(ClientData, Tcl_Interp *interp,
int argc, Tcl_Obj *
const objv[]) {
566 Tcl_WrongNumArgs(interp, 1, objv, (
char *)
"?vector?");
576 for (
int i=0; i<num; i++) {
581 Tcl_Obj *tcl_result = Tcl_GetObjResult(interp);
582 Tcl_SetDoubleObj(tcl_result, sum);
587 static int obj_vecmean(ClientData, Tcl_Interp *interp,
int argc, Tcl_Obj *
const objv[]) {
589 Tcl_WrongNumArgs(interp, 1, objv, (
char *)
"?vector?");
599 for (
int i=0; i<num; i++) {
605 Tcl_Obj *tcl_result = Tcl_GetObjResult(interp);
606 Tcl_SetDoubleObj(tcl_result, sum);
611 static int obj_vecstddev(ClientData, Tcl_Interp *interp,
int argc, Tcl_Obj *
const objv[]) {
613 Tcl_WrongNumArgs(interp, 1, objv, (
char *)
"?vector?");
623 for (i=0; i<num; i++) {
626 mean /= (double) num;
629 for (i=0; i<num; i++) {
630 double tmp = list[i] - mean;
633 stddev /= (double) num;
634 stddev = sqrt(stddev);
637 Tcl_Obj *tcl_result = Tcl_GetObjResult(interp);
638 Tcl_SetDoubleObj(tcl_result, stddev);
644 Tcl_CreateObjCommand(interp,
"vecadd",
obj_vecadd,
645 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
646 Tcl_CreateObjCommand(interp,
"vecsub",
obj_vecsub,
647 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
649 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
651 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
653 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
655 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
656 Tcl_CreateObjCommand(interp,
"vecmean",
obj_vecmean,
657 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
659 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
660 Tcl_CreateObjCommand(interp,
"vecsum",
obj_vecsum,
661 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
663 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
665 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
667 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
int Vec_Init(Tcl_Interp *interp)
static int obj_vectrans(ClientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[])
void transvecinv(double x, double y, double z)
apply a rotation such that the given vector is brought along 'x'.
void tcl_append_matrix(Tcl_Interp *interp, const double *mat)
static int obj_vecmean(ClientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[])
static int obj_transvecinv(ClientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[])
static int obj_transmult(ClientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[])
4x4 matrix class with numerous operators, conversions, etc.
static int obj_vecscale(ClientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[])
static int obj_vecsum(ClientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[])
static int obj_vecadd(ClientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[])
static int obj_vecstddev(ClientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[])
int tcl_get_matrix(const char *fctn, Tcl_Interp *interp, Tcl_Obj *s, double *mat)
Given a string with a matrix in it, return the matrix.
static int obj_transvec(ClientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[])
void rotate_axis(const double axis[3], double angle)
apply a rotation around the given vector; angle in radians.
static int obj_transabout(ClientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[])
double mat[16]
the matrix itself
void transvec(double x, double y, double z)
apply a rotation such that 'x' is brought along the given vector.
static int obj_vecsub(ClientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[])
static int obj_veclength(ClientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[])
static double * obj_getdoublearray(Tcl_Interp *interp, Tcl_Obj *const objv[], int *len)