From 95d6c999c3681325f97462a825763359e32007d8 Mon Sep 17 00:00:00 2001 From: Ksenia Date: Mon, 16 Mar 2026 19:45:00 +0100 Subject: [PATCH 01/10] Move globals to structure --- src/v.c | 107 +++++++++++++++------------------- src/v/ac3_draw.c | 49 +++++++++------- src/v/load.c | 14 +++++ src/v/loop.c | 18 +++--- src/v/tools.c | 13 ----- src/v/v.h | 2 +- src/v/x.c | 147 +++++++++++++++++++++++------------------------ src/v/x.h | 22 +++---- src/v/xinput.c | 4 +- 9 files changed, 179 insertions(+), 197 deletions(-) diff --git a/src/v.c b/src/v.c index a56c657..455c697 100644 --- a/src/v.c +++ b/src/v.c @@ -2,61 +2,54 @@ #include "x.h" #include "evr.h" -Display * dis; -int screen; -Window win; -GC gc_white, gc_black, gc_red, gc_dot[2], gcc[NCOLORS]; -Pixmap px; -Drawable canv; -XFontStruct * fontInfo; -int W,H; -int (*myDrawString)(); - +draw_world_t world; static void init_keys(ptf kp[NKP]){ memset(kp, 0, sizeof(ptf)*NKP); - kp[ XKeysymToKeycode(dis, XK_Escape ) ] = kp_exit ; - kp[ XKeysymToKeycode(dis, XK_period ) ] = kp_pg ; - kp[ XKeysymToKeycode(dis, XK_1 ) ] = kp_rl_dec ; - kp[ XKeysymToKeycode(dis, XK_2 ) ] = kp_rl_inc ; - kp[ XKeysymToKeycode(dis, XK_3 ) ] = kp_r_dec ; - kp[ XKeysymToKeycode(dis, XK_4 ) ] = kp_r_inc ; - kp[ XKeysymToKeycode(dis, XK_0 ) ] = kp_goto_1st ; - kp[ XKeysymToKeycode(dis, XK_equal ) ] = kp_goto_last ; - kp[ XKeysymToKeycode(dis, XK_BackSpace ) ] = kp_frame_dec ; - kp[ XKeysymToKeycode(dis, XK_Tab ) ] = kp_readmore ; - kp[ XKeysymToKeycode(dis, XK_q ) ] = kp_exit ; - kp[ XKeysymToKeycode(dis, XK_w ) ] = kp_move_u ; - kp[ XKeysymToKeycode(dis, XK_r ) ] = kp_readagain ; - kp[ XKeysymToKeycode(dis, XK_t ) ] = kp_t_toggle ; - kp[ XKeysymToKeycode(dis, XK_u ) ] = kp_printrot ; - kp[ XKeysymToKeycode(dis, XK_p ) ] = kp_print2fig ; - kp[ XKeysymToKeycode(dis, XK_Return ) ] = kp_frame_inc ; - kp[ XKeysymToKeycode(dis, XK_a ) ] = kp_move_l ; - kp[ XKeysymToKeycode(dis, XK_s ) ] = kp_move_d ; - kp[ XKeysymToKeycode(dis, XK_d ) ] = kp_move_r ; - kp[ XKeysymToKeycode(dis, XK_f ) ] = kp_film ; - kp[ XKeysymToKeycode(dis, XK_j ) ] = kp_jump ; - kp[ XKeysymToKeycode(dis, XK_l ) ] = kp_l_toggle ; - kp[ XKeysymToKeycode(dis, XK_z ) ] = kp_print_xyz ; - kp[ XKeysymToKeycode(dis, XK_x ) ] = kp_print ; - kp[ XKeysymToKeycode(dis, XK_b ) ] = kp_b_toggle ; - kp[ XKeysymToKeycode(dis, XK_n ) ] = kp_n_toggle ; - kp[ XKeysymToKeycode(dis, XK_m ) ] = kp_savepic ; - kp[ XKeysymToKeycode(dis, XK_End ) ] = kp_zoom_out ; - kp[ XKeysymToKeycode(dis, XK_Up ) ] = kp_rotx_r ; - kp[ XKeysymToKeycode(dis, XK_Page_Up ) ] = kp_rotz_l ; - kp[ XKeysymToKeycode(dis, XK_Left ) ] = kp_roty_l ; - kp[ XKeysymToKeycode(dis, XK_Right ) ] = kp_roty_r ; - kp[ XKeysymToKeycode(dis, XK_Home ) ] = kp_zoom_in ; - kp[ XKeysymToKeycode(dis, XK_Down ) ] = kp_rotx_l ; - kp[ XKeysymToKeycode(dis, XK_Page_Down ) ] = kp_rotz_r ; - kp[ XKeysymToKeycode(dis, XK_Insert ) ] = kp_fw_toggle ; - kp[ XKeysymToKeycode(dis, XK_Delete ) ] = kp_bw_toggle ; - kp[ XKeysymToKeycode(dis, XK_KP_Up ) ] = kp_move_u ; - kp[ XKeysymToKeycode(dis, XK_KP_Left ) ] = kp_move_l ; - kp[ XKeysymToKeycode(dis, XK_KP_Right ) ] = kp_move_r ; - kp[ XKeysymToKeycode(dis, XK_KP_Down ) ] = kp_move_d ; +#define ASSIGN_KEY(KEY, ACTION) { kp[XKeysymToKeycode(world.dis, (KEY))] = (ACTION); } + ASSIGN_KEY( XK_Escape , kp_exit ); + ASSIGN_KEY( XK_period , kp_pg ); + ASSIGN_KEY( XK_1 , kp_rl_dec ); + ASSIGN_KEY( XK_2 , kp_rl_inc ); + ASSIGN_KEY( XK_3 , kp_r_dec ); + ASSIGN_KEY( XK_4 , kp_r_inc ); + ASSIGN_KEY( XK_0 , kp_goto_1st ); + ASSIGN_KEY( XK_equal , kp_goto_last ); + ASSIGN_KEY( XK_BackSpace , kp_frame_dec ); + ASSIGN_KEY( XK_Tab , kp_readmore ); + ASSIGN_KEY( XK_q , kp_exit ); + ASSIGN_KEY( XK_w , kp_move_u ); + ASSIGN_KEY( XK_r , kp_readagain ); + ASSIGN_KEY( XK_t , kp_t_toggle ); + ASSIGN_KEY( XK_u , kp_printrot ); + ASSIGN_KEY( XK_p , kp_print2fig ); + ASSIGN_KEY( XK_Return , kp_frame_inc ); + ASSIGN_KEY( XK_a , kp_move_l ); + ASSIGN_KEY( XK_s , kp_move_d ); + ASSIGN_KEY( XK_d , kp_move_r ); + ASSIGN_KEY( XK_f , kp_film ); + ASSIGN_KEY( XK_j , kp_jump ); + ASSIGN_KEY( XK_l , kp_l_toggle ); + ASSIGN_KEY( XK_z , kp_print_xyz ); + ASSIGN_KEY( XK_x , kp_print ); + ASSIGN_KEY( XK_b , kp_b_toggle ); + ASSIGN_KEY( XK_n , kp_n_toggle ); + ASSIGN_KEY( XK_m , kp_savepic ); + ASSIGN_KEY( XK_End , kp_zoom_out ); + ASSIGN_KEY( XK_Up , kp_rotx_r ); + ASSIGN_KEY( XK_Page_Up , kp_rotz_l ); + ASSIGN_KEY( XK_Left , kp_roty_l ); + ASSIGN_KEY( XK_Right , kp_roty_r ); + ASSIGN_KEY( XK_Home , kp_zoom_in ); + ASSIGN_KEY( XK_Down , kp_rotx_l ); + ASSIGN_KEY( XK_Page_Down , kp_rotz_r ); + ASSIGN_KEY( XK_Insert , kp_fw_toggle ); + ASSIGN_KEY( XK_Delete , kp_bw_toggle ); + ASSIGN_KEY( XK_KP_Up , kp_move_u ); + ASSIGN_KEY( XK_KP_Left , kp_move_l ); + ASSIGN_KEY( XK_KP_Right , kp_move_r ); + ASSIGN_KEY( XK_KP_Down , kp_move_d ); +#undef ASSIGN_KEY return; } @@ -104,16 +97,6 @@ int main (int argc, char * argv[]) { init_x(dp->read.fname, ap.ip.colors); init_keys(kp); init_font(ap.ip.fontname); -#if 0 - myDrawString = &XDrawString; -#else - myDrawString = &XDrawImageString; -#endif -#if 0 - canv = win; -#else - canv = px; -#endif /*= Main loop ==============================================================*/ main_loop(ent, dp, kp); diff --git a/src/v/ac3_draw.c b/src/v/ac3_draw.c index 657dcbe..8afbffd 100644 --- a/src/v/ac3_draw.c +++ b/src/v/ac3_draw.c @@ -2,17 +2,24 @@ #include "x.h" #define EPS 1e-15 -#define BOND_OFFSET 0.666 // bond line starts this fraction of the atom radius away from the atom center -#define RESOL_SCALE (128.0/768.0) // reference resolution for atom sizes - -extern int W,H; -extern int screen; -extern Display * dis; -extern GC gc_white, gc_black, gc_dot[2], gcc[NCOLORS]; -extern Window win; -extern Pixmap px; -extern Drawable canv; -extern int (*myDrawString)(); +#define BOND_OFFSET 0.666 // bond line starts this fraction of the atom radius away from the atom center +#define RESOL_SCALE (128.0/768.0) // reference resolution for atom sizes +#define XDRAWSTRING XDrawImageString // change to XDrawString to remove white boxes behind atom/bond labels + +#define CLEARCANV \ + if(world.canv == world.px){\ + XFillRectangle(world.dis, world.px, world.gc_white, 0, 0, world.W, world.H);\ + }\ + else if(world.canv == world.win){\ + XClearWindow(world.dis, world.win);\ + } + +#define FILLCANV \ + if(world.canv == world.px){\ + XCopyArea(world.dis, world.px, world.win, world.gc_white, 0, 0, world.W, world.H, 0, 0);\ + } + +extern draw_world_t world; static inline int getgci(int q){ return abs(q)0) ? malloc(sizeof(int)*n) : NULL; - double d = MIN(H,W) * rend.scale; - double resol = MIN(H,W) * RESOL_SCALE; + double d = MIN(world.H,world.W) * rend.scale; + double resol = MIN(world.H,world.W) * RESOL_SCALE; double r1 = rend.r * resol * rend.scale; for(int k=0; kq[k]); int r = MAX(1, rt); - XFillArc (dis, canv, gcc[getgci(q)], x-r, y-r, 2*r, 2*r, 0, 360*64); + XFillArc (world.dis, world.canv, world.gcc[getgci(q)], x-r, y-r, 2*r, 2*r, 0, 360*64); if(r>1){ - XDrawArc(dis, canv, q>0?gc_black:gc_dot[1], x-r, y-r, 2*r, 2*r, 0, 360*64); + XDrawArc(world.dis, world.canv, q>0?world.gc_black:world.gc_dot[1], x-r, y-r, 2*r, 2*r, 0, 360*64); } if(rend.num == 1){ char text[16]; snprintf(text, sizeof(text), "%d", k+1); - myDrawString(dis, canv, gc_black, x, y, text, strlen(text)); + XDRAWSTRING(world.dis, world.canv, world.gc_black, x, y, text, strlen(text)); } else if(rend.num == -1){ char text[16]; const char * s = getname(q); s ? snprintf(text, sizeof(text), "%s", s) : snprintf(text, sizeof(text), "%d", q ); - myDrawString(dis, canv, gc_black, x, y, text, strlen(text)); + XDRAWSTRING(world.dis, world.canv, world.gc_black, x, y, text, strlen(text)); } if(rend.bonds>0){ @@ -104,11 +111,11 @@ void ac3_draw(atcoord * ac, rendpars rend){ continue; } double dd = BOND_OFFSET * r / sqrt(r2d); - XDrawLine(dis, canv, gc_black, x+dd*dx, y+dd*dy, x1, y1); + XDrawLine(world.dis, world.canv, world.gc_black, x+dd*dx, y+dd*dy, x1, y1); if(rend.bonds==2){ char text[16]; snprintf(text, sizeof(text), "%.3lf", ac->bonds.r[j]); - myDrawString(dis, canv, gc_black, x+dx/2, y+dy/2, text, strlen(text)); + XDRAWSTRING(world.dis, world.canv, world.gc_black, x+dx/2, y+dy/2, text, strlen(text)); } } } diff --git a/src/v/load.c b/src/v/load.c index 2246d2c..e04d96f 100644 --- a/src/v/load.c +++ b/src/v/load.c @@ -13,6 +13,20 @@ static inline void fill_nf(object * acs, int n0){ return; } +void newmol_prep(object * acs, drawpars * dp){ + for(int j=dp->N; jn; j++){ + atcoord * ac = acs->m[j]; + for(int i=0; in; i++){ + double v[3]; + r3mx(v, ac->r+3*i, dp->rend.ac3rmx); + r3cp(ac->r+3*i, v); + } + } + dp->N = acs->n; + return; +} + + void acs_readmore(readpars read, int b, geompars geom, object * acs){ // needed to reset nf diff --git a/src/v/loop.c b/src/v/loop.c index 1dd4971..2efd4f7 100644 --- a/src/v/loop.c +++ b/src/v/loop.c @@ -4,9 +4,7 @@ #define VIBRO_SUBSTEPS 4 -extern int W,H; -extern Display * dis; -extern Window win; +extern draw_world_t world; typedef struct { int click; @@ -18,7 +16,7 @@ static void process_mouse(XMotionEvent * event, object * ent, drawpars * dp, mou if(mouse->click){ int x = event->x; int y = event->y; - rot_ent_pointer(ent, dp, x-mouse->x0, y-mouse->y0, POINTER_SPEED/MIN(W,H)); + rot_ent_pointer(ent, dp, x-mouse->x0, y-mouse->y0, POINTER_SPEED/MIN(world.W,world.H)); exp_redraw(ent, dp); mouse->x0 = x; mouse->y0 = y; @@ -71,8 +69,8 @@ static void run_animation(object * ent, drawpars * dp, int * tr){ void main_loop(object * ent, drawpars * dp, ptf kp[NKP]){ // To handle window closing. Thanks to https://stackoverflow.com/a/1186544 - Atom wm_delete_window = XInternAtom(dis, "WM_DELETE_WINDOW", False); - XSetWMProtocols(dis, win, &wm_delete_window, 1); + Atom wm_delete_window = XInternAtom(world.dis, "WM_DELETE_WINDOW", False); + XSetWMProtocols(world.dis, world.win, &wm_delete_window, 1); mouse_state_t mouse = {.click=0, .x0=0, .y0=0}; int tr = 0; @@ -80,7 +78,7 @@ void main_loop(object * ent, drawpars * dp, ptf kp[NKP]){ XEvent event_rec; XEvent * event = NULL; do{ - XNextEvent(dis, &event_rec); + XNextEvent(world.dis, &event_rec); #if 0 printf("%d\n", event_rec.type); #endif @@ -90,7 +88,7 @@ void main_loop(object * ent, drawpars * dp, ptf kp[NKP]){ if(event->type == ButtonPress || event->type == ButtonRelease){ break; } - } while(XEventsQueued(dis, QueuedAlready)); + } while(XEventsQueued(world.dis, QueuedAlready)); if (event->type == ClientMessage) { if ((Atom)event->xclient.data.l[0] == wm_delete_window) { @@ -103,8 +101,8 @@ void main_loop(object * ent, drawpars * dp, ptf kp[NKP]){ } else if(event->type == ConfigureNotify){ - W = event->xconfigure.width; - H = event->xconfigure.height; + world.W = event->xconfigure.width; + world.H = event->xconfigure.height; dp->rend.xy0[0] = dp->rend.xy0[1] = 0.0; exp_redraw(ent, dp); } diff --git a/src/v/tools.c b/src/v/tools.c index d186adf..25a6d49 100644 --- a/src/v/tools.c +++ b/src/v/tools.c @@ -13,19 +13,6 @@ void obj_free(object * ent){ return; } -void newmol_prep(object * acs, drawpars * dp){ - for(int j=dp->N; jn; j++){ - atcoord * ac = acs->m[j]; - for(int i=0; in; i++){ - double v[3]; - r3mx(v, ac->r+3*i, dp->rend.ac3rmx); - r3cp(ac->r+3*i, v); - } - } - dp->N = acs->n; - return; -} - void ac3_text(atcoord * ac, drawpars * dp){ char text[STRLEN]; int tp = snprintf(text, sizeof(text), diff --git a/src/v/v.h b/src/v/v.h index f649ae8..e3cf204 100644 --- a/src/v/v.h +++ b/src/v/v.h @@ -54,6 +54,7 @@ typedef struct { // load.c +void newmol_prep(object * acs, drawpars * dp); object * acs_from_var(int n, mol * m, vibr_t vib, allpars * ap); void acs_readmore (readpars read, int b, geompars geom, object * acs); object * read_files(allpars * ap); @@ -109,7 +110,6 @@ int process_x_input(char input_text[STRLEN], unsigned int keycode); // tools.c void obj_free(object * ent); -void newmol_prep(object * acs, drawpars * dp); void ac3_text(atcoord * ac, drawpars * dp); void vibro_text(vibr_t * ms, drawpars * dp); void pg(atcoord * a, double symtol); diff --git a/src/v/x.c b/src/v/x.c index 74b436d..4401db2 100644 --- a/src/v/x.c +++ b/src/v/x.c @@ -2,31 +2,23 @@ #include "x.h" #include "vec2.h" -extern Display * dis; -extern int screen; -extern Window win; -extern GC gc_white, gc_black, gc_red, gc_dot[2], gcc[NCOLORS]; -extern Pixmap px; -extern Drawable canv; -extern XFontStruct * fontInfo; - -extern int W,H; +extern draw_world_t world; void close_x(void) { - XFreeGC(dis, gc_red); - XFreeGC(dis, gc_black); - XFreeGC(dis, gc_white); - XFreeGC(dis, gc_dot[0]); - XFreeGC(dis, gc_dot[1]); + XFreeGC(world.dis, world.gc_red); + XFreeGC(world.dis, world.gc_black); + XFreeGC(world.dis, world.gc_white); + XFreeGC(world.dis, world.gc_dot[0]); + XFreeGC(world.dis, world.gc_dot[1]); for(int i=0; iscreen_sizes[i]){ font_size = font_sizes[i]; @@ -131,9 +128,9 @@ void init_font(char * fontname){ fontname = s; autosize_font(fontname); } - fontInfo = XLoadQueryFont(dis, fontname); - if(fontInfo){ - XSetFont (dis, gc_black, fontInfo->fid); + world.fontInfo = XLoadQueryFont(world.dis, fontname); + if(world.fontInfo){ + XSetFont (world.dis, world.gc_black, world.fontInfo->fid); } else{ PRINT_WARN("cannot load font '%s'\n", fontname); @@ -142,22 +139,22 @@ void init_font(char * fontname){ } void textincorner(const char * const text1, const char * const text2){ - int voffset = fontInfo ? (fontInfo->ascent + fontInfo->descent + 5) : 20; - XDrawString(dis, win, gc_black, 10, voffset, text1, strlen(text1)); + int voffset = world.fontInfo ? (world.fontInfo->ascent + world.fontInfo->descent + 5) : 20; + XDrawString(world.dis, world.win, world.gc_black, 10, voffset, text1, strlen(text1)); if(text2){ - XDrawString(dis, win, gc_black, 10, voffset*2, text2, strlen(text2)); + XDrawString(world.dis, world.win, world.gc_black, 10, voffset*2, text2, strlen(text2)); } return; } void textincorner2(const char * const text1){ - int voffset = fontInfo ? (fontInfo->ascent + fontInfo->descent + 5) : 20; - XDrawString(dis, win, gc_red, 10, voffset*3, text1, strlen(text1)); + int voffset = world.fontInfo ? (world.fontInfo->ascent + world.fontInfo->descent + 5) : 20; + XDrawString(world.dis, world.win, world.gc_red, 10, voffset*3, text1, strlen(text1)); return; } void setcaption(const char * const capt){ - XStoreName(dis, win, capt); + XStoreName(world.dis, world.win, capt); return; } @@ -166,14 +163,14 @@ void draw_edge(double vi[3], double vj[3], double scale, double xy0[2]){ double pi[2], pj[2]; r2sum(pi, xy0, vi); r2sum(pj, xy0, vj); - XDrawLine(dis, win, gc_dot[iw], - W/2+scale*pi[0], H/2-scale*pi[1], - W/2+scale*pj[0], H/2-scale*pj[1]); + XDrawLine(world.dis, world.win, world.gc_dot[iw], + world.W/2+scale*pi[0], world.H/2-scale*pi[1], + world.W/2+scale*pj[0], world.H/2-scale*pj[1]); return; } void drawvertices(double * v, double scale, double xy0[2]){ - double d = MIN(H, W)*scale; + double d = MIN(world.H, world.W)*scale; #define LINE(i,j) draw_edge(v+(i)*3, v+(j)*3, d, xy0) for(int i=0; i<8; i+=2){ LINE(i,i+1); // || z-axis @@ -189,12 +186,12 @@ void drawvertices(double * v, double scale, double xy0[2]){ } void drawshell(double rmin, double rmax, double scale, double xy0[2]){ - double d = MIN(H,W)*scale; + double d = MIN(world.H,world.W)*scale; double r[] = {rmax*d, rmin*d}; - int x = W/2+d*xy0[0]; - int y = H/2-d*xy0[1]; + int x = world.W/2+d*xy0[0]; + int y = world.H/2-d*xy0[1]; for(int i=0; i<2; i++){ - XDrawArc(dis, win, gc_dot[i], x-r[i], y-r[i], 2*r[i], 2*r[i], 0, 360*64); + XDrawArc(world.dis, world.win, world.gc_dot[i], x-r[i], y-r[i], 2*r[i], 2*r[i], 0, 360*64); } return; } @@ -202,9 +199,9 @@ void drawshell(double rmin, double rmax, double scale, double xy0[2]){ int savepic(char * s){ XpmAttributes a; a.valuemask = (0 | XpmSize) ; - a.width = W; - a.height = H; - XCopyArea (dis, win, px, gc_white, 0, 0, W, H, 0, 0); /* with text */ - return XpmWriteFileFromPixmap(dis, s, px, 0, &a); + a.width = world.W; + a.height = world.H; + XCopyArea (world.dis, world.win, world.px, world.gc_white, 0, 0, world.W, world.H, 0, 0); /* with text */ + return XpmWriteFileFromPixmap(world.dis, s, world.px, 0, &a); } diff --git a/src/v/x.h b/src/v/x.h index a9d5fa5..9e51422 100644 --- a/src/v/x.h +++ b/src/v/x.h @@ -6,16 +6,12 @@ #define NCOLORS 110 -#define CLEARCANV \ - if(canv == px){\ - XFillRectangle(dis, px, gc_white, 0, 0, W, H);\ - }\ - else if(canv == win){\ - XClearWindow(dis, win);\ - } - -#define FILLCANV \ - if(canv == px){\ - XCopyArea(dis, px, win, gc_white, 0, 0, W, H, 0, 0);\ - } - +typedef struct { + Display * dis; + Window win; + GC gc_white, gc_black, gc_red, gc_dot[2], gcc[NCOLORS]; + Pixmap px; + Drawable canv; + XFontStruct * fontInfo; + int W,H; +} draw_world_t; diff --git a/src/v/xinput.c b/src/v/xinput.c index 0e0aab6..4ac1994 100644 --- a/src/v/xinput.c +++ b/src/v/xinput.c @@ -1,11 +1,11 @@ #include "v.h" #include "x.h" -extern Display * dis; +extern draw_world_t world; int process_x_input(char input_text[STRLEN], unsigned int keycode){ int keysyms_per_keycode_return; - KeySym * keysym = XGetKeyboardMapping(dis, keycode, 1, &keysyms_per_keycode_return); + KeySym * keysym = XGetKeyboardMapping(world.dis, keycode, 1, &keysyms_per_keycode_return); int input_length = strlen(input_text); if(!((keysym[0]>='0' && keysym[0]<='9')||(keysym[0]>='a' && keysym[0]<='z'))){ if(keysym[0]==XK_Escape){ From 80cae88ff1a17cbda971f5ddafa57e815ca2a4af Mon Sep 17 00:00:00 2001 From: Ksenia Date: Mon, 16 Mar 2026 19:53:07 +0100 Subject: [PATCH 02/10] Stop text from blinking when playing animation --- src/v/ac3_draw.c | 17 ----------------- src/v/evr.c | 5 ++++- src/v/v.h | 2 ++ src/v/x.c | 28 ++++++++++++++++++---------- 4 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/v/ac3_draw.c b/src/v/ac3_draw.c index 8afbffd..da6f1bc 100644 --- a/src/v/ac3_draw.c +++ b/src/v/ac3_draw.c @@ -6,19 +6,6 @@ #define RESOL_SCALE (128.0/768.0) // reference resolution for atom sizes #define XDRAWSTRING XDrawImageString // change to XDrawString to remove white boxes behind atom/bond labels -#define CLEARCANV \ - if(world.canv == world.px){\ - XFillRectangle(world.dis, world.px, world.gc_white, 0, 0, world.W, world.H);\ - }\ - else if(world.canv == world.win){\ - XClearWindow(world.dis, world.win);\ - } - -#define FILLCANV \ - if(world.canv == world.px){\ - XCopyArea(world.dis, world.px, world.win, world.gc_white, 0, 0, world.W, world.H, 0, 0);\ - } - extern draw_world_t world; static inline int getgci(int q){ @@ -46,8 +33,6 @@ void ac3_draw(atcoord * ac, rendpars rend){ #define SCREEN_X(X) (world.W/2 + d*(rend.xy0[0] + (X))) #define SCREEN_Y(Y) (world.H/2 - d*(rend.xy0[1] + (Y))) - CLEARCANV; - int n = ac->n; kzstr * kz = malloc(sizeof(kzstr)*n); int * ks = (rend.bonds>0) ? malloc(sizeof(int)*n) : NULL; @@ -119,11 +104,9 @@ void ac3_draw(atcoord * ac, rendpars rend){ } } } - } free(kz); free(ks); - FILLCANV; return; } diff --git a/src/v/evr.c b/src/v/evr.c index 04d15ce..0523f1a 100644 --- a/src/v/evr.c +++ b/src/v/evr.c @@ -20,6 +20,7 @@ static void redraw_ac3(object * ent, drawpars * dp){ bonds_fill(dp->bond, ac); } + clear_canv(); ac3_draw(ac, dp->rend); ac3_text(ac, dp); @@ -33,6 +34,7 @@ static void redraw_ac3(object * ent, drawpars * dp){ else if(dp->cell.vert == 2){ drawshell(dp->cell.vertices[0], dp->cell.vertices[1], dp->rend.scale, dp->rend.xy0); } + fill_canv(); return; } @@ -54,9 +56,10 @@ static void redraw_vibro(object * ent, drawpars * dp){ r3cp(m->r+3*j, v); } + clear_canv(); ac3_draw(m, dp->rend); vibro_text(ent->vib, dp); - + fill_canv(); return; } diff --git a/src/v/v.h b/src/v/v.h index e3cf204..c878382 100644 --- a/src/v/v.h +++ b/src/v/v.h @@ -105,6 +105,8 @@ void setcaption (const char * const capt); void drawvertices (double * v, double scale, double xy0[2]); void drawshell (double rmin, double rmax, double scale, double * xy0); int savepic (char * s); +void clear_canv(); +void fill_canv(); // xinput.c int process_x_input(char input_text[STRLEN], unsigned int keycode); diff --git a/src/v/x.c b/src/v/x.c index 4401db2..422a9af 100644 --- a/src/v/x.c +++ b/src/v/x.c @@ -99,11 +99,7 @@ void init_x(const char * const capt, const colorscheme_t colorscheme){ XMapRaised (dis, world.win); world.px = XCreatePixmap(dis, world.win, world.W, world.H, DefaultDepth(dis, 0)); -#if 1 - world.canv = world.win; -#else world.canv = world.px; -#endif return; }; @@ -140,16 +136,16 @@ void init_font(char * fontname){ void textincorner(const char * const text1, const char * const text2){ int voffset = world.fontInfo ? (world.fontInfo->ascent + world.fontInfo->descent + 5) : 20; - XDrawString(world.dis, world.win, world.gc_black, 10, voffset, text1, strlen(text1)); + XDrawString(world.dis, world.canv, world.gc_black, 10, voffset, text1, strlen(text1)); if(text2){ - XDrawString(world.dis, world.win, world.gc_black, 10, voffset*2, text2, strlen(text2)); + XDrawString(world.dis, world.canv, world.gc_black, 10, voffset*2, text2, strlen(text2)); } return; } void textincorner2(const char * const text1){ int voffset = world.fontInfo ? (world.fontInfo->ascent + world.fontInfo->descent + 5) : 20; - XDrawString(world.dis, world.win, world.gc_red, 10, voffset*3, text1, strlen(text1)); + XDrawString(world.dis, world.canv, world.gc_red, 10, voffset*3, text1, strlen(text1)); return; } @@ -163,7 +159,7 @@ void draw_edge(double vi[3], double vj[3], double scale, double xy0[2]){ double pi[2], pj[2]; r2sum(pi, xy0, vi); r2sum(pj, xy0, vj); - XDrawLine(world.dis, world.win, world.gc_dot[iw], + XDrawLine(world.dis, world.canv, world.gc_dot[iw], world.W/2+scale*pi[0], world.H/2-scale*pi[1], world.W/2+scale*pj[0], world.H/2-scale*pj[1]); return; @@ -191,7 +187,7 @@ void drawshell(double rmin, double rmax, double scale, double xy0[2]){ int x = world.W/2+d*xy0[0]; int y = world.H/2-d*xy0[1]; for(int i=0; i<2; i++){ - XDrawArc(world.dis, world.win, world.gc_dot[i], x-r[i], y-r[i], 2*r[i], 2*r[i], 0, 360*64); + XDrawArc(world.dis, world.canv, world.gc_dot[i], x-r[i], y-r[i], 2*r[i], 2*r[i], 0, 360*64); } return; } @@ -201,7 +197,19 @@ int savepic(char * s){ a.valuemask = (0 | XpmSize) ; a.width = world.W; a.height = world.H; - XCopyArea (world.dis, world.win, world.px, world.gc_white, 0, 0, world.W, world.H, 0, 0); /* with text */ return XpmWriteFileFromPixmap(world.dis, s, world.px, 0, &a); } +void clear_canv(){ // TODO other canvases? + if(world.canv == world.px){ + XFillRectangle(world.dis, world.canv, world.gc_white, 0, 0, world.W, world.H);\ + } + return; +} + +void fill_canv(){ + if(world.canv == world.px){ // TODO other canvases? + XCopyArea(world.dis, world.canv, world.win, world.gc_white, 0, 0, world.W, world.H, 0, 0); + } + return; +} From a655aa1cea4e172f3089a7981726b2a24317858d Mon Sep 17 00:00:00 2001 From: Ksenia Date: Mon, 16 Mar 2026 20:46:54 +0100 Subject: [PATCH 03/10] Refactor text-in-corner --- src/v/evr.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/v/tools.c | 46 ---------------------------------------------- src/v/v.h | 6 ++---- src/v/x.c | 16 ++++++---------- 4 files changed, 54 insertions(+), 60 deletions(-) diff --git a/src/v/evr.c b/src/v/evr.c index 0523f1a..3ca32af 100644 --- a/src/v/evr.c +++ b/src/v/evr.c @@ -13,6 +13,52 @@ static const double step_mod = 0.03125; static const double rl_move_pbc_scale = 0.9; static const double vibration_amplitude = 0.1; +static void ac3_text(atcoord * ac, drawpars * dp){ + char text[STRLEN], text2[STRLEN], text_inp[STRLEN]; + const char * lines[MAX_LINES] = {[0] = text, [1] = dp->read.fname}; + const int lines_red[MAX_LINES] = {[2] = 1}; + + int tp = snprintf(text, sizeof(text), "%*d / %d r = %.1lf rl = %.1lf", 1+(int)(log10(dp->N)), dp->n+1, dp->N, dp->rend.r, dp->bond.rl); + if( tpanal.intcoord[0] ){ + tp += snprintf(text+tp, sizeof(text)-tp, " | %d,%d,%d,%d,%d: %lf", dp->anal.intcoord[0], dp->anal.intcoord[1], dp->anal.intcoord[2], dp->anal.intcoord[3], dp->anal.intcoord[4], intcoord_calc(1, ac->n, dp->anal.intcoord, ac->r)); + } + if( tpsym[0] ){ + tp += snprintf(text+tp, sizeof(text)-tp, " | PG: %s", ac->sym); + } + + if(ac->nf[1]!=dp->N){ + snprintf(text2, sizeof(text2), "%s (%*d / %d)", ac->fname, 1+(int)(log10(ac->nf[1])), ac->nf[0]+1, ac->nf[1]); + lines[1] = text2; + } + + if(dp->ui.input==1){ + snprintf(text_inp, sizeof(text_inp), "JUMP TO >>> %s", dp->ui.input_text); + lines[2] = text_inp; + } + + textincorner(lines, lines_red); + setcaption(ac->fname); + return; +} + +void vibro_text(vibr_t * ms, drawpars * dp){ + char text[STRLEN], text_inp[STRLEN]; + const char * lines[MAX_LINES] = {[0] = text, [1] = dp->read.fname}; + const int lines_red[MAX_LINES] = {[2] = 1}; + + double fq = ms->freq[dp->n]; + char i = fq > 0.0 ? ' ' : 'i'; + snprintf(text, sizeof(text), + "%*d / %d freq = %.1lf%c cm-1 int = %.1lf km/mole mass = %.1lf amu | r = %.1lf rl = %.1lf", + 1+(int)(log10(ms->n)), dp->n+1, ms->n, fabs(fq), i, ms->ints[dp->n], ms->mass[dp->n], dp->rend.r, dp->bond.rl); + if(dp->ui.input==1){ + snprintf(text_inp, sizeof(text_inp), "JUMP TO >>> %s", dp->ui.input_text); + lines[2] = text_inp; + } + textincorner(lines, lines_red); + return; +} + static void redraw_ac3(object * ent, drawpars * dp){ atcoord * ac = ent->m[dp->n]; diff --git a/src/v/tools.c b/src/v/tools.c index 25a6d49..d700545 100644 --- a/src/v/tools.c +++ b/src/v/tools.c @@ -13,52 +13,6 @@ void obj_free(object * ent){ return; } -void ac3_text(atcoord * ac, drawpars * dp){ - char text[STRLEN]; - int tp = snprintf(text, sizeof(text), - "%*d / %d r = %.1lf rl = %.1lf", - 1+(int)(log10(dp->N)), dp->n+1, dp->N, dp->rend.r, dp->bond.rl); - if( tpanal.intcoord[0] ){ - tp += snprintf(text+tp, sizeof(text)-tp, " | %d,%d,%d,%d,%d: %lf", dp->anal.intcoord[0], dp->anal.intcoord[1], dp->anal.intcoord[2], dp->anal.intcoord[3], dp->anal.intcoord[4], intcoord_calc(1, ac->n, dp->anal.intcoord, ac->r)); - } - if( tpsym[0] ){ - tp += snprintf(text+tp, sizeof(text)-tp, " | PG: %s", ac->sym); - } - if(ac->nf[1]==dp->N){ - textincorner(text, ac->fname); - } - else{ - char text2[STRLEN]; - snprintf(text2, sizeof(text2), "%s (%*d / %d)", ac->fname, 1+(int)(log10(ac->nf[1])), ac->nf[0]+1, ac->nf[1]); - textincorner(text, text2); - } - - if(dp->ui.input==1){ - char text3[STRLEN]; - snprintf(text3, sizeof(text3), "JUMP TO >>> %s", dp->ui.input_text); - textincorner2(text3); - } - - setcaption(ac->fname); - return; -} - -void vibro_text(vibr_t * ms, drawpars * dp){ - char text[STRLEN]; - double fq = ms->freq[dp->n]; - char i = fq > 0.0 ? ' ' : 'i'; - snprintf(text, sizeof(text), - "%*d / %d freq = %.1lf%c cm-1 int = %.1lf km/mole mass = %.1lf amu | r = %.1lf rl = %.1lf", - 1+(int)(log10(ms->n)), dp->n+1, ms->n, fabs(fq), i, ms->ints[dp->n], ms->mass[dp->n], dp->rend.r, dp->bond.rl); - textincorner(text, dp->read.fname); - if(dp->ui.input==1){ - char text3[STRLEN]; - snprintf(text3, sizeof(text3), "JUMP TO >>> %s", dp->ui.input_text); - textincorner2(text3); - } - return; -} - void pg(atcoord * a, double symtol){ int n = a->n; diff --git a/src/v/v.h b/src/v/v.h index c878382..74a6e93 100644 --- a/src/v/v.h +++ b/src/v/v.h @@ -7,6 +7,7 @@ #define POINTER_SPEED 2.0 #define STRLEN 256 #define BIGSTRLEN 4096 +#define MAX_LINES 3 #include "pars.h" @@ -99,8 +100,7 @@ int get_element(char * s); void close_x (void); void init_x (const char * const capt, const colorscheme_t colorscheme); void init_font (char * fontname); -void textincorner (const char * const text1, const char * const text2); -void textincorner2(const char * const text1); +void textincorner (const char * const lines[MAX_LINES], const int red[MAX_LINES]); void setcaption (const char * const capt); void drawvertices (double * v, double scale, double xy0[2]); void drawshell (double rmin, double rmax, double scale, double * xy0); @@ -112,8 +112,6 @@ int process_x_input(char input_text[STRLEN], unsigned int keycode); // tools.c void obj_free(object * ent); -void ac3_text(atcoord * ac, drawpars * dp); -void vibro_text(vibr_t * ms, drawpars * dp); void pg(atcoord * a, double symtol); // headless.c diff --git a/src/v/x.c b/src/v/x.c index 422a9af..671bf94 100644 --- a/src/v/x.c +++ b/src/v/x.c @@ -127,6 +127,7 @@ void init_font(char * fontname){ world.fontInfo = XLoadQueryFont(world.dis, fontname); if(world.fontInfo){ XSetFont (world.dis, world.gc_black, world.fontInfo->fid); + XSetFont (world.dis, world.gc_red, world.fontInfo->fid); } else{ PRINT_WARN("cannot load font '%s'\n", fontname); @@ -134,21 +135,16 @@ void init_font(char * fontname){ return; } -void textincorner(const char * const text1, const char * const text2){ +void textincorner(const char * const lines[MAX_LINES], const int red[MAX_LINES]){ int voffset = world.fontInfo ? (world.fontInfo->ascent + world.fontInfo->descent + 5) : 20; - XDrawString(world.dis, world.canv, world.gc_black, 10, voffset, text1, strlen(text1)); - if(text2){ - XDrawString(world.dis, world.canv, world.gc_black, 10, voffset*2, text2, strlen(text2)); + for(int i=0; iascent + world.fontInfo->descent + 5) : 20; - XDrawString(world.dis, world.canv, world.gc_red, 10, voffset*3, text1, strlen(text1)); - return; -} - void setcaption(const char * const capt){ XStoreName(world.dis, world.win, capt); return; From 19a2d80121a6ad625ec1aaad68290680cd71fce1 Mon Sep 17 00:00:00 2001 From: Ksenia Date: Mon, 16 Mar 2026 21:02:54 +0100 Subject: [PATCH 04/10] Move redraw functions to redraw.c --- obj/v.d | 3 +- obj/v/evr.d | 4 +- obj/v/headless.d | 3 +- obj/v/loop.d | 3 +- obj/v/redraw.d | 3 + src/v/evr.c | 156 ++++++++--------------------------------------- src/v/evr.h | 8 ++- src/v/redraw.c | 100 ++++++++++++++++++++++++++++++ src/v/v.h | 4 ++ src/v/x.c | 2 +- 10 files changed, 146 insertions(+), 140 deletions(-) create mode 100644 obj/v/redraw.d create mode 100644 src/v/redraw.c diff --git a/obj/v.d b/obj/v.d index f0ff6dc..fafe15f 100644 --- a/obj/v.d +++ b/obj/v.d @@ -1,3 +1,2 @@ obj/v.o obj-pic/v.o: src/v.c src/v/v.h src/mol/mol.h src/mol/common.h \ - src/v/pars.h src/v/x.h src/v/evr.h src/math/3d.h src/math/matrix.h \ - src/math/vecn.h + src/v/pars.h src/v/x.h src/v/evr.h diff --git a/obj/v/evr.d b/obj/v/evr.d index 540e7cf..6bf6af3 100644 --- a/obj/v/evr.d +++ b/obj/v/evr.d @@ -1,3 +1,3 @@ obj/v/evr.o obj-pic/v/evr.o: src/v/evr.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/v/pars.h src/v/x.h src/v/evr.h src/math/3d.h \ - src/math/matrix.h src/math/vecn.h src/math/vec3.h + src/mol/common.h src/v/pars.h src/v/evr.h src/math/vec3.h src/math/3d.h \ + src/math/matrix.h src/math/vecn.h diff --git a/obj/v/headless.d b/obj/v/headless.d index 3048fee..f1ae2e2 100644 --- a/obj/v/headless.d +++ b/obj/v/headless.d @@ -1,3 +1,2 @@ obj/v/headless.o obj-pic/v/headless.o: src/v/headless.c src/v/v.h \ - src/mol/mol.h src/mol/common.h src/v/pars.h src/v/evr.h src/math/3d.h \ - src/math/matrix.h src/math/vecn.h + src/mol/mol.h src/mol/common.h src/v/pars.h src/v/evr.h diff --git a/obj/v/loop.d b/obj/v/loop.d index 4af8815..dfb61ee 100644 --- a/obj/v/loop.d +++ b/obj/v/loop.d @@ -1,3 +1,2 @@ obj/v/loop.o obj-pic/v/loop.o: src/v/loop.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/v/pars.h src/v/x.h src/v/evr.h src/math/3d.h \ - src/math/matrix.h src/math/vecn.h + src/mol/common.h src/v/pars.h src/v/x.h src/v/evr.h diff --git a/obj/v/redraw.d b/obj/v/redraw.d new file mode 100644 index 0000000..0642b21 --- /dev/null +++ b/obj/v/redraw.d @@ -0,0 +1,3 @@ +obj/v/redraw.o obj-pic/v/redraw.o: src/v/redraw.c src/v/v.h src/mol/mol.h \ + src/mol/common.h src/v/pars.h src/v/evr.h src/math/vec3.h \ + src/math/vecn.h diff --git a/src/v/evr.c b/src/v/evr.c index 3ca32af..9e98258 100644 --- a/src/v/evr.c +++ b/src/v/evr.c @@ -1,114 +1,10 @@ #include "v.h" -#include "x.h" #include "evr.h" #include "vec3.h" +#include "3d.h" #define EPS_INV 1e-15 -static const double step_rot = M_PI/90.0; -static const double step_move = 0.2; -static const double step_zoom = 1.1; -static const double step_r = 1.1; -static const double step_mod = 0.03125; -static const double rl_move_pbc_scale = 0.9; -static const double vibration_amplitude = 0.1; - -static void ac3_text(atcoord * ac, drawpars * dp){ - char text[STRLEN], text2[STRLEN], text_inp[STRLEN]; - const char * lines[MAX_LINES] = {[0] = text, [1] = dp->read.fname}; - const int lines_red[MAX_LINES] = {[2] = 1}; - - int tp = snprintf(text, sizeof(text), "%*d / %d r = %.1lf rl = %.1lf", 1+(int)(log10(dp->N)), dp->n+1, dp->N, dp->rend.r, dp->bond.rl); - if( tpanal.intcoord[0] ){ - tp += snprintf(text+tp, sizeof(text)-tp, " | %d,%d,%d,%d,%d: %lf", dp->anal.intcoord[0], dp->anal.intcoord[1], dp->anal.intcoord[2], dp->anal.intcoord[3], dp->anal.intcoord[4], intcoord_calc(1, ac->n, dp->anal.intcoord, ac->r)); - } - if( tpsym[0] ){ - tp += snprintf(text+tp, sizeof(text)-tp, " | PG: %s", ac->sym); - } - - if(ac->nf[1]!=dp->N){ - snprintf(text2, sizeof(text2), "%s (%*d / %d)", ac->fname, 1+(int)(log10(ac->nf[1])), ac->nf[0]+1, ac->nf[1]); - lines[1] = text2; - } - - if(dp->ui.input==1){ - snprintf(text_inp, sizeof(text_inp), "JUMP TO >>> %s", dp->ui.input_text); - lines[2] = text_inp; - } - - textincorner(lines, lines_red); - setcaption(ac->fname); - return; -} - -void vibro_text(vibr_t * ms, drawpars * dp){ - char text[STRLEN], text_inp[STRLEN]; - const char * lines[MAX_LINES] = {[0] = text, [1] = dp->read.fname}; - const int lines_red[MAX_LINES] = {[2] = 1}; - - double fq = ms->freq[dp->n]; - char i = fq > 0.0 ? ' ' : 'i'; - snprintf(text, sizeof(text), - "%*d / %d freq = %.1lf%c cm-1 int = %.1lf km/mole mass = %.1lf amu | r = %.1lf rl = %.1lf", - 1+(int)(log10(ms->n)), dp->n+1, ms->n, fabs(fq), i, ms->ints[dp->n], ms->mass[dp->n], dp->rend.r, dp->bond.rl); - if(dp->ui.input==1){ - snprintf(text_inp, sizeof(text_inp), "JUMP TO >>> %s", dp->ui.input_text); - lines[2] = text_inp; - } - textincorner(lines, lines_red); - return; -} - -static void redraw_ac3(object * ent, drawpars * dp){ - atcoord * ac = ent->m[dp->n]; - - if(dp->rend.bonds>0){ - bonds_fill(dp->bond, ac); - } - - clear_canv(); - ac3_draw(ac, dp->rend); - ac3_text(ac, dp); - - if(dp->cell.vert == 1){ - double v[24]; - for(int i=0; i<8; i++){ - r3mx (v+3*i, dp->cell.vertices+3*i, dp->rend.ac3rmx); - } - drawvertices(v, dp->rend.scale, dp->rend.xy0); - } - else if(dp->cell.vert == 2){ - drawshell(dp->cell.vertices[0], dp->cell.vertices[1], dp->rend.scale, dp->rend.xy0); - } - fill_canv(); - - return; -} - -static void redraw_vibro(object * ent, drawpars * dp){ - - atcoord * m = ent->m[0]; - double * r0 = ent->vib->r0; - double * dr = ent->vib->disp + dp->n * m->n*3; - - if(dp->rend.bonds>0){ - bonds_fill(dp->bond, m); - } - - vecsums(m->n*3, m->r, r0, dr, sin( dp->anim.t * 2.0*M_PI/TMAX ) * vibration_amplitude*sqrt(m->n) ); - for(int j=0; jn; j++){ - double v[3]; - r3mx(v, m->r+3*j, dp->rend.ac3rmx); - r3cp(m->r+3*j, v); - } - - clear_canv(); - ac3_draw(m, dp->rend); - vibro_text(ent->vib, dp); - fill_canv(); - return; -} - void kp_readmore(object * ent, drawpars * dp){ if(dp->task == AT3COORDS){ object * acs = ent; @@ -195,7 +91,7 @@ static void rl_changed(object * ent, drawpars * dp){ void kp_rl_dec(object * ent, drawpars * dp){ if(dp->rend.bonds>0){ - dp->bond.rl /= step_r; + dp->bond.rl /= STEP_R; rl_changed(ent, dp); } return; @@ -203,32 +99,32 @@ void kp_rl_dec(object * ent, drawpars * dp){ void kp_rl_inc(object * ent, drawpars * dp){ if(dp->rend.bonds>0){ - dp->bond.rl *= step_r; + dp->bond.rl *= STEP_R; rl_changed(ent, dp); } return; } void kp_r_dec(object * ent, drawpars * dp){ - dp->rend.r /= step_r; + dp->rend.r /= STEP_R; exp_redraw(ent, dp); return; } void kp_r_inc(object * ent, drawpars * dp){ - dp->rend.r *= step_r; + dp->rend.r *= STEP_R; exp_redraw(ent, dp); return; } void kp_zoom_out(object * ent, drawpars * dp){ - dp->rend.scale /= step_zoom; + dp->rend.scale /= STEP_ZOOM; exp_redraw(ent, dp); return; } void kp_zoom_in(object * ent, drawpars * dp){ - dp->rend.scale *= step_zoom; + dp->rend.scale *= STEP_ZOOM; exp_redraw(ent, dp); return; } @@ -274,7 +170,7 @@ void rot_ent_pointer(object * ent, drawpars * dp, int dx, int dy, double speed){ static void rot_ent(object * ent, drawpars * dp, int axis, double angle){ if(dp->ui.modkey){ - angle *= step_mod; + angle *= STEP_MOD; } double m[9]; @@ -290,37 +186,37 @@ static void rot_ent(object * ent, drawpars * dp, int axis, double angle){ } void kp_rotx_l(object * ent, drawpars * dp){ - rot_ent(ent, dp, 0, +step_rot); + rot_ent(ent, dp, 0, +STEP_ROT); exp_redraw(ent, dp); return; } void kp_rotx_r(object * ent, drawpars * dp){ - rot_ent(ent, dp, 0, -step_rot); + rot_ent(ent, dp, 0, -STEP_ROT); exp_redraw(ent, dp); return; } void kp_roty_l(object * ent, drawpars * dp){ - rot_ent(ent, dp, 1, +step_rot); + rot_ent(ent, dp, 1, +STEP_ROT); exp_redraw(ent, dp); return; } void kp_roty_r(object * ent, drawpars * dp){ - rot_ent(ent, dp, 1, -step_rot); + rot_ent(ent, dp, 1, -STEP_ROT); exp_redraw(ent, dp); return; } void kp_rotz_l(object * ent, drawpars * dp){ - rot_ent(ent, dp, 2, +step_rot); + rot_ent(ent, dp, 2, +STEP_ROT); exp_redraw(ent, dp); return; } void kp_rotz_r(object * ent, drawpars * dp){ - rot_ent(ent, dp, 2, -step_rot); + rot_ent(ent, dp, 2, -STEP_ROT); exp_redraw(ent, dp); return; } @@ -354,7 +250,7 @@ static void move_pbc(object * acs, drawpars * dp, int dir, double d){ } if(dp->rend.bonds>0){ acs->m[i]->bonds.flag = 0; - acs->m[i]->bonds.rl *= rl_move_pbc_scale; + acs->m[i]->bonds.rl *= RL_MOVE_PBC_SCALE; } } return; @@ -362,7 +258,7 @@ static void move_pbc(object * acs, drawpars * dp, int dir, double d){ static void move_ent(object * ent, drawpars * dp, int dir, double step){ if(dp->ui.modkey){ - step *= step_mod; + step *= STEP_MOD; } if(dp->cell.vert == 1){ move_pbc(ent, dp, dir, step); @@ -374,25 +270,25 @@ static void move_ent(object * ent, drawpars * dp, int dir, double step){ } void kp_move_l(object * ent, drawpars * dp){ - move_ent(ent, dp, 0, -step_move); + move_ent(ent, dp, 0, -STEP_MOVE); exp_redraw(ent, dp); return; } void kp_move_r(object * ent, drawpars * dp){ - move_ent(ent, dp, 0, +step_move); + move_ent(ent, dp, 0, +STEP_MOVE); exp_redraw(ent, dp); return; } void kp_move_u(object * ent, drawpars * dp){ - move_ent(ent, dp, 1, +step_move); + move_ent(ent, dp, 1, +STEP_MOVE); exp_redraw(ent, dp); return; } void kp_move_d(object * ent, drawpars * dp){ - move_ent(ent, dp, 1, -step_move); + move_ent(ent, dp, 1, -STEP_MOVE); exp_redraw(ent, dp); return; } @@ -489,11 +385,11 @@ static void savevib(drawpars * dp, int c){ char s[STRLEN]; int l = (int)(log10( dp->N + 0.5 )) + 1; snprintf(s, sizeof(s), "%s_%0*d_%02d.xpm", dp->read.fname, l, dp->n+1, c); - if (savepic(s) != XpmSuccess){ - PRINT_ERR("cannot save '%s'\n", s); + if(savepic(s)){ + fprintf(stderr, "%s\n", s); } else{ - fprintf(stderr, "%s\n", s); + PRINT_ERR("cannot save '%s'\n", s); } return; } @@ -503,11 +399,11 @@ void kp_savepic(object * ent __attribute__ ((unused)), drawpars * dp){ int l = (int)(log10(dp->N+0.5))+1; atcoord * ac = ent->m[dp->n]; snprintf(s, sizeof(s), "%s_%0*d.xpm", ac->fname, l, dp->n+1); - if (savepic(s) != XpmSuccess){ - PRINT_ERR("cannot save '%s'\n", s); + if(savepic(s)){ + fprintf(stderr, "%s\n", s); } else{ - fprintf(stderr, "%s\n", s); + PRINT_ERR("cannot save '%s'\n", s); } return; } diff --git a/src/v/evr.h b/src/v/evr.h index 949e32d..52302aa 100644 --- a/src/v/evr.h +++ b/src/v/evr.h @@ -1,5 +1,11 @@ -#include "3d.h" #define TMAX 20 +#define VIBR_AMP 0.1 +#define STEP_ROT (M_PI/90.0) +#define STEP_MOVE 0.2 +#define STEP_ZOOM 1.1 +#define STEP_R 1.1 +#define STEP_MOD 0.03125 +#define RL_MOVE_PBC_SCALE 0.9 void kp_readmore (object * ent, drawpars * dp); void kp_readagain(object * ent, drawpars * dp); diff --git a/src/v/redraw.c b/src/v/redraw.c new file mode 100644 index 0000000..3d57a3d --- /dev/null +++ b/src/v/redraw.c @@ -0,0 +1,100 @@ +#include "v.h" +#include "evr.h" +#include "vec3.h" +#include "vecn.h" + +static void ac3_text(atcoord * ac, drawpars * dp){ + char text[STRLEN], text2[STRLEN], text_inp[STRLEN]; + const char * lines[MAX_LINES] = {[0] = text, [1] = dp->read.fname}; + const int lines_red[MAX_LINES] = {[2] = 1}; + + int tp = snprintf(text, sizeof(text), "%*d / %d r = %.1lf rl = %.1lf", 1+(int)(log10(dp->N)), dp->n+1, dp->N, dp->rend.r, dp->bond.rl); + if( tpanal.intcoord[0] ){ + tp += snprintf(text+tp, sizeof(text)-tp, " | %d,%d,%d,%d,%d: %lf", dp->anal.intcoord[0], dp->anal.intcoord[1], dp->anal.intcoord[2], dp->anal.intcoord[3], dp->anal.intcoord[4], intcoord_calc(1, ac->n, dp->anal.intcoord, ac->r)); + } + if( tpsym[0] ){ + tp += snprintf(text+tp, sizeof(text)-tp, " | PG: %s", ac->sym); + } + + if(ac->nf[1]!=dp->N){ + snprintf(text2, sizeof(text2), "%s (%*d / %d)", ac->fname, 1+(int)(log10(ac->nf[1])), ac->nf[0]+1, ac->nf[1]); + lines[1] = text2; + } + + if(dp->ui.input==1){ + snprintf(text_inp, sizeof(text_inp), "JUMP TO >>> %s", dp->ui.input_text); + lines[2] = text_inp; + } + + textincorner(lines, lines_red); + setcaption(ac->fname); + return; +} + +void vibro_text(vibr_t * ms, drawpars * dp){ + char text[STRLEN], text_inp[STRLEN]; + const char * lines[MAX_LINES] = {[0] = text, [1] = dp->read.fname}; + const int lines_red[MAX_LINES] = {[2] = 1}; + + double fq = ms->freq[dp->n]; + char i = fq > 0.0 ? ' ' : 'i'; + snprintf(text, sizeof(text), + "%*d / %d freq = %.1lf%c cm-1 int = %.1lf km/mole mass = %.1lf amu | r = %.1lf rl = %.1lf", + 1+(int)(log10(ms->n)), dp->n+1, ms->n, fabs(fq), i, ms->ints[dp->n], ms->mass[dp->n], dp->rend.r, dp->bond.rl); + if(dp->ui.input==1){ + snprintf(text_inp, sizeof(text_inp), "JUMP TO >>> %s", dp->ui.input_text); + lines[2] = text_inp; + } + textincorner(lines, lines_red); + return; +} + +void redraw_ac3(object * ent, drawpars * dp){ + atcoord * ac = ent->m[dp->n]; + + if(dp->rend.bonds>0){ + bonds_fill(dp->bond, ac); + } + + clear_canv(); + ac3_draw(ac, dp->rend); + ac3_text(ac, dp); + + if(dp->cell.vert == 1){ + double v[24]; + for(int i=0; i<8; i++){ + r3mx (v+3*i, dp->cell.vertices+3*i, dp->rend.ac3rmx); + } + drawvertices(v, dp->rend.scale, dp->rend.xy0); + } + else if(dp->cell.vert == 2){ + drawshell(dp->cell.vertices[0], dp->cell.vertices[1], dp->rend.scale, dp->rend.xy0); + } + fill_canv(); + + return; +} + +void redraw_vibro(object * ent, drawpars * dp){ + + atcoord * m = ent->m[0]; + double * r0 = ent->vib->r0; + double * dr = ent->vib->disp + dp->n * m->n*3; + + if(dp->rend.bonds>0){ + bonds_fill(dp->bond, m); + } + + vecsums(m->n*3, m->r, r0, dr, sin( dp->anim.t * 2.0*M_PI/TMAX ) * VIBR_AMP*sqrt(m->n) ); + for(int j=0; jn; j++){ + double v[3]; + r3mx(v, m->r+3*j, dp->rend.ac3rmx); + r3cp(m->r+3*j, v); + } + + clear_canv(); + ac3_draw(m, dp->rend); + vibro_text(ent->vib, dp); + fill_canv(); + return; +} diff --git a/src/v/v.h b/src/v/v.h index 74a6e93..0330f56 100644 --- a/src/v/v.h +++ b/src/v/v.h @@ -81,6 +81,10 @@ allpars cli_parse(int argc, char ** argv); // loop.c void main_loop(object * ent, drawpars * dp, ptf kp[NKP]); +// redraw.c +void redraw_ac3(object * ent, drawpars * dp); +void redraw_vibro(object * ent, drawpars * dp); + // ac3_draw.c void ac3_draw (atcoord * ac, rendpars rend); // ac3_print.c diff --git a/src/v/x.c b/src/v/x.c index 671bf94..4c14c6a 100644 --- a/src/v/x.c +++ b/src/v/x.c @@ -193,7 +193,7 @@ int savepic(char * s){ a.valuemask = (0 | XpmSize) ; a.width = world.W; a.height = world.H; - return XpmWriteFileFromPixmap(world.dis, s, world.px, 0, &a); + return XpmWriteFileFromPixmap(world.dis, s, world.px, 0, &a)==XpmSuccess; } void clear_canv(){ // TODO other canvases? From d4c62797fa151d9a45335a92202940ccef3231d2 Mon Sep 17 00:00:00 2001 From: Ksenia Date: Mon, 16 Mar 2026 21:12:43 +0100 Subject: [PATCH 05/10] Rememeber world size instead of recomputing --- src/v/ac3_draw.c | 4 ++-- src/v/loop.c | 3 ++- src/v/x.c | 10 +++++----- src/v/x.h | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/v/ac3_draw.c b/src/v/ac3_draw.c index da6f1bc..bf93d9f 100644 --- a/src/v/ac3_draw.c +++ b/src/v/ac3_draw.c @@ -37,8 +37,8 @@ void ac3_draw(atcoord * ac, rendpars rend){ kzstr * kz = malloc(sizeof(kzstr)*n); int * ks = (rend.bonds>0) ? malloc(sizeof(int)*n) : NULL; - double d = MIN(world.H,world.W) * rend.scale; - double resol = MIN(world.H,world.W) * RESOL_SCALE; + double d = world.size * rend.scale; + double resol = world.size * RESOL_SCALE; double r1 = rend.r * resol * rend.scale; for(int k=0; kclick){ int x = event->x; int y = event->y; - rot_ent_pointer(ent, dp, x-mouse->x0, y-mouse->y0, POINTER_SPEED/MIN(world.W,world.H)); + rot_ent_pointer(ent, dp, x-mouse->x0, y-mouse->y0, POINTER_SPEED/world.size); exp_redraw(ent, dp); mouse->x0 = x; mouse->y0 = y; @@ -103,6 +103,7 @@ void main_loop(object * ent, drawpars * dp, ptf kp[NKP]){ else if(event->type == ConfigureNotify){ world.W = event->xconfigure.width; world.H = event->xconfigure.height; + world.size = MIN(world.H, world.W); dp->rend.xy0[0] = dp->rend.xy0[1] = 0.0; exp_redraw(ent, dp); } diff --git a/src/v/x.c b/src/v/x.c index 4c14c6a..d5196d9 100644 --- a/src/v/x.c +++ b/src/v/x.c @@ -59,6 +59,7 @@ void init_x(const char * const capt, const colorscheme_t colorscheme){ int screen = DefaultScreen(dis); world.W = DisplayWidth (dis, screen); world.H = DisplayHeight (dis, screen); + world.size = MIN(world.H, world.W); unsigned long bp = BlackPixel (dis, screen); unsigned long wp = WhitePixel (dis, screen); @@ -105,11 +106,10 @@ void init_x(const char * const capt, const colorscheme_t colorscheme){ static void autosize_font(char * fontname){ const int screen_sizes[] = {1200, 1080, 960, 900, 840, 768}; - const int font_sizes[] = { 24, 20, 18, 16, 15, 14}; // font_size='ceil'(screen_size) / 60 + const int font_sizes[] = { 24, 20, 18, 16, 15, 14}; // font_size='ceil'(world.size) / 60 int font_size = 13; - int screen_size = MIN(world.W, world.H); for(int i=0; iscreen_sizes[i]){ + if(world.size>screen_sizes[i]){ font_size = font_sizes[i]; break; } @@ -162,7 +162,7 @@ void draw_edge(double vi[3], double vj[3], double scale, double xy0[2]){ } void drawvertices(double * v, double scale, double xy0[2]){ - double d = MIN(world.H, world.W)*scale; + double d = world.size * scale; #define LINE(i,j) draw_edge(v+(i)*3, v+(j)*3, d, xy0) for(int i=0; i<8; i+=2){ LINE(i,i+1); // || z-axis @@ -178,7 +178,7 @@ void drawvertices(double * v, double scale, double xy0[2]){ } void drawshell(double rmin, double rmax, double scale, double xy0[2]){ - double d = MIN(world.H,world.W)*scale; + double d = world.size * scale; double r[] = {rmax*d, rmin*d}; int x = world.W/2+d*xy0[0]; int y = world.H/2-d*xy0[1]; diff --git a/src/v/x.h b/src/v/x.h index 9e51422..c2a9674 100644 --- a/src/v/x.h +++ b/src/v/x.h @@ -13,5 +13,5 @@ typedef struct { Pixmap px; Drawable canv; XFontStruct * fontInfo; - int W,H; + int W, H, size; } draw_world_t; From 8a98d8c8432b7626090c56a188b6de2fb48c927d Mon Sep 17 00:00:00 2001 From: Ksenia Date: Mon, 16 Mar 2026 21:49:51 +0100 Subject: [PATCH 06/10] Unify drawing wrt screen center --- obj/v/x.d | 4 +-- src/math/vec2.h | 73 ------------------------------------------------ src/v/ac3_draw.c | 5 ---- src/v/pars.h | 11 ++++---- src/v/redraw.c | 4 +-- src/v/v.h | 4 +-- src/v/x.c | 25 ++++++----------- src/v/x.h | 3 ++ 8 files changed, 23 insertions(+), 106 deletions(-) delete mode 100644 src/math/vec2.h diff --git a/obj/v/x.d b/obj/v/x.d index a00fd1b..4491afd 100644 --- a/obj/v/x.d +++ b/obj/v/x.d @@ -1,3 +1,3 @@ obj/v/x.o obj-pic/v/x.o: src/v/x.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/v/pars.h src/v/x.h src/math/vec2.h \ - src/mol/palette_v.h src/mol/palette_cpk.h + src/mol/common.h src/v/pars.h src/v/x.h src/mol/palette_v.h \ + src/mol/palette_cpk.h diff --git a/src/math/vec2.h b/src/math/vec2.h deleted file mode 100644 index da7bbf1..0000000 --- a/src/math/vec2.h +++ /dev/null @@ -1,73 +0,0 @@ - -static inline double r2dot (double * u, double * v){ - return (u[0]*v[0] + u[1]*v[1]); -} - -static inline double r2x (double * u, double * v){ - return u[0]*v[1]-u[1]*v[0]; -} - -static inline void r2mx (double * u, double * v, double * m){ - u[0] = v[0]*m[0] + v[1]*m[1]; - u[1] = v[0]*m[2] + v[1]*m[3]; - return; -} - -static inline void r2scal (double * u, double c){ - u[0] *= c; - u[1] *= c; - return; -} - -static inline void r2adds (double * u, double * v, double c){ - u[0] += c*v[0]; - u[1] += c*v[1]; - return; -} - -static inline void r2add (double * u, double * v){ - u[0] += v[0]; - u[1] += v[1]; - return; -} - -static inline void r2min (double * u, double * v){ - u[0] -= v[0]; - u[1] -= v[1]; - return; -} - -static inline void r2sum (double * w, double * u, double * v){ - w[0] = u[0] + v[0]; - w[1] = u[1] + v[1]; - return; -} - -static inline void r2diff (double * w, double * u, double * v){ - w[0] = u[0] - v[0]; - w[1] = u[1] - v[1]; - return; -} - -static inline void r2cp (double * u, double * v){ - u[0] = v[0]; - u[1] = v[1]; - return; -} - -static inline void cart2raw(double r[3], double x, double y){ -#define EPS 1e-10 - r[0] = sqrt(x*x+y*y); - - if (r[0]n; kzstr * kz = malloc(sizeof(kzstr)*n); int * ks = (rend.bonds>0) ? malloc(sizeof(int)*n) : NULL; - double d = world.size * rend.scale; double resol = world.size * RESOL_SCALE; double r1 = rend.r * resol * rend.scale; diff --git a/src/v/pars.h b/src/v/pars.h index a347ec1..a536b12 100644 --- a/src/v/pars.h +++ b/src/v/pars.h @@ -10,11 +10,11 @@ typedef enum { } colorscheme_t; typedef struct { + colorscheme_t colors; // colorscheme (v or cpk) int gui; // if gui is enabled - char * fontname; // font int input_files_n; // number of input files + char * fontname; // font char ** input_files; // input files - colorscheme_t colors; // colorscheme (v or cpk) } initpars; typedef struct { @@ -28,13 +28,12 @@ typedef struct { int bohr; // 0: Å 1: Bohr } geompars; - typedef struct { - int closed; // 1: time to go + char input_text[STRLEN]; char * com; // command string for gui:0 char * on_exit; // command string to run on exit - int input; // 0=no input regime, 1=jump, ... - char input_text[STRLEN]; + int closed; // 1: time to go + int input; // 0=no input regime, 1=jump, ... int modkey; // whether ctrl or shift are pressed } uipars; diff --git a/src/v/redraw.c b/src/v/redraw.c index 3d57a3d..cf7917e 100644 --- a/src/v/redraw.c +++ b/src/v/redraw.c @@ -65,10 +65,10 @@ void redraw_ac3(object * ent, drawpars * dp){ for(int i=0; i<8; i++){ r3mx (v+3*i, dp->cell.vertices+3*i, dp->rend.ac3rmx); } - drawvertices(v, dp->rend.scale, dp->rend.xy0); + drawvertices(v, dp->rend); } else if(dp->cell.vert == 2){ - drawshell(dp->cell.vertices[0], dp->cell.vertices[1], dp->rend.scale, dp->rend.xy0); + drawshell(dp->cell.vertices, dp->rend); } fill_canv(); diff --git a/src/v/v.h b/src/v/v.h index 0330f56..3bdc0a2 100644 --- a/src/v/v.h +++ b/src/v/v.h @@ -106,8 +106,8 @@ void init_x (const char * const capt, const colorscheme_t colorscheme); void init_font (char * fontname); void textincorner (const char * const lines[MAX_LINES], const int red[MAX_LINES]); void setcaption (const char * const capt); -void drawvertices (double * v, double scale, double xy0[2]); -void drawshell (double rmin, double rmax, double scale, double * xy0); +void drawvertices (double * v, rendpars rend); +void drawshell (double r[2], rendpars rend); int savepic (char * s); void clear_canv(); void fill_canv(); diff --git a/src/v/x.c b/src/v/x.c index d5196d9..984fd7b 100644 --- a/src/v/x.c +++ b/src/v/x.c @@ -1,6 +1,5 @@ #include "v.h" #include "x.h" -#include "vec2.h" extern draw_world_t world; @@ -150,20 +149,15 @@ void setcaption(const char * const capt){ return; } -void draw_edge(double vi[3], double vj[3], double scale, double xy0[2]){ +void draw_edge(double vi[3], double vj[3], rendpars rend){ int iw = (vi[2]>0.0 || vj[2]>0.0) ? 0 : 1; - double pi[2], pj[2]; - r2sum(pi, xy0, vi); - r2sum(pj, xy0, vj); XDrawLine(world.dis, world.canv, world.gc_dot[iw], - world.W/2+scale*pi[0], world.H/2-scale*pi[1], - world.W/2+scale*pj[0], world.H/2-scale*pj[1]); + SCREEN_X(vi[0]), SCREEN_Y(vi[1]), SCREEN_X(vj[0]), SCREEN_Y(vj[1])); return; } -void drawvertices(double * v, double scale, double xy0[2]){ - double d = world.size * scale; -#define LINE(i,j) draw_edge(v+(i)*3, v+(j)*3, d, xy0) +void drawvertices(double * v, rendpars rend){ +#define LINE(i,j) draw_edge(v+(i)*3, v+(j)*3, rend) for(int i=0; i<8; i+=2){ LINE(i,i+1); // || z-axis } @@ -177,13 +171,12 @@ void drawvertices(double * v, double scale, double xy0[2]){ return; } -void drawshell(double rmin, double rmax, double scale, double xy0[2]){ - double d = world.size * scale; - double r[] = {rmax*d, rmin*d}; - int x = world.W/2+d*xy0[0]; - int y = world.H/2-d*xy0[1]; +void drawshell(double r[2], rendpars rend){ + double d = world.size * rend.scale; for(int i=0; i<2; i++){ - XDrawArc(world.dis, world.canv, world.gc_dot[i], x-r[i], y-r[i], 2*r[i], 2*r[i], 0, 360*64); + XDrawArc(world.dis, world.canv, world.gc_dot[1-i], + SCREEN_X(-r[i]), SCREEN_Y(r[i]), + 2*r[i]*d, 2*r[i]*d, 0, 360*64); } return; } diff --git a/src/v/x.h b/src/v/x.h index c2a9674..60ef34b 100644 --- a/src/v/x.h +++ b/src/v/x.h @@ -6,6 +6,9 @@ #define NCOLORS 110 +#define SCREEN_X(X) (world.W/2 + world.size * rend.scale*(rend.xy0[0] + (X))) +#define SCREEN_Y(Y) (world.H/2 - world.size * rend.scale*(rend.xy0[1] + (Y))) + typedef struct { Display * dis; Window win; From b572575dfead9e50e9111631d2061a36c8f29d4c Mon Sep 17 00:00:00 2001 From: Ksenia Date: Tue, 17 Mar 2026 15:49:33 +0100 Subject: [PATCH 07/10] Optimize rotations --- obj/v.d | 3 +- obj/v/ac3_print.d | 2 +- obj/v/evr.d | 4 +- obj/v/headless.d | 3 +- obj/v/loop.d | 3 +- obj/v/redraw.d | 4 +- src/math/3d.h | 6 ++- src/math/matrix.c | 2 +- src/math/matrix.h | 2 +- src/math/rot3d.c | 24 +++++++---- src/math/vec3.h | 45 +++++++++++--------- src/v/ac3_print.c | 14 +++---- src/v/ac3_read.c | 15 ++++--- src/v/evr.c | 104 ++++++++++++++++++---------------------------- src/v/evr.h | 17 ++++++++ src/v/headless.c | 6 +-- src/v/load.c | 18 +------- src/v/redraw.c | 35 +++++----------- src/v/v.h | 8 ++-- 19 files changed, 152 insertions(+), 163 deletions(-) diff --git a/obj/v.d b/obj/v.d index fafe15f..f0ff6dc 100644 --- a/obj/v.d +++ b/obj/v.d @@ -1,2 +1,3 @@ obj/v.o obj-pic/v.o: src/v.c src/v/v.h src/mol/mol.h src/mol/common.h \ - src/v/pars.h src/v/x.h src/v/evr.h + src/v/pars.h src/v/x.h src/v/evr.h src/math/3d.h src/math/matrix.h \ + src/math/vecn.h diff --git a/obj/v/ac3_print.d b/obj/v/ac3_print.d index 197fbc5..0ca5016 100644 --- a/obj/v/ac3_print.d +++ b/obj/v/ac3_print.d @@ -1,2 +1,2 @@ obj/v/ac3_print.o obj-pic/v/ac3_print.o: src/v/ac3_print.c src/v/v.h \ - src/mol/mol.h src/mol/common.h src/v/pars.h + src/mol/mol.h src/mol/common.h src/v/pars.h src/math/vec3.h diff --git a/obj/v/evr.d b/obj/v/evr.d index 6bf6af3..349aa02 100644 --- a/obj/v/evr.d +++ b/obj/v/evr.d @@ -1,3 +1,3 @@ obj/v/evr.o obj-pic/v/evr.o: src/v/evr.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/v/pars.h src/v/evr.h src/math/vec3.h src/math/3d.h \ - src/math/matrix.h src/math/vecn.h + src/mol/common.h src/v/pars.h src/v/evr.h src/math/3d.h \ + src/math/matrix.h src/math/vecn.h src/math/vec3.h diff --git a/obj/v/headless.d b/obj/v/headless.d index f1ae2e2..3048fee 100644 --- a/obj/v/headless.d +++ b/obj/v/headless.d @@ -1,2 +1,3 @@ obj/v/headless.o obj-pic/v/headless.o: src/v/headless.c src/v/v.h \ - src/mol/mol.h src/mol/common.h src/v/pars.h src/v/evr.h + src/mol/mol.h src/mol/common.h src/v/pars.h src/v/evr.h src/math/3d.h \ + src/math/matrix.h src/math/vecn.h diff --git a/obj/v/loop.d b/obj/v/loop.d index dfb61ee..4af8815 100644 --- a/obj/v/loop.d +++ b/obj/v/loop.d @@ -1,2 +1,3 @@ obj/v/loop.o obj-pic/v/loop.o: src/v/loop.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/v/pars.h src/v/x.h src/v/evr.h + src/mol/common.h src/v/pars.h src/v/x.h src/v/evr.h src/math/3d.h \ + src/math/matrix.h src/math/vecn.h diff --git a/obj/v/redraw.d b/obj/v/redraw.d index 0642b21..f33fa35 100644 --- a/obj/v/redraw.d +++ b/obj/v/redraw.d @@ -1,3 +1,3 @@ obj/v/redraw.o obj-pic/v/redraw.o: src/v/redraw.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/v/pars.h src/v/evr.h src/math/vec3.h \ - src/math/vecn.h + src/mol/common.h src/v/pars.h src/v/evr.h src/math/3d.h \ + src/math/matrix.h src/math/vecn.h diff --git a/src/math/3d.h b/src/math/3d.h index 04f9de9..d0fbe6b 100644 --- a/src/math/3d.h +++ b/src/math/3d.h @@ -2,10 +2,12 @@ #define DEG2RAD (M_PI/180.0) -void rotmx0_update(double mx[9], double mx1[9], double phi, int axis); -void rot3d (int n, double * r, double m[9]); +void rotmx0_update(double mx[9], double phi, int axis); +void rot3d(int n, double * v, const double * r, const double m[9]); +void rot3d_inplace(int n, double * r, const double m[9]); void rotmx (double * rot, double * u, double phi); void rot_around_perp(double rot[9], double dx, double dy, double factor); +void mx3_lmultmx(const double A[9], double B[9]); int zmat2cart(int n, double r[3], double a[3], double b[3], double c[3], diff --git a/src/math/matrix.c b/src/math/matrix.c index 76adf84..d2c49a1 100644 --- a/src/math/matrix.c +++ b/src/math/matrix.c @@ -11,7 +11,7 @@ void mx_id(unsigned int n, double * a){ } void mx_multmx(unsigned int m, unsigned int n, unsigned int q, - double * p, double * a, double * b){ + double * p, const double * a, const double * b){ /* a: m*n * b: n*q * p = ab: m*q diff --git a/src/math/matrix.h b/src/math/matrix.h index 3f71c0e..924ec96 100644 --- a/src/math/matrix.h +++ b/src/math/matrix.h @@ -15,7 +15,7 @@ static inline unsigned int mpos(unsigned int i, unsigned int j){ #endif void mx_id (unsigned int n, double * a); -void mx_multmx (unsigned int m, unsigned int n, unsigned int q, double * p, double * a, double * b); +void mx_multmx (unsigned int m, unsigned int n, unsigned int q, double * p, const double * a, const double * b); int mx_inv (unsigned int n, unsigned int r, double * b, double * a, double eps); void jacobi (double * a, double * b, double * d, unsigned int n, double eps, unsigned int rot, FILE * f); diff --git a/src/math/rot3d.c b/src/math/rot3d.c index 0310504..39ed53b 100644 --- a/src/math/rot3d.c +++ b/src/math/rot3d.c @@ -1,8 +1,7 @@ #include "3d.h" #include "vec3.h" -void rotmx0_update(double mx[9], double mx1[9], double phi, int axis){ - +void rotmx0_update(double mx[9], double phi, int axis){ double c = cos(phi); double s = sin(phi); double ms[3][9]={ @@ -10,15 +9,18 @@ void rotmx0_update(double mx[9], double mx1[9], double phi, int axis){ { c, 0.0, -s, 0.0, 1.0, 0.0, s, 0.0, c }, { c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0 } }; - veccp(9, mx1, ms[axis]); + mx3_lmultmx(ms[axis], mx); + return; +} - double mx0[9]; - veccp(9, mx0, mx); - mx_multmx(3,3,3, mx, mx1, mx0); +void rot3d(int n, double * v, const double * r, const double m[9]){ + for(int i=0; in; for(int i=0; iq[i], @@ -52,12 +52,12 @@ void ac3_print2fig(atcoord * ac, rendpars rend, double * v){ ac->r[i*3+2]); } - if(v){ + if(vert){ for(int i=0; i<8; i++){ + double v[3]; + r3mx(v, vert+3*i, rend.ac3rmx); PRINTOUT(stdout, "atom %3d% 13.7lf% 13.7lf% 13.7lf\n", 0, - rend.xy0[0] + v[i*3 ], - rend.xy0[1] + v[i*3+1], - v[i*3+2]); + rend.xy0[0] + v[0], rend.xy0[1] + v[1], v[2]); } } @@ -75,7 +75,7 @@ void ac3_print2fig(atcoord * ac, rendpars rend, double * v){ } } - if(v){ + if(vert){ #define LINE(I,J) PRINTOUT(stdout, "bond %3d %3d % 3d\n", (J)+n+1, (I)+n+1, -1) for(int i=0; i<8; i+=2){ LINE(i,i+1); // || z-axis diff --git a/src/v/ac3_read.c b/src/v/ac3_read.c index daf57e9..18e081b 100644 --- a/src/v/ac3_read.c +++ b/src/v/ac3_read.c @@ -7,21 +7,24 @@ atcoord * atcoord_fill(mol * m0, int b, const geompars geom){ size_t q_size = sizeof(int ) * n; size_t r_size = sizeof(double) * n*3; + size_t r0_size = sizeof(double) * n*3; struct {size_t r_size; size_t a_size;} bonds = {0, 0}; if(b!=-1){ bonds.a_size = sizeof(int ) * n*BONDS_MAX; bonds.r_size = sizeof(double) * n*BONDS_MAX; } - size_t size = sizeof(atcoord) + q_size + r_size + bonds.a_size + bonds.r_size; + size_t size = sizeof(atcoord) + q_size + r_size + r0_size + bonds.a_size + bonds.r_size; atcoord * m = calloc(size, 1); if(b==-1){ m->r = (double *) (m + 1); - m->q = (int *) MEM_END(m,r); + m->r0 = (double *) MEM_END(m,r); + m->q = (int *) MEM_END(m,r0); } else{ m->r = (double *) (m + 1); - m->bonds.r = (double *) MEM_END(m,r); + m->r0 = (double *) MEM_END(m,r); + m->bonds.r = (double *) MEM_END(m,r0); m->q = (int *) MEM_END(m,bonds.r); m->bonds.a = (int *) MEM_END(m,q); } @@ -30,20 +33,20 @@ atcoord * atcoord_fill(mol * m0, int b, const geompars geom){ m->fname = m0->name; for(int i=0; iq[i] = m0->q[i]; - r3cp(m->r+i*3, m0->r+i*3); } + veccp(n*3, m->r, m0->r); if(geom.bohr){ vecscal(n*3, m->r, BA); } if(geom.inertia){ - // should not change m0 + // we should not change m0 position(&((mol){.n=n, .q=m->q, .r=m->r}), NULL, 1); } if(geom.center){ center_mol(n, m->r, geom.center==2 ? m->q : NULL); } - + veccp(n*3, m->r0, m->r); return m; } diff --git a/src/v/evr.c b/src/v/evr.c index 9e98258..f502917 100644 --- a/src/v/evr.c +++ b/src/v/evr.c @@ -3,19 +3,16 @@ #include "vec3.h" #include "3d.h" -#define EPS_INV 1e-15 - void kp_readmore(object * ent, drawpars * dp){ if(dp->task == AT3COORDS){ - object * acs = ent; if(!dp->read.f){ PRINT_ERR("cannot read from the file '%s'\n", dp->read.fname); return; } fseek(dp->read.f, 0, SEEK_CUR); - acs_readmore(dp->read, dp->rend.bonds, dp->geom, acs); - newmol_prep(acs, dp); - redraw_ac3 (acs, dp); + acs_readmore(dp->read, dp->rend.bonds, dp->geom, ent); + dp->N = ent->n; + redraw_ac3 (ent, dp); } return; } @@ -28,31 +25,27 @@ void kp_readagain(object * ent, drawpars * dp){ return; } - object * acs = ent; - for(int i=0; in; i++){ - free(acs->m[i]); + for(int i=0; in; i++){ + free(ent->m[i]); } - acs->n = dp->N = dp->n = 0; - - acs_readmore(dp->read, dp->rend.bonds, dp->geom, acs); - newmol_prep(acs, dp); - redraw_ac3 (acs, dp); + ent->n = dp->N = dp->n = 0; + acs_readmore(dp->read, dp->rend.bonds, dp->geom, ent); + dp->N = ent->n; + redraw_ac3 (ent, dp); } return; } void kp_print(object * ent, drawpars * dp){ if (dp->task == AT3COORDS){ - atcoord * ac = ent->m[dp->n]; - ac3_print(ac, dp->rend); + ac3_print(ent->m[dp->n], dp->rend); } return; } void kp_print_xyz(object * ent, drawpars * dp){ if (dp->task == AT3COORDS){ - atcoord * ac = ent->m[dp->n]; - ac3_print_xyz(ac, dp->rend); + ac3_print_xyz(ent->m[dp->n], dp->rend); } return; } @@ -69,14 +62,7 @@ void kp_printrot(object * ent __attribute__ ((unused)), drawpars * dp){ void kp_print2fig(object * ent, drawpars * dp){ if (dp->task == AT3COORDS){ - double v[3*8]; - if(dp->cell.vert == 1){ - for(int i=0; i<8; i++){ - r3mx (v+3*i, dp->cell.vertices+3*i, dp->rend.ac3rmx); - } - } - atcoord * ac = ent->m[dp->n]; - ac3_print2fig(ac, dp->rend, dp->cell.vert==1?v:NULL); + ac3_print2fig(ent->m[dp->n], dp->rend, dp->cell.vert==1?dp->cell.vertices:NULL); } return; } @@ -151,36 +137,23 @@ void kp_frame_dec(object * ent, drawpars * dp){ return; } -void rot_ent_pointer(object * ent, drawpars * dp, int dx, int dy, double speed){ - - double rotation_matrix[9]; - rot_around_perp(rotation_matrix, (double)dx, (double)dy, speed); - - double mx0[9]; - veccp(9, mx0, dp->rend.ac3rmx); - mx_multmx(3,3,3, dp->rend.ac3rmx, rotation_matrix, mx0); - if(dp->task == AT3COORDS){ - object * acs = ent; - for(int i=0; iN; i++){ - rot3d(acs->m[i]->n, acs->m[i]->r, rotation_matrix); - } +void rot_ent_pointer(object * ent __attribute__ ((unused)), drawpars * dp, int dx, int dy, double speed){ + double mx[9]; + rot_around_perp(mx, (double)dx, (double)dy, speed); + mx3_lmultmx(mx, dp->rend.ac3rmx); + for(int i=0; in; i++){ + ent->m[i]->rotated = 0; } return; } -static void rot_ent(object * ent, drawpars * dp, int axis, double angle){ +static void rot_ent(object * ent __attribute__ ((unused)), drawpars * dp, int axis, double angle){ if(dp->ui.modkey){ angle *= STEP_MOD; } - - double m[9]; - rotmx0_update(dp->rend.ac3rmx, m, angle, axis); - - if(dp->task == AT3COORDS){ - object * acs = ent; - for(int i=0; iN; i++){ - rot3d(acs->m[i]->n, acs->m[i]->r, m); - } + rotmx0_update(dp->rend.ac3rmx, angle, axis); + for(int i=0; in; i++){ + ent->m[i]->rotated = 0; } return; } @@ -221,13 +194,9 @@ void kp_rotz_r(object * ent, drawpars * dp){ return; } -static void mol2cell(double r0[3], drawpars * dp){ - double mat[9], r[3]; - veccp(9, mat, dp->rend.ac3rmx); - r3cp(r, r0); - mx_inv (3, 1, r, mat, EPS_INV); +static void mol2cell(double r[3], cellpars * cell){ double rcell[3]; - r3mx(rcell, r, dp->cell.rot_to_cell_basis); + r3mx(rcell, r, cell->rot_to_cell_basis); for(int i=0; i<3; i++){ if(rcell[i]<-0.5){ rcell[i] += 1.0; @@ -236,21 +205,28 @@ static void mol2cell(double r0[3], drawpars * dp){ rcell[i] -= 1.0; } } - r3mx(r, rcell, dp->cell.rot_to_lab_basis); - r3mx(r0, r, dp->rend.ac3rmx); + r3mx(r, rcell, cell->rot_to_lab_basis); return; } static void move_pbc(object * acs, drawpars * dp, int dir, double d){ - for(int i=0; iN; i++){ - for(int j=0; jm[i]->n; j++){ - double * r = acs->m[i]->r+j*3; - r[dir] += d; - mol2cell(r, dp); + + double dr[3], v[3] = {}; + v[dir] = d; // translation in the view basis + r3mxt(dr, v, dp->rend.ac3rmx); // translation in the mol basis. + // not true if the initial "rotation" from CLI is not unitary, but ignore this + for(int i=0; in; i++){ + atcoord * m = acs->m[i]; + for(int j=0; jn; j++){ + double * r = m->r0+j*3; + r3add(r, dr); + mol2cell(r, &dp->cell); + r3cp(m->r+j*3, r); + m->rotated = 0; } if(dp->rend.bonds>0){ - acs->m[i]->bonds.flag = 0; - acs->m[i]->bonds.rl *= RL_MOVE_PBC_SCALE; + m->bonds.flag = 0; + m->bonds.rl *= RL_MOVE_PBC_SCALE; } } return; diff --git a/src/v/evr.h b/src/v/evr.h index 52302aa..c311015 100644 --- a/src/v/evr.h +++ b/src/v/evr.h @@ -1,3 +1,5 @@ +#include "3d.h" + #define TMAX 20 #define VIBR_AMP 0.1 #define STEP_ROT (M_PI/90.0) @@ -7,6 +9,21 @@ #define STEP_MOD 0.03125 #define RL_MOVE_PBC_SCALE 0.9 +static inline void fill_bonds(atcoord * m, drawpars * dp){ + if(dp->rend.bonds>0){ + bonds_fill(dp->bond, m); + } + return; +} + +static inline void rotate_mol(atcoord * m, drawpars * dp){ + if(!m->rotated){ + rot3d(m->n, m->r, m->r0, dp->rend.ac3rmx); + m->rotated = 1; + } + return; +} + void kp_readmore (object * ent, drawpars * dp); void kp_readagain(object * ent, drawpars * dp); void kp_print (object * ent, drawpars * dp); diff --git a/src/v/headless.c b/src/v/headless.c index 485ad84..b4a07ee 100644 --- a/src/v/headless.c +++ b/src/v/headless.c @@ -48,10 +48,8 @@ void run_commands(FILE * f, char * command, drawpars * dp, object * ent){ } int headless(drawpars * dp, object * ent){ - atcoord * ac = ent->m[dp->n]; - if(dp->rend.bonds>0){ - bonds_fill(dp->bond, ac); - } + fill_bonds(ent->m[dp->n], dp); + rotate_mol(ent->m[dp->n], dp); run_commands(stdin, dp->ui.com, dp, ent); obj_free(ent); CLOSE0(dp->read.f); diff --git a/src/v/load.c b/src/v/load.c index e04d96f..fdbc58e 100644 --- a/src/v/load.c +++ b/src/v/load.c @@ -13,20 +13,6 @@ static inline void fill_nf(object * acs, int n0){ return; } -void newmol_prep(object * acs, drawpars * dp){ - for(int j=dp->N; jn; j++){ - atcoord * ac = acs->m[j]; - for(int i=0; in; i++){ - double v[3]; - r3mx(v, ac->r+3*i, dp->rend.ac3rmx); - r3cp(ac->r+3*i, v); - } - } - dp->N = acs->n; - return; -} - - void acs_readmore(readpars read, int b, geompars geom, object * acs){ // needed to reset nf @@ -174,7 +160,7 @@ object * read_files(allpars * ap){ } } dp->rend.scale = acs_scale(acs); - newmol_prep(acs, dp); + dp->N = acs->n; intcoord_check(INT_MAX, dp->anal.intcoord); } else{ @@ -212,7 +198,7 @@ object * acs_from_var(int n, mol * m, vibr_t vib, allpars * ap){ fill_nf(ent, 0); dp->rend.scale = acs_scale(ent); - newmol_prep(ent, dp); + dp->N = ent->n; int natmax = 0; for(int i=0; im[dp->n]; - - if(dp->rend.bonds>0){ - bonds_fill(dp->bond, ac); - } + atcoord * m = ent->m[dp->n]; + fill_bonds(m, dp); + rotate_mol(m, dp); clear_canv(); - ac3_draw(ac, dp->rend); - ac3_text(ac, dp); - + ac3_draw(m, dp->rend); + ac3_text(m, dp); if(dp->cell.vert == 1){ - double v[24]; - for(int i=0; i<8; i++){ - r3mx (v+3*i, dp->cell.vertices+3*i, dp->rend.ac3rmx); - } + double v[8*3]; + rot3d(8, v, dp->cell.vertices, dp->rend.ac3rmx); drawvertices(v, dp->rend); } else if(dp->cell.vert == 2){ drawshell(dp->cell.vertices, dp->rend); } fill_canv(); - return; } @@ -81,16 +73,9 @@ void redraw_vibro(object * ent, drawpars * dp){ double * r0 = ent->vib->r0; double * dr = ent->vib->disp + dp->n * m->n*3; - if(dp->rend.bonds>0){ - bonds_fill(dp->bond, m); - } - - vecsums(m->n*3, m->r, r0, dr, sin( dp->anim.t * 2.0*M_PI/TMAX ) * VIBR_AMP*sqrt(m->n) ); - for(int j=0; jn; j++){ - double v[3]; - r3mx(v, m->r+3*j, dp->rend.ac3rmx); - r3cp(m->r+3*j, v); - } + fill_bonds(m, dp); + vecsums(m->n*3, m->r, r0, dr, VIBR_AMP*sqrt(m->n)*sin(dp->anim.t * 2.0*M_PI/TMAX)); + rot3d_inplace(m->n, m->r, dp->rend.ac3rmx); clear_canv(); ac3_draw(m, dp->rend); diff --git a/src/v/v.h b/src/v/v.h index 3bdc0a2..ec6ed7f 100644 --- a/src/v/v.h +++ b/src/v/v.h @@ -29,10 +29,13 @@ typedef struct { typedef struct { int n; // number of atoms - int * q; // charges of atoms - double * r; // coordinates of atoms + int * q; // atom charges + double * r; // atom coordinates (rotated) const char * fname; // file name + int rotated; // is `r` up-to-date + double * r0; // atom coordinates (original) + int nf[2]; // number of molecule in file, file size styp sym; // point group bondstr bonds; @@ -55,7 +58,6 @@ typedef struct { // load.c -void newmol_prep(object * acs, drawpars * dp); object * acs_from_var(int n, mol * m, vibr_t vib, allpars * ap); void acs_readmore (readpars read, int b, geompars geom, object * acs); object * read_files(allpars * ap); From fe4eeb5d607a4f7a95f0a143eb64b995b7b634ef Mon Sep 17 00:00:00 2001 From: Ksenia Date: Tue, 17 Mar 2026 16:19:50 +0100 Subject: [PATCH 08/10] Use atcoords.r0 added in b572575 instead of vibrstr.r0 --- python/vmol/main.py | 8 +++----- src/v/load.c | 43 ++++++++++++++++++++----------------------- src/v/mode_read.c | 6 ++---- src/v/redraw.c | 3 +-- src/v/v.h | 1 - 5 files changed, 26 insertions(+), 35 deletions(-) diff --git a/python/vmol/main.py b/python/vmol/main.py index 3f1ea56..974a800 100644 --- a/python/vmol/main.py +++ b/python/vmol/main.py @@ -47,7 +47,6 @@ class vibr_t(ctypes.Structure): # noqa: N801 double * ints; double * disp; double * mass; - double * r0; int n; } vibr_t; ``` @@ -58,7 +57,6 @@ class vibr_t(ctypes.Structure): # noqa: N801 ("ints", c_double_p), ("disp", c_double_p), ("mass", c_double_p), - ("r0", c_double_p), ("n", c_int), ) @@ -399,13 +397,13 @@ def vib2struct(nat, vib=None): Returns: vibr_t: An instance of `vibr_t` with the fields set. If missing, the optional fields are set to 0, - and the `r0` is set to NULL. If the input dictionary is None, everything is set to 0/NULL. + If the input dictionary is None, everything is set to 0/NULL. Raises: TypeError: If mol is neither a dictionary nor None. """ if vib is None: - return vibr_t(n=c_int(0), disp=None, freq=None, ints=None, mass=None, r0=None) + return vibr_t(n=c_int(0), disp=None, freq=None, ints=None, mass=None) if not isinstance(vib, dict): msg = f"vib must be None or a dictionary, but got {type(vib)}" @@ -452,7 +450,7 @@ def check_array(key, required=True, shape=None, ndim=None, dtype=c_double): for key, val in vdict.items(): vdict[key] = val.ctypes.data_as(c_double_p) - v = vibr_t(n=nvib, disp=vdict['disp'], freq=vdict['freq'], ints=vdict['ints'], mass=vdict['mass'], r0=None) + v = vibr_t(n=nvib, disp=vdict['disp'], freq=vdict['freq'], ints=vdict['ints'], mass=vdict['mass']) v._keepalive = (nvib, vdict['disp'], vdict['freq'], vdict['ints'], vdict['mass']) # keep strong references return v diff --git a/src/v/load.c b/src/v/load.c index fdbc58e..d211db9 100644 --- a/src/v/load.c +++ b/src/v/load.c @@ -49,30 +49,32 @@ void acs_readmore(readpars read, int b, geompars geom, object * acs){ return; } -static object * mode_read_try(FILE * f, atcoord * ac){ +static object * mode_read_try(FILE * f, object * ent, drawpars * dp){ long pos = ftell(f); rewind(f); + atcoord * m = ent->m[ent->n-1]; + vibr_t * vib = mode_read(f, m->n); - int n = ac->n; - vibr_t * modes = mode_read(f, n); - - if(modes){ - object * ent = malloc(sizeof(object)); - ent->Nmem = ent->n = 1; - ent->m = malloc(ent->Nmem*sizeof(atcoord *)); - ent->m[0] = ac; - ent->vib = modes; - veccp(n*3, ent->vib->r0, ac->r); - return ent; - } - else{ + if(!vib){ fseek(f, pos, SEEK_SET); return NULL; } + else{ + for(int i=0; in-1; i++){ + free(ent->m[i]); + } + ent->Nmem = ent->n = 1; + ent->m = realloc(ent->m, sizeof(atcoord *)); + ent->m[0] = m; + ent->vib = vib; + dp->rend.scale = ac3_scale(m); + dp->N = vib->n; + return ent; + } } -static FILE * acs_read_newfile(object * acs, char * fname, drawpars * dp){ +static FILE * acs_read_newfile(char * fname, object * acs, drawpars * dp){ FILE * f; if(!strcmp(fname, "-")){ f = stdin; @@ -95,7 +97,7 @@ static object * ent_read(char * fname, drawpars * dp){ acs->m = NULL; acs->vib = NULL; - FILE * f = acs_read_newfile(acs, fname, dp); + FILE * f = acs_read_newfile(fname, acs, dp); if(!f || !acs->n){ free(acs); return NULL; @@ -103,13 +105,9 @@ static object * ent_read(char * fname, drawpars * dp){ dp->read.fname = fname; if(dp->task==UNKNOWN || dp->task==VIBRO){ - object * vib = mode_read_try(f, acs->m[acs->n-1]); + object * vib = mode_read_try(f, acs, dp); if(vib){ - acs->n--; - obj_free(acs); fclose(f); - dp->rend.scale = ac3_scale(vib->m[0]); - dp->N = vib->vib->n; dp->task = VIBRO; return vib; } @@ -145,7 +143,7 @@ object * read_files(allpars * ap){ object * acs = ent; int n0 = acs->n; for(i++; im[0] = atcoord_fill(m+n-1, dp->rend.bonds, dp->geom); int nat = ent->m[0]->n; ent->vib = make_vibr_t(vib.n, nat); - veccp(nat*3, ent->vib->r0, ent->m[0]->r); veccp(vib.n*nat*3, ent->vib->disp, vib.disp); veccp(vib.n, ent->vib->freq, vib.freq); veccp(vib.n, ent->vib->ints, vib.ints); diff --git a/src/v/mode_read.c b/src/v/mode_read.c index 6723b93..90e257e 100644 --- a/src/v/mode_read.c +++ b/src/v/mode_read.c @@ -9,15 +9,13 @@ vibr_t * make_vibr_t(int n_modes, int n_atoms){ size_t freq_size = sizeof(double) * n_modes; size_t ints_size = sizeof(double) * n_modes; size_t mass_size = sizeof(double) * n_modes; - size_t r0_size = sizeof(double) * n_atoms*3; size_t disp_size = sizeof(double) * n_modes*n_atoms*3; - size_t size = sizeof(vibr_t) + freq_size + r0_size + disp_size + ints_size + mass_size; + size_t size = sizeof(vibr_t) + freq_size + disp_size + ints_size + mass_size; vibr_t * v = malloc(size); v->n = n_modes; v->freq = (double *) (v + 1); v->disp = (double *) MEM_END(v,freq); - v->r0 = (double *) MEM_END(v,disp); - v->ints = (double *) MEM_END(v,r0); + v->ints = (double *) MEM_END(v,disp); v->mass = (double *) MEM_END(v,ints); return v; } diff --git a/src/v/redraw.c b/src/v/redraw.c index b52ea52..0d4ff8e 100644 --- a/src/v/redraw.c +++ b/src/v/redraw.c @@ -70,11 +70,10 @@ void redraw_ac3(object * ent, drawpars * dp){ void redraw_vibro(object * ent, drawpars * dp){ atcoord * m = ent->m[0]; - double * r0 = ent->vib->r0; double * dr = ent->vib->disp + dp->n * m->n*3; fill_bonds(m, dp); - vecsums(m->n*3, m->r, r0, dr, VIBR_AMP*sqrt(m->n)*sin(dp->anim.t * 2.0*M_PI/TMAX)); + vecsums(m->n*3, m->r, m->r0, dr, VIBR_AMP*sqrt(m->n)*sin(dp->anim.t * 2.0*M_PI/TMAX)); rot3d_inplace(m->n, m->r, dp->rend.ac3rmx); clear_canv(); diff --git a/src/v/v.h b/src/v/v.h index ec6ed7f..b70d78d 100644 --- a/src/v/v.h +++ b/src/v/v.h @@ -46,7 +46,6 @@ typedef struct { double * ints; // intensities double * disp; // displacements double * mass; // masses - double * r0; // atom configuration at the central point int n; // number of modes } vibr_t; From de242c7dd52a51e94165c05782019bb12c16e88e Mon Sep 17 00:00:00 2001 From: Ksenia Date: Tue, 17 Mar 2026 23:36:21 +0100 Subject: [PATCH 09/10] Improve text in corner --- src/v/redraw.c | 58 +++++++++++++++++++++++++++++++++++++------------- src/v/v.h | 2 +- src/v/x.c | 14 +++++++----- src/v/x.h | 1 + 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/src/v/redraw.c b/src/v/redraw.c index 0d4ff8e..190b134 100644 --- a/src/v/redraw.c +++ b/src/v/redraw.c @@ -2,26 +2,54 @@ #include "evr.h" static void ac3_text(atcoord * ac, drawpars * dp){ - char text[STRLEN], text2[STRLEN], text_inp[STRLEN]; - const char * lines[MAX_LINES] = {[0] = text, [1] = dp->read.fname}; - const int lines_red[MAX_LINES] = {[2] = 1}; + char text[32]; + char text_fname[STRLEN]; + char text_input[STRLEN]; + char text_coord[STRLEN]; + char text_point[32]; + + const char * lines[MAX_LINES] = {}; + int lines_red[MAX_LINES] = {}; + + int il=0; + snprintf(text, sizeof(text), "%*d / %d", 1+(int)(log10(dp->N)), dp->n+1, dp->N); + lines[il++] = text; - int tp = snprintf(text, sizeof(text), "%*d / %d r = %.1lf rl = %.1lf", 1+(int)(log10(dp->N)), dp->n+1, dp->N, dp->rend.r, dp->bond.rl); - if( tpanal.intcoord[0] ){ - tp += snprintf(text+tp, sizeof(text)-tp, " | %d,%d,%d,%d,%d: %lf", dp->anal.intcoord[0], dp->anal.intcoord[1], dp->anal.intcoord[2], dp->anal.intcoord[3], dp->anal.intcoord[4], intcoord_calc(1, ac->n, dp->anal.intcoord, ac->r)); + if(ac->nf[1]==dp->N){ + lines[il++] = dp->read.fname; } - if( tpsym[0] ){ - tp += snprintf(text+tp, sizeof(text)-tp, " | PG: %s", ac->sym); + else{ + snprintf(text_fname, sizeof(text_fname), "%s (%*d / %d)", ac->fname, 1+(int)(log10(ac->nf[1])), ac->nf[0]+1, ac->nf[1]); + lines[il++] = text_fname; } - if(ac->nf[1]!=dp->N){ - snprintf(text2, sizeof(text2), "%s (%*d / %d)", ac->fname, 1+(int)(log10(ac->nf[1])), ac->nf[0]+1, ac->nf[1]); - lines[1] = text2; + if(dp->anal.intcoord[0]){ + double z = intcoord_calc(1, ac->n, dp->anal.intcoord, ac->r); + switch(dp->anal.intcoord[0]){ + case 1: + snprintf(text_coord, sizeof(text_coord), "bond %d-%d: %.3lf", dp->anal.intcoord[1], dp->anal.intcoord[2], z); + break; + case 2: + snprintf(text_coord, sizeof(text_coord), "angle %d-%d-%d: %.1lf", dp->anal.intcoord[1], dp->anal.intcoord[2], dp->anal.intcoord[3], z); + break; + case 3: + snprintf(text_coord, sizeof(text_coord), "dihedral %d-%d-%d-%d: % .1lf", dp->anal.intcoord[1], dp->anal.intcoord[2], dp->anal.intcoord[3], dp->anal.intcoord[4], z); + break; + default: + break; + } + lines[il++] = text_coord; + } + + if(ac->sym[0]){ + snprintf(text_point, sizeof(text_point), "point group: %s", ac->sym); + lines[il++] = text_point; } if(dp->ui.input==1){ - snprintf(text_inp, sizeof(text_inp), "JUMP TO >>> %s", dp->ui.input_text); - lines[2] = text_inp; + snprintf(text_input, sizeof(text_input), "JUMP TO >>> %s", dp->ui.input_text); + lines_red[il] = 1; + lines[il++] = text_input; } textincorner(lines, lines_red); @@ -37,8 +65,8 @@ void vibro_text(vibr_t * ms, drawpars * dp){ double fq = ms->freq[dp->n]; char i = fq > 0.0 ? ' ' : 'i'; snprintf(text, sizeof(text), - "%*d / %d freq = %.1lf%c cm-1 int = %.1lf km/mole mass = %.1lf amu | r = %.1lf rl = %.1lf", - 1+(int)(log10(ms->n)), dp->n+1, ms->n, fabs(fq), i, ms->ints[dp->n], ms->mass[dp->n], dp->rend.r, dp->bond.rl); + "%*d / %d freq = %.1lf%c cm-1 int = %.1lf km/mole mass = %.1lf amu", + 1+(int)(log10(ms->n)), dp->n+1, ms->n, fabs(fq), i, ms->ints[dp->n], ms->mass[dp->n]); if(dp->ui.input==1){ snprintf(text_inp, sizeof(text_inp), "JUMP TO >>> %s", dp->ui.input_text); lines[2] = text_inp; diff --git a/src/v/v.h b/src/v/v.h index b70d78d..05aecae 100644 --- a/src/v/v.h +++ b/src/v/v.h @@ -7,7 +7,7 @@ #define POINTER_SPEED 2.0 #define STRLEN 256 #define BIGSTRLEN 4096 -#define MAX_LINES 3 +#define MAX_LINES 5 #include "pars.h" diff --git a/src/v/x.c b/src/v/x.c index 984fd7b..d28333a 100644 --- a/src/v/x.c +++ b/src/v/x.c @@ -77,7 +77,7 @@ void init_x(const char * const capt, const colorscheme_t colorscheme){ world.gc_black = XCreateGC (dis, world.win, 0, 0); XSetBackground (dis, world.gc_black, wp); XSetForeground (dis, world.gc_black, bp); - XSetLineAttributes(dis, world.gc_black, 2, 0, 0, 0); + XSetLineAttributes(dis, world.gc_black, LINE_WIDTH, LineSolid, 0, 0); world.gc_red = XCreateGC (dis, world.win, 0, 0); XSetBackground (dis, world.gc_red, wp); @@ -86,12 +86,12 @@ void init_x(const char * const capt, const colorscheme_t colorscheme){ world.gc_dot[0] = XCreateGC (dis, world.win, 0, 0); XSetBackground (dis, world.gc_black, wp); XSetForeground (dis, world.gc_black, bp); - XSetLineAttributes(dis, world.gc_dot[0], 2, 1, 0, 0); + XSetLineAttributes(dis, world.gc_dot[0], LINE_WIDTH, LineOnOffDash, 0, 0); world.gc_dot[1] = XCreateGC (dis, world.win, 0, 0); XSetBackground (dis, world.gc_black, wp); XSetForeground (dis, world.gc_black, bp); - XSetLineAttributes(dis, world.gc_dot[1], 0, 1, 0, 0); + XSetLineAttributes(dis, world.gc_dot[1], 0, LineOnOffDash, 0, 0); setcolors(colorscheme); @@ -135,10 +135,14 @@ void init_font(char * fontname){ } void textincorner(const char * const lines[MAX_LINES], const int red[MAX_LINES]){ - int voffset = world.fontInfo ? (world.fontInfo->ascent + world.fontInfo->descent + 5) : 20; + XCharStruct _o; + int _d, font_ascent, font_descent; + XQueryTextExtents(world.dis, XGContextFromGC(world.gc_black), ".", 1, &_d, &font_ascent, &font_descent, &_o); + int voffset = font_ascent + font_descent + 5; + int hoffset = 10; for(int i=0; i #define NCOLORS 110 +#define LINE_WIDTH 2 #define SCREEN_X(X) (world.W/2 + world.size * rend.scale*(rend.xy0[0] + (X))) #define SCREEN_Y(Y) (world.H/2 - world.size * rend.scale*(rend.xy0[1] + (Y))) From f5e157c4776c91db9899aef122da109580aaf29d Mon Sep 17 00:00:00 2001 From: Ksenia Date: Tue, 17 Mar 2026 23:45:59 +0100 Subject: [PATCH 10/10] Update changelog --- .github/CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 9e228b5..727a9cb 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -14,8 +14,9 @@ * Remove case sensitivity of xyz file inputs (#9) * Add CLI option to disable centering of molecules (#14) * Disable default rotation wrt inertia axis for z-matrix input and add a CLI option to force it (#14) -* Read molecules from the standard input -* Show infrared intensities and mode masses +* Read molecules from the standard input (#28) +* Show infrared intensities and mode masses (#35) +* Improve the text-in-corner look (de242c7, #36) * Improve data structures and code readability ### Fixes @@ -24,6 +25,7 @@ * Fix NaNs when compute dihedrals (#14) * Fix the "readagain" (`r`) and "readmore" (`tab`) bugs (#31) * Fix z-matrix input with unit=bohr (8554864) +* Fix text blinking when playing animation (80cae88, #36) ### Coming in the next version: * extended xyz (#16, #17)