00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <math.h>
00026 #include "VMDApp.h"
00027 #include "Inform.h"
00028 #include "GraphLayout.h"
00029 #include <tcl.h>
00030 #include "TclCommands.h"
00031 #include "config.h"
00032
00033
00034
00035
00036
00037 int layout_fr(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00038 int i;
00039 if ((argc <3) || (argc > 12 )) {
00040 msgErr << "Usage: node_count iterations [-weights weightlist]" << sendmsg;
00041 return 0;
00042 }
00043
00044 int n = 0;
00045 int iters = 0;
00046 float area = 1.0f;
00047 float kscale = 1.0e3f;
00048 float tempscale = 0.2f;
00049 float distance_epsilon = 1.0e-6f;
00050 float *weights = NULL;
00051
00052 if (Tcl_GetIntFromObj(interp, objv[1], &n) != TCL_OK) {
00053 Tcl_AppendResult(interp, "\n node_count incorrectly specified",NULL);
00054 return TCL_ERROR;
00055 }
00056 if (n<1) {
00057 Tcl_AppendResult(interp, "\n node_count incorrectly specified",NULL);
00058 return TCL_ERROR;
00059 }
00060
00061 if (Tcl_GetIntFromObj(interp, objv[2], &iters) != TCL_OK) {
00062 Tcl_AppendResult(interp, "\n iterations incorrectly specified",NULL);
00063 return TCL_ERROR;
00064 }
00065 if (iters<0) {
00066 Tcl_AppendResult(interp, "\n iterations incorrectly specified",NULL);
00067 return TCL_ERROR;
00068 }
00069
00070
00071 for (i=3; i < argc; i++) {
00072 char *opt = Tcl_GetStringFromObj(objv[i], NULL);
00073 if (!strcmp(opt, "-weights")) {
00074 if (i == argc-1) {
00075 Tcl_AppendResult(interp, "No weights specified",NULL);
00076 return TCL_ERROR;
00077 }
00078
00079 int matlen = 0;
00080 Tcl_Obj **data;
00081 if (Tcl_ListObjGetElements(interp, objv[i+1], &matlen, &data) != TCL_OK) {
00082 return TCL_ERROR;
00083 }
00084
00085 if (matlen != (n*n)) {
00086 Tcl_AppendResult(interp, "Incorrect weight matrix size specified",NULL);
00087 return TCL_ERROR;
00088 }
00089
00090 weights = new float[n*n];
00091 for (i=0; i<matlen; i++) {
00092 double tmp;
00093 if (Tcl_GetDoubleFromObj(interp, data[i], &tmp) != TCL_OK) {
00094 delete [] weights;
00095 return TCL_ERROR;
00096 }
00097 weights[i] = float(tmp);
00098 }
00099 }
00100
00101 if (!strcmp(opt, "-area")) {
00102 double tmp;
00103 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
00104 return TCL_ERROR;
00105 }
00106 area = float(tmp);
00107 }
00108
00109 if (!strcmp(opt, "-kscale")) {
00110 double tmp;
00111 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
00112 return TCL_ERROR;
00113 }
00114 kscale = float(tmp);
00115 }
00116
00117 if (!strcmp(opt, "-tempscale")) {
00118 double tmp;
00119 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
00120 return TCL_ERROR;
00121 }
00122 tempscale = float(tmp);
00123 }
00124
00125 if (!strcmp(opt, "-distance_epsilon")) {
00126 double tmp;
00127 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
00128 return TCL_ERROR;
00129 }
00130 distance_epsilon = float(tmp);
00131 }
00132 }
00133
00134
00135
00136 GraphLayout *g = new GraphLayout(n, 0);
00137
00138
00139 g->init_positions_box();
00140
00141 if (weights != NULL) {
00142
00143 g->add_weight_matrix(weights);
00144 }
00145
00146
00147 g->compute(iters, area, kscale, tempscale, distance_epsilon);
00148
00149
00150
00151 int numverts=0;
00152 const float *posx, *posy;
00153 g->get_vertex_ptrs(numverts, posx, posy);
00154
00155
00156 Tcl_Obj *vertexlist = Tcl_NewListObj(0, NULL);
00157 for (i=0; i<numverts; i++) {
00158 Tcl_Obj *vertex = Tcl_NewListObj(0, NULL);
00159 Tcl_ListObjAppendElement(interp, vertex, Tcl_NewDoubleObj(posx[i]));
00160 Tcl_ListObjAppendElement(interp, vertex, Tcl_NewDoubleObj(posy[i]));
00161 Tcl_ListObjAppendElement(interp, vertexlist, vertex);
00162 }
00163 Tcl_SetObjResult(interp, vertexlist);
00164
00165
00166 delete g;
00167
00168 if (weights) {
00169
00170 delete [] weights;
00171 }
00172
00173 return 0;
00174 }
00175
00176
00177 int obj_graphlayout(ClientData cd, Tcl_Interp *interp, int argc,
00178 Tcl_Obj * const objv[]){
00179 if (argc < 2) {
00180 Tcl_SetResult(interp,
00181 (char *) "Usage: graphlayout <command> [args...]\n"
00182 "Commands:\n"
00183 "fr -- Perform Fruchterman-Reingold style spring layout\n"
00184 ,
00185 TCL_STATIC);
00186 return TCL_ERROR;
00187 }
00188 char *argv1 = Tcl_GetStringFromObj(objv[1],NULL);
00189
00190 VMDApp *app = (VMDApp *)cd;
00191 if (!strupncmp(argv1, "fr", CMDLEN))
00192 return layout_fr(app, argc-1, objv+1, interp);
00193
00194 Tcl_SetResult(interp, (char *) "Type 'graphlayout' for summary of usage\n", TCL_VOLATILE);
00195 return TCL_OK;
00196 }
00197
00198