@Test public void testCalculateMissingHydrogens_Aromatic() throws Exception { IAtomContainer pyrrole = MoleculeFactory.makePyrrole(); IAtom n = pyrrole.getAtom(1); IRingSet rs = (new SSSRFinder(pyrrole)).findSSSR(); IRing ring = (IRing) rs.getAtomContainer(0); for (int j = 0; j < ring.getBondCount(); j++) { ring.getBond(j).setFlag(CDKConstants.ISAROMATIC, true); } Assert.assertEquals(5, ring.getBondCount()); Assert.assertEquals(1, satcheck.calculateNumberOfImplicitHydrogens(n, pyrrole)); }
/** * Place ring with user provided angles. * * @param ring the ring to place. * @param ringCenter center coordinates of the ring. * @param bondLength given bond length. * @param startAngles a map with start angles when drawing the ring. */ public void placeRing( IRing ring, Point2d ringCenter, double bondLength, Map<Integer, Double> startAngles) { double radius = this.getNativeRingRadius(ring, bondLength); double addAngle = 2 * Math.PI / ring.getRingSize(); IAtom startAtom = ring.getFirstAtom(); Point2d p = new Point2d(ringCenter.x + radius, ringCenter.y); startAtom.setPoint2d(p); double startAngle = Math.PI * 0.5; /* Different ring sizes get different start angles to have * visually correct placement */ int ringSize = ring.getRingSize(); if (startAngles.get(ringSize) != null) startAngle = startAngles.get(ringSize); List<IBond> bonds = ring.getConnectedBondsList(startAtom); /* * Store all atoms to draw in consecutive order relative to the * chosen bond. */ Vector<IAtom> atomsToDraw = new Vector<IAtom>(); IAtom currentAtom = startAtom; IBond currentBond = (IBond) bonds.get(0); for (int i = 0; i < ring.getBondCount(); i++) { currentBond = ring.getNextBond(currentBond, currentAtom); currentAtom = currentBond.getConnectedAtom(currentAtom); atomsToDraw.addElement(currentAtom); } atomPlacer.populatePolygonCorners(atomsToDraw, ringCenter, startAngle, addAngle, radius); }
/** * Generated coordinates for a given ring, which is connected to a spiro ring. The rings share * exactly one atom. * * @param ring The ring to be placed * @param sharedAtoms The atoms of this ring, also members of another ring, which are already * placed * @param sharedAtomsCenter The geometric center of these atoms * @param ringCenterVector A vector pointing the the center of the new ring * @param bondLength The standard bondlength */ public void placeSpiroRing( IRing ring, IAtomContainer sharedAtoms, Point2d sharedAtomsCenter, Vector2d ringCenterVector, double bondLength) { logger.debug("placeSpiroRing"); double radius = getNativeRingRadius(ring, bondLength); Point2d ringCenter = new Point2d(sharedAtomsCenter); ringCenterVector.normalize(); ringCenterVector.scale(radius); ringCenter.add(ringCenterVector); double addAngle = 2 * Math.PI / ring.getRingSize(); IAtom startAtom = sharedAtoms.getAtom(0); // double centerX = ringCenter.x; // double centerY = ringCenter.y; // int direction = 1; IAtom currentAtom = startAtom; double startAngle = GeometryTools.getAngle( startAtom.getPoint2d().x - ringCenter.x, startAtom.getPoint2d().y - ringCenter.y); /* * Get one bond connected to the spiro bridge atom. * It doesn't matter in which direction we draw. */ java.util.List bonds = ring.getConnectedBondsList(startAtom); IBond currentBond = (IBond) bonds.get(0); Vector atomsToDraw = new Vector(); /* * Store all atoms to draw in consequtive order relative to the * chosen bond. */ for (int i = 0; i < ring.getBondCount(); i++) { currentBond = ring.getNextBond(currentBond, currentAtom); currentAtom = currentBond.getConnectedAtom(currentAtom); atomsToDraw.addElement(currentAtom); } logger.debug("currentAtom " + currentAtom); logger.debug("startAtom " + startAtom); atomPlacer.populatePolygonCorners(atomsToDraw, ringCenter, startAngle, addAngle, radius); }
/** * Generated coordinates for a given ring, which is fused to another ring. The rings share exactly * one bond. * * @param ring The ring to be placed * @param sharedAtoms The atoms of this ring, also members of another ring, which are already * placed * @param sharedAtomsCenter The geometric center of these atoms * @param ringCenterVector A vector pointing the the center of the new ring * @param bondLength The standard bondlength */ public void placeFusedRing( IRing ring, IAtomContainer sharedAtoms, Point2d sharedAtomsCenter, Vector2d ringCenterVector, double bondLength) { logger.debug("RingPlacer.placeFusedRing() start"); Point2d ringCenter = new Point2d(sharedAtomsCenter); double radius = getNativeRingRadius(ring, bondLength); double newRingPerpendicular = Math.sqrt(Math.pow(radius, 2) - Math.pow(bondLength / 2, 2)); ringCenterVector.normalize(); logger.debug("placeFusedRing->: ringCenterVector.length()" + ringCenterVector.length()); ringCenterVector.scale(newRingPerpendicular); ringCenter.add(ringCenterVector); IAtom bondAtom1 = sharedAtoms.getAtom(0); IAtom bondAtom2 = sharedAtoms.getAtom(1); Vector2d bondAtom1Vector = new Vector2d(bondAtom1.getPoint2d()); Vector2d bondAtom2Vector = new Vector2d(bondAtom2.getPoint2d()); Vector2d originRingCenterVector = new Vector2d(ringCenter); bondAtom1Vector.sub(originRingCenterVector); bondAtom2Vector.sub(originRingCenterVector); double occupiedAngle = bondAtom1Vector.angle(bondAtom2Vector); double remainingAngle = (2 * Math.PI) - occupiedAngle; double addAngle = remainingAngle / (ring.getRingSize() - 1); logger.debug("placeFusedRing->occupiedAngle: " + Math.toDegrees(occupiedAngle)); logger.debug("placeFusedRing->remainingAngle: " + Math.toDegrees(remainingAngle)); logger.debug("placeFusedRing->addAngle: " + Math.toDegrees(addAngle)); IAtom startAtom; double centerX = ringCenter.x; double centerY = ringCenter.y; double xDiff = bondAtom1.getPoint2d().x - bondAtom2.getPoint2d().x; double yDiff = bondAtom1.getPoint2d().y - bondAtom2.getPoint2d().y; double startAngle; ; int direction = 1; // if bond is vertical if (xDiff == 0) { logger.debug("placeFusedRing->Bond is vertical"); // starts with the lower Atom if (bondAtom1.getPoint2d().y > bondAtom2.getPoint2d().y) { startAtom = bondAtom1; } else { startAtom = bondAtom2; } // changes the drawing direction if (centerX < bondAtom1.getPoint2d().x) { direction = 1; } else { direction = -1; } } // if bond is not vertical else { // starts with the left Atom if (bondAtom1.getPoint2d().x > bondAtom2.getPoint2d().x) { startAtom = bondAtom1; } else { startAtom = bondAtom2; } // changes the drawing direction if (centerY - bondAtom1.getPoint2d().y > (centerX - bondAtom1.getPoint2d().x) * yDiff / xDiff) { direction = 1; } else { direction = -1; } } startAngle = GeometryTools.getAngle( startAtom.getPoint2d().x - ringCenter.x, startAtom.getPoint2d().y - ringCenter.y); IAtom currentAtom = startAtom; // determine first bond in Ring // int k = 0; // for (k = 0; k < ring.getElectronContainerCount(); k++) { // if (ring.getElectronContainer(k) instanceof IBond) break; // } IBond currentBond = sharedAtoms.getBond(0); Vector atomsToDraw = new Vector(); for (int i = 0; i < ring.getBondCount() - 2; i++) { currentBond = ring.getNextBond(currentBond, currentAtom); currentAtom = currentBond.getConnectedAtom(currentAtom); atomsToDraw.addElement(currentAtom); } addAngle = addAngle * direction; try { logger.debug("placeFusedRing->startAngle: " + Math.toDegrees(startAngle)); logger.debug("placeFusedRing->addAngle: " + Math.toDegrees(addAngle)); logger.debug("placeFusedRing->startAtom is: " + (molecule.getAtomNumber(startAtom) + 1)); logger.debug("AtomsToDraw: " + atomPlacer.listNumbers(molecule, atomsToDraw)); } catch (Exception exc) { logger.debug("Caught an exception while logging in RingPlacer"); } atomPlacer.populatePolygonCorners(atomsToDraw, ringCenter, startAngle, addAngle, radius); }