Index: src/Actions/GlobalListOfActions.hpp
===================================================================
--- src/Actions/GlobalListOfActions.hpp	(revision f63e41b6a0ddb762209a7c4ba24753bc9ceb33a2)
+++ src/Actions/GlobalListOfActions.hpp	(revision 8b886f03775fdc38d05053874958082ee74602f3)
@@ -31,4 +31,5 @@
   (MoleculeVerletIntegration) \
   (MoleculeChangeName) \
+  (MoleculeChangeBondAngle) \
   (MoleculeRotateAroundSelfByAngle) \
   (MoleculeSaveSelectedMolecules) \
Index: src/Actions/Makefile.am
===================================================================
--- src/Actions/Makefile.am	(revision f63e41b6a0ddb762209a7c4ba24753bc9ceb33a2)
+++ src/Actions/Makefile.am	(revision 8b886f03775fdc38d05053874958082ee74602f3)
@@ -241,4 +241,5 @@
 MOLECULEACTIONSOURCE = \
   Actions/MoleculeAction/BondFileAction.cpp \
+  Actions/MoleculeAction/ChangeBondAngleAction.cpp \
   Actions/MoleculeAction/ChangeNameAction.cpp \
   Actions/MoleculeAction/CopyAction.cpp \
@@ -258,4 +259,5 @@
 MOLECULEACTIONHEADER = \
   Actions/MoleculeAction/BondFileAction.hpp \
+  Actions/MoleculeAction/ChangeBondAngleAction.hpp \
   Actions/MoleculeAction/ChangeNameAction.hpp \
   Actions/MoleculeAction/CopyAction.hpp \
@@ -275,4 +277,5 @@
 MOLECULEACTIONDEFS = \
   Actions/MoleculeAction/BondFileAction.def \
+  Actions/MoleculeAction/ChangeBondAngleAction.def \
   Actions/MoleculeAction/ChangeNameAction.def \
   Actions/MoleculeAction/CopyAction.def \
Index: src/Actions/MoleculeAction/ChangeBondAngleAction.cpp
===================================================================
--- src/Actions/MoleculeAction/ChangeBondAngleAction.cpp	(revision 8b886f03775fdc38d05053874958082ee74602f3)
+++ src/Actions/MoleculeAction/ChangeBondAngleAction.cpp	(revision 8b886f03775fdc38d05053874958082ee74602f3)
@@ -0,0 +1,184 @@
+/*
+ * Project: MoleCuilder
+ * Description: creates and alters molecular systems
+ * Copyright (C)  2012 University of Bonn. All rights reserved.
+ * 
+ *
+ *   This file is part of MoleCuilder.
+ *
+ *    MoleCuilder is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    MoleCuilder is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with MoleCuilder.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * ChangeBondAngleAction.cpp
+ *
+ *  Created on: Nov 14, 2012
+ *      Author: heber
+ */
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "CodePatterns/MemDebug.hpp"
+
+#include "Actions/MoleculeAction/ChangeBondAngleAction.hpp"
+
+#include <boost/assign.hpp>
+
+#include "CodePatterns/Log.hpp"
+#include "CodePatterns/Verbose.hpp"
+
+#include "LinearAlgebra/Plane.hpp"
+#include "LinearAlgebra/Vector.hpp"
+
+#include "Atom/atom.hpp"
+#include "Bond/bond.hpp"
+#include "CodePatterns/Log.hpp"
+#include "CodePatterns/Verbose.hpp"
+#include "Descriptors/AtomIdDescriptor.hpp"
+#include "molecule.hpp"
+#include "World.hpp"
+#include "WorldTime.hpp"
+
+using namespace boost::assign;
+using namespace MoleCuilder;
+
+// and construct the stuff
+#include "ChangeBondAngleAction.def"
+#include "Action_impl_pre.hpp"
+/** =========== define the function ====================== */
+
+const std::vector<size_t> sortIndicesFromCentralAtom(const std::vector< atom *> &atoms)
+{
+  std::vector<size_t> indices;
+  {
+    std::vector<size_t> matches;
+    size_t index = 0;
+    for (; index < 3; ++index)
+      if ((atoms[index]->IsBondedTo(WorldTime::getTime(), atoms[(index+1)%3]))
+          && (atoms[index]->IsBondedTo(WorldTime::getTime(), atoms[(index+2)%3])))
+        matches.push_back(index);
+    if (matches.size() != 1) {
+      ELOG(1, "The three atoms are not linearly bonded.");
+    } else {
+      LOG(1, "INFO: Picking " << *atoms[ matches[0] ] << " as the central atom.");
+      indices += matches[0], (matches[0]+1)%3, (matches[0]+2)%3;
+    }
+  }
+  return indices;
+}
+
+void ChangeBondAngleSymmetrically(
+    const std::vector<size_t> &indices,
+    const double newangle,
+    const std::vector<atom*> &atoms)
+{
+  const Vector firstPosition = atoms[ indices[1] ]->getPosition();
+  const Vector secondPosition = atoms[ indices[2] ]->getPosition();
+
+  // create the bond plane and mid-distance
+  const double normaldistance = firstPosition.distance(secondPosition);
+  const Vector NormalVector = (1. / normaldistance) * (firstPosition - secondPosition);
+  const Vector OffsetVector = atoms[indices[0]]->getPosition();
+  Plane midplane(NormalVector, OffsetVector);
+  // go through the molecule and stretch each atom relative two plane
+  for (size_t index = 1; index < 3; ++index) {
+    const Vector &position = atoms[indices[index]]->getPosition();
+    const Vector planespot = midplane.getClosestPoint(position);
+    const double opposite_side = position.distance(planespot);
+    const double adjacent_side = OffsetVector.distance(planespot);
+    const double hypotenuse = position.distance(OffsetVector);
+    if (fabs(hypotenuse) > MYEPSILON) {
+      const double angle = acos(adjacent_side / hypotenuse);
+      LOG(1, "INFO: Old angle is " << (180. / M_PI) * (2. * angle) << ".");
+      const double new_opposite_side = hypotenuse * sin(newangle);
+      const double new_adjacent_side = hypotenuse * cos(newangle);
+      Vector newposition = (new_opposite_side / opposite_side) * (position - planespot);
+      newposition += (new_adjacent_side / adjacent_side) * (planespot - OffsetVector);
+      newposition += OffsetVector;
+      atoms[indices[index]]->setPosition(newposition);
+    }
+  }
+}
+
+Action::state_ptr MoleculeChangeBondAngleAction::performCall()
+{
+  // check precondition: three atoms
+  const std::vector< atom *> atoms = World::getInstance().getSelectedAtoms();
+  if (atoms.size() != 3) {
+    ELOG(1, "Exactly three atoms must be selected.");
+    return Action::failure;
+  }
+  // check precondition: linearly bonded atoms
+  const std::vector<size_t> indices = sortIndicesFromCentralAtom(atoms);
+  if (indices.size() != 3)
+    return Action::failure;
+  const molecule *mol = atoms[0]->getMolecule();
+  if ((mol != atoms[1]->getMolecule()) || (mol != atoms[2]->getMolecule())) {
+    ELOG(1, "The two selected atoms must belong to the same molecule.");
+    return Action::failure;
+  }
+
+  // gather undo info
+  const Vector firstPosition = atoms[ indices[1] ]->getPosition();
+  const Vector secondPosition = atoms[ indices[2] ]->getPosition();
+
+  // change the bond angle
+  const double newangle = .5* (M_PI / 180.) * params.bondangle.get();
+  LOG(1, "INFO: New angle is " << (180. / M_PI) * (2. * newangle) << ".");
+  ChangeBondAngleSymmetrically(indices, newangle, atoms);
+
+  // create undo information
+  MoleculeChangeBondAngleState *UndoState =  new MoleculeChangeBondAngleState(
+      indices[1], indices[2],
+      firstPosition, secondPosition,
+      atoms[ indices[1] ]->getPosition(), atoms[ indices[2] ]->getPosition(),
+      params);
+  return Action::state_ptr(UndoState);
+}
+
+Action::state_ptr MoleculeChangeBondAngleAction::performUndo(Action::state_ptr _state) {
+  MoleculeChangeBondAngleState *state = assert_cast<MoleculeChangeBondAngleState*>(_state.get());
+
+  // undo both position changes
+  atom * const first = World::getInstance().getAtom(AtomById(state->firstId));
+  atom * const second = World::getInstance().getAtom(AtomById(state->secondId));
+  first->setPosition(state->firstOldPosition);
+  second->setPosition(state->secondOldPosition);
+
+  return Action::state_ptr(_state);
+}
+
+Action::state_ptr MoleculeChangeBondAngleAction::performRedo(Action::state_ptr _state){
+  MoleculeChangeBondAngleState *state = assert_cast<MoleculeChangeBondAngleState*>(_state.get());
+
+  // redo both position changes
+  atom * const first = World::getInstance().getAtom(AtomById(state->firstId));
+  atom * const second = World::getInstance().getAtom(AtomById(state->secondId));
+  first->setPosition(state->firstNewPosition);
+  second->setPosition(state->secondNewPosition);
+
+  return Action::state_ptr(_state);
+}
+
+bool MoleculeChangeBondAngleAction::canUndo() {
+  return true;
+}
+
+bool MoleculeChangeBondAngleAction::shouldUndo() {
+  return true;
+}
+/** =========== end of function ====================== */
Index: src/Actions/MoleculeAction/ChangeBondAngleAction.def
===================================================================
--- src/Actions/MoleculeAction/ChangeBondAngleAction.def	(revision 8b886f03775fdc38d05053874958082ee74602f3)
+++ src/Actions/MoleculeAction/ChangeBondAngleAction.def	(revision 8b886f03775fdc38d05053874958082ee74602f3)
@@ -0,0 +1,36 @@
+/*
+ * ChangeBondAngleAction.def
+ *
+ *  Created on: Nov 14, 2012
+ *      Author: heber
+ */
+
+// all includes and forward declarations necessary for non-integral types below
+
+#include "Parameters/Validators/Specific/RotationAngleValidator.hpp"
+
+// i.e. there is an integer with variable name Z that can be found in
+// ValueStorage by the token "Z" -> first column: int, Z, "Z"
+// "undefine" if no parameters are required, use (NOPARAM_DEFAULT) for each (undefined) default value
+#define paramtypes (double)
+#define paramtokens ("change-bond-angle")
+#define paramdescriptions ("new bond angle in degree")
+#define paramdefaults (NOPARAM_DEFAULT)
+#define paramreferences (bondangle)
+#define paramvalids \
+(RotationAngleValidator())
+
+#define statetypes (atomId_t)(atomId_t)(Vector)(Vector)(Vector)(Vector)
+#define statereferences (firstId)(secondId)(firstOldPosition)(secondOldPosition)(firstNewPosition)(secondNewPosition)
+
+// some defines for all the names, you may use ACTION, STATE and PARAMS
+#define CATEGORY Molecule
+#define MENUNAME "molecule"
+#define MENUPOSITION 11
+#define ACTIONNAME ChangeBondAngle
+#define TOKEN "change-bond-angle"
+
+
+// finally the information stored in the ActionTrait specialization
+#define DESCRIPTION "changes symmetrically the positions of the two outer ones of three linearly bonded atoms such that the angle in between matches the desired one"
+#undef SHORTFORM
Index: src/Actions/MoleculeAction/ChangeBondAngleAction.hpp
===================================================================
--- src/Actions/MoleculeAction/ChangeBondAngleAction.hpp	(revision 8b886f03775fdc38d05053874958082ee74602f3)
+++ src/Actions/MoleculeAction/ChangeBondAngleAction.hpp	(revision 8b886f03775fdc38d05053874958082ee74602f3)
@@ -0,0 +1,22 @@
+/*
+ * ChangeBondAngleAction.hpp
+ *
+ *  Created on: Nov 14, 2012
+ *      Author: heber
+ */
+
+#ifndef CHANGEBONDANGLEACTION_HPP
+#define CHANGEBONDANGLEACTION_HPP
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "Actions/Action.hpp"
+
+#include "ChangeBondAngleAction.def"
+#include "Action_impl_header.hpp"
+
+#endif // CHANGEBONDANGLEACTION_HPP
