From 47f9a78df9facf86ed77b80f7df97fc8c1d6807a Mon Sep 17 00:00:00 2001 From: toshinagata1964 Date: Mon, 17 Mar 2014 05:18:52 +0000 Subject: [PATCH] Line/Ball-and-stick/Space-filling modes are implemented git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/molby/trunk@473 a2be9bc6-48de-4e38-9406-05402d4bc13c --- MolLib/MainView.c | 239 ++++++++----------------------------------- MolLib/MainView.h | 6 +- MolLib/MainViewCommon.c | 4 +- MolLib/Molecule.c | 65 ++++++++---- MolLib/Ruby_bind/ruby_bind.c | 123 +++++++++++++++++++++- MolLib/Trackball.c | 58 ++++------- MolLib/Trackball.h | 30 +++--- Scripts/view.rb | 76 ++++++++++++-- wxSources/MyApp.cpp | 2 +- 9 files changed, 317 insertions(+), 286 deletions(-) diff --git a/MolLib/MainView.c b/MolLib/MainView.c index 5525e52..769b51d 100755 --- a/MolLib/MainView.c +++ b/MolLib/MainView.c @@ -223,7 +223,7 @@ void MainView_resizeToFit(MainView *mview) { Vector p; - float f[4]; + double f[4]; if (mview == NULL || mview->mol == NULL) return; if (mview->mol->natoms == 0) { @@ -231,8 +231,6 @@ MainView_resizeToFit(MainView *mview) return; } MoleculeCenterOfMass(mview->mol, &p, NULL); -/* if (mview->mol->is_xtal_coord) - TransformVec(&p, mview->mol->cell->tr, &p); */ f[0] = -p.x / mview->dimension; f[1] = -p.y / mview->dimension; f[2] = -p.z / mview->dimension; @@ -250,8 +248,6 @@ MainView_resizeToFit(MainView *mview) double r0 = 0.0, r1, scale; for (i = 0, ap = mview->mol->atoms; i < mview->mol->natoms; i++, ap = ATOM_NEXT(ap)) { q = ap->r; - /* if (mview->mol->is_xtal_coord) - TransformVec(&q, mview->mol->cell->tr, &q); */ VecDec(q, p); r1 = VecLength(q); if (r1 > r0) @@ -268,96 +264,10 @@ MainView_resizeToFit(MainView *mview) } MainViewCallback_setNeedsDisplay(mview, 1); - -#if 0 - GLdouble mm[4][4]; - GLdouble p0[4]; - int i, j, natoms; - const Atom *ap; - const ElementPar *app; - GLdouble *pp, *p1; - GLdouble max[3], min[3], center[3]; - float frame[4], width, height, cot15, rsin15, cot_th, rsin_th, d, trans[3]; - Molecule *mol; - - if (mview == NULL || mview->mol == NULL) - return; - mol = mview->mol; - - /* Transform the coordinates of all atoms with the rotation part of - * the model-view matrix */ - memmove((GLdouble *)mm, mview->modelview_matrix, sizeof(float) * 16); - natoms = mol->natoms; - pp = (GLdouble *)calloc(sizeof(GLdouble), 4 * natoms); - MALLOC_CHECK(pp, "resizing the model to fit"); - for (i = 0; i < natoms; i++) { - ap = ATOM_AT_INDEX(mol->atoms, i); - if (ap == NULL) - continue; - p0[0] = ap->r.x; p0[1] = ap->r.y; p0[2] = ap->r.z; - p0[3] = 0.0; /* This disables the translation part */ - p1 = &pp[i * 4]; - MAT_DOT_VEC_4X4(p1, mm, p0); /* #define'd in GLUT/vvector.h */ - } - - /* Determine the center for each axis */ - max[0] = max[1] = max[2] = -1e20; - min[0] = min[1] = min[2] = 1e20; - for (i = 0; i < natoms; i++) { - p1 = &pp[i * 4]; - for (j = 0; j < 3; j++) { - if (p1[j] > max[j]) - max[j] = p1[j]; - if (p1[j] < min[j]) - min[j] = p1[j]; - } - } - for (j = 0; j < 3; j++) - center[j] = (min[j] + max[j]) * 0.5; - - /* Get the frame size */ - MainViewCallback_frame(mview, frame); - width = frame[2] - frame[0]; - height = frame[3] - frame[1]; - - /* Calculate the minimum distance from which the view angle of - * the atom becomes no more than 15 degree (for the y direction) - * and theta degree (for the x direction, theta = arctan(h/w*tan(15 deg))) */ - cot15 = 3.73205080756888; - rsin15 = 3.86370330515628; - cot_th = width / height * cot15; - rsin_th = sqrt(1.0 + cot_th * cot_th); - d = 0; - for (i = 0; i < natoms; i++) { - float dx, dy, z, r; - ap = ATOM_AT_INDEX(mol->atoms, i); - if (ap == NULL) - continue; - app = &(gBuiltinParameters->atomPars[ap->atomicNumber]); - if (app == NULL) - continue; - r = app->radius * mview->atomRadius; - z = pp[i * 4 + 2] - center[2]; - dx = pp[i * 4] * cot_th + r * rsin_th + z; - dy = pp[i * 4 + 1] * cot15 + r * rsin15 + z; - if (d < dx) - d = dx; - if (d < dy) - d = dy; - } - mview->dimension = d / cot15; - TrackballSetScale(mview->track, 1.0); - trans[0] = center[0] / mview->dimension; - trans[1] = center[1] / mview->dimension; - trans[2] = center[2] / mview->dimension; - TrackballSetTranslate(mview->track, trans); - - free(pp); -#endif } int -MainView_convertScreenPositionToObjectPosition(MainView *mview, const GLfloat *screenPos, GLfloat *objectPos) +MainView_convertScreenPositionToObjectPosition(MainView *mview, const GLfloat *screenPos, double *objectPos) { float rect[4]; GLint viewport[4], n; @@ -387,7 +297,7 @@ MainView_convertScreenPositionToObjectPosition(MainView *mview, const GLfloat *s } int -MainView_convertObjectPositionToScreenPosition(MainView *mview, const GLfloat *objectPos, GLfloat *screenPos) +MainView_convertObjectPositionToScreenPosition(MainView *mview, const double *objectPos, GLfloat *screenPos) { float rect[4]; GLint viewport[4]; @@ -411,7 +321,8 @@ MainView_convertObjectPositionToScreenPosition(MainView *mview, const GLfloat *o int MainView_findObjectAtPoint(MainView *mview, const float *mousePos, int *outIndex1, int *outIndex2, int mouseCheck, int ignoreExpandedAtoms) { - float screenPos[3], op[3], oq[3], pqlen, pqlen2; + float screenPos[3]; + double op[3], oq[3], pqlen, pqlen2; Vector pq, pa, v1, r1, r2; int i, natoms, nbonds; float r, d2, z; @@ -428,7 +339,6 @@ MainView_findObjectAtPoint(MainView *mview, const float *mousePos, int *outIndex } mol = mview->mol; -#if 1 screenPos[0] = mousePos[0]; screenPos[1] = mousePos[1]; screenPos[2] = -1.0; @@ -450,7 +360,7 @@ MainView_findObjectAtPoint(MainView *mview, const float *mousePos, int *outIndex minDepth = 100.0; for (i = 0; i < natoms; i++) { Vector pq1, pa1; - float pq1len2, pq1len; + double pq1len2, pq1len; if (mouseCheck && i % 50 == 0 && MainViewCallback_mouseCheck(mview)) return 0; /* If mouse event is detected return immediately */ /* Examine if an atom is visible or not */ @@ -470,7 +380,7 @@ MainView_findObjectAtPoint(MainView *mview, const float *mousePos, int *outIndex pa.x = r1.x - op[0]; pa.y = r1.y - op[1]; pa.z = r1.z - op[2]; - if (ap->aniso != NULL) { + if (mview->showEllipsoids && ap->aniso != NULL) { /* Convert to ellipsoid principal axes */ Mat33 m1; Aniso *anp = ap->aniso; @@ -487,7 +397,7 @@ MainView_findObjectAtPoint(MainView *mview, const float *mousePos, int *outIndex ep = &(gElementParameters[ap->atomicNumber]); if (ep == NULL) continue; - r = ep->radius * mview->atomRadius; + r = ep->radius * 2 * mview->atomRadius; } pa1 = pa; pq1 = pq; @@ -574,76 +484,6 @@ MainView_findObjectAtPoint(MainView *mview, const float *mousePos, int *outIndex *outIndex1 = n1; *outIndex2 = n2; return (n1 >= 0 || n2 >= 0); - -#else - /* Examine if anything is drawn at the point */ - screenPos[0] = mousePos[0]; - screenPos[1] = mousePos[1]; - screenPos[2] = -1.0; - if (MainView_convertScreenPositionToObjectPosition(mview, screenPos, objectPos) == 0) - return 0; /* Nothing is here */ - op[0] = objectPos[0]; - op[1] = objectPos[1]; - op[2] = objectPos[2]; - - /* Examine the distance from the atom center with op, and select the one - with the smallest difference with the radius on the screen */ - atomRadius = mview->atomRadius; - bondRadius = mview->bondRadius; - natoms = mol->natoms; - mindr = 100.0; - n1 = n2 = -1; - for (i = 0; i < natoms; i++) { - ap = ATOM_AT_INDEX(mol->atoms, i); - if (ap == NULL) - continue; - dp = &(gBuiltinParameters->atomPars[ap->atomicNumber]); - if (dp == NULL) - continue; - p[0] = objectPos[0] - ap->r.x; - p[1] = objectPos[1] - ap->r.y; - p[2] = objectPos[2] - ap->r.z; - rr = sqrt(p[0]*p[0] + p[1]*p[1] + p[2]*p[2]) / (dp->radius * atomRadius); - dr = fabs(1.0 - rr); - if (dr < mindr) { - mindr = dr; - n1 = i; - } - } - if (mindr > 0.1) - n1 = -1; - nbonds = mol->nbonds; - for (i = 0; i < nbonds; i++) { - float q; - ip = &(mol->bonds[i * 2]); - ap = ATOM_AT_INDEX(mol->atoms, ip[0]); - bp = ATOM_AT_INDEX(mol->atoms, ip[1]); - p[0] = objectPos[0] - ap->r.x; - p[1] = objectPos[1] - ap->r.y; - p[2] = objectPos[2] - ap->r.z; - b[0] = bp->r.x - ap->r.x; - b[1] = bp->r.y - ap->r.y; - b[2] = bp->r.z - ap->r.z; - /* ap.r + q*(b[0],b[1],b[2]) is the closest point on line AB to objectPos */ - /* If q is outside [0, 1] then the point is outside the line segment AB - so it is ignored */ - q = (p[0]*b[0]+p[1]*b[1]+p[2]*b[2])/(b[0]*b[0]+b[1]*b[1]+b[2]*b[2]); - if (q < 0 || q > 1) - continue; - p[0] -= q * b[0]; - p[1] -= q * b[1]; - p[2] -= q * b[2]; - dr = fabs(bondRadius - sqrt(p[0]*p[0] + p[1]*p[1] + p[2]*p[2])); - if (dr < mindr) { - mindr = dr; - n1 = ip[0]; - n2 = ip[1]; - } - } - *outIndex1 = n1; - *outIndex2 = n2; - return (n1 >= 0 || n2 >= 0); -#endif } int @@ -653,7 +493,7 @@ MainView_screenCenterPointOfAtom(MainView *mview, int index, float *outScreenPos const ElementPar *dp; Vector cv, pv, v; Double rad, w; - float p[3]; + double p[3]; if (mview == NULL || mview->mol == NULL || index < 0 || index >= mview->mol->natoms) return 0; @@ -696,7 +536,7 @@ MainView_screenCenterPointOfAtom(MainView *mview, int index, float *outScreenPos } } else { dp = &(gElementParameters[ap->atomicNumber]); - rad = dp->radius * mview->atomRadius; + rad = dp->radius * 2 * mview->atomRadius; w = rad / VecLength(pv) * 1.1; VecScaleSelf(pv, w); } @@ -1021,7 +861,7 @@ temporarySelection(MainView *mview, int flags, int clickCount, int ignoreExpande continue; if (mview->draggingMode == kMainViewSelectingRegion) { /* Check if this atom is within the selection rectangle */ - GLfloat objectPos[3]; + double objectPos[3]; GLfloat screenPos[3]; Vector r1; r1 = ap->r; @@ -1141,6 +981,7 @@ drawAtom(MainView *mview, int i1, int selected, const Vector *dragOffset, const int expanded = 0; Vector r1; GLfloat p[6]; + double pp[3]; char label[16]; GLfloat rgba[4]; Transform *trp = NULL; @@ -1211,21 +1052,24 @@ drawAtom(MainView *mview, int i1, int selected, const Vector *dragOffset, const for (i = 0; i < 9; i++) elip[i] = ap->aniso->pmat[i] * mview->probabilityScale; } - drawEllipsoid(p, elip, elip+3, elip+6, 15); + drawEllipsoid(p, elip, elip+3, elip+6, mview->atomResolution * 3 / 2); /* Use higher resolution than spheres */ } else { Double rad; if (ap != NULL) { rad = biso2radius(ap->tempFactor); rad *= mview->probabilityScale; } else { - rad = dp->radius * mview->atomRadius; + rad = dp->radius * 2 * mview->atomRadius; } - drawSphere(p, rad, 8); + drawSphere(p, rad, mview->atomResolution); } } else { - drawSphere(p, dp->radius * mview->atomRadius, 12); + drawSphere(p, dp->radius * 2 * mview->atomRadius, mview->atomResolution); } - if (MainView_convertObjectPositionToScreenPosition(mview, p, p + 3)) { + pp[0] = p[0]; + pp[1] = p[1]; + pp[2] = p[2]; + if (MainView_convertObjectPositionToScreenPosition(mview, pp, p + 3)) { /* fprintf(stderr, "atom %d: {%f, %f, %f}\n", i1, p[3], p[4], p[5]); */ float fp[3]; fp[0] = p[3]; fp[1] = p[4]; fp[2] = p[5]; @@ -1324,7 +1168,7 @@ drawBond(MainView *mview, int i1, int i2, int selected, int selected2, int draft glEnd(); } else { glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, rgba); - drawCylinder(p, p + 3, mview->bondRadius * rad_mul, 8, 0); + drawCylinder(p, p + 3, mview->bondRadius * rad_mul, mview->bondResolution, 0); } dp = &(gElementParameters[an[1]]); if (dp == NULL) @@ -1356,7 +1200,7 @@ drawBond(MainView *mview, int i1, int i2, int selected, int selected2, int draft static void calcDragOffset(MainView *mview, Vector *outVector) { - GLfloat p[6]; + double p[6]; if (mview->draggingMode == kMainViewDraggingSelectedAtoms && MainView_convertScreenPositionToObjectPosition(mview, mview->dragStartPos, p) && MainView_convertScreenPositionToObjectPosition(mview, mview->dragEndPos, p + 3)) { @@ -1684,9 +1528,9 @@ static void drawRotationCenter(MainView *mview) { GLfloat ps[3], pe[3], col[4]; - float fd[2]; /* Fovy and distance */ - float tr[3]; /* Translation */ - float r, rr; + double fd[2]; /* Fovy and distance */ + double tr[3]; /* Translation */ + double r, rr; if (mview == NULL || !mview->showRotationCenter) return; TrackballGetTranslate(mview->track, tr); @@ -1828,7 +1672,7 @@ drawLabels(MainView *mview) void MainView_drawModel(MainView *mview) { - float w[4], dimension, distance; + double w[4], dimension, distance; float frame[4], width, height; GLdouble *pp; Transform mtr; @@ -2098,8 +1942,10 @@ showAtomsInInfoText(MainView *mview, int n1, int n2) void MainView_mouseDown(MainView *mview, const float *mousePos, int flags) { - float p[3]; - float screenPos[3], objectPos[3]; + double p[3]; + float fp[3]; + float screenPos[3]; + double objectPos[3]; int n1, n2, found; Atom *ap; mview->dragStartPos[0] = mousePos[0]; @@ -2127,11 +1973,11 @@ MainView_mouseDown(MainView *mview, const float *mousePos, int flags) objectPos[0] = r2.x; objectPos[1] = r2.y; objectPos[2] = r2.z; - if (MainView_convertObjectPositionToScreenPosition(mview, objectPos, p)) { + if (MainView_convertObjectPositionToScreenPosition(mview, objectPos, fp)) { Double w; - r1.x = p[0] - screenPos[0]; - r1.y = p[1] - screenPos[1]; - r1.z = p[2] - screenPos[2]; + r1.x = fp[0] - screenPos[0]; + r1.y = fp[1] - screenPos[1]; + r1.z = fp[2] - screenPos[2]; NormalizeVec(&r1, &r1); r2.x = mousePos[0] - screenPos[0]; r2.y = mousePos[1] - screenPos[1]; @@ -2161,8 +2007,8 @@ MainView_mouseDown(MainView *mview, const float *mousePos, int flags) case kTrackballTranslateMode: case kTrackballScaleMode: if (!found) { - mousePosToTrackballPos(mview, mousePos, p); - TrackballStartDragging(mview->track, p, mview->mode); + mousePosToTrackballPos(mview, mousePos, fp); + TrackballStartDragging(mview->track, fp, mview->mode); mview->draggingMode = kMainViewMovingTrackball; break; } else { @@ -2277,7 +2123,8 @@ MainView_mouseDragged(MainView *mview, const float *mousePos, int flags) mview->tempAtoms[1] = n1; mview->tempAtomPos[1] = ap->r; } else { - float screenPos[3], objectPos[3]; + float screenPos[3]; + double objectPos[3]; Vector r1; mview->tempAtoms[1] = -1; /* Convert the position of temporary atom 0 to screen position */ @@ -2516,7 +2363,7 @@ MainView_rotateBySlider(MainView *mview, float angle, int mode, int mouseStatus, } else return; } else if ((modifierFlags & kAltKeyMask) != 0) { /* Rotate selection */ - float tr[3]; + double tr[3]; if (mview->mol->selection == NULL) return; mview->rotateFragment = IntGroupNewFromIntGroup(mview->mol->selection); @@ -2574,9 +2421,9 @@ MainView_rotateBySlider(MainView *mview, float angle, int mode, int mouseStatus, } } else { - float quat[4]; - float cs = cos(angle / 2); - float sn = sin(angle / 2); + double quat[4]; + double cs = cos(angle / 2); + double sn = sin(angle / 2); if (mouseStatus == 0) { /* mouseUp */ TrackballEndDragging(mview->track, NULL); } else { /* mouseDragged */ @@ -2647,7 +2494,7 @@ MainView_centerSelection(MainView *mview) { IntGroup *ig; Vector c; - float tr[3]; + double tr[3]; if (mview == NULL || mview->mol == NULL) return; ig = MoleculeGetSelection(mview->mol); diff --git a/MolLib/MainView.h b/MolLib/MainView.h index b25cff8..842bc0c 100755 --- a/MolLib/MainView.h +++ b/MolLib/MainView.h @@ -121,8 +121,10 @@ typedef struct MainView { Byte lineMode; /* Draw the model with lines */ - float atomRadius; /* Scale the vdW radius by this value */ - float bondRadius; /* in angstrom */ + float atomRadius; /* Scale the vdW radius by this value (default: 0.2) */ + float bondRadius; /* in angstrom (default: 0.1) */ + int atomResolution; /* Resolution in drawing atoms (default: 12) */ + int bondResolution; /* Resolution in drawing atoms (default: 8) */ float probabilityScale; Byte freezeScreen; float dimension; diff --git a/MolLib/MainViewCommon.c b/MolLib/MainViewCommon.c index b92759f..c3f7787 100755 --- a/MolLib/MainViewCommon.c +++ b/MolLib/MainViewCommon.c @@ -34,8 +34,10 @@ MainView_new(void) /* Initialize common members (that are used both in GUI and CMD versions */ memset(mview, 0, sizeof(MainView)); mview->track = TrackballNew(); - mview->atomRadius = 0.4; + mview->atomRadius = 0.2; mview->bondRadius = 0.1; + mview->atomResolution = 12; + mview->bondResolution = 8; mview->probabilityScale = 1.5382; mview->dimension = 10.0; mview->showHydrogens = mview->showDummyAtoms = mview->showExpandedAtoms = 1; diff --git a/MolLib/Molecule.c b/MolLib/Molecule.c index a3e6913..4274b93 100755 --- a/MolLib/Molecule.c +++ b/MolLib/Molecule.c @@ -766,8 +766,8 @@ MoleculeLoadMbsfFile(Molecule *mp, const char *fname, char **errbuf) int ibuf[12]; Int iibuf[4]; double dbuf[12]; - int mview_ibuf[16]; - float mview_fbuf[8]; + int mview_ibuf[18]; + double mview_dbuf[10]; char cbuf[12][8]; const char **pp; char *bufp, *valp, *comp; @@ -788,9 +788,9 @@ MoleculeLoadMbsfFile(Molecule *mp, const char *fname, char **errbuf) s_append_asprintf(errbuf, "Cannot open file"); return 1; } - for (i = 0; i < 8; i++) - mview_fbuf[i] = kUndefined; - for (i = 0; i < 16; i++) + for (i = 0; i < 10; i++) + mview_dbuf[i] = kUndefined; + for (i = 0; i < 18; i++) mview_ibuf[i] = kUndefined; /* flockfile(fp); */ lineNumber = 0; @@ -1581,11 +1581,11 @@ MoleculeLoadMbsfFile(Molecule *mp, const char *fname, char **errbuf) if (buf[0] == '\n') break; /* scale; trx try trz; theta_deg x y z */ - if ((i == 0 && sscanf(buf, "%f", &mview_fbuf[0]) < 1) - || (i == 1 && sscanf(buf, "%f %f %f", - &mview_fbuf[1], &mview_fbuf[2], &mview_fbuf[3]) < 3) - || (i == 2 && sscanf(buf, "%f %f %f %f", - &mview_fbuf[4], &mview_fbuf[5], &mview_fbuf[6], &mview_fbuf[7]) < 4)) { + if ((i == 0 && sscanf(buf, "%lf", &mview_dbuf[0]) < 1) + || (i == 1 && sscanf(buf, "%lf %lf %lf", + &mview_dbuf[1], &mview_dbuf[2], &mview_dbuf[3]) < 3) + || (i == 2 && sscanf(buf, "%lf %lf %lf %lf", + &mview_dbuf[4], &mview_dbuf[5], &mview_dbuf[6], &mview_dbuf[7]) < 4)) { s_append_asprintf(errbuf, "line %d: bad trackball format", lineNumber); goto err_exit; } @@ -1615,12 +1615,17 @@ MoleculeLoadMbsfFile(Molecule *mp, const char *fname, char **errbuf) || (strcmp(comp, "show_rotation_center") == 0 && (i = 7)) || (strcmp(comp, "show_graphite_flag") == 0 && (i = 8)) || (strcmp(comp, "show_periodic_image_flag") == 0 && (i = 9)) - || (strcmp(comp, "show_graphite") == 0 && (i = 10))) { + || (strcmp(comp, "show_graphite") == 0 && (i = 10)) + || (strcmp(comp, "atom_resolution") == 0 && (i = 11)) + || (strcmp(comp, "bond_resolution") == 0 && (i = 12))) { mview_ibuf[i - 1] = atoi(valp); + } else if ((strcmp(comp, "atom_radius") == 0 && (i = 8)) + || (strcmp(comp, "bond_radius") == 0 && (i = 9))) { + mview_dbuf[i] = strtod(valp, NULL); } else if (strcmp(comp, "show_periodic_image") == 0) { sscanf(valp, "%d %d %d %d %d %d", - &mview_ibuf[10], &mview_ibuf[11], &mview_ibuf[12], - &mview_ibuf[13], &mview_ibuf[14], &mview_ibuf[15]); + &mview_ibuf[12], &mview_ibuf[13], &mview_ibuf[14], + &mview_ibuf[15], &mview_ibuf[16], &mview_ibuf[17]); } } continue; @@ -1654,17 +1659,25 @@ MoleculeLoadMbsfFile(Molecule *mp, const char *fname, char **errbuf) mp->mview->showPeriodicImageFlag = mview_ibuf[8]; if (mview_ibuf[9] != kUndefined) mp->mview->showGraphite = mview_ibuf[9]; + if (mview_ibuf[10] != kUndefined && mview_ibuf[10] >= 6) + mp->mview->atomResolution = mview_ibuf[10]; + if (mview_ibuf[11] != kUndefined && mview_ibuf[11] >= 4) + mp->mview->bondResolution = mview_ibuf[11]; for (i = 0; i < 6; i++) { - if (mview_ibuf[10 + i] != kUndefined) - mp->mview->showPeriodicImage[i] = mview_ibuf[10 + i]; + if (mview_ibuf[12 + i] != kUndefined) + mp->mview->showPeriodicImage[i] = mview_ibuf[12 + i]; } + if (mview_dbuf[8] != kUndefined) + mp->mview->atomRadius = mview_dbuf[8]; + if (mview_dbuf[9] != kUndefined) + mp->mview->bondRadius = mview_dbuf[9]; if (mp->mview->track != NULL) { - if (mview_fbuf[0] != kUndefined) - TrackballSetScale(mp->mview->track, mview_fbuf[0]); - if (mview_fbuf[1] != kUndefined) - TrackballSetTranslate(mp->mview->track, mview_fbuf + 1); - if (mview_fbuf[4] != kUndefined) - TrackballSetRotate(mp->mview->track, mview_fbuf + 4); + if (mview_dbuf[0] != kUndefined) + TrackballSetScale(mp->mview->track, mview_dbuf[0]); + if (mview_dbuf[1] != kUndefined) + TrackballSetTranslate(mp->mview->track, mview_dbuf + 1); + if (mview_dbuf[4] != kUndefined) + TrackballSetRotate(mp->mview->track, mview_dbuf + 4); } } @@ -4136,7 +4149,7 @@ MoleculeWriteToMbsfFile(Molecule *mp, const char *fname, char **errbuf) } if (mp->mview != NULL) { - float f[4]; + double f[4]; if (mp->mview->track != NULL) { fprintf(fp, "!:trackball\n"); fprintf(fp, "! scale; trx try trz; theta_deg x y z\n"); @@ -4163,6 +4176,14 @@ MoleculeWriteToMbsfFile(Molecule *mp, const char *fname, char **errbuf) mp->mview->showPeriodicImage[0], mp->mview->showPeriodicImage[1], mp->mview->showPeriodicImage[2], mp->mview->showPeriodicImage[3], mp->mview->showPeriodicImage[4], mp->mview->showPeriodicImage[5]); + if (mp->mview->atomRadius != 0.2) + fprintf(fp, "atom_radius %f\n", mp->mview->atomRadius); + if (mp->mview->bondRadius != 0.1) + fprintf(fp, "bond_radius %f\n", mp->mview->bondRadius); + if (mp->mview->atomResolution != 12) + fprintf(fp, "atom_resolution %d\n", mp->mview->atomResolution); + if (mp->mview->bondResolution != 8) + fprintf(fp, "bond_resolution %d\n", mp->mview->bondResolution); fprintf(fp, "\n"); } diff --git a/MolLib/Ruby_bind/ruby_bind.c b/MolLib/Ruby_bind/ruby_bind.c index 32c6016..ea5caf4 100644 --- a/MolLib/Ruby_bind/ruby_bind.c +++ b/MolLib/Ruby_bind/ruby_bind.c @@ -9301,6 +9301,113 @@ s_Molecule_LineMode(int argc, VALUE *argv, VALUE self) /* * call-seq: + * atom_radius = float + * atom_radius + * + * Set the atom radius (multiple of the vdw radius) used in drawing the model in normal (non-line) mode. + * (Default = 0.4) + * If no argument is given, the current value is returned. + */ +static VALUE +s_Molecule_AtomRadius(int argc, VALUE *argv, VALUE self) +{ + Molecule *mol; + Data_Get_Struct(self, Molecule, mol); + if (mol->mview == NULL) + return Qnil; + if (argc > 0) { + double rad = NUM2DBL(rb_Float(argv[0])); + if (rad > 0.0) { + mol->mview->atomRadius = rad; + MainViewCallback_setNeedsDisplay(mol->mview, 1); + } + return argv[0]; + } + return rb_float_new(mol->mview->atomRadius); +} + +/* + * call-seq: + * bond_radius = float + * bond_radius + * + * Set the bond radius (in angstrom) used in drawing the model in normal (non-line) mode. (Default = 0.1) + * If no argument is given, the current value is returned. + */ +static VALUE +s_Molecule_BondRadius(int argc, VALUE *argv, VALUE self) +{ + Molecule *mol; + Data_Get_Struct(self, Molecule, mol); + if (mol->mview == NULL) + return Qnil; + if (argc > 0) { + double rad = NUM2DBL(rb_Float(argv[0])); + if (rad > 0.0) { + mol->mview->bondRadius = rad; + MainViewCallback_setNeedsDisplay(mol->mview, 1); + } + return argv[0]; + } + return rb_float_new(mol->mview->bondRadius); +} + +/* + * call-seq: + * atom_resolution = integer + * atom_resolution + * + * Set the atom resolution used in drawing the model in normal (non-line) mode. + * (Default = 12; minimum = 6) + * If no argument is given, the current value is returned. + */ +static VALUE +s_Molecule_AtomResolution(int argc, VALUE *argv, VALUE self) +{ + Molecule *mol; + Data_Get_Struct(self, Molecule, mol); + if (mol->mview == NULL) + return Qnil; + if (argc > 0) { + int res = NUM2INT(rb_Integer(argv[0])); + if (res < 6) + rb_raise(rb_eRangeError, "The atom resolution (%d) less than 6 is not acceptable", res); + mol->mview->atomResolution = res; + MainViewCallback_setNeedsDisplay(mol->mview, 1); + return INT2NUM(res); + } + return INT2NUM(mol->mview->atomResolution); +} + +/* + * call-seq: + * bond_resolution = integer + * bond_resolution + * + * Set the bond resolution used in drawing the model in normal (non-line) mode. + * (Default = 8; minimum = 4) + * If no argument is given, the current value is returned. + */ +static VALUE +s_Molecule_BondResolution(int argc, VALUE *argv, VALUE self) +{ + Molecule *mol; + Data_Get_Struct(self, Molecule, mol); + if (mol->mview == NULL) + return Qnil; + if (argc > 0) { + int res = NUM2INT(rb_Integer(argv[0])); + if (res < 4) + rb_raise(rb_eRangeError, "The bond resolution (%d) less than 4 is not acceptable", res); + mol->mview->bondResolution = res; + MainViewCallback_setNeedsDisplay(mol->mview, 1); + return INT2NUM(res); + } + return INT2NUM(mol->mview->bondResolution); +} + +/* + * call-seq: * resize_to_fit * * Resize the model drawing to fit in the window. @@ -9325,7 +9432,7 @@ static VALUE s_Molecule_GetViewRotation(VALUE self) { Molecule *mol; - float f[4]; + double f[4]; Vector v; Data_Get_Struct(self, Molecule, mol); if (mol->mview == NULL) @@ -9364,7 +9471,7 @@ static VALUE s_Molecule_GetViewCenter(VALUE self) { Molecule *mol; - float f[4]; + double f[4]; Vector v; Data_Get_Struct(self, Molecule, mol); if (mol->mview == NULL) @@ -9386,7 +9493,7 @@ static VALUE s_Molecule_SetViewRotation(VALUE self, VALUE aval, VALUE angval) { Molecule *mol; - float f[4]; + double f[4]; Vector v; Data_Get_Struct(self, Molecule, mol); if (mol->mview == NULL) @@ -9432,7 +9539,7 @@ s_Molecule_SetViewCenter(VALUE self, VALUE aval) { Molecule *mol; Vector v; - float f[4]; + double f[4]; Data_Get_Struct(self, Molecule, mol); if (mol->mview == NULL) return Qnil; @@ -10748,6 +10855,14 @@ Init_Molby(void) rb_define_alias(rb_cMolecule, "show_rotation_center=", "show_rotation_center"); rb_define_method(rb_cMolecule, "line_mode", s_Molecule_LineMode, -1); rb_define_alias(rb_cMolecule, "line_mode=", "line_mode"); + rb_define_method(rb_cMolecule, "atom_radius", s_Molecule_AtomRadius, -1); + rb_define_alias(rb_cMolecule, "atom_radius=", "atom_radius"); + rb_define_method(rb_cMolecule, "bond_radius", s_Molecule_BondRadius, -1); + rb_define_alias(rb_cMolecule, "bond_radius=", "bond_radius"); + rb_define_method(rb_cMolecule, "atom_resolution", s_Molecule_AtomResolution, -1); + rb_define_alias(rb_cMolecule, "atom_resolution=", "atom_resolution"); + rb_define_method(rb_cMolecule, "bond_resolution", s_Molecule_BondResolution, -1); + rb_define_alias(rb_cMolecule, "bond_resolution=", "bond_resolution"); rb_define_method(rb_cMolecule, "resize_to_fit", s_Molecule_ResizeToFit, 0); #if 1 || !defined(__CMDMAC__) rb_define_method(rb_cMolecule, "get_view_rotation", s_Molecule_GetViewRotation, 0); diff --git a/MolLib/Trackball.c b/MolLib/Trackball.c index ca08f55..b5785ab 100644 --- a/MolLib/Trackball.c +++ b/MolLib/Trackball.c @@ -21,7 +21,7 @@ #pragma mark ====== Internal functions ====== static void -multiplyQuat(const float *a, const float *b, float *c) +multiplyQuat(const double *a, const double *b, double *c) { c[0] = a[0] * b[0] - (a[1] * b[1] + a[2] * b[2] + a[3] * b[3]); c[1] = b[0] * a[1] + a[0] * b[1] + (a[2] * b[3] - a[3] * b[2]); @@ -30,7 +30,7 @@ multiplyQuat(const float *a, const float *b, float *c) } static void -normalizeQuat(float *a) +normalizeQuat(double *a) { float f; f = 1.0 / sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2] + a[3] * a[3]); @@ -41,7 +41,7 @@ normalizeQuat(float *a) } static void -getRotationToCenter(float x, float y, float radius, float *quat) +getRotationToCenter(double x, double y, double radius, double *quat) { const float sqrt2 = 1.41421356 / 2; float r, r2; @@ -76,7 +76,7 @@ getRotationToCenter(float x, float y, float radius, float *quat) } static void -rotation2Quat(const float *A, float *q) +rotation2Quat(const double *A, double *q) { float ang2; /* The half-angle */ float sinAng2; /* sin(half-angle) */ @@ -125,11 +125,10 @@ TrackballGetScale(const Trackball *track) } /* Get the current rotation (in GL format) */ -//- (void)getRotate:(float *)a void -TrackballGetRotate(const Trackball *track, float *a) +TrackballGetRotate(const Trackball *track, double *a) { - float w[4], t, f; + double w[4], t, f; NULL_CHECK(track, "TrackballGetRotate"); /* Rotate: multiply the two quaternions and convert it to a GL rotater */ multiplyQuat(track->tempQuat, track->quat, w); @@ -154,30 +153,21 @@ TrackballGetRotate(const Trackball *track, float *a) /* Get the current translation. The result values should be multiplied with * the dimension of the model. */ void -TrackballGetTranslate(const Trackball *track, float *a) -//- (void)getTranslate:(float *)a +TrackballGetTranslate(const Trackball *track, double *a) { NULL_CHECK(track, "TrackballGetTranslate"); a[0] = track->tempTrans[0] + track->trans[0]; a[1] = track->tempTrans[1] + track->trans[1]; a[2] = track->tempTrans[2] + track->trans[2]; -/* f = a[0] * a[0] + a[1] * a[1] + a[2] * a[2]; - if (f > 1.0) { - f = 1.0 / sqrt(f); - a[0] *= f; - a[1] *= f; - a[2] *= f; - } */ } /* Get the perspective parameter (fovy and distance) * Fovy (a[0]) is in degree. * Distance (a[1]) should be multiplied with the dimension of the model. */ void -TrackballGetPerspective(const Trackball *track, float *a) -//- (void)getPerspective:(float *)a +TrackballGetPerspective(const Trackball *track, double *a) { - float f; + double f; NULL_CHECK(track, "TrackballGetPerspective"); /* Get the current scale factor (-1.0 to 1.0 for x1/10 to x10) */ f = track->tempScale + track->scale; @@ -217,7 +207,7 @@ TrackballReset(Trackball *track) } void -TrackballSetScale(Trackball *track, float scale) +TrackballSetScale(Trackball *track, double scale) { NULL_CHECK(track, "TrackballSetScale"); track->tempScale = 0; @@ -226,9 +216,9 @@ TrackballSetScale(Trackball *track, float scale) } void -TrackballSetRotate(Trackball *track, const float *a) +TrackballSetRotate(Trackball *track, const double *a) { - float k; + double k; NULL_CHECK(track, "TrackballSetRotate"); track->tempQuat[0] = 1.0; track->tempQuat[1] = track->tempQuat[2] = track->tempQuat[3] = 0.0; @@ -241,7 +231,7 @@ TrackballSetRotate(Trackball *track, const float *a) } void -TrackballSetTranslate(Trackball *track, const float *a) +TrackballSetTranslate(Trackball *track, const double *a) { NULL_CHECK(track, "TrackballSetTranslate"); track->tempTrans[0] = track->tempTrans[1] = track->tempTrans[2] = 0; @@ -255,7 +245,6 @@ TrackballSetTranslate(Trackball *track, const float *a) void TrackballStartDragging(Trackball *track, const float *mousePos, TrackballMode mode) -//- (void)startAt:(NSPoint)pt sender:(NSView *)sender mode:(int)inMode { NULL_CHECK(track, "TrackballStartDragging"); @@ -275,18 +264,17 @@ TrackballStartDragging(Trackball *track, const float *mousePos, TrackballMode mo } void -TrackballSetTemporaryRotation(Trackball *track, const float *q) +TrackballSetTemporaryRotation(Trackball *track, const double *q) { - memmove(track->tempQuat, q, sizeof(float) * 4); + memmove(track->tempQuat, q, sizeof(double) * 4); } void TrackballDrag(Trackball *track, const float *mousePos) -//- (void)dragTo:(NSPoint)pt sender:(NSView *)sender { - float rot[4]; - float w1[4], w2[4]; - float w; + double rot[4]; + double w1[4], w2[4]; + double w; NULL_CHECK(track, "TrackballDrag"); if (track->mode == kTrackballRotateMode) { @@ -334,9 +322,8 @@ TrackballDrag(Trackball *track, const float *mousePos) void TrackballEndDragging(Trackball *track, const float *mousePos) -//- (void)endAt:(NSPoint)pt sender:(NSView *)sender { - float w[4]; + double w[4]; NULL_CHECK(track, "TrackballEndDragging"); if (mousePos != NULL) TrackballDrag(track, mousePos); @@ -351,13 +338,6 @@ TrackballEndDragging(Trackball *track, const float *mousePos) track->trans[0] += track->tempTrans[0]; track->trans[1] += track->tempTrans[1]; track->trans[2] += track->tempTrans[2]; -/* f = track->trans[0] * track->trans[0] + track->trans[1] * track->trans[1] + track->trans[2] * track->trans[2]; - if (f > 1.0) { - f = 1.0 / sqrt(f); - track->trans[0] *= f; - track->trans[1] *= f; - track->trans[2] *= f; - } */ track->tempTrans[0] = track->tempTrans[1] = track->tempTrans[2] = 0.0; track->scale += track->tempScale; if (track->scale > 5.0) diff --git a/MolLib/Trackball.h b/MolLib/Trackball.h index adbf01e..b716da8 100644 --- a/MolLib/Trackball.h +++ b/MolLib/Trackball.h @@ -52,16 +52,16 @@ typedef enum TrackballMode { * view is (0, 0), and the half of the screen height (or width) is 1.0) */ typedef struct Trackball { int refCount; - float start[2]; /* Drag started here */ - float startQuat[4]; /* Rotation from the start point to the center (of the trackball) */ + double start[2]; /* Drag started here */ + double startQuat[4]; /* Rotation from the start point to the center (of the trackball) */ TrackballMode mode; - float quat[4]; /* Rotation (in quaternion) */ - float tempQuat[4]; /* Temporary rotation during dragging of trackball */ - float trans[3]; /* Translation */ - float tempTrans[3]; /* Temporary translation */ - float scale; /* Scale */ - float tempScale; /* Temporary scale */ + double quat[4]; /* Rotation (in quaternion) */ + double tempQuat[4]; /* Temporary rotation during dragging of trackball */ + double trans[3]; /* Translation */ + double tempTrans[3]; /* Temporary translation */ + double scale; /* Scale */ + double tempScale; /* Temporary scale */ int modifyCount; } Trackball; @@ -71,19 +71,19 @@ void TrackballRetain(Trackball *track); void TrackballRelease(Trackball *track); float TrackballGetScale(const Trackball *track); -void TrackballGetRotate(const Trackball *track, float *a); -void TrackballGetTranslate(const Trackball *track, float *a); -void TrackballGetPerspective(const Trackball *track, float *a); +void TrackballGetRotate(const Trackball *track, double *a); +void TrackballGetTranslate(const Trackball *track, double *a); +void TrackballGetPerspective(const Trackball *track, double *a); void TrackballReset(Trackball *track); -void TrackballSetScale(Trackball *track, float scale); -void TrackballSetRotate(Trackball *track, const float *a); -void TrackballSetTranslate(Trackball *track, const float *a); +void TrackballSetScale(Trackball *track, double scale); +void TrackballSetRotate(Trackball *track, const double *a); +void TrackballSetTranslate(Trackball *track, const double *a); int TrackballGetModifyCount(Trackball *track); void TrackballStartDragging(Trackball *track, const float *mousePos, TrackballMode mode); -void TrackballSetTemporaryRotation(Trackball *track, const float *q); +void TrackballSetTemporaryRotation(Trackball *track, const double *q); void TrackballDrag(Trackball *track, const float *mousePos); void TrackballEndDragging(Trackball *track, const float *mousePos); diff --git a/Scripts/view.rb b/Scripts/view.rb index 700b46f..63cc920 100755 --- a/Scripts/view.rb +++ b/Scripts/view.rb @@ -39,10 +39,6 @@ def cmd_show_rotation_center self.show_rotation_center = !self.show_rotation_center end -def cmd_line_mode - self.line_mode = !self.line_mode -end - def cmd_show_graphite n = self.show_graphite flag = self.show_graphite? @@ -58,7 +54,71 @@ def cmd_show_graphite self.show_graphite(hash["show_graphite"] == 1 ? true : false) end end - + +def cmd_line_mode + self.line_mode = !self.line_mode +end + +def cmd_ball_and_stick_mode + mol = self + rad = mol.atom_radius + res = mol.atom_resolution + brad = mol.bond_radius + bres = mol.bond_resolution + if mol.line_mode == true || mol.atom_radius >= 0.5 + rad = 0.2 + res = 12 + brad = 0.1 + bres = 8 + end + hash = Dialog.run("Ball and Stick") { + layout(2, + item(:text, :title=>"Atom Radius (0..0.5, default 0.2)"), + item(:textfield, :width=>100, :tag=>"atom_radius", :value=>rad.to_s), + item(:text, :title=>"Atom Resolution (default 12)"), + item(:textfield, :width=>100, :tag=>"atom_resolution", :value=>res.to_s), + item(:text, :title=>"Bond Radius (default 0.1)"), + item(:textfield, :width=>100, :tag=>"bond_radius", :value=>brad.to_s), + item(:text, :title=>"Atom Resolution (default 8)"), + item(:textfield, :width=>100, :tag=>"bond_resolution", :value=>bres.to_s)) + } + if hash[:status] == 0 + f = hash["atom_radius"].to_f + self.atom_radius = f if f > 0.0 && f < 0.5 + n = hash["atom_resolution"].to_i + self.atom_resolution = n if n >= 6 && n < 100 + f = hash["bond_radius"].to_f + self.bond_radius = f if f > 0.0 + n = hash["bond_resolution"].to_i + self.bond_resolution = n if n >= 4 && n < 100 + self.line_mode = false + end +end + +def cmd_space_filling_mode + mol = self + rad = mol.atom_radius + res = mol.atom_resolution + if mol.line_mode == true || mol.atom_radius < 0.5 + rad = 1.0 + res = 18 + end + hash = Dialog.run("Space Filling") { + layout(2, + item(:text, :title=>"Atom Radius (0.5..2.0, default 1.0)"), + item(:textfield, :width=>100, :tag=>"atom_radius", :value=>rad.to_s), + item(:text, :title=>"Atom Resolution (default 18)"), + item(:textfield, :width=>100, :tag=>"atom_resolution", :value=>res.to_s)) + } + if hash[:status] == 0 + f = hash["atom_radius"].to_f + self.atom_radius = f if f >= 0.5 && f <= 2.0 + n = hash["atom_resolution"].to_i + self.atom_resolution = n if n >= 6 && n < 100 + self.line_mode = false + end +end + end register_menu("View\t-", nil) @@ -78,5 +138,9 @@ register_menu("View\t-", nil) register_menu("View\t^Show Graphite...", :cmd_show_graphite, lambda { |m| [m != nil, m.show_graphite?] } ) register_menu("View\t-", nil) -register_menu("View\t^Line Mode", :cmd_line_mode, +register_menu("View\tAppearance\t^Line", :cmd_line_mode, lambda { |m| [m != nil, m.line_mode] } ) +register_menu("View\tAppearance\t^Ball and Stick", :cmd_ball_and_stick_mode, + lambda { |m| [m != nil, !m.line_mode && m.atom_radius < 0.5] } ) +register_menu("View\tAppearance\t^Space Filling", :cmd_space_filling_mode, + lambda { |m| [m != nil, !m.line_mode && m.atom_radius >= 0.5] } ) diff --git a/wxSources/MyApp.cpp b/wxSources/MyApp.cpp index 31a9524..dcb6dff 100755 --- a/wxSources/MyApp.cpp +++ b/wxSources/MyApp.cpp @@ -807,7 +807,7 @@ MyApp::UpdateScriptMenu(wxMenuBar *mbar) menu->Append(myMenuID_CustomScript + i + depth * 1000, menuTitle, newMenu1); menu = newMenu1; } else { - menu->FindItem(mid, &menu); + menu = menu->FindItem(mid)->GetSubMenu(); } } s = p + 1; -- 2.11.0