From 1f244ed67a5869327901219529b526e9ab0f2558 Mon Sep 17 00:00:00 2001 From: toshinagata1964 Date: Tue, 31 Jan 2012 10:04:29 +0000 Subject: [PATCH] Ruby: Molecule#make_front, set_name, get_view_rotation, get_view_scale, get_view_translation, set_view_rotation, set_view_scale, set_view_translation, set_graphic_color, hide_graphic, show_graphic are implemented. git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/molby/trunk@179 a2be9bc6-48de-4e38-9406-05402d4bc13c --- MolLib/MainView.c | 88 ++++++++------ MolLib/MainView.h | 4 +- MolLib/Molecule.h | 1 + MolLib/Ruby_bind/ruby_bind.c | 267 ++++++++++++++++++++++++++++++++++++++++++- MolLib/Types.h | 2 + wxSources/MoleculeView.cpp | 8 ++ wxSources/MyDocument.cpp | 12 ++ 7 files changed, 344 insertions(+), 38 deletions(-) diff --git a/MolLib/MainView.c b/MolLib/MainView.c index 598b102..10e31e2 100755 --- a/MolLib/MainView.c +++ b/MolLib/MainView.c @@ -906,9 +906,8 @@ drawCone(const GLfloat *a, const GLfloat *b, GLfloat r, int sect, int closed) { GLfloat *c, *s; int n, i; - float nx, ny, nz; GLfloat d[3], v[3], w[3]; - Vector p1, p2; + Vector p1, nv; n = setSinCache(sect); if (n <= 0) return; @@ -920,31 +919,32 @@ drawCone(const GLfloat *a, const GLfloat *b, GLfloat r, int sect, int closed) if (getOrthogonalVectors(d, v, w) == 0) return; glBegin(GL_TRIANGLE_FAN); - glVertex3f(a[0], a[1], a[2]); - p1.x = b[0] + r * (v[0] * c[0] + w[0] * s[0]); - p1.y = b[1] + r * (v[1] * c[0] + w[1] * s[0]); - p1.z = b[2] + r * (v[2] * c[0] + w[2] * s[0]); - glVertex3f(p1.x, p1.y, p1.z); - for (i = 1; i <= n; i++) { - p2.x = b[0] + r * (v[0] * c[i] + w[0] * s[i]); - p2.y = b[1] + r * (v[1] * c[i] + w[1] * s[i]); - p2.z = b[2] + r * (v[2] * c[i] + w[2] * s[i]); - nx = p1.x + p2.x - b[0] * 2; - ny = p1.y + p2.y - b[1] * 2; - nz = p1.z + p2.z - b[2] * 2; - glNormal3f(nx, ny, nz); - glVertex3f(p2.x, p2.y, p2.z); - p1 = p2; + nv.x = d[0]; + nv.y = d[1]; + nv.z = d[2]; + NormalizeVec(&nv, &nv); + glNormal3f(nv.x, nv.y, nv.z); + glVertex3f(b[0], b[1], b[2]); + for (i = 0; i <= n; i++) { + nv.x = v[0] * c[i] + w[0] * s[i]; + nv.y = v[1] * c[i] + w[1] * s[i]; + nv.z = v[2] * c[i] + w[2] * s[i]; + glNormal3f(nv.x, nv.y, nv.z); + p1.x = a[0] + r * nv.x; + p1.y = a[1] + r * nv.y; + p1.z = a[2] + r * nv.z; + glNormal3f(nv.x, nv.y, nv.z); + glVertex3f(p1.x, p1.y, p1.z); } glEnd(); if (closed) { glBegin(GL_TRIANGLE_FAN); glNormal3f(d[0], d[1], d[2]); for (i = 0; i <= n; i++) { - p2.x = b[0] + r * (v[0] * c[i] + w[0] * s[i]); - p2.y = b[1] + r * (v[1] * c[i] + w[1] * s[i]); - p2.z = b[2] + r * (v[2] * c[i] + w[2] * s[i]); - glVertex3f(p2.x, p2.y, p2.z); + p1.x = a[0] + r * (v[0] * c[i] + w[0] * s[i]); + p1.y = a[1] + r * (v[1] * c[i] + w[1] * s[i]); + p1.z = a[2] + r * (v[2] * c[i] + w[2] * s[i]); + glVertex3f(p1.x, p1.y, p1.z); } glEnd(); } @@ -1610,40 +1610,60 @@ skip: static void drawGraphics(MainView *mview) { - int i, j, n; + int i, j; MainViewGraphic *g; for (i = 0; i < mview->ngraphics; i++) { g = &mview->graphics[i]; + if (g->visible == 0) + continue; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, g->rgba); switch (g->kind) { case kMainViewGraphicLine: glDisable(GL_LIGHTING); glColor4fv(g->rgba); - glBegin(GL_LINES); - n = g->npoints; - if (n % 2 == 1) - n--; - for (j = 0; j < n; j++) + glBegin(GL_LINE_STRIP); + for (j = 0; j < g->npoints; j++) { + if (g->points[j * 3] >= kInvalidFloat) + break; glVertex3fv(&g->points[j * 3]); + } glEnd(); glEnable(GL_LIGHTING); break; - case kMainViewGraphicPoly: + case kMainViewGraphicPoly: { + Vector v0, v1, v2, v3; glBegin(GL_TRIANGLE_FAN); - for (j = 0; j < g->npoints; j++) + v1.x = g->points[0] - g->points[g->npoints - 3]; + v1.y = g->points[1] - g->points[g->npoints - 2]; + v1.z = g->points[2] - g->points[g->npoints - 1]; + v0 = v1; + for (j = 0; j < g->npoints; j++) { + v2.x = g->points[j * 3 + 3] - g->points[j * 3]; + v2.y = g->points[j * 3 + 4] - g->points[j * 3 + 1]; + v2.z = g->points[j * 3 + 5] - g->points[j * 3 + 2]; + VecCross(v3, v1, v2); + if (NormalizeVec(&v3, &v3) == 0) + glNormal3f(v3.x, v3.y, v3.z); glVertex3fv(&g->points[j * 3]); - if (g->closed) + v1 = v2; + } + if (g->closed) { + VecCross(v3, v1, v0); + if (NormalizeVec(&v3, &v3) == 0) + glNormal3f(v3.x, v3.y, v3.z); glVertex3fv(g->points); + } glEnd(); break; + } case kMainViewGraphicCylinder: - drawCylinder(g->points, g->points + 3, g->points[6], 6, g->closed); + drawCylinder(g->points, g->points + 3, g->points[6], 15, g->closed); break; case kMainViewGraphicCone: - drawCone(g->points, g->points + 3, g->points[6], 6, g->closed); + drawCone(g->points, g->points + 3, g->points[6], 15, g->closed); break; case kMainViewGraphicEllipsoid: - drawEllipsoid(g->points, g->points + 3, g->points + 6, g->points + 9, 6); + drawEllipsoid(g->points, g->points + 3, g->points + 6, g->points + 9, 8); break; } } @@ -1806,7 +1826,7 @@ compareLabelByDepth(const void *ap, const void *bp) static void drawLabels(MainView *mview) { - Transform *trp; +/* Transform *trp; */ Atom *ap; LabelRecord *lp; int i, nlabels; diff --git a/MolLib/MainView.h b/MolLib/MainView.h index eca59ec..a12dadc 100755 --- a/MolLib/MainView.h +++ b/MolLib/MainView.h @@ -85,7 +85,8 @@ enum { typedef struct MainViewGraphic { Int kind; - Int closed; + Byte closed; + Byte visible; GLfloat rgba[4]; Int npoints; GLfloat *points; @@ -235,6 +236,7 @@ STUB void MainViewCallback_lockFocus(MainView *mview); STUB void MainViewCallback_unlockFocus(MainView *mview); STUB void MainViewCallback_frame(MainView *mview, float *rect); STUB void MainViewCallback_display(MainView *mview); +STUB void MainViewCallback_makeFront(MainView *mview); STUB void MainViewCallback_setNeedsDisplay(MainView *mview, int flag); STUB void MainViewCallback_setKeyboardFocus(MainView *mview); STUB int MainViewCallback_mouseCheck(MainView *mview); diff --git a/MolLib/Molecule.h b/MolLib/Molecule.h index 86c721e..00b0998 100755 --- a/MolLib/Molecule.h +++ b/MolLib/Molecule.h @@ -509,6 +509,7 @@ STUB Molecule *MoleculeCallback_moleculeAtIndex(int idx); STUB Molecule *MoleculeCallback_moleculeAtOrderedIndex(int idx); STUB void MoleculeCallback_displayName(Molecule *mol, char *buf, int bufsize); STUB void MoleculeCallback_pathName(Molecule *mol, char *buf, int bufsize); +STUB int MoleculeCallback_setDisplayName(Molecule *mol, const char *name); STUB void MoleculeCallback_lockMutex(void *mutex); STUB void MoleculeCallback_unlockMutex(void *mutex); diff --git a/MolLib/Ruby_bind/ruby_bind.c b/MolLib/Ruby_bind/ruby_bind.c index 54b863c..91d5f9c 100644 --- a/MolLib/Ruby_bind/ruby_bind.c +++ b/MolLib/Ruby_bind/ruby_bind.c @@ -4664,6 +4664,24 @@ s_Molecule_Name(VALUE self) /* * call-seq: + * set_name(string) -> self + * + * Set the name of an untitled molecule. If the molecule is not associated with window + * or it already has an associated file, then exception is thrown. + */ +static VALUE +s_Molecule_SetName(VALUE self, VALUE nval) +{ + Molecule *mol; + Data_Get_Struct(self, Molecule, mol); + if (MoleculeCallback_setDisplayName(mol, StringValuePtr(nval))) + rb_raise(rb_eMolbyError, "Cannot change the window title"); + return self; +} + + +/* + * call-seq: * path -> String * * Returns the full path name of the molecule, if it is associated with a file. @@ -7470,6 +7488,22 @@ s_Molecule_Display(VALUE self) /* * call-seq: + * make_front + * + * Make the window frontmost if this molecule is bound to a view. Otherwise do nothing. + */ +static VALUE +s_Molecule_MakeFront(VALUE self) +{ + Molecule *mol; + Data_Get_Struct(self, Molecule, mol); + if (mol->mview != NULL) + MainViewCallback_makeFront(mol->mview); + return Qnil; +} + +/* + * call-seq: * update_enabled? -> bool * * Returns true if screen update is enabled; otherwise no. @@ -7771,6 +7805,135 @@ s_Molecule_ResizeToFit(VALUE self) /* * call-seq: + * get_view_rotation -> [[ax, ay, az], angle] + * + * Get the current rotation for the view. Angle is in degree, not radian. + */ +static VALUE +s_Molecule_GetViewRotation(VALUE self) +{ + Molecule *mol; + float f[4]; + Vector v; + Data_Get_Struct(self, Molecule, mol); + if (mol->mview == NULL) + return Qnil; + TrackballGetRotate(mol->mview->track, f); + v.x = f[1]; + v.y = f[2]; + v.z = f[3]; + return rb_ary_new3(2, ValueFromVector(&v), rb_float_new(f[0])); +} + +/* + * call-seq: + * get_view_scale -> float + * + * Get the current scale for the view. + */ +static VALUE +s_Molecule_GetViewScale(VALUE self) +{ + Molecule *mol; + Data_Get_Struct(self, Molecule, mol); + if (mol->mview == NULL) + return Qnil; + return rb_float_new(TrackballGetScale(mol->mview->track)); +} + +/* + * call-seq: + * get_view_translation -> Vector + * + * Get the current translation factor for the view. + */ +static VALUE +s_Molecule_GetViewTranslation(VALUE self) +{ + Molecule *mol; + float f[4]; + Vector v; + Data_Get_Struct(self, Molecule, mol); + if (mol->mview == NULL) + return Qnil; + TrackballGetTranslate(mol->mview->track, f); + v.x = f[0]; + v.y = f[1]; + v.z = f[2]; + return ValueFromVector(&v); +} + +/* + * call-seq: + * set_view_rotation([ax, ay, az], angle) -> self + * + * Set the current rotation for the view. Angle is in degree, not radian. + */ +static VALUE +s_Molecule_SetViewRotation(VALUE self, VALUE aval, VALUE angval) +{ + Molecule *mol; + float f[4]; + Vector v; + Data_Get_Struct(self, Molecule, mol); + if (mol->mview == NULL) + return Qnil; + VectorFromValue(aval, &v); + if (NormalizeVec(&v, &v)) + rb_raise(rb_eMolbyError, "Cannot normalize nearly zero vector"); + f[1] = v.x; + f[2] = v.y; + f[3] = v.z; + f[0] = NUM2DBL(rb_Float(angval)); + TrackballSetRotate(mol->mview->track, f); + MainViewCallback_setNeedsDisplay(mol->mview, 0); + return self; +} + +/* + * call-seq: + * set_view_scale(scale) -> self + * + * Set the current scale for the view. + */ +static VALUE +s_Molecule_SetViewScale(VALUE self, VALUE aval) +{ + Molecule *mol; + Data_Get_Struct(self, Molecule, mol); + if (mol->mview == NULL) + return Qnil; + TrackballSetScale(mol->mview->track, NUM2DBL(rb_Float(aval))); + MainViewCallback_setNeedsDisplay(mol->mview, 0); + return self; +} + +/* + * call-seq: + * set_view_translation(vec) -> self + * + * Set the current translation for the view. + */ +static VALUE +s_Molecule_SetViewTranslation(VALUE self, VALUE aval) +{ + Molecule *mol; + Vector v; + float f[4]; + Data_Get_Struct(self, Molecule, mol); + if (mol->mview == NULL) + return Qnil; + VectorFromValue(aval, &v); + f[0] = v.x; + f[1] = v.y; + f[2] = v.z; + TrackballSetTranslate(mol->mview->track, f); + MainViewCallback_setNeedsDisplay(mol->mview, 0); + return self; +} + +/* + * call-seq: * set_background_color(red, green, blue) * * Set the background color of the model window. @@ -7812,6 +7975,7 @@ s_Molecule_CreateGraphic(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "31", &kval, &cval, &pval, &fval); kval = rb_obj_as_string(kval); memset(&g, 0, sizeof(g)); + g.visible = 1; p = RSTRING_PTR(kval); if (strcmp(p, "line") == 0) g.kind = kMainViewGraphicLine; @@ -7840,8 +8004,8 @@ s_Molecule_CreateGraphic(int argc, VALUE *argv, VALUE self) rb_raise(rb_eArgError, "no control points are given"); switch (g.kind) { case kMainViewGraphicLine: - if (n % 2 != 0) - rb_raise(rb_eArgError, "the line object must have even number of control points"); + if (n < 2) + rb_raise(rb_eArgError, "the line object must have at least two control points"); break; case kMainViewGraphicPoly: if (n < 3) @@ -7954,7 +8118,10 @@ s_Molecule_SetGraphicPoint(VALUE self, VALUE gval, VALUE pval, VALUE nval) return nval; } else rb_raise(rb_eArgError, "the argument must be an array-like object"); } else { - VectorFromValue(nval, &v); + if (nval == Qnil) { + v.x = kInvalidFloat; + v.y = v.z = 0.0; + } else VectorFromValue(nval, &v); } gp->points[index * 3] = v.x; gp->points[index * 3 + 1] = v.y; @@ -7965,6 +8132,89 @@ s_Molecule_SetGraphicPoint(VALUE self, VALUE gval, VALUE pval, VALUE nval) /* * call-seq: + * set_graphic_color(graphic_index, new_value) -> new_value + * + * Change the color of graphic_index-th graphic object + * + */ +static VALUE +s_Molecule_SetGraphicColor(VALUE self, VALUE gval, VALUE cval) +{ + MainViewGraphic *gp; + Molecule *mol; + int index, n; + Data_Get_Struct(self, Molecule, mol); + if (mol->mview == NULL) + rb_raise(rb_eMolbyError, "this molecule has no associated graphic view"); + index = NUM2INT(rb_Integer(gval)); + if (index < 0 || index >= mol->mview->ngraphics) + rb_raise(rb_eArgError, "the graphic index is out of range"); + gp = mol->mview->graphics + index; + cval = rb_ary_to_ary(cval); + n = RARRAY_LEN(cval); + if (n != 3 && n != 4) + rb_raise(rb_eArgError, "the color argument must have 3 or 4 numbers"); + for (index = 0; index < n; index++) { + gp->rgba[index] = NUM2DBL(rb_Float(RARRAY_PTR(cval)[index])); + } + if (n == 3) + gp->rgba[3] = 1.0; + MoleculeCallback_notifyModification(mol, 0); + return cval; +} + +/* + * call-seq: + * show_graphic(graphic_index) -> self + * + * Enable the visible flag of the graphic_index-th graphic object + * + */ +static VALUE +s_Molecule_ShowGraphic(VALUE self, VALUE gval) +{ + MainViewGraphic *gp; + Molecule *mol; + int index; + Data_Get_Struct(self, Molecule, mol); + if (mol->mview == NULL) + rb_raise(rb_eMolbyError, "this molecule has no associated graphic view"); + index = NUM2INT(rb_Integer(gval)); + if (index < 0 || index >= mol->mview->ngraphics) + rb_raise(rb_eArgError, "the graphic index is out of range"); + gp = mol->mview->graphics + index; + gp->visible = 1; + MoleculeCallback_notifyModification(mol, 0); + return self; +} + +/* + * call-seq: + * hide_graphic(graphic_index) -> self + * + * Disable the visible flag of the graphic_index-th graphic object + * + */ +static VALUE +s_Molecule_HideGraphic(VALUE self, VALUE gval) +{ + MainViewGraphic *gp; + Molecule *mol; + int index; + Data_Get_Struct(self, Molecule, mol); + if (mol->mview == NULL) + rb_raise(rb_eMolbyError, "this molecule has no associated graphic view"); + index = NUM2INT(rb_Integer(gval)); + if (index < 0 || index >= mol->mview->ngraphics) + rb_raise(rb_eArgError, "the graphic index is out of range"); + gp = mol->mview->graphics + index; + gp->visible = 0; + MoleculeCallback_notifyModification(mol, 0); + return self; +} + +/* + * call-seq: * show_text(string) * * Show the string in the info text box. @@ -8562,6 +8812,7 @@ Init_Molby(void) rb_define_method(rb_cMolecule, "savedcd", s_Molecule_Savedcd, 1); rb_define_method(rb_cMolecule, "savetep", s_Molecule_Savetep, 1); rb_define_method(rb_cMolecule, "name", s_Molecule_Name, 0); + rb_define_method(rb_cMolecule, "set_name", s_Molecule_SetName, 1); rb_define_method(rb_cMolecule, "path", s_Molecule_Path, 0); rb_define_method(rb_cMolecule, "dir", s_Molecule_Dir, 0); rb_define_method(rb_cMolecule, "inspect", s_Molecule_Inspect, 0); @@ -8670,6 +8921,7 @@ Init_Molby(void) rb_define_method(rb_cMolecule, "wrap_unit_cell", s_Molecule_WrapUnitCell, 1); rb_define_method(rb_cMolecule, "find_conflicts", s_Molecule_FindConflicts, -1); rb_define_method(rb_cMolecule, "display", s_Molecule_Display, 0); + rb_define_method(rb_cMolecule, "make_front", s_Molecule_MakeFront, 0); rb_define_method(rb_cMolecule, "update_enabled?", s_Molecule_UpdateEnabled, 0); rb_define_method(rb_cMolecule, "update_enabled=", s_Molecule_SetUpdateEnabled, 1); rb_define_method(rb_cMolecule, "show_unitcell", s_Molecule_ShowUnitCell, -1); @@ -8697,11 +8949,20 @@ Init_Molby(void) 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, "resize_to_fit", s_Molecule_ResizeToFit, 0); + rb_define_method(rb_cMolecule, "get_view_rotation", s_Molecule_GetViewRotation, 0); + rb_define_method(rb_cMolecule, "get_view_scale", s_Molecule_GetViewScale, 0); + rb_define_method(rb_cMolecule, "get_view_translation", s_Molecule_GetViewTranslation, 0); + rb_define_method(rb_cMolecule, "set_view_rotation", s_Molecule_SetViewRotation, 2); + rb_define_method(rb_cMolecule, "set_view_scale", s_Molecule_SetViewScale, 1); + rb_define_method(rb_cMolecule, "set_view_translation", s_Molecule_SetViewTranslation, 1); rb_define_method(rb_cMolecule, "set_background_color", s_Molecule_SetBackgroundColor, -1); rb_define_method(rb_cMolecule, "create_graphic", s_Molecule_CreateGraphic, -1); rb_define_method(rb_cMolecule, "delete_graphic", s_Molecule_DeleteGraphic, 1); rb_define_method(rb_cMolecule, "ngraphics", s_Molecule_NGraphics, 0); rb_define_method(rb_cMolecule, "set_graphic_point", s_Molecule_SetGraphicPoint, 3); + rb_define_method(rb_cMolecule, "set_graphic_color", s_Molecule_SetGraphicColor, 2); + rb_define_method(rb_cMolecule, "show_graphic", s_Molecule_ShowGraphic, 1); + rb_define_method(rb_cMolecule, "hide_graphic", s_Molecule_HideGraphic, 1); rb_define_method(rb_cMolecule, "show_text", s_Molecule_ShowText, 1); rb_define_method(rb_cMolecule, "md_arena", s_Molecule_MDArena, 0); rb_define_method(rb_cMolecule, "set_parameter_attr", s_Molecule_SetParameterAttr, 5); diff --git a/MolLib/Types.h b/MolLib/Types.h index 3d4c88b..dd78283 100755 --- a/MolLib/Types.h +++ b/MolLib/Types.h @@ -71,6 +71,8 @@ typedef unsigned int UInt; #define kInvalidIndex -99999999 /* Used for terminating integer array */ +#define kInvalidFloat 1e30 + typedef struct Vector { Double x, y, z; } Vector; typedef struct Quat { Double x, y, z, w; } Quat; /* A quaternion */ typedef Double Mat33[9]; /* Columns first! */ diff --git a/wxSources/MoleculeView.cpp b/wxSources/MoleculeView.cpp index 40ca4b7..f632fdf 100755 --- a/wxSources/MoleculeView.cpp +++ b/wxSources/MoleculeView.cpp @@ -831,6 +831,14 @@ MainViewCallback_display(MainView *mview) } void +MainViewCallback_makeFront(MainView *mview) +{ + if (mview != NULL && mview->ref != NULL) { + ((MoleculeView *)(mview->ref))->GetFrame()->Raise(); + } +} + +void MainViewCallback_setNeedsDisplay(MainView *mview, int flag) { if (mview != NULL && mview->ref != NULL) { diff --git a/wxSources/MyDocument.cpp b/wxSources/MyDocument.cpp index dc650d6..8a812de 100755 --- a/wxSources/MyDocument.cpp +++ b/wxSources/MyDocument.cpp @@ -1662,6 +1662,18 @@ MoleculeCallback_pathName(Molecule *mol, char *buf, int bufsize) else buf[0] = 0; } +int +MoleculeCallback_setDisplayName(Molecule *mol, const char *name) +{ + MyDocument *doc = MyDocumentFromMolecule(mol); + if (doc == NULL || doc->hasFile) + return 1; /* Cannot change file-associated window title */ + wxString fname(name, wxConvFile); + doc->SetTitle(fname); + doc->GetFirstView()->OnChangeFilename(); + return 0; +} + void MoleculeCallback_lockMutex(void *mutex) { -- 2.11.0