org.xmlcml.cml.tools.AngleTool Maven / Gradle / Ivy
/**
* Copyright 2011 Peter Murray-Rust et. al.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.xmlcml.cml.tools;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.xmlcml.cml.base.AbstractTool;
import org.xmlcml.cml.base.CMLElement.CoordinateType;
import org.xmlcml.cml.element.CMLAngle;
import org.xmlcml.cml.element.CMLAtom;
import org.xmlcml.cml.element.CMLAtomSet;
import org.xmlcml.cml.element.CMLMolecule;
import org.xmlcml.cml.element.CMLTransform3;
import org.xmlcml.euclid.Angle;
import org.xmlcml.euclid.Point3;
import org.xmlcml.euclid.Transform3;
import org.xmlcml.euclid.Vector3;
/**
* tool for managing angles
*
* @author pmr
*
*/
public class AngleTool extends AbstractTool {
final static Logger LOG = Logger.getLogger(AngleTool.class);
CMLAngle angle = null;
/** constructor.
* requires molecule to contain and optionally
* @param molecule
* @throws RuntimeException must contain a crystal
*/
public AngleTool(CMLAngle angle) throws RuntimeException {
init();
this.angle = angle;
}
void init() {
}
/**
* get angle.
*
* @return the angle or null
*/
public CMLAngle getAngle() {
return this.angle;
}
/** gets AngleTool associated with angle.
* if null creates one and sets it in angle
* @param angle
* @return tool
*/
public static AngleTool getOrCreateTool(CMLAngle angle) {
AngleTool angleTool = (angle == null) ? null : (AngleTool) angle.getTool();
if (angleTool == null) {
angleTool = new AngleTool(angle);
angle.setTool(angleTool);
}
return angleTool;
}
/** adjusts coordinates in molecule to torsion angle.
* moves atoms downstream of atom0/atom1
* @param molecule
*/
public void adjustCoordinates(CMLMolecule molecule) {
String[] atomRefs3 = angle.getAtomRefs3();
CMLAtomSet fixedAtomSet = new CMLAtomSet(molecule, atomRefs3);
CMLAtom atom0 = fixedAtomSet.getAtom(0);
CMLAtom atom1 = fixedAtomSet.getAtom(1);
MoleculeTool moleculeTool = MoleculeTool.getOrCreateTool(molecule);
CMLAtomSet moveableSet = moleculeTool.getDownstreamAtoms(atom1, atom0);
adjustCoordinates(fixedAtomSet, moveableSet);
}
/** applies transformation to reset angle.
*
* @param angle
* @param atomSet to define torsion (could be the molecule)
* @param moveableSet set of atoms which can be moved
* (normally those downstream of the rotatable bond)
* coordinates of these atoms will be altered
*/
public void adjustCoordinates(Angle angle, CMLAtomSet atomSet, CMLAtomSet moveableSet) {
// make sure there are exactly 3 atoms in order
CMLAtomSet atom3Set = atomSet.getAtomSetById(this.angle.getAtomRefs3());
CMLTransform3 transform = this.getTransformationToNewAngle(
angle, atom3Set.getAtoms());
AtomSetTool.getOrCreateTool(moveableSet).transformCartesians(transform);
}
/** applies transformation to reset torsion angle.
*
* @param amount
* @param atomSet to define torsion (could be the molecule)
* @param moveableSet set of atoms which can be moved
* (normally those downstream of the rotatable bond)
* coordinates of these atoms will be altered
* @exception RuntimeException bad value for angle
*/
void adjustCoordinates(CMLAtomSet atomSet, CMLAtomSet moveableSet)
throws RuntimeException {
if (angle.getValue().trim().length() == 0) {
//
} else {
Double d = angle.getXMLContent();
if (!Double.isNaN(d)) {
Angle angle = new Angle(d, Angle.Units.DEGREES);
// make sure there are exactly 3 atoms in order
CMLAtomSet atom3Set = atomSet.getAtomSetById(this.angle.getAtomRefs3());
CMLTransform3 transform = this.getTransformationToNewAngle(
angle, atom3Set.getAtoms());
AtomSetTool.getOrCreateTool(moveableSet).transformCartesians(transform);
}
}
}
/** calculates transformation to reset angle.
* T1 = translateion of atom2 to origin
* R = rotation
* T1' = -T1
*
* T = T1' * R * T1
* @param angle
* @param atomSet of 3 atoms a1 - a2 - a3
* @return the transform (or null if problems)
*/
private CMLTransform3 getTransformationToNewAngle(Angle angle, List atomList) {
if (atomList == null) {
throw new RuntimeException("Null atomList");
}
if (atomList.size() != 3) {
throw new RuntimeException("Must have 3 atoms in angle: was "+atomList.size());
}
// NOT YET WORKING - REQUIRES TESTING
Transform3 transform = null;
double ang0 = this.angle.getCalculatedAngle(atomList);
CMLAtom atom0 = atomList.get(0);
CMLAtom atom1 = atomList.get(1);
CMLAtom atom2 = atomList.get(2);
// get cross product
Vector3 v10 = atom0.getVector3(atom1);
Vector3 v12 = atom2.getVector3(atom1);
Vector3 vcross = v10.cross(v12);
vcross = vcross.normalize();
Point3 point1 = atom1.getPoint3(CoordinateType.CARTESIAN);
double delta = angle.getDegrees() - ang0;
// translate moveable atoms to origin
Vector3 v2 = new Point3(0.0, 0.0, 0.0).subtract(point1);
Transform3 t1 = new Transform3(v2);
Transform3 t1prime = new Transform3(v2.negative());
Transform3 r = new Transform3(vcross, new Angle(delta, Angle.Units.DEGREES));
transform = r.concatenate(t1);
// translate back
transform = t1prime.concatenate(transform);
return new CMLTransform3(transform);
}
/**
* gets atoms as array of atoms.
*
* @param atomSet
* @return the atoms (null if no atomRefs3)
*/
public List getAtoms(CMLAtomSet atomSet) {
List atomList = null;
if (atomSet != null) {
String[] atomIds = angle.getAtomRefs3();
if (atomIds != null && atomIds.length == 3) {
atomList = new ArrayList();
for (String atomId : atomIds) {
CMLAtom atom = atomSet.getAtomById(atomId);
if (atom == null) {
throw new RuntimeException("cannot find atom " + atomId);
}
atomList.add(atom);
}
}
}
return atomList;
}
};
© 2015 - 2025 Weber Informatics LLC | Privacy Policy