00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * RCS INFORMATION: 00011 * 00012 * $RCSfile: TclGraphLayout.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.5 $ $Date: 2020年10月15日 16:07:31 $ 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" // for CMDLEN 00032 00033 //#if defined(VMDCUDA) 00034 //#include "CUDAGraphLayout.h" 00035 //#endif 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 //printf("layout_fr()\n"); 00136 GraphLayout *g = new GraphLayout(n, 0); 00137 00138 //printf("init_positions()\n"); 00139 g->init_positions_box(); 00140 00141 if (weights != NULL) { 00142 //printf("add_weight_matrix()\n"); 00143 g->add_weight_matrix(weights); 00144 } 00145 00146 //printf("compute()\n"); 00147 g->compute(iters, area, kscale, tempscale, distance_epsilon); 00148 00149 00150 //printf("get_vertex_ptrs()\n"); 00151 int numverts=0; 00152 const float *posx, *posy; 00153 g->get_vertex_ptrs(numverts, posx, posy); 00154 00155 //printf("generating vertex positions resul list...\n"); 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 //printf("delete g\n"); 00166 delete g; 00167 00168 if (weights) { 00169 //printf("delete weights\n"); 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