/// <summary> /// Search and place branches of a chain or ring. /// </summary> /// <param name="chain">AtomContainer if atoms in an aliphatic chain or ring system</param> private void SearchAndPlaceBranches(IAtomContainer molecule, IAtomContainer chain, AtomPlacer3D ap3d, AtomTetrahedralLigandPlacer3D atlp3d, AtomPlacer atomPlacer) { //Debug.WriteLine("****** SEARCH AND PLACE ****** Chain length: "+chain.Atoms.Count); IAtomContainer branchAtoms = molecule.Builder.NewAtomContainer(); IAtomContainer connectedAtoms = molecule.Builder.NewAtomContainer(); for (int i = 0; i < chain.Atoms.Count; i++) { var atoms = molecule.GetConnectedAtoms(chain.Atoms[i]); foreach (var atom in atoms) { if (!atom.AtomicNumber.Equals(AtomicNumbers.H) & !atom.IsPlaced & !atom.IsInRing) { connectedAtoms.Add(ap3d.GetPlacedHeavyAtoms(molecule, chain.Atoms[i])); try { SetBranchAtom(molecule, atom, chain.Atoms[i], connectedAtoms, ap3d, atlp3d); } catch (CDKException ex2) { Trace.TraceError($"SearchAndPlaceBranchERROR: Cannot find enough neighbour atoms due to {ex2.ToString()}"); throw new CDKException($"SearchAndPlaceBranchERROR: Cannot find enough neighbour atoms: {ex2.Message}", ex2); } branchAtoms.Atoms.Add(atom); connectedAtoms.RemoveAllElements(); } } }//for ac.getAtomCount PlaceLinearChains3D(molecule, branchAtoms, ap3d, atlp3d, atomPlacer); }
/// <summary> /// Positions the aliphatic substituents of a ring system /// </summary> /// <param name="rs">The RingSystem for which the substituents are to be laid out</param> /// <returns>A list of atoms that where laid out</returns> public IAtomContainer PlaceRingSubstituents(IRingSet rs, double bondLength) { Debug.WriteLine("RingPlacer.PlaceRingSubstituents() start"); IRing ring = null; IAtom atom = null; IAtomContainer unplacedPartners = rs.Builder.NewAtomContainer(); IAtomContainer sharedAtoms = rs.Builder.NewAtomContainer(); IAtomContainer primaryAtoms = rs.Builder.NewAtomContainer(); IAtomContainer treatedAtoms = rs.Builder.NewAtomContainer(); for (int j = 0; j < rs.Count; j++) { ring = (IRing)rs[j]; // Get the j-th Ring in RingSet rs for (int k = 0; k < ring.Atoms.Count; k++) { unplacedPartners.RemoveAllElements(); sharedAtoms.RemoveAllElements(); primaryAtoms.RemoveAllElements(); atom = ring.Atoms[k]; var rings = rs.GetRings(atom); var centerOfRingGravity = GeometryUtil.Get2DCenter(rings); AtomPlacer.PartitionPartners(atom, unplacedPartners, sharedAtoms); AtomPlacer.MarkNotPlaced(unplacedPartners); try { for (int f = 0; f < unplacedPartners.Atoms.Count; f++) { Debug.WriteLine("placeRingSubstituents->unplacedPartners: " + (Molecule.Atoms.IndexOf(unplacedPartners.Atoms[f]) + 1)); } } catch (Exception) { } treatedAtoms.Add(unplacedPartners); if (unplacedPartners.Atoms.Count > 0) { AtomPlacer.DistributePartners(atom, sharedAtoms, centerOfRingGravity, unplacedPartners, bondLength); } } } Debug.WriteLine("RingPlacer.PlaceRingSubstituents() end"); return(treatedAtoms); }
/// <summary> /// Layout all aliphatic chains with ZMatrix. /// </summary> /// <param name="startAtoms">AtomContainer of possible start atoms for a chain</param> private void PlaceLinearChains3D(IAtomContainer molecule, IAtomContainer startAtoms, AtomPlacer3D ap3d, AtomTetrahedralLigandPlacer3D atlp3d, AtomPlacer atomPlacer) { //Debug.WriteLine("****** PLACE LINEAR CHAINS ******"); IAtom dihPlacedAtom = null; IAtom thirdPlacedAtom = null; IAtomContainer longestUnplacedChain = molecule.Builder.NewAtomContainer(); if (startAtoms.Atoms.Count == 0) { //no branch points ->linear chain //Debug.WriteLine("------ LINEAR CHAIN - FINISH ------"); } else { for (int i = 0; i < startAtoms.Atoms.Count; i++) { //Debug.WriteLine("FOUND BRANCHED ALKAN"); //Debug.WriteLine("Atom NOT NULL:" + molecule.Atoms.IndexOf(startAtoms.GetAtomAt(i))); thirdPlacedAtom = ap3d.GetPlacedHeavyAtom(molecule, startAtoms.Atoms[i]); dihPlacedAtom = ap3d.GetPlacedHeavyAtom(molecule, thirdPlacedAtom, startAtoms.Atoms[i]); longestUnplacedChain.Atoms.Add(dihPlacedAtom); longestUnplacedChain.Atoms.Add(thirdPlacedAtom); longestUnplacedChain.Atoms.Add(startAtoms.Atoms[i]); longestUnplacedChain.Add(AtomPlacer.GetLongestUnplacedChain(molecule, startAtoms.Atoms[i])); SetAtomsToUnVisited(molecule); if (longestUnplacedChain.Atoms.Count < 4) { //di,third,sec //Debug.WriteLine("------ Single BRANCH METHYLTYP ------"); //break; } else { //Debug.WriteLine("LongestUnchainLength:"+longestUnplacedChain.Atoms.Count); ap3d.PlaceAliphaticHeavyChain(molecule, longestUnplacedChain); ap3d.ZMatrixChainToCartesian(molecule, true); SearchAndPlaceBranches(molecule, longestUnplacedChain, ap3d, atlp3d, atomPlacer); } longestUnplacedChain.RemoveAllElements(); }//for } //Debug.WriteLine("****** HANDLE ALIPHATICS END ******"); }
/// <summary> /// Generate coordinates for all atoms which are singly bonded and have no /// coordinates. This is useful when hydrogens are present but have no coordinates. /// It knows about C, O, N, S only and will give tetrahedral or trigonal /// geometry elsewhere. Bond lengths are computed from covalent radii or taken /// out of a parameter set if available. Angles are tetrahedral or trigonal /// </summary> /// <param name="atomContainer">the set of atoms involved</param> // @cdk.keyword coordinate calculation // @cdk.keyword 3D model public virtual void Add3DCoordinatesForSinglyBondedLigands(IAtomContainer atomContainer) { IAtom refAtom = null; IAtom atomC = null; int nwanted = 0; for (int i = 0; i < atomContainer.Atoms.Count; i++) { refAtom = atomContainer.Atoms[i]; if (!refAtom.AtomicNumber.Equals(AtomicNumbers.H) && HasUnsetNeighbour(refAtom, atomContainer)) { IAtomContainer noCoords = GetUnsetAtomsInAtomContainer(refAtom, atomContainer); IAtomContainer withCoords = GetPlacedAtomsInAtomContainer(refAtom, atomContainer); if (withCoords.Atoms.Count > 0) { atomC = GetPlacedHeavyAtomInAtomContainer(withCoords.Atoms[0], refAtom, atomContainer); } if (refAtom.FormalNeighbourCount == 0 && refAtom.AtomicNumber.Equals(AtomicNumbers.C)) { nwanted = noCoords.Atoms.Count; } else if (refAtom.FormalNeighbourCount == 0 && !refAtom.AtomicNumber.Equals(AtomicNumbers.C)) { nwanted = 4; } else { nwanted = refAtom.FormalNeighbourCount.Value - withCoords.Atoms.Count; } Vector3[] newPoints = Get3DCoordinatesForLigands(refAtom, noCoords, withCoords, atomC, nwanted, DefaultBondLengthH, -1); for (int j = 0; j < noCoords.Atoms.Count; j++) { IAtom ligand = noCoords.Atoms[j]; Vector3 newPoint = RescaleBondLength(refAtom, ligand, newPoints[j]); ligand.Point3D = newPoint; ligand.IsPlaced = true; } noCoords.RemoveAllElements(); withCoords.RemoveAllElements(); } } }