⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atomplacer.java

📁 化学图形处理软件
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*  $RCSfile$ *  $Author: egonw $ *  $Date: 2007-08-28 11:23:21 +0200 (Tue, 28 Aug 2007) $ *  $Revision: 8737 $ * *  Copyright (C) 2003-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.Comparator;import java.util.HashMap;import java.util.Vector;import javax.vecmath.Point2d;import javax.vecmath.Vector2d;import org.openscience.cdk.CDKConstants;import org.openscience.cdk.geometry.BondTools;import org.openscience.cdk.geometry.GeometryTools;import org.openscience.cdk.geometry.GeometryToolsInternalCoordinates;import org.openscience.cdk.graph.PathTools;import org.openscience.cdk.graph.matrix.ConnectionMatrix;import org.openscience.cdk.interfaces.IAtom;import org.openscience.cdk.interfaces.IAtomContainer;import org.openscience.cdk.interfaces.IBond;import org.openscience.cdk.interfaces.IMolecule;//removed during debugging. Before you put this in again, contact// er@doktor-steinbeck.de//import org.openscience.cdk.tools.HydrogenAdder;import org.openscience.cdk.tools.LoggingTool;import org.openscience.cdk.tools.manipulator.AtomContainerManipulator;/** *  Methods for generating coordinates for atoms in various situations. They can *  be used for Automated Structure Diagram Generation or in the interactive *  buildup of molecules by the user. * *@author      steinbeck *@cdk.created 2003-08-29 *@cdk.module  sdg */public class AtomPlacer{    public final static boolean debug = true;    private static LoggingTool logger = new LoggingTool(AtomPlacer.class);    /**     *  The molecule to be laid out. To be assigned from outside     */     IAtomContainer molecule = null;    final  Comparator ATOM_ORDER =        new Comparator()        {            public int compare(Object o1, Object o2)            {                IAtom a1 = (IAtom) o1;                IAtom a2 = (IAtom) o2;                int i1 = ((Integer) a1.getProperty("Weight")).intValue();                int i2 = ((Integer) a2.getProperty("Weight")).intValue();                if (i1 < i2)                {                    return -1;                }                if (i1 == i2)                {                    return 0;                }                return 1;            }        };    /**     *  Constructor for the AtomPlacer object     */    public AtomPlacer()    {    }    /**     *  Return the molecule the AtomPlacer currently works with     *     *@return    the molecule the AtomPlacer currently works with     */    public IAtomContainer getMolecule()    {        return this.molecule;    }    /**     *  Sets the molecule the AtomPlacer currently works with     *     *@param  molecule  the molecule the AtomPlacer currently works with     */    public void setMolecule(IAtomContainer molecule)    {        this.molecule = molecule;    }    /**     *  Distribute the bonded atoms (neighbours) of an atom such that they fill the     *  remaining space around an atom in a geometrically nice way.     *  IMPORTANT: This method is not supposed to handle the     *  case of one or no place neighbor. In the case of     *  one placed neigbor, the chain placement methods     *  should be used.     *     *@param  atom                The atom whose partners are to be placed     *@param  placedNeighbours    The atoms which are already placed     *@param  unplacedNeighbours  The partners to be placed     *@param  bondLength          The standared bond length for the newly placed     *      Atoms     *@param  sharedAtomsCenter   The 2D centre of the placed Atoms     */    public void distributePartners(IAtom atom, IAtomContainer placedNeighbours, Point2d sharedAtomsCenter,            IAtomContainer unplacedNeighbours, double bondLength)    {        distributePartners(atom, placedNeighbours, sharedAtomsCenter, unplacedNeighbours, bondLength, null);    }    /**     *  Distribute the bonded atoms (neighbours) of an atom such that they fill the     *  remaining space around an atom in a geometrically nice way.     *  IMPORTANT: This method is not supposed to handle the     *  case of one or no place neighbor. In the case of     *  one placed neigbor, the chain placement methods     *  should be used.     *     *@param  atom                The atom whose partners are to be placed     *@param  placedNeighbours    The atoms which are already placed     *@param  unplacedNeighbours  The partners to be placed     *@param  bondLength          The standared bond length for the newly placed     *      Atoms     *@param  sharedAtomsCenter   The 2D centre of the placed Atoms     */    public void distributePartners(IAtom atom, IAtomContainer placedNeighbours, Point2d sharedAtomsCenter,            IAtomContainer unplacedNeighbours, double bondLength, HashMap renderingCoordinates)    {        double occupiedAngle = 0;        //double smallestDistance = Double.MAX_VALUE;        //IAtom[] nearestAtoms = new IAtom[2];        IAtom[] sortedAtoms = null;        double startAngle = 0.0;        double addAngle = 0.0;        double radius = 0.0;        double remainingAngle = 0.0;        /*         *  calculate the direction away from the already placed partners of atom         */        //Point2d sharedAtomsCenter = sharedAtoms.get2DCenter();        Vector2d sharedAtomsCenterVector = new Vector2d(sharedAtomsCenter);        Vector2d newDirection = new Vector2d(atom.getPoint2d());        if(renderingCoordinates!=null && renderingCoordinates.get(atom)!=null)            newDirection = new Vector2d((Point2d)renderingCoordinates.get(atom));        Vector2d occupiedDirection = new Vector2d(sharedAtomsCenter);        occupiedDirection.sub(newDirection);        logger.debug("distributePartners->occupiedDirection.lenght(): " + occupiedDirection.length());        Vector atomsToDraw = new Vector();        logger.debug("Number of shared atoms: ", placedNeighbours.getAtomCount());        /*         *    IMPORTANT: This method is not supposed to handle the         *    case of one or no place neighbor. In the case of         *    one placed neigbor, the chain placement methods         *    should be used.         */        if (placedNeighbours.getAtomCount() == 1)        {            logger.debug("Only one neighbour...");            for (int f = 0; f < unplacedNeighbours.getAtomCount(); f++)            {                atomsToDraw.addElement(unplacedNeighbours.getAtom(f));            }            addAngle = Math.PI * 2 / (unplacedNeighbours.getAtomCount() + placedNeighbours.getAtomCount());            /*             *  IMPORTANT: At this point we need a calculation of the             *  start angle.             *  Not done yet.             */            IAtom placedAtom = placedNeighbours.getAtom(0);//			double xDiff = atom.getX2d() - placedAtom.getX2d();//			double yDiff = atom.getY2d() - placedAtom.getY2d();            double xDiff = placedAtom.getPoint2d().x - atom.getPoint2d().x;            double yDiff = placedAtom.getPoint2d().y - atom.getPoint2d().y;            if(renderingCoordinates!=null){                if(renderingCoordinates.get(atom)==null)                    renderingCoordinates.put(atom,atom.getPoint2d());                xDiff = ((Point2d)renderingCoordinates.get(placedAtom)).x - ((Point2d)renderingCoordinates.get(atom)).x;                yDiff = ((Point2d)renderingCoordinates.get(placedAtom)).y - ((Point2d)renderingCoordinates.get(atom)).y;            }            logger.debug("distributePartners->xdiff: " + Math.toDegrees(xDiff));            logger.debug("distributePartners->ydiff: " + Math.toDegrees(yDiff));            startAngle = GeometryToolsInternalCoordinates.getAngle(xDiff, yDiff);            //- (Math.PI / 2.0);            logger.debug("distributePartners->angle: " + Math.toDegrees(startAngle));            populatePolygonCorners(atomsToDraw, new Point2d(renderingCoordinates==null ? atom.getPoint2d() : ((Point2d)renderingCoordinates.get(atom))), startAngle, addAngle, bondLength,renderingCoordinates);            return;        } else if (placedNeighbours.getAtomCount() == 0)        {            logger.debug("First atom...");            for (int f = 0; f < unplacedNeighbours.getAtomCount(); f++)            {                atomsToDraw.addElement(unplacedNeighbours.getAtom(f));            }            addAngle = Math.PI * 2.0 / unplacedNeighbours.getAtomCount();            /*             * IMPORTANT: At this point we need a calculation of the             * start angle. Not done yet.             */            startAngle = 0.0;            populatePolygonCorners(atomsToDraw, new Point2d(renderingCoordinates==null ? atom.getPoint2d() : ((Point2d)renderingCoordinates.get(atom))), startAngle, addAngle, bondLength,renderingCoordinates);            return;        }        /*         *  if the least hindered side of the atom is clearly defined (bondLength / 10 is an arbitrary value that seemed reasonable)         */        //newDirection.sub(sharedAtomsCenterVector);        sharedAtomsCenterVector.sub(newDirection);        newDirection = sharedAtomsCenterVector;        newDirection.normalize();        newDirection.scale(bondLength);        newDirection.negate();        logger.debug("distributePartners->newDirection.lenght(): " + newDirection.length());        Point2d distanceMeasure = new Point2d(atom.getPoint2d());        distanceMeasure.add(newDirection);        /*         *  get the two sharedAtom partners with the smallest distance to the new center         */        sortedAtoms = AtomContainerManipulator.getAtomArray(placedNeighbours);        if(renderingCoordinates!=null)            GeometryTools.sortBy2DDistance(sortedAtoms, distanceMeasure,renderingCoordinates);        else            GeometryToolsInternalCoordinates.sortBy2DDistance(sortedAtoms, distanceMeasure);        Vector2d closestPoint1 = new Vector2d(sortedAtoms[0].getPoint2d());        Vector2d closestPoint2 = new Vector2d(sortedAtoms[1].getPoint2d());        closestPoint1.sub(new Vector2d(atom.getPoint2d()));        closestPoint2.sub(new Vector2d(atom.getPoint2d()));        if(renderingCoordinates!=null){            GeometryTools.sortBy2DDistance(sortedAtoms, distanceMeasure, renderingCoordinates);            closestPoint1 = new Vector2d(((Point2d)renderingCoordinates.get(sortedAtoms[0])));            closestPoint2 = new Vector2d(((Point2d)renderingCoordinates.get(sortedAtoms[1])));            closestPoint1.sub(new Vector2d(((Point2d)renderingCoordinates.get(atom))));            closestPoint2.sub(new Vector2d(((Point2d)renderingCoordinates.get(atom))));        }        occupiedAngle = closestPoint1.angle(occupiedDirection);        occupiedAngle += closestPoint2.angle(occupiedDirection);        double angle1 = GeometryTools.getAngle(sortedAtoms[0].getPoint2d().x - atom.getPoint2d().x, sortedAtoms[0].getPoint2d().y - atom.getPoint2d().y);        double angle2 = GeometryTools.getAngle(sortedAtoms[1].getPoint2d().x - atom.getPoint2d().x, sortedAtoms[1].getPoint2d().y - atom.getPoint2d().y);        double angle3 = GeometryTools.getAngle(distanceMeasure.x - atom.getPoint2d().x, distanceMeasure.y - atom.getPoint2d().y);        if(renderingCoordinates!=null){            angle1 = GeometryTools.getAngle(((Point2d)renderingCoordinates.get(sortedAtoms[0])).x - ((Point2d)renderingCoordinates.get(atom)).x, ((Point2d)renderingCoordinates.get(sortedAtoms[0])).y - ((Point2d)renderingCoordinates.get(atom)).y);            angle2 = GeometryTools.getAngle(((Point2d)renderingCoordinates.get(sortedAtoms[1])).x - ((Point2d)renderingCoordinates.get(atom)).x, ((Point2d)renderingCoordinates.get(sortedAtoms[1])).y - ((Point2d)renderingCoordinates.get(atom)).y);            angle3 = GeometryTools.getAngle(distanceMeasure.x - ((Point2d)renderingCoordinates.get(atom)).x, distanceMeasure.y - ((Point2d)renderingCoordinates.get(atom)).y);        }        if (debug)        {            try            {                logger.debug("distributePartners->sortedAtoms[0]: ", (molecule.getAtomNumber(sortedAtoms[0]) + 1));                logger.debug("distributePartners->sortedAtoms[1]: ", (molecule.getAtomNumber(sortedAtoms[1]) + 1));                logger.debug("distributePartners->angle1: ", Math.toDegrees(angle1));                logger.debug("distributePartners->angle2: ", Math.toDegrees(angle2));            } catch (Exception exc) {                logger.debug(exc);            }        }        IAtom startAtom = null;        if (angle1 > angle3)        {            if (angle1 - angle3 < Math.PI)            {                startAtom = sortedAtoms[1];            } else            {                // 12 o'clock is between the two vectors                startAtom = sortedAtoms[0];            }        } else        {            if (angle3 - angle1 < Math.PI)            {                startAtom = sortedAtoms[0];            } else            {                // 12 o'clock is between the two vectors                startAtom = sortedAtoms[1];            }        }        remainingAngle = (2 * Math.PI) - occupiedAngle;        addAngle = remainingAngle / (unplacedNeighbours.getAtomCount() + 1);        if (debug)        {            try            {                logger.debug("distributePartners->startAtom: " + (molecule.getAtomNumber(startAtom) + 1));                logger.debug("distributePartners->remainingAngle: " + Math.toDegrees(remainingAngle));                logger.debug("distributePartners->addAngle: " + Math.toDegrees(addAngle));                logger.debug("distributePartners-> partners.getAtomCount(): " + unplacedNeighbours.getAtomCount());            } catch (Exception exc)            {                logger.debug(exc);            }        }        for (int f = 0; f < unplacedNeighbours.getAtomCount(); f++)        {            atomsToDraw.addElement(unplacedNeighbours.getAtom(f));        }        radius = bondLength;        startAngle = GeometryTools.getAngle(startAtom.getPoint2d().x - atom.getPoint2d().x, startAtom.getPoint2d().y - atom.getPoint2d().y);        if(renderingCoordinates!=null){            startAngle = GeometryTools.getAngle(((Point2d)renderingCoordinates.get(startAtom)).x - ((Point2d)renderingCoordinates.get(atom)).x, ((Point2d)renderingCoordinates.get(startAtom)).y - ((Point2d)renderingCoordinates.get(atom)).y);        }        logger.debug("Before check: distributePartners->startAngle: " + startAngle);//        if (startAngle < (Math.PI + 0.001) && startAngle > (Math.PI//            -0.001))//        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -