/* $Revision$ $Author$ $Date$
*
* Copyright (C) 2005-2007 Christian Hoppe <chhoppe@users.sf.net>
*
* Contact: cdk-devel@lists.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
* All we ask is that proper credit is given for our work, which includes
* - but is not limited to - adding the above copyright notice to the beginning
* of your source code files, and to any copyright notice that you may distribute
* with programs based on this work.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.openscience.cdk.modeling.builder3d;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.exception.CDKException;
import org.openscience.cdk.exception.NoSuchAtomTypeException;
import org.openscience.cdk.geometry.GeometryTools;
import org.openscience.cdk.graph.ConnectivityChecker;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IBond;
import org.openscience.cdk.interfaces.IMolecule;
import org.openscience.cdk.interfaces.IRingSet;
import org.openscience.cdk.layout.AtomPlacer;
import org.openscience.cdk.ringsearch.RingPartitioner;
import org.openscience.cdk.tools.ILoggingTool;
import org.openscience.cdk.tools.LoggingToolFactory;
import org.openscience.cdk.tools.manipulator.RingSetManipulator;
/**
* The main class to generate the 3D coordinates of a molecule ModelBuilder3D.
* Its use looks like:
* <pre>
* ModelBuilder3D mb3d = ModelBuilder3D.getInstance();
* IMolecule molecule = mb3d.generate3DCoordinates(molecule, false);
* </pre>
*
* <p>Standing problems:
* <ul>
* <li>condensed ring systems which are unknown for the template class
* <li>vdWaals clashes
* <li>stereochemistry
* <li>chains running through ring systems
* </ul>
*
* @author cho
* @author steinbeck
* @cdk.created 2004-09-07
* @cdk.module builder3d
* @cdk.githash
* @cdk.keyword 3D coordinates
* @cdk.keyword coordinate generation, 3D
*/
public class ModelBuilder3D {
private static Map<String,ModelBuilder3D> memyselfandi = new HashMap<String,ModelBuilder3D>();
private TemplateHandler3D templateHandler = null;
private Map parameterSet = null;
private final ForceFieldConfigurator ffc = new ForceFieldConfigurator();
String forceFieldName = "mm2";
private static ILoggingTool logger =
LoggingToolFactory.createLoggingTool(ModelBuilder3D.class);
/**
* Constructor for the ModelBuilder3D object.
*
* @param templateHandler templateHandler Object
* @param ffname name of force field
*/
private ModelBuilder3D(TemplateHandler3D templateHandler, String ffname) throws CDKException {
setTemplateHandler(templateHandler);
setForceField(ffname);
}
public static ModelBuilder3D getInstance(TemplateHandler3D templateHandler, String ffname) throws CDKException {
if (ffname == null || ffname.length() == 0) throw new CDKException("The given ffname is null or empty!");
if (templateHandler == null) throw new CDKException("The given template handler is null!");
String builderCode = templateHandler.getClass().getName()+ "#" + ffname;
if (!memyselfandi.containsKey(builderCode)) {
ModelBuilder3D builder = new ModelBuilder3D(
templateHandler, ffname
);
memyselfandi.put(builderCode, builder);
return builder;
}
return memyselfandi.get(builderCode);
}
public static ModelBuilder3D getInstance() throws CDKException {
return getInstance(TemplateHandler3D.getInstance(), "mm2");
}
/**
* Gives a list of possible force field types.
*
* @return the list
*/
public String[] getFfTypes(){
return ffc.getFfTypes();
}
/**
* Sets the forceField attribute of the ModelBuilder3D object.
*
* @param ffname forceField name
*/
private void setForceField(String ffname) throws CDKException {
if (ffname == null) {
ffname = "mm2";
}
try {
forceFieldName = ffname;
ffc.setForceFieldConfigurator(ffname);
parameterSet = ffc.getParameterSet();
} catch (CDKException ex1) {
logger.error("Problem with ForceField configuration due to>" + ex1.getMessage());
logger.debug(ex1);
throw new CDKException("Problem with ForceField configuration due to>" + ex1.getMessage(), ex1);
}
}
/**
* Generate 3D coordinates with force field information.
*/
public IMolecule generate3DCoordinates(IMolecule molecule, boolean clone)
throws CDKException, NoSuchAtomTypeException,
CloneNotSupportedException, IOException{
String[] originalAtomTypeNames = new String[molecule.getAtomCount()];
for (int i=0; i<originalAtomTypeNames.length; i++) {
originalAtomTypeNames[i] = molecule.getAtom(i).getAtomTypeName();
}
logger.debug("******** GENERATE COORDINATES ********");
for(int i=0;i<molecule.getAtomCount();i++){
molecule.getAtom(i).setFlag(CDKConstants.ISPLACED,false);
molecule.getAtom(i).setFlag(CDKConstants.VISITED,false);
}
//CHECK FOR CONNECTIVITY!
logger.debug("#atoms>"+molecule.getAtomCount());
if (!ConnectivityChecker.isConnected(molecule)) {
throw new CDKException("Molecule is NOT connected, could not layout.");
}
// setup helper classes
AtomPlacer atomPlacer = new AtomPlacer();
AtomPlacer3D ap3d = new AtomPlacer3D();
AtomTetrahedralLigandPlacer3D atlp3d = new AtomTetrahedralLigandPlacer3D();
ap3d.initilize(parameterSet);
atlp3d.setParameterSet(parameterSet);
if (clone) molecule = (IMolecule)molecule.clone();
atomPlacer.setMolecule(molecule);
if (ap3d.numberOfUnplacedHeavyAtoms(molecule) == 1) {
logger.debug("Only one Heavy Atom");
molecule.getAtom(0).setPoint3d(new Point3d(0.0, 0.0, 0.0));
try {
atlp3d.add3DCoordinatesForSinglyBondedLigands(molecule);
} catch (CDKException ex3) {
logger.error("PlaceSubstitutensERROR: Cannot place substitutents due to:" + ex3.getMessage());
logger.debug(ex3);
throw new CDKException("PlaceSubstitutensERROR: Cannot place substitutents due to:" + ex3.getMessage(), ex3);
}
return molecule;
}
//Assing Atoms to Rings,Aliphatic and Atomtype
IRingSet ringSetMolecule = ffc.assignAtomTyps(molecule);
List ringSystems = null;
IRingSet largestRingSet = null;
double NumberOfRingAtoms = 0;
if (ringSetMolecule.getAtomContainerCount() > 0) {
if(templateHandler==null){
throw new CDKException("You are trying to generate coordinates for a molecule with rings, but you have no template handler set. Please do setTemplateHandler() before generation!");
}
ringSystems = RingPartitioner.partitionRings(ringSetMolecule);
largestRingSet = RingSetManipulator.getLargestRingSet(ringSystems);
IAtomContainer largestRingSetContainer = RingSetManipulator.getAllInOneContainer(largestRingSet);
NumberOfRingAtoms = (double)largestRingSetContainer.getAtomCount();
templateHandler.mapTemplates(largestRingSetContainer, NumberOfRingAtoms);
if (!checkAllRingAtomsHasCoordinates(largestRingSetContainer)) {
throw new CDKException("RingAtomLayoutError: Not every ring atom is placed! Molecule cannot be layout.");
}
setAtomsToPlace(largestRingSetContainer);
searchAndPlaceBranches(molecule, largestRingSetContainer, ap3d, atlp3d, atomPlacer);
largestRingSet = null;
} else {
//logger.debug("****** Start of handling aliphatic molecule ******");
IAtomContainer ac = null;
ac = atomPlacer.getInitialLongestChain(molecule);
setAtomsToUnVisited(molecule);
setAtomsToUnPlaced(molecule);
ap3d.placeAliphaticHeavyChain(molecule, ac);
//ZMatrixApproach
ap3d.zmatrixChainToCartesian(molecule, false);
searchAndPlaceBranches(molecule, ac, ap3d, atlp3d, atomPlacer);
}
layoutMolecule(ringSystems, molecule, ap3d, atlp3d, atomPlacer);
//logger.debug("******* PLACE SUBSTITUENTS ******");
try {
atlp3d.add3DCoordinatesForSinglyBondedLigands(molecule);
} catch (CDKException ex3) {
logger.error("PlaceSubstitutensERROR: Cannot place substitutents due to:" + ex3.getMessage());
logger.debug(ex3);
throw new CDKException("PlaceSubstitutensERROR: Cannot place substitutents due to:" + ex3.getMessage(), ex3);
}
// restore the original atom type names
for (int i=0; i<originalAtomTypeNames.length; i++) {
molecule.getAtom(i).setAtomTypeName(originalAtomTypeNames[i]);
}
return molecule;
}
/**
* Gets the ringSetOfAtom attribute of the ModelBuilder3D object.
*
*@return The ringSetOfAtom value
*/
private IRingSet getRingSetOfAtom(List ringSystems, IAtom atom) {
IRingSet ringSetOfAtom = null;
for (int i = 0; i < ringSystems.size(); i++) {
if (((IRingSet) ringSystems.get(i)).contains(atom)) {
return (IRingSet) ringSystems.get(i);
}
}
return ringSetOfAtom;
}
/**
* Layout the molecule, starts with ring systems and than aliphatic chains.
*
*@param ringSetMolecule ringSystems of the molecule
*/
private void layoutMolecule(List ringSetMolecule, IMolecule molecule, AtomPlacer3D ap3d, AtomTetrahedralLigandPlacer3D atlp3d, AtomPlacer atomPlacer) throws CDKException, IOException, CloneNotSupportedException {
//logger.debug("****** LAYOUT MOLECULE MAIN *******");
IAtomContainer ac = null;
int safetyCounter = 0;
IAtom atom = null;
//Place rest Chains/Atoms
do {
safetyCounter++;
atom = ap3d.getNextPlacedHeavyAtomWithUnplacedRingNeighbour(molecule);
if (atom != null) {
//logger.debug("layout RingSystem...");
IAtom unplacedAtom = ap3d.getUnplacedRingHeavyAtom(molecule, atom);
IRingSet ringSetA = getRingSetOfAtom(ringSetMolecule, unplacedAtom);
IAtomContainer ringSetAContainer = RingSetManipulator.getAllInOneContainer(ringSetA);
templateHandler.mapTemplates(ringSetAContainer, (double)ringSetAContainer.getAtomCount());
if (checkAllRingAtomsHasCoordinates(ringSetAContainer)) {
} else {
throw new IOException("RingAtomLayoutError: Not every ring atom is placed! Molecule cannot be layout.Sorry");
}
Point3d firstAtomOriginalCoord = unplacedAtom.getPoint3d();
Point3d centerPlacedMolecule = ap3d.geometricCenterAllPlacedAtoms(molecule);
setBranchAtom(molecule, unplacedAtom, atom, ap3d.getPlacedHeavyAtoms(molecule, atom), ap3d, atlp3d);
layoutRingSystem(firstAtomOriginalCoord, unplacedAtom, ringSetA, centerPlacedMolecule, atom, ap3d);
searchAndPlaceBranches(molecule, ringSetAContainer, ap3d, atlp3d, atomPlacer);
//logger.debug("Ready layout Ring System");
ringSetA = null;
unplacedAtom = null;
firstAtomOriginalCoord = null;
centerPlacedMolecule = null;
} else {
//logger.debug("layout chains...");
setAtomsToUnVisited(molecule);
atom = ap3d.getNextPlacedHeavyAtomWithUnplacedAliphaticNeighbour(molecule);
if (atom != null) {
ac = atom.getBuilder().newAtomContainer();
ac.addAtom(atom);
searchAndPlaceBranches(molecule, ac, ap3d, atlp3d, atomPlacer);
ac = null;
}
}
} while (!ap3d.allHeavyAtomsPlaced(molecule) || safetyCounter > molecule.getAtomCount());
}
/**
* Layout the ring system, rotate and translate the template.
*
*@param originalCoord coordinates of the placedRingAtom from the template
*@param placedRingAtom placedRingAtom
*@param ringSet ring system which placedRingAtom is part of
*@param centerPlacedMolecule the geometric center of the already placed molecule
*@param atomB placed neighbour atom of placedRingAtom
*/
private void layoutRingSystem(Point3d originalCoord, IAtom placedRingAtom, IRingSet ringSet, Point3d centerPlacedMolecule, IAtom atomB, AtomPlacer3D ap3d) {
//logger.debug("****** Layout ring System ******");System.out.println(">around atom:"+molecule.getAtomNumber(placedRingAtom));
IAtomContainer ac = RingSetManipulator.getAllInOneContainer(ringSet);
Point3d newCoord = placedRingAtom.getPoint3d();
Vector3d axis = new Vector3d(atomB.getPoint3d().x - newCoord.x, atomB.getPoint3d().y - newCoord.y, atomB.getPoint3d().z - newCoord.z);
translateStructure(originalCoord, newCoord, ac);
//Rotate Ringsystem to farthest possible point
Vector3d startAtomVector = new Vector3d(newCoord.x - atomB.getPoint3d().x, newCoord.y - atomB.getPoint3d().y, newCoord.z - atomB.getPoint3d().z);
IAtom farthestAtom = ap3d.getFarthestAtom(placedRingAtom.getPoint3d(), ac);
Vector3d farthestAtomVector = new Vector3d(farthestAtom.getPoint3d().x - newCoord.x, farthestAtom.getPoint3d().y - newCoord.y, farthestAtom.getPoint3d().z - newCoord.z);
Vector3d n1 = new Vector3d();
n1.cross(axis, farthestAtomVector);
n1.normalize();
double lengthFarthestAtomVector = farthestAtomVector.length();
Vector3d farthestVector = new Vector3d(startAtomVector);
farthestVector.normalize();
farthestVector.scale((startAtomVector.length() + lengthFarthestAtomVector));
double dotProduct = farthestAtomVector.dot(farthestVector);
double angle = Math.acos(dotProduct / (farthestAtomVector.length() * farthestVector.length()));
Vector3d ringCenter = new Vector3d();
for (int i = 0; i < ac.getAtomCount(); i++) {
if (!(ac.getAtom(i).getFlag(CDKConstants.ISPLACED))) {
ringCenter.x = (ac.getAtom(i).getPoint3d()).x - newCoord.x;
ringCenter.y = (ac.getAtom(i).getPoint3d()).y - newCoord.y;
ringCenter.z = (ac.getAtom(i).getPoint3d()).z - newCoord.z;
ringCenter = AtomTetrahedralLigandPlacer3D.rotate(ringCenter, n1, angle);
ac.getAtom(i).setPoint3d(
new Point3d(
ringCenter.x + newCoord.x,
ringCenter.y + newCoord.y,
ringCenter.z + newCoord.z
)
);
//ac.getAtomAt(i).setFlag(CDKConstants.ISPLACED, true);
}
}
//Rotate Ring so that geometric center is max from placed center
//logger.debug("Rotate RINGSYSTEM");
Point3d pointRingCenter = GeometryTools.get3DCenter(ac);
double distance = 0;
double rotAngleMax = 0;
angle = 1 / 180 * Math.PI;
ringCenter = new Vector3d(pointRingCenter.x, pointRingCenter.y, pointRingCenter.z);
ringCenter.x = ringCenter.x - newCoord.x;
ringCenter.y = ringCenter.y - newCoord.y;
ringCenter.z = ringCenter.z - newCoord.z;
for (int i = 1; i < 360; i++) {
ringCenter = AtomTetrahedralLigandPlacer3D.rotate(ringCenter, axis, angle);
if (centerPlacedMolecule.distance(new Point3d(ringCenter.x, ringCenter.y, ringCenter.z)) > distance) {
rotAngleMax = i;
distance = centerPlacedMolecule.distance(new Point3d(ringCenter.x, ringCenter.y, ringCenter.z));
}
}
//rotate ring around axis with best angle
rotAngleMax = (rotAngleMax / 180) * Math.PI;
for (int i = 0; i < ac.getAtomCount(); i++) {
if (!(ac.getAtom(i).getFlag(CDKConstants.ISPLACED))) {
ringCenter.x = (ac.getAtom(i).getPoint3d()).x;
ringCenter.y = (ac.getAtom(i).getPoint3d()).y;
ringCenter.z = (ac.getAtom(i).getPoint3d()).z;
ringCenter = AtomTetrahedralLigandPlacer3D.rotate(ringCenter, axis, rotAngleMax);
ac.getAtom(i).setPoint3d(
new Point3d(
ringCenter.x,
ringCenter.y,
ringCenter.z
)
);
ac.getAtom(i).setFlag(CDKConstants.ISPLACED, true);
}
}
}
/**
* Sets a branch atom to a ring or aliphatic chain.
*
*@param unplacedAtom The new branchAtom
*@param atomA placed atom to which the unplaced satom is connected
*@param atomNeighbours placed atomNeighbours of atomA
*/
private void setBranchAtom(IMolecule molecule, IAtom unplacedAtom, IAtom atomA, IAtomContainer atomNeighbours, AtomPlacer3D ap3d, AtomTetrahedralLigandPlacer3D atlp3d) throws CDKException {
//logger.debug("****** SET Branch Atom ****** >"+molecule.getAtomNumber(unplacedAtom));
IAtomContainer noCoords = molecule.getBuilder().newAtomContainer();
noCoords.addAtom(unplacedAtom);
Point3d centerPlacedMolecule = ap3d.geometricCenterAllPlacedAtoms(molecule);
IAtom atomB = atomNeighbours.getAtom(0);
String atypeNameA = atomA.getAtomTypeName();
String atypeNameB = atomB.getAtomTypeName();
String atypeNameUnplaced = unplacedAtom.getAtomTypeName();
double length = ap3d.getBondLengthValue(atypeNameA, atypeNameUnplaced);
double angle = (ap3d.getAngleValue(atypeNameB, atypeNameA, atypeNameUnplaced)) * Math.PI / 180;
/*
* System.out.println("A:"+atomA.getSymbol()+" "+atomA.getAtomTypeName()+" B:"+atomB.getSymbol()+" "+atomB.getAtomTypeName()
* +" unplaced Atom:"+unplacedAtom.getAtomTypeName()+" BL:"+length+" Angle:"+angle
* +" FormalNeighbour:"+atomA.getFormalNeighbourCount()+" HYB:"+atomA.getFlag(CDKConstants.HYBRIDIZATION_SP2)
* +" #Neigbhours:"+atomNeighbours.getAtomCount());
*/
IAtom atomC = ap3d.getPlacedHeavyAtom(molecule, atomB, atomA);
Point3d[] branchPoints = atlp3d.get3DCoordinatesForLigands(atomA, noCoords, atomNeighbours, atomC
, (atomA.getFormalNeighbourCount() - atomNeighbours.getAtomCount())
, length, angle);
double distance = 0;
int farthestPoint = 0;
for (int i = 0; i < branchPoints.length; i++) {
if (Math.abs(branchPoints[i].distance(centerPlacedMolecule)) > Math.abs(distance)) {
distance = branchPoints[i].distance(centerPlacedMolecule);
farthestPoint = i;
}
}
int stereo = -1;
IBond unplacedBond = molecule.getBond(atomA, unplacedAtom);
if (atomA.getStereoParity() != CDKConstants.UNSET && atomA.getStereoParity() != 0 ||
(unplacedBond.getStereo() == IBond.Stereo.UP ||
unplacedBond.getStereo() == IBond.Stereo.DOWN)
&& molecule.getMaximumBondOrder(atomA) == IBond.Order.SINGLE) {
if (atomNeighbours.getAtomCount() > 1) {
stereo = atlp3d.makeStereocenter(atomA.getPoint3d(), molecule.getBond(atomA, unplacedAtom), (atomNeighbours.getAtom(0)).getPoint3d(), (atomNeighbours.getAtom(1)).getPoint3d(), branchPoints);
}
}
if (stereo != -1) {
farthestPoint = stereo;
}
unplacedAtom.setPoint3d(branchPoints[farthestPoint]);
unplacedAtom.setFlag(CDKConstants.ISPLACED, true);
}
/**
* Search and place branches of a chain or ring.
*
*@param chain AtomContainer if atoms in an aliphatic chain or ring system
*/
private void searchAndPlaceBranches(IMolecule molecule, IAtomContainer chain, AtomPlacer3D ap3d, AtomTetrahedralLigandPlacer3D atlp3d, AtomPlacer atomPlacer) throws CDKException {
//logger.debug("****** SEARCH AND PLACE ****** Chain length: "+chain.getAtomCount());
java.util.List atoms = null;
IAtomContainer branchAtoms = molecule.getBuilder().newAtomContainer();
IAtomContainer connectedAtoms = molecule.getBuilder().newAtomContainer();
for (int i = 0; i < chain.getAtomCount(); i++) {
atoms = molecule.getConnectedAtomsList(chain.getAtom(i));
for (int j = 0; j < atoms.size(); j++) {
IAtom atom = (IAtom)atoms.get(j);
if (!(atom.getSymbol()).equals("H") & !(atom.getFlag(CDKConstants.ISPLACED)) & !(atom.getFlag(CDKConstants.ISINRING))) {
//logger.debug("SEARCH PLACE AND FOUND Branch Atom "+molecule.getAtomNumber(chain.getAtomAt(i))+
// " New Atom:"+molecule.getAtomNumber(atoms[j])+" -> STORE");
connectedAtoms.add(ap3d.getPlacedHeavyAtoms(molecule, chain.getAtom(i)));
//logger.debug("Connected atom1:"+molecule.getAtomNumber(connectedAtoms.getAtomAt(0))+" atom2:"+
//molecule.getAtomNumber(connectedAtoms.getAtomAt(1))+ " Length:"+connectedAtoms.getAtomCount());
try {
setBranchAtom(molecule, atom, chain.getAtom(i), connectedAtoms, ap3d, atlp3d);
} catch (CDKException ex2) {
logger.error("SearchAndPlaceBranchERROR: Cannot find enough neighbour atoms due to" + ex2.toString());
throw new CDKException("SearchAndPlaceBranchERROR: Cannot find enough neighbour atoms: " + ex2.getMessage(), ex2);
}
branchAtoms.addAtom(atom);
connectedAtoms.removeAllElements();
}
}
}//for ac.getAtomCount
placeLinearChains3D(molecule, branchAtoms, ap3d, atlp3d, atomPlacer);
}
/**
* Layout all aliphatic chains with ZMatrix.
*
*@param startAtoms AtomContainer of possible start atoms for a chain
*/
private void placeLinearChains3D(IMolecule molecule, IAtomContainer startAtoms, AtomPlacer3D ap3d, AtomTetrahedralLigandPlacer3D atlp3d, AtomPlacer atomPlacer) throws CDKException {
//logger.debug("****** PLACE LINEAR CHAINS ******");
IAtom dihPlacedAtom = null;
IAtom thirdPlacedAtom = null;
IAtomContainer longestUnplacedChain = molecule.getBuilder().newAtomContainer();
if (startAtoms.getAtomCount() == 0) {
//no branch points ->linear chain
//logger.debug("------ LINEAR CHAIN - FINISH ------");
} else {
for (int i = 0; i < startAtoms.getAtomCount(); i++) {
//logger.debug("FOUND BRANCHED ALKAN");
//logger.debug("Atom NOT NULL:" + molecule.getAtomNumber(startAtoms.getAtomAt(i)));
thirdPlacedAtom = ap3d.getPlacedHeavyAtom(molecule, startAtoms.getAtom(i));
dihPlacedAtom = ap3d.getPlacedHeavyAtom(molecule, thirdPlacedAtom, startAtoms.getAtom(i));
longestUnplacedChain.addAtom(dihPlacedAtom);
longestUnplacedChain.addAtom(thirdPlacedAtom);
longestUnplacedChain.addAtom(startAtoms.getAtom(i));
longestUnplacedChain.add(atomPlacer.getLongestUnplacedChain(molecule, startAtoms.getAtom(i)));
setAtomsToUnVisited(molecule);
if (longestUnplacedChain.getAtomCount() < 4) {
//di,third,sec
//logger.debug("------ SINGLE BRANCH METHYLTYP ------");
//break;
} else {
//logger.debug("LongestUnchainLength:"+longestUnplacedChain.getAtomCount());
ap3d.placeAliphaticHeavyChain(molecule, longestUnplacedChain);
ap3d.zmatrixChainToCartesian(molecule, true);
searchAndPlaceBranches(molecule, longestUnplacedChain, ap3d, atlp3d, atomPlacer);
}
longestUnplacedChain.removeAllElements();
}//for
}
//logger.debug("****** HANDLE ALIPHATICS END ******");
}
/**
* Translates the template ring system to new coordinates.
*
*@param originalCoord original coordinates of the placed ring atom from template
*@param newCoord new coordinates from branch placement
*@param ac AtomContainer contains atoms of ring system
*/
private void translateStructure(Point3d originalCoord, Point3d newCoord, IAtomContainer ac) {
Point3d transVector = new Point3d(originalCoord);
transVector.sub(newCoord);
for (int i = 0; i < ac.getAtomCount(); i++) {
if (!(ac.getAtom(i).getFlag(CDKConstants.ISPLACED))) {
ac.getAtom(i).getPoint3d().sub(transVector);
//ac.getAtomAt(i).setFlag(CDKConstants.ISPLACED, true);
}
}
}
/**
* Returns the largest (number of atoms) ring set in a molecule.
*
*@param ac AtomContainer
*@return boolean
*/
private boolean checkAllRingAtomsHasCoordinates(IAtomContainer ac) {
for (int i = 0; i < ac.getAtomCount(); i++) {
if (ac.getAtom(i).getPoint3d() != null && ac.getAtom(i).getFlag(CDKConstants.ISINRING)) {
} else if (!ac.getAtom(i).getFlag(CDKConstants.ISINRING)) {
} else {
return false;
}
}
return true;
}
/**
* Sets the atomsToPlace attribute of the ModelBuilder3D object.
*
*@param ac The new atomsToPlace value
*/
private void setAtomsToPlace(IAtomContainer ac) {
for (int i = 0; i < ac.getAtomCount(); i++) {
ac.getAtom(i).setFlag(CDKConstants.ISPLACED, true);
}
}
/**
* Sets the atomsToUnPlaced attribute of the ModelBuilder3D object.
*/
private void setAtomsToUnPlaced(IMolecule molecule) {
for (int i = 0; i < molecule.getAtomCount(); i++) {
molecule.getAtom(i).setFlag(CDKConstants.ISPLACED, false);
}
}
/**
* Sets the atomsToUnVisited attribute of the ModelBuilder3D object.
*/
private void setAtomsToUnVisited(IMolecule molecule) {
for (int i = 0; i < molecule.getAtomCount(); i++) {
molecule.getAtom(i).setFlag(CDKConstants.VISITED, false);
}
}
/**
* Sets the templateHandler attribute of the ModelBuilder3D object.
*
* @param templateHandler The new templateHandler value
*/
private void setTemplateHandler(TemplateHandler3D templateHandler) throws CDKException {
if (templateHandler == null) throw new NullPointerException("The given template handler is null!");
this.templateHandler = templateHandler;
}
/**
* Returns the number of loaded templates. Note that it may return 0 because
* templates are lazy loaded, that is upon the first ring being layed out.
*
* @return 0, if not templates are loaded
*/
public int getTemplateCount() {
return this.templateHandler.getTemplateCount();
}
}