Hi all,

I've made some modifications to the ball and stick engine to draw correctly 
bonds that cross periodic boundaries. However, I cannot push the commit 
because gerrit rejects my ssh connection.

I created a gerrit account and generated an ssh public key. Yet, I get the 
error

$ git gerrit-push
Permission denied (publickey).
fatal: The remote end hung up unexpectedly

The public key I pasted to my gerrit account matches my id_rsa.pub file for 
sure. I went through all the troubleshooting instructions to no avail.

I don't know how to solve this problem. Therefore I'm sending the patch here 
as an attachment.

Best,
Tuukka Verho
diff --git a/libavogadro/src/engines/bsdyengine.cpp b/libavogadro/src/engines/bsdyengine.cpp
index d485c86..a409755 100644
--- a/libavogadro/src/engines/bsdyengine.cpp
+++ b/libavogadro/src/engines/bsdyengine.cpp
@@ -151,9 +151,9 @@ namespace Avogadro
 
       Vector3d v1(*atom1->pos());
       Vector3d v2(*atom2->pos());
-      Vector3d d = v2 - v1;
-      d.normalize();
-      Vector3d v3((v1 + v2 + d*(radius(atom1) - radius(atom2))) / 2);
+      Vector3d d = distanceVector(v1, v2, pd);
+      
+      double centerAdjust = (radius(atom1) - radius(atom2)) / d.norm();
 
       double shift = 0.15;
       int order = 1;
@@ -164,14 +164,14 @@ namespace Avogadro
         pd->painter()->setColor( map );
       else
         pd->painter()->setColor(atom1->customColorName());
-      pd->painter()->drawMultiCylinder( v1, v3, m_bondRadius, order, shift );
+      pd->painter()->drawMultiCylinder( v1, v1 + d*(1+centerAdjust)/2, m_bondRadius, order, shift );
 
       map->setFromPrimitive(atom2);
       if (atom2->customColorName().isEmpty())
         pd->painter()->setColor( map );
       else
         pd->painter()->setColor(atom2->customColorName());
-      pd->painter()->drawMultiCylinder( v3, v2, m_bondRadius, order, shift );
+      pd->painter()->drawMultiCylinder( v2, v2 - d*(1-centerAdjust)/2, m_bondRadius, order, shift );
     }
 
     glDisable( GL_NORMALIZE );
@@ -237,9 +237,9 @@ namespace Avogadro
 
       Vector3d v1(*atom1->pos());
       Vector3d v2(*atom2->pos());
-      Vector3d d = v2 - v1;
-      d.normalize();
-      Vector3d v3((v1 + v2 + d*(radius(atom1) - radius(atom2))) / 2);
+      Vector3d d = distanceVector(v1, v2, pd);
+      
+      double centerAdjust = (radius(atom1) - radius(atom2)) / d.norm();
 
       double shift = 0.15;
       int order = 1;
@@ -250,19 +250,22 @@ namespace Avogadro
         map->setFromPrimitive(atom1);
         map->setAlpha(m_alpha);
         pd->painter()->setColor( map );
-        pd->painter()->drawMultiCylinder( v1, v3, m_bondRadius, order, shift );
+        pd->painter()->drawMultiCylinder( v1, v1 + d*(1+centerAdjust)/2, m_bondRadius, order, shift );
 
         map->setFromPrimitive(atom2);
         map->setAlpha(m_alpha);
         pd->painter()->setColor( map );
-        pd->painter()->drawMultiCylinder( v3, v2, m_bondRadius, order, shift );
+        pd->painter()->drawMultiCylinder( v2, v2 - d*(1-centerAdjust)/2, m_bondRadius, order, shift );
       }
 
       // Render the selected bond.
       if (pd->isSelected(b)) {
         pd->painter()->setColor(&selectionMap);
-        pd->painter()->drawMultiCylinder( v1, v2,
-                           SEL_BOND_EXTRA_RADIUS + m_bondRadius, order, shift );
+        pd->painter()->drawMultiCylinder(v1, v1 + d*(1+centerAdjust)/2, SEL_BOND_EXTRA_RADIUS +
+                                         m_bondRadius, order, shift);
+        pd->painter()->drawMultiCylinder(v2, v2 - d*(1-centerAdjust)/2, SEL_BOND_EXTRA_RADIUS +
+                                         m_bondRadius, order, shift);
+       
       }
     }
     return true;
@@ -281,9 +284,7 @@ namespace Avogadro
       Atom* atom2 = pd->molecule()->atomById(b->endAtomId());
       Vector3d v1(*atom1->pos());
       Vector3d v2(*atom2->pos());
-      Vector3d d = v2 - v1;
-      d.normalize();
-      Vector3d v3((v1 + v2 + d*(radius(atom1)-radius(atom2))) / 2);
+      Vector3d d = distanceVector(v1, v2, pd);
 
       double shift = 0.15;
       int order = 1;
@@ -291,17 +292,19 @@ namespace Avogadro
 
       if (pd->isSelected(b)) {
         pd->painter()->setColor(&cSel);
-        pd->painter()->drawMultiCylinder(v1, v2, SEL_BOND_EXTRA_RADIUS +
+        pd->painter()->drawMultiCylinder(v1, v1 + d/2, SEL_BOND_EXTRA_RADIUS +
+                                         m_bondRadius, order, shift);
+        pd->painter()->drawMultiCylinder(v2, v2 - d/2, SEL_BOND_EXTRA_RADIUS +
                                          m_bondRadius, order, shift);
       }
       else {
         map->setFromPrimitive(atom1);
         pd->painter()->setColor(map);
-        pd->painter()->drawMultiCylinder(v1, v3, m_bondRadius, order, shift);
+        pd->painter()->drawMultiCylinder(v1, v1 + d/2, m_bondRadius, order, shift);
 
         map->setFromPrimitive( atom2 );
         pd->painter()->setColor(map);
-        pd->painter()->drawMultiCylinder(v3, v2, m_bondRadius, order, shift);
+        pd->painter()->drawMultiCylinder(v2 , v2 - d/2, m_bondRadius, order, shift);
       }
     }
 
@@ -330,11 +333,18 @@ namespace Avogadro
   bool BSDYEngine::renderPick(PainterDevice *pd)
   {
     // Render the bonds
-    foreach(Bond *b, bonds()) {
-      pd->painter()->setName(b);
+    foreach(Bond *b, bonds()) {  
+      Vector3d v1(*b->beginPos());
+      Vector3d v2(*b->endPos());
+      Vector3d d = distanceVector(v1, v2, pd);
+
       // Add a slight slop factor to make it easier to pick
       // (e.g., for bond-centric tool)
-      pd->painter()->drawCylinder(*b->beginPos(), *b->endPos(), m_bondRadius+0.05);
+
+      pd->painter()->setName(b);
+      pd->painter()->drawCylinder(v1, v1 + d/2, m_bondRadius+0.05);
+      pd->painter()->setName(b);
+      pd->painter()->drawCylinder(v2, v2 - d/2, m_bondRadius+0.05);
     }
 
     // Render the atoms
@@ -361,6 +371,31 @@ namespace Avogadro
     }
     return m_atomRadiusPercentage;
   }
+  
+  // Get the shortest vector from v1 to v2 taking into account possible
+  // periodic boundary conditions
+  Vector3d BSDYEngine::distanceVector(const Vector3d& v1, const Vector3d& v2, PainterDevice* pd)
+  {
+    Vector3d d = v2 - v1;
+    OpenBabel::OBUnitCell* unitCell = pd->molecule()->OBUnitCell();
+    if (unitCell) {
+      std::vector<OpenBabel::vector3> cv = unitCell->GetCellVectors();
+      Vector3d a = Vector3d(cv[0].x(), cv[0].y(), cv[0].z());
+      Vector3d b = Vector3d(cv[1].x(), cv[1].y(), cv[1].z());
+      Vector3d c = Vector3d(cv[2].x(), cv[2].y(), cv[2].z());
+      for (int i=-1; i<2; i++) {
+        for (int j=-1; j<2; j++) {
+          for (int k=-1; k<2; k++) {
+            Vector3d v2_ = v2 + i*a + j*b + k*c;
+            Vector3d d_ = v2_ - v1;
+            if (d_.norm() < d.norm()) 
+              d = d_;
+          }
+        }
+      }
+    }
+    return d;
+  }
 
   void BSDYEngine::setAtomRadiusPercentage(int value)
   {
diff --git a/libavogadro/src/engines/bsdyengine.h b/libavogadro/src/engines/bsdyengine.h
index 30917f5..ac23d53 100644
--- a/libavogadro/src/engines/bsdyengine.h
+++ b/libavogadro/src/engines/bsdyengine.h
@@ -34,7 +34,7 @@ namespace Avogadro {
 
   //! Ball and Stick Engine class.
   class Atom;
-  class BSDYSettingsWidget;
+  class BSDYSettingsWidget;  
   class BSDYEngine : public Engine
   {
     Q_OBJECT
@@ -80,6 +80,7 @@ namespace Avogadro {
 
     private:
       double radius(const Atom *atom) const;
+      Eigen::Vector3d distanceVector(const Eigen::Vector3d& v1, const Eigen::Vector3d& v2, PainterDevice* pd);
 
       BSDYSettingsWidget *m_settingsWidget;
 
------------------------------------------------------------------------------
For Developers, A Lot Can Happen In A Second.
Boundary is the first to Know...and Tell You.
Monitor Your Applications in Ultra-Fine Resolution. Try it FREE!
http://p.sf.net/sfu/Boundary-d2dvs2
_______________________________________________
Avogadro-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/avogadro-devel

Reply via email to