private void generateCoordinates(Vector2d firstBondVector, boolean isConnected, boolean isSubLayout) throws CDKException {

        final int numAtoms = molecule.getAtomCount();
        final int numBonds = molecule.getBondCount();
        this.firstBondVector = firstBondVector;

        // if molecule contains only one Atom, don't fail, simply set
        // coordinates to simplest: 0,0. See bug #780545
        logger.debug("Entry point of generateCoordinates()");
        logger.debug("We have a molecules with " + numAtoms + " atoms.");
        if (numAtoms == 0) {
            return;
        } 
        if (numAtoms == 1) {
            molecule.getAtom(0).setPoint2d(new Point2d(0, 0));
            return;
        } else if (molecule.getBondCount() == 1 && molecule.getAtomCount() == 2) {
            double xOffset = 0;
            for (IAtom atom : molecule.atoms()) {
                atom.setPoint2d(new Point2d(xOffset, 0));
                xOffset += bondLength;
            }
            return;
        }

        // intercept fragment molecules and lay them out in a grid
        if (!isConnected) {
            final IAtomContainerSet frags = ConnectivityChecker.partitionIntoMolecules(molecule);
            if (frags.getAtomContainerCount() > 1) {
                IAtomContainer rollback = molecule;
                generateFragmentCoordinates(molecule, toList(frags));
                // don't call set molecule as it wipes x,y coordinates!
                // this looks like a self assignment but actually the fragment
                // method changes this.molecule
                this.molecule = rollback;
                atomPlacer.setMolecule(this.molecule);
                ringPlacer.setMolecule(this.molecule);
                macroPlacer = new MacroCycleLayout(this.molecule);
                return;
            }
        }

        // initial layout seeding either from a ring system of longest chain
        seedLayout();

        // Now, do the layout of the rest of the molecule
        int iter = 0;
        for (; !AtomPlacer.allPlaced(molecule) && iter < numAtoms; iter++) {
            logger.debug("*** Start of handling the rest of the molecule. ***");
            // layout for all acyclic parts of the molecule which are
            // connected to the parts which have already been laid out.
            layoutAcyclicParts();
            // layout cyclic parts of the molecule which
            // are connected to the parts which have already been laid out.
            layoutCyclicParts();
        }

        // display reasonable error on failed layout, otherwise we'll have a NPE somewhere
        if (iter == numAtoms && !AtomPlacer.allPlaced(molecule))
            throw new CDKException("Could not generate layout? If a set of 'fixed' atoms were provided"
                                       + " try removing these and regenerating the layout.");

        if (!isSubLayout) {
            // correct double-bond stereo, this changes the layout and in reality
            // should be done during the initial placement
            if (molecule.stereoElements().iterator().hasNext())
                CorrectGeometricConfiguration.correct(molecule);
        }

        refinePlacement(molecule);
        finalizeLayout(molecule);

        // stereo must be after refinement (due to flipping!)
        if (!isSubLayout)
            assignStereochem(molecule);

    }
private void generateCoordinates ( Vector2d firstBondVector , boolean isConnected , boolean isSubLayout ) throws CDKException { final int numAtoms = molecule . getAtomCount ( ) ; final int numBonds = molecule . getBondCount ( ) ; this . firstBondVector = firstBondVector ; logger . debug ( "Entry point of generateCoordinates()" ) ; logger . debug ( "We have a molecules with " + numAtoms + " atoms." ) ; if ( numAtoms == 0 ) { return ; } if ( numAtoms == 1 ) { molecule . getAtom ( 0 ) . setPoint2d ( new Point2d ( 0 , 0 ) ) ; return ; } else if ( molecule . getBondCount ( ) == 1 && molecule . getAtomCount ( ) == 2 ) { double xOffset = 0 ; for ( IAtom atom : molecule . atoms ( ) ) { atom . setPoint2d ( new Point2d ( xOffset , 0 ) ) ; xOffset += bondLength ; } return ; } if ( ! isConnected ) { final IAtomContainerSet frags = ConnectivityChecker . partitionIntoMolecules ( molecule ) ; if ( frags . getAtomContainerCount ( ) > 1 ) { IAtomContainer rollback = molecule ; generateFragmentCoordinates ( molecule , toList ( frags ) ) ; this . molecule = rollback ; atomPlacer . setMolecule ( this . molecule ) ; ringPlacer . setMolecule ( this . molecule ) ; macroPlacer = new MacroCycleLayout ( this . molecule ) ; return ; } } seedLayout ( ) ; int iter = 0 ; for ( ; ! AtomPlacer . allPlaced ( molecule ) && iter < numAtoms ; iter ++ ) { logger . debug ( "*** Start of handling the rest of the molecule. ***" ) ; layoutAcyclicParts ( ) ; layoutCyclicParts ( ) ; } if ( iter == numAtoms && ! AtomPlacer . allPlaced ( molecule ) ) throw new CDKException ( "Could not generate layout? If a set of 'fixed' atoms were provided" + " try removing these and regenerating the layout." ) ; if ( ! isSubLayout ) { if ( molecule . stereoElements ( ) . iterator ( ) . hasNext ( ) ) CorrectGeometricConfiguration . correct ( molecule ) ; } refinePlacement ( molecule ) ; finalizeLayout ( molecule ) ; if ( ! isSubLayout ) assignStereochem ( molecule ) ; }
The main method of this StructureDiagramGenerator. Assign a molecule to the
StructureDiagramGenerator, call the generateCoordinates() method and get
your molecule back.

@param firstBondVector the vector of the first bond to lay out
@param isConnected     the 'molecule' attribute is guaranteed to be connected (we have checked)
@param isSubLayout     the 'molecule' is being laid out as part of a large collection of fragments
@throws CDKException problem occurred during layout