public virtual void TestGetConnectedRings_IRing()
        {
            IRingSet ringset = (IRingSet)NewChemObject();

            IAtom ring1Atom1  = ringset.Builder.NewAtom("C"); // rather artificial molecule
            IAtom ring1Atom2  = ringset.Builder.NewAtom("C");
            IAtom sharedAtom1 = ringset.Builder.NewAtom("C");
            IAtom sharedAtom2 = ringset.Builder.NewAtom("C");
            IAtom ring2Atom1  = ringset.Builder.NewAtom("C");
            IAtom ring2Atom2  = ringset.Builder.NewAtom("C");
            IBond ring1Bond1  = ringset.Builder.NewBond(ring1Atom1, ring1Atom2);
            IBond ring1Bond2  = ringset.Builder.NewBond(sharedAtom1, ring1Atom1);
            IBond ring1Bond3  = ringset.Builder.NewBond(sharedAtom2, ring1Atom2);
            IBond sharedBond  = ringset.Builder.NewBond(sharedAtom1, sharedAtom2);
            IBond ring2Bond1  = ringset.Builder.NewBond(ring2Atom1, ring2Atom2);
            IBond ring2Bond2  = ringset.Builder.NewBond(sharedAtom1, ring2Atom1);
            IBond ring2Bond3  = ringset.Builder.NewBond(sharedAtom2, ring2Atom2);

            IRing ring1 = ringset.Builder.NewRing();

            ring1.Atoms.Add(ring1Atom1);
            ring1.Atoms.Add(ring1Atom2);
            ring1.Atoms.Add(sharedAtom1);
            ring1.Atoms.Add(sharedAtom2);
            ring1.Bonds.Add(ring1Bond1);
            ring1.Bonds.Add(ring1Bond2);
            ring1.Bonds.Add(ring1Bond3);
            ring1.Bonds.Add(sharedBond);
            IRing ring2 = ringset.Builder.NewRing();

            ring2.Atoms.Add(ring2Atom1);
            ring2.Atoms.Add(ring2Atom2);
            ring2.Atoms.Add(sharedAtom1);
            ring2.Atoms.Add(sharedAtom2);
            ring2.Bonds.Add(ring2Bond1);
            ring2.Bonds.Add(ring2Bond2);
            ring2.Bonds.Add(ring2Bond3);
            ring2.Bonds.Add(sharedBond);

            ringset.Add(ring1);
            ringset.Add(ring2);

            Assert.AreEqual(1, ringset.GetConnectedRings(ring2).Count());
            Assert.AreEqual(1, ringset.GetConnectedRings(ring1).Count());
        }
Exemple #2
0
        /// <summary>
        /// Perform a walk in the given RingSet, starting at a given Ring and
        /// recursively searching for other Rings connected to this ring. By doing
        /// this it finds all rings in the RingSet connected to the start ring,
        /// putting them in newRs, and removing them from rs.
        /// </summary>
        /// <param name="rs">The RingSet to be searched</param>
        /// <param name="ring">The ring to start with</param>
        /// <param name="newRs">The RingSet containing all Rings connected to ring</param>
        /// <returns>newRs The RingSet containing all Rings connected to ring</returns>
        private static IRingSet WalkRingSystem(IRingSet rs, IRing ring, IRingSet newRs)
        {
            IRing tempRing;
            var   tempRings = rs.GetConnectedRings(ring);

            rs.Remove(ring);
            foreach (var container in tempRings)
            {
                tempRing = (IRing)container;
                if (!newRs.Contains(tempRing))
                {
                    newRs.Add(tempRing);
                    newRs.Add(WalkRingSystem(rs, tempRing, newRs));
                }
            }
            return(newRs);
        }
Exemple #3
0
        /// <summary>
        /// Layout all rings in the given RingSet that are connected to a given Ring
        /// </summary>
        /// <param name="rs">The RingSet to be searched for rings connected to Ring</param>
        /// <param name="ring">The Ring for which all connected rings in RingSet are to be layed out.</param>
        public void PlaceConnectedRings(IRingSet rs, IRing ring, int handleType, double bondLength)
        {
            var connectedRings = rs.GetConnectedRings(ring);

            //        Debug.WriteLine(rs.ReportRingList(Molecule));
            foreach (var container in connectedRings)
            {
                IRing connectedRing = (IRing)container;
                if (!connectedRing.IsPlaced)
                {
                    //                Debug.WriteLine(ring.ToString(Molecule));
                    //                Debug.WriteLine(connectedRing.ToString(Molecule));
                    IAtomContainer sharedAtoms    = AtomContainerManipulator.GetIntersection(ring, connectedRing);
                    int            numSharedAtoms = sharedAtoms.Atoms.Count;
                    Debug.WriteLine("placeConnectedRings-> connectedRing: " + (ring.ToString()));
                    if ((numSharedAtoms == 2 && handleType == Fused) ||
                        (numSharedAtoms == 1 && handleType == Spiro) ||
                        (numSharedAtoms > 2 && handleType == Bridged))
                    {
                        Vector2 sharedAtomsCenter   = GeometryUtil.Get2DCenter(sharedAtoms);
                        Vector2 oldRingCenter       = GeometryUtil.Get2DCenter(ring);
                        Vector2 tempVector          = sharedAtomsCenter;
                        Vector2 newRingCenterVector = tempVector;
                        newRingCenterVector -= oldRingCenter;

                        // zero (or v. small ring center)
                        if (Math.Abs(newRingCenterVector.X) < 0.001 && Math.Abs(newRingCenterVector.Y) < 0.001)
                        {
                            // first see if we can use terminal bonds
                            IAtomContainer terminalOnly = Molecule.Builder.NewAtomContainer();

                            foreach (IAtom atom in ring.Atoms)
                            {
                                if (ring.GetConnectedBonds(atom).Count() == 1)
                                {
                                    terminalOnly.Atoms.Add(atom);
                                }
                            }

                            if (terminalOnly.Atoms.Count == 2)
                            {
                                newRingCenterVector = GeometryUtil.Get2DCenter(terminalOnly);
                                newRingCenterVector = oldRingCenter;
                                connectedRing.SetProperty(RingPlacer.SnapHint, true);
                            }
                            else
                            {
                                // project coordinates on 12 axis (30 degree snaps) and choose one with most spread
                                Vector2 vec     = new Vector2(0, 1);
                                double  bestLen = -double.MaxValue;

                                for (int i = 0; i < 12; i++)
                                {
                                    Vector2 orth = new Vector2(-vec.Y, vec.X);
                                    orth = Vector2.Normalize(orth);
                                    double min = double.MaxValue, max = -double.MaxValue;
                                    foreach (IAtom atom in sharedAtoms.Atoms)
                                    {
                                        // s: scalar projection
                                        double s = Vector2.Dot(orth, atom.Point2D.Value);
                                        if (s < min)
                                        {
                                            min = s;
                                        }
                                        if (s > max)
                                        {
                                            max = s;
                                        }
                                    }
                                    double len = max - min;
                                    if (len > bestLen)
                                    {
                                        bestLen             = len;
                                        newRingCenterVector = vec;
                                    }
                                    Rotate(vec, RAD_30);
                                }
                            }
                        }

                        Vector2 oldRingCenterVector = newRingCenterVector;
                        Debug.WriteLine($"placeConnectedRing -> tempVector: {tempVector}, tempVector.Length: {tempVector.Length()}");
                        Debug.WriteLine($"placeConnectedRing -> bondCenter: {sharedAtomsCenter}");
                        Debug.WriteLine($"placeConnectedRing -> oldRingCenterVector.Length: {oldRingCenterVector.Length()}");
                        Debug.WriteLine($"placeConnectedRing -> newRingCenterVector.Length: {newRingCenterVector.Length()}");
                        Vector2 tempPoint = sharedAtomsCenter;
                        tempPoint += newRingCenterVector;
                        PlaceRing(connectedRing, sharedAtoms, sharedAtomsCenter, newRingCenterVector, bondLength);
                        connectedRing.IsPlaced = true;
                        PlaceConnectedRings(rs, connectedRing, handleType, bondLength);
                    }
                }
            }
        }
        public virtual void TestGetConnectedRingsBug1772613()
        {
            // Build a bridged and fused norbomane like ring system
            // C1CCC2C(C1)C4CC2C3CCCCC34
            IRingSet ringSet           = (IRingSet)NewChemObject();
            IRing    leftCyclohexane   = ringSet.Builder.NewRing(6, "C");
            IRing    rightCyclopentane = ringSet.Builder.NewRing(5, "C");

            IRing leftCyclopentane = ringSet.Builder.NewRing();
            IBond leftCyclohexane0RightCyclopentane4 = ringSet.Builder.NewBond(leftCyclohexane.Atoms[0], rightCyclopentane.Atoms[4]);
            IBond leftCyclohexane1RightCyclopentane2 = ringSet.Builder.NewBond(leftCyclohexane.Atoms[1], rightCyclopentane.Atoms[2]);

            leftCyclopentane.Atoms.Add(leftCyclohexane.Atoms[0]);
            leftCyclopentane.Atoms.Add(leftCyclohexane.Atoms[1]);
            leftCyclopentane.Atoms.Add(rightCyclopentane.Atoms[2]);
            leftCyclopentane.Atoms.Add(rightCyclopentane.Atoms[3]);
            leftCyclopentane.Atoms.Add(rightCyclopentane.Atoms[4]);
            leftCyclopentane.Bonds.Add(leftCyclohexane.GetBond(leftCyclohexane.Atoms[0], leftCyclohexane.Atoms[1]));
            leftCyclopentane.Bonds.Add(leftCyclohexane1RightCyclopentane2);
            leftCyclopentane.Bonds.Add(rightCyclopentane.GetBond(rightCyclopentane.Atoms[2], rightCyclopentane.Atoms[3]));
            leftCyclopentane.Bonds.Add(rightCyclopentane.GetBond(rightCyclopentane.Atoms[3], rightCyclopentane.Atoms[4]));
            leftCyclopentane.Bonds.Add(leftCyclohexane0RightCyclopentane4);

            IRing rightCyclohexane           = ringSet.Builder.NewRing();
            IAtom rightCyclohexaneAtom0      = ringSet.Builder.NewAtom("C");
            IAtom rightCyclohexaneAtom1      = ringSet.Builder.NewAtom("C");
            IAtom rightCyclohexaneAtom2      = ringSet.Builder.NewAtom("C");
            IAtom rightCyclohexaneAtom5      = ringSet.Builder.NewAtom("C");
            IBond rightCyclohexaneAtom0Atom1 = ringSet.Builder.NewBond(rightCyclohexaneAtom0,
                                                                       rightCyclohexaneAtom1);
            IBond rightCyclohexaneAtom1Atom2 = ringSet.Builder.NewBond(rightCyclohexaneAtom1,
                                                                       rightCyclohexaneAtom2);
            IBond rightCyclohexane2rightCyclopentane1 = ringSet.Builder.NewBond(rightCyclohexaneAtom2, rightCyclopentane.Atoms[1]);
            IBond rightCyclohexane5rightCyclopentane0 = ringSet.Builder.NewBond(rightCyclohexaneAtom5, rightCyclopentane.Atoms[0]);
            IBond rightCyclohexaneAtom0Atom5          = ringSet.Builder.NewBond(rightCyclohexaneAtom0,
                                                                                rightCyclohexaneAtom5);

            rightCyclohexane.Atoms.Add(rightCyclohexaneAtom0);
            rightCyclohexane.Atoms.Add(rightCyclohexaneAtom1);
            rightCyclohexane.Atoms.Add(rightCyclohexaneAtom2);
            rightCyclohexane.Atoms.Add(rightCyclopentane.Atoms[1]);
            rightCyclohexane.Atoms.Add(rightCyclopentane.Atoms[0]);
            rightCyclohexane.Atoms.Add(rightCyclohexaneAtom5);
            rightCyclohexane.Bonds.Add(rightCyclohexaneAtom0Atom1);
            rightCyclohexane.Bonds.Add(rightCyclohexaneAtom1Atom2);
            rightCyclohexane.Bonds.Add(rightCyclohexane2rightCyclopentane1);
            rightCyclohexane.Bonds.Add(rightCyclopentane.GetBond(rightCyclopentane.Atoms[0], rightCyclopentane.Atoms[1]));
            rightCyclohexane.Bonds.Add(rightCyclohexane5rightCyclopentane0);
            rightCyclohexane.Bonds.Add(rightCyclohexaneAtom0Atom5);

            ringSet.Add(leftCyclohexane);
            ringSet.Add(leftCyclopentane);
            ringSet.Add(rightCyclopentane);
            ringSet.Add(rightCyclohexane);

            // Get connected rings
            var connectedRings = ringSet.GetConnectedRings(leftCyclohexane);

            // Iterate over the connectedRings and fail if any duplicate is found
            IList <IRing> foundRings = new List <IRing>();

            foreach (var container in connectedRings)
            {
                IRing connectedRing = (IRing)container;
                if (foundRings.Contains(connectedRing))
                {
                    Assert.Fail("The list of connected rings contains duplicates.");
                }
                foundRings.Add(connectedRing);
            }
        }