/// <summary>  Builds  the nodes of the RGraph ( resolution graph ), from
        /// two atom containers (description of the two molecules to compare)
        /// 
        /// </summary>
        /// <param name="gr">  the target RGraph
        /// </param>
        /// <param name="ac1"> description of the first molecule
        /// </param>
        /// <param name="ac2"> description of the second molecule
        /// </param>
        private static void nodeConstructor(RGraph gr, IAtomContainer ac1, IAtomContainer ac2)
        {
            // resets the target graph.
            gr.clear();
            IBond[] bondsA1 = ac1.Bonds;
            IBond[] bondsA2 = ac2.Bonds;

            // compares each bond of G1 to each bond of G2
            for (int i = 0; i < bondsA1.Length; i++)
            {
                for (int j = 0; j < bondsA2.Length; j++)
                {
                    if (timeout > -1 && ((System.DateTime.Now.Ticks - 621355968000000000) / 10000 - start) > timeout)
                        throw new CDKException("Timeout exceeded in getOverlaps");
                    IBond bondA2 = bondsA2[j];
                    if (bondA2 is IQueryBond)
                    {
                        IQueryBond queryBond = (IQueryBond)bondA2;
                        IQueryAtom atom1 = (IQueryAtom)(bondA2.getAtomAt(0));
                        IQueryAtom atom2 = (IQueryAtom)(bondA2.getAtomAt(1));
                        IBond bond = bondsA1[i];
                        if (queryBond.matches(bond))
                        {
                            // ok, bonds match
                            if (atom1.matches(bond.getAtomAt(0)) && atom2.matches(bond.getAtomAt(1)) || atom1.matches(bond.getAtomAt(1)) && atom2.matches(bond.getAtomAt(0)))
                            {
                                // ok, atoms match in either order
                                gr.addNode(new RNode(i, j));
                            }
                        }
                    }
                    else
                    {
                        // if both bonds are compatible then create an association node
                        // in the resolution graph
                        if (((bondsA1[i].Order == bondsA2[j].Order && bondsA1[i].getFlag(CDKConstants.ISAROMATIC) == bondsA2[j].getFlag(CDKConstants.ISAROMATIC)) || (bondsA1[i].getFlag(CDKConstants.ISAROMATIC) && bondsA2[j].getFlag(CDKConstants.ISAROMATIC))) && ((bondsA1[i].getAtomAt(0).Symbol.Equals(bondsA2[j].getAtomAt(0).Symbol) && bondsA1[i].getAtomAt(1).Symbol.Equals(bondsA2[j].getAtomAt(1).Symbol)) || (bondsA1[i].getAtomAt(0).Symbol.Equals(bondsA2[j].getAtomAt(1).Symbol) && bondsA1[i].getAtomAt(1).Symbol.Equals(bondsA2[j].getAtomAt(0).Symbol))))
                        {
                            gr.addNode(new RNode(i, j));
                        }
                    }
                }
            }
        }
        /// <summary>  Build edges of the RGraphs
        /// This method create the edge of the RGraph and
        /// calculates the incompatibility and neighbourhood
        /// relationships between RGraph nodes.
        /// 
        /// </summary>
        /// <param name="gr">  the rGraph
        /// </param>
        /// <param name="ac1"> Description of the first molecule
        /// </param>
        /// <param name="ac2"> Description of the second molecule
        /// </param>
        private static void arcConstructor(RGraph gr, IAtomContainer ac1, IAtomContainer ac2)
        {
            // each node is incompatible with himself
            for (int i = 0; i < gr.Graph.Count; i++)
            {
                RNode x = (RNode)gr.Graph[i];
                SupportClass.BitArraySupport.Set(x.Forbidden, i);
            }

            IBond a1;
            IBond a2;
            IBond b1;
            IBond b2;

            IBond[] bondsA1 = ac1.Bonds;
            IBond[] bondsA2 = ac2.Bonds;

            gr.FirstGraphSize = ac1.getBondCount();
            gr.SecondGraphSize = ac2.getBondCount();

            for (int i = 0; i < gr.Graph.Count; i++)
            {
                RNode x = (RNode)gr.Graph[i];

                // two nodes are neighbours if their adjacency
                // relationship in are equivalent in G1 and G2
                // else they are incompatible.
                for (int j = i + 1; j < gr.Graph.Count; j++)
                {
                    if (timeout > -1 && ((System.DateTime.Now.Ticks - 621355968000000000) / 10000 - start) > timeout)
                        throw new CDKException("Timeout exceeded in getOverlaps");
                    RNode y = (RNode)gr.Graph[j];

                    a1 = bondsA1[((RNode)gr.Graph[i]).RMap.Id1];
                    a2 = bondsA2[((RNode)gr.Graph[i]).RMap.Id2];
                    b1 = bondsA1[((RNode)gr.Graph[j]).RMap.Id1];
                    b2 = bondsA2[((RNode)gr.Graph[j]).RMap.Id2];

                    if (a2 is IQueryBond)
                    {
                        if (a1.Equals(b1) || a2.Equals(b2) || !queryAdjacency(a1, b1, a2, b2))
                        {
                            SupportClass.BitArraySupport.Set(x.Forbidden, j);
                            SupportClass.BitArraySupport.Set(y.Forbidden, i);
                        }
                        else if (hasCommonAtom(a1, b1))
                        {
                            SupportClass.BitArraySupport.Set(x.Extension, j);
                            SupportClass.BitArraySupport.Set(y.Extension, i);
                        }
                    }
                    else
                    {
                        if (a1.Equals(b1) || a2.Equals(b2) || (!getCommonSymbol(a1, b1).Equals(getCommonSymbol(a2, b2))))
                        {
                            SupportClass.BitArraySupport.Set(x.Forbidden, j);
                            SupportClass.BitArraySupport.Set(y.Forbidden, i);
                        }
                        else if (hasCommonAtom(a1, b1))
                        {
                            SupportClass.BitArraySupport.Set(x.Extension, j);
                            SupportClass.BitArraySupport.Set(y.Extension, i);
                        }
                    }
                }
            }
        }
        //////////////////////////////////////////////////
        //          Internal methods

        /// <summary>  Builds the RGraph ( resolution graph ), from two atomContainer
        /// (description of the two molecules to compare)
        /// This is the interface point between the CDK model and
        /// the generic MCSS algorithm based on the RGRaph.
        /// 
        /// </summary>
        /// <param name="g1"> Description of the first molecule
        /// </param>
        /// <param name="g2"> Description of the second molecule
        /// </param>
        /// <returns>     the rGraph
        /// </returns>
        public static RGraph buildRGraph(IAtomContainer g1, IAtomContainer g2)
        {
            RGraph rGraph = new RGraph();
            nodeConstructor(rGraph, g1, g2);
            arcConstructor(rGraph, g1, g2);
            return rGraph;
        }