/// <summary> /// Layout the molecule, starts with ring systems and than aliphatic chains. /// </summary> /// <param name="ringSetMolecule">ringSystems of the molecule</param> private void LayoutMolecule(IReadOnlyList <IRingSet> ringSetMolecule, IAtomContainer molecule, AtomPlacer3D ap3d, AtomTetrahedralLigandPlacer3D atlp3d, AtomPlacer atomPlacer) { //Debug.WriteLine("****** 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) { //Debug.WriteLine("layout RingSystem..."); var unplacedAtom = ap3d.GetUnplacedRingHeavyAtom(molecule, atom); var ringSetA = GetRingSetOfAtom(ringSetMolecule, unplacedAtom); var ringSetAContainer = RingSetManipulator.GetAllInOneContainer(ringSetA); templateHandler.MapTemplates(ringSetAContainer, ringSetAContainer.Atoms.Count); if (CheckAllRingAtomsHasCoordinates(ringSetAContainer)) { } else { throw new IOException("RingAtomLayoutError: Not every ring atom is placed! Molecule cannot be layout. Sorry"); } Vector3 firstAtomOriginalCoord = unplacedAtom.Point3D.Value; Vector3 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); //Debug.WriteLine("Ready layout Ring System"); ringSetA = null; unplacedAtom = null; } else { //Debug.WriteLine("layout chains..."); SetAtomsToUnVisited(molecule); atom = ap3d.GetNextPlacedHeavyAtomWithUnplacedAliphaticNeighbour(molecule); if (atom != null) { ac = atom.Builder.NewAtomContainer(); ac.Atoms.Add(atom); SearchAndPlaceBranches(molecule, ac, ap3d, atlp3d, atomPlacer); ac = null; } } } while (!ap3d.AllHeavyAtomsPlaced(molecule) || safetyCounter > molecule.Atoms.Count); }
public override void TestGeometricCenterAllPlacedAtoms_IAtomContainer() { AtomPlacer3D atmplacer = new AtomPlacer3D(); IAtomContainer molecule = TestMoleculeFactory.MakeAlkane(2); foreach (var atom in molecule.Atoms) { atom.IsPlaced = true; } molecule.Atoms[0].Point3D = new Vector3(-1.0, 0.0, 0.0); molecule.Atoms[1].Point3D = new Vector3(1.0, 0.0, 0.0); Vector3 center = atmplacer.GeometricCenterAllPlacedAtoms(molecule); Assert.AreEqual(0.0, center.X, 0.01); Assert.AreEqual(0.0, center.Y, 0.01); Assert.AreEqual(0.0, center.Z, 0.01); }
/// <summary> /// Sets a branch atom to a ring or aliphatic chain. /// </summary> /// <param name="unplacedAtom">The new branchAtom</param> /// <param name="atomA">placed atom to which the unplaced atom is connected</param> /// <param name="atomNeighbours">placed atomNeighbours of atomA</param> private static void SetBranchAtom(IAtomContainer molecule, IAtom unplacedAtom, IAtom atomA, IAtomContainer atomNeighbours, AtomPlacer3D ap3d, AtomTetrahedralLigandPlacer3D atlp3d) { //Debug.WriteLine("****** SET Branch Atom ****** >"+molecule.Atoms.IndexOf(unplacedAtom)); IAtomContainer noCoords = molecule.Builder.NewAtomContainer(); noCoords.Atoms.Add(unplacedAtom); Vector3 centerPlacedMolecule = ap3d.GeometricCenterAllPlacedAtoms(molecule); IAtom atomB = atomNeighbours.Atoms[0]; string atypeNameA = atomA.AtomTypeName; string atypeNameB = atomB.AtomTypeName; string atypeNameUnplaced = unplacedAtom.AtomTypeName; double length = ap3d.GetBondLengthValue(atypeNameA, atypeNameUnplaced); double angle = (ap3d.GetAngleValue(atypeNameB, atypeNameA, atypeNameUnplaced)) * Math.PI / 180; // Console.Out.WriteLine("A:"+atomA.Symbol+" "+atomA.AtomTypeName+ // " B:"+atomB.Symbol+" "+atomB.AtomTypeName // +" unplaced Atom:" // +unplacedAtom.AtomTypeName+" BL:"+length+" Angle:"+angle // +" FormalNeighbour:" // +atomA.FormalNeighbourCount+" HYB:"+atomA.getFlag // (CDKConstants.HYBRIDIZATION_SP2) // +" #Neigbhours:"+atomNeighbours.Atoms.Count); IAtom atomC = ap3d.GetPlacedHeavyAtom(molecule, atomB, atomA); Vector3[] branchPoints = atlp3d.Get3DCoordinatesForLigands(atomA, noCoords, atomNeighbours, atomC, (atomA.FormalNeighbourCount.Value - atomNeighbours.Atoms.Count), length, angle); double distance = 0; int farthestPoint = 0; for (int i = 0; i < branchPoints.Length; i++) { if (Math.Abs(Vector3.Distance(branchPoints[i], centerPlacedMolecule)) > Math.Abs(distance)) { distance = Vector3.Distance(branchPoints[i], centerPlacedMolecule); farthestPoint = i; } } int stereo = -1; IBond unplacedBond = molecule.GetBond(atomA, unplacedAtom); if (atomA.StereoParity != 0 || (unplacedBond.Stereo == BondStereo.Up || unplacedBond.Stereo == BondStereo.Down) && molecule.GetMaximumBondOrder(atomA) == BondOrder.Single) { if (atomNeighbours.Atoms.Count > 1) { stereo = AtomTetrahedralLigandPlacer3D.MakeStereocenter(atomA.Point3D.Value, molecule.GetBond(atomA, unplacedAtom), (atomNeighbours.Atoms[0]).Point3D.Value, (atomNeighbours.Atoms[1]).Point3D.Value, branchPoints); } } if (stereo != -1) { farthestPoint = stereo; } unplacedAtom.Point3D = branchPoints[farthestPoint]; unplacedAtom.IsPlaced = true; }