📄 ringplacer.java
字号:
/* $RCSfile$ * $Author: egonw $ * $Date: 2007-08-28 11:16:54 +0200 (Tue, 28 Aug 2007) $ * $Revision: 8733 $ * * Copyright (C) 1997-2007 The Chemistry Development Kit (CDK) project * * Contact: cdk-devel@lists.sourceforge.net * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * All we ask is that proper credit is given for our work, which includes * - but is not limited to - adding the above copyright notice to the beginning * of your source code files, and to any copyright notice that you may distribute * with programs based on this work. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * */package org.openscience.cdk.layout;import java.util.Iterator;import java.util.List;import java.util.Vector;import javax.vecmath.Point2d;import javax.vecmath.Vector2d;import org.openscience.cdk.CDKConstants;import org.openscience.cdk.geometry.GeometryToolsInternalCoordinates;import org.openscience.cdk.interfaces.IAtom;import org.openscience.cdk.interfaces.IAtomContainer;import org.openscience.cdk.interfaces.IBond;import org.openscience.cdk.interfaces.IMolecule;import org.openscience.cdk.interfaces.IRing;import org.openscience.cdk.interfaces.IRingSet;import org.openscience.cdk.tools.LoggingTool;import org.openscience.cdk.tools.manipulator.AtomContainerManipulator;/** * Class providing methods for generating coordinates for ring atoms. * Various situations are supported, like condensation, spiro-attachment, etc. * They can be used for Automated Structure Diagram Generation or in the interactive * buildup of ringsystems by the user. * * @cdk.module sdg **/public class RingPlacer { final static boolean debug = false; private LoggingTool logger; private IMolecule molecule; private AtomPlacer atomPlacer = new AtomPlacer(); static int FUSED = 0; static int BRIDGED = 1; static int SPIRO = 2; /** * The empty constructor. */ public RingPlacer() { logger = new LoggingTool(this); } /** * Generated coordinates for a given ring. Multiplexes to special handlers * for the different possible situations (spiro-, fusion-, bridged attachement) * * @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 placeRing(IRing ring, IAtomContainer sharedAtoms, Point2d sharedAtomsCenter, Vector2d ringCenterVector, double bondLength) { int sharedAtomCount = sharedAtoms.getAtomCount(); logger.debug("placeRing -> sharedAtomCount: " + sharedAtomCount); if (sharedAtomCount > 2) { placeBridgedRing(ring, sharedAtoms, sharedAtomsCenter, ringCenterVector, bondLength); } else if (sharedAtomCount == 2) { placeFusedRing(ring, sharedAtoms, sharedAtomsCenter, ringCenterVector, bondLength); } else if (sharedAtomCount == 1) { placeSpiroRing(ring, sharedAtoms, sharedAtomsCenter, ringCenterVector, bondLength); } } /** * Positions the aliphatic substituents of a ring system * * @param rs The RingSystem for which the substituents are to be laid out * @return A list of atoms that where laid out */ public IAtomContainer placeRingSubstituents(IRingSet rs, double bondLength) { logger.debug("RingPlacer.placeRingSubstituents() start"); IRing ring = null; IAtom atom = null; IRingSet rings = null; IAtomContainer unplacedPartners = rs.getBuilder().newAtomContainer(); IAtomContainer sharedAtoms = rs.getBuilder().newAtomContainer(); IAtomContainer primaryAtoms = rs.getBuilder().newAtomContainer(); IAtomContainer treatedAtoms = rs.getBuilder().newAtomContainer(); Point2d centerOfRingGravity = null; for (int j = 0; j < rs.getAtomContainerCount(); j++) { ring = (IRing)rs.getAtomContainer(j); /* Get the j-th Ring in RingSet rs */ for (int k = 0; k < ring.getAtomCount(); k++) { unplacedPartners.removeAllElements(); sharedAtoms.removeAllElements(); primaryAtoms.removeAllElements(); atom = ring.getAtom(k); rings = rs.getRings(atom); centerOfRingGravity = GeometryToolsInternalCoordinates.get2DCenter(rings); atomPlacer.partitionPartners(atom, unplacedPartners, sharedAtoms); atomPlacer.markNotPlaced(unplacedPartners); try { for (int f = 0; f < unplacedPartners.getAtomCount(); f++) { logger.debug("placeRingSubstituents->unplacedPartners: " + (molecule.getAtomNumber(unplacedPartners.getAtom(f)) + 1)); } } catch(Exception exc) { } treatedAtoms.add(unplacedPartners); if (unplacedPartners.getAtomCount() > 0) { atomPlacer.distributePartners(atom, sharedAtoms, centerOfRingGravity, unplacedPartners, bondLength); } } } logger.debug("RingPlacer.placeRingSubstituents() end"); return treatedAtoms; } /** * Generated coordinates for a given ring, which is connected to another ring a bridged ring, * i.e. it shares more than two atoms with another ring. * * @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 */ private void placeBridgedRing(IRing ring, IAtomContainer sharedAtoms, Point2d sharedAtomsCenter, Vector2d ringCenterVector, double bondLength ) { double radius = getNativeRingRadius(ring, bondLength); Point2d ringCenter = new Point2d(sharedAtomsCenter); ringCenterVector.normalize(); logger.debug("placeBridgedRing->: ringCenterVector.length()" + ringCenterVector.length()); ringCenterVector.scale(radius); ringCenter.add(ringCenterVector); IAtom[] bridgeAtoms = getBridgeAtoms(sharedAtoms); IAtom bondAtom1 = bridgeAtoms[0]; IAtom bondAtom2 = bridgeAtoms[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() - sharedAtoms.getAtomCount() + 1); logger.debug("placeBridgedRing->occupiedAngle: " + Math.toDegrees(occupiedAngle)); logger.debug("placeBridgedRing->remainingAngle: " + Math.toDegrees(remainingAngle)); logger.debug("placeBridgedRing->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("placeBridgedRing->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 = GeometryToolsInternalCoordinates.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(); i++) { currentBond = ring.getNextBond(currentBond, currentAtom); currentAtom = currentBond.getConnectedAtom(currentAtom); if (!sharedAtoms.contains(currentAtom)) { atomsToDraw.addElement(currentAtom); } } try { logger.debug("placeBridgedRing->atomsToPlace: " + atomPlacer.listNumbers(molecule, atomsToDraw)); logger.debug("placeBridgedRing->startAtom is: " + (molecule.getAtomNumber(startAtom) + 1)); logger.debug("placeBridgedRing->startAngle: " + Math.toDegrees(startAngle)); logger.debug("placeBridgedRing->addAngle: " + Math.toDegrees(addAngle)); } catch(Exception exc) { logger.debug("Caught an exception while logging in RingPlacer"); } addAngle = addAngle * direction; 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 = GeometryToolsInternalCoordinates.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); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -