Logo Search packages:      
Sourcecode: cdk version File versions

GeometryTools.java

/*
 *  $RCSfile$
 *  $Author: egonw $
 *  $Date: 2007-08-28 11:23:21 +0200 (Tue, 28 Aug 2007) $
 *  $Revision: 8737 $
 *
 *  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.geometry;

import org.openscience.cdk.interfaces.*;
import org.openscience.cdk.tools.LoggingTool;
import org.openscience.cdk.tools.manipulator.ChemModelManipulator;

import javax.vecmath.Point2d;
import javax.vecmath.Vector2d;
import java.awt.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

/**
 * A set of static utility classes for geometric calculations and operations.
 * This class is extensively used, for example, by JChemPaint to edit molecule.
 * All methods in this class use an external set of coordinates (e. g. from the rendererModel). If you want to change the coordinates in the atoms, use GeometryToolsInternalCoordinates.
 *
 * @author          Christopn Steinbeck
 * @author        seb
 * @author        Stefan Kuhn
 * @author        Egon Willighagen
 * @author        Ludovic Petain
 * @author        Christian Hoppe
 * 
 * @cdk.module    standard
 */
00057 public class GeometryTools {

      private static LoggingTool logger = new LoggingTool(GeometryTools.class);


      /**
       *  Adds an automatically calculated offset to the coordinates of all atoms
       *  such that all coordinates are positive and the smallest x or y coordinate
       *  is exactly zero, using an external set of coordinates.
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  atomCon  AtomContainer for which all the atoms are translated to
       *      positive coordinates
       *@param   renderingCoordinates  The set of coordinates to use coming from RendererModel2D
       */
00072       public static void translateAllPositive(IAtomContainer atomCon,HashMap renderingCoordinates) {
            double minX = Double.MAX_VALUE;
            double
                        minY = Double.MAX_VALUE;
            java.util.Iterator atoms = atomCon.atoms();
            while (atoms.hasNext()) {
                  IAtom atom = (IAtom)atoms.next();
                  if (renderingCoordinates.get(atom) == null && atom.getPoint2d()!=null) {
                        renderingCoordinates.put(atom,new Point2d(atom.getPoint2d().x,atom.getPoint2d().y));
                  }
                  if (renderingCoordinates.get(atom) != null) {
                        if (((Point2d)renderingCoordinates.get(atom)).x < minX) {
                              minX = ((Point2d)renderingCoordinates.get(atom)).x;
                        }
                        if (((Point2d)renderingCoordinates.get(atom)).y < minY) {
                              minY = ((Point2d)renderingCoordinates.get(atom)).y;
                        }
                  }
            }
            logger.debug("Translating: minx=" + minX + ", minY=" + minY);
            translate2D(atomCon, minX * -1, minY * -1, renderingCoordinates);
      }


      /**
       *  Translates the given molecule by the given Vector, using an external set of coordinates.
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  atomCon  The molecule to be translated
       *@param  transX   translation in x direction
       *@param  transY   translation in y direction
       *@param   renderingCoordinates  The set of coordinates to use coming from RendererModel2D
       */
00105       public static void translate2D(IAtomContainer atomCon, double transX, double transY,HashMap renderingCoordinates) {
            translate2D(atomCon, new Vector2d(transX, transY), renderingCoordinates);
      }


      /**
       *  Multiplies all the coordinates of the atoms of the given molecule with the
       *  scalefactor, using an external set of coordinates..
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  atomCon      The molecule to be scaled
       *@param  scaleFactor  Description of the Parameter
       *@param   renderingCoordinates  The set of coordinates to use coming from RendererModel2D
       */
00119       public static void scaleMolecule(IAtomContainer atomCon, double scaleFactor, HashMap renderingCoordinates) {
            for (int i = 0; i < atomCon.getAtomCount(); i++) {
                  if(renderingCoordinates.get(atomCon.getAtom(i))!=null){
                        ((Point2d)renderingCoordinates.get(atomCon.getAtom(i))).x *= scaleFactor;
                        ((Point2d)renderingCoordinates.get(atomCon.getAtom(i))).y *= scaleFactor;
                  }
            }
      }


    /**
       *  Scales a molecule such that it fills a given percentage of a given
       *  dimension, using an external set of coordinates
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  atomCon     The molecule to be scaled
       *@param  areaDim     The dimension to be filled
       *@param  fillFactor  The percentage of the dimension to be filled
       *@param   renderingCoordinates  The set of coordinates to use coming from RendererModel2D
       */
00139       public static void scaleMolecule(IAtomContainer atomCon, Dimension areaDim, double fillFactor, HashMap renderingCoordinates) {
            Dimension molDim = get2DDimension(atomCon, renderingCoordinates);
            double widthFactor = (double) areaDim.width / (double) molDim.width;
            double heightFactor = (double) areaDim.height / (double) molDim.height;
            double scaleFactor = Math.min(widthFactor, heightFactor) * fillFactor;
            scaleMolecule(atomCon, scaleFactor, renderingCoordinates);
      }


      /**
       *  Returns the java.awt.Dimension of a molecule
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  atomCon  of which the dimension should be returned
       *@return          The java.awt.Dimension of this molecule
       */
00155       public static Dimension get2DDimension(IAtomContainer atomCon, HashMap renderingCoordinates) {
            double[] minmax = getMinMax(atomCon, renderingCoordinates);
            double maxX = minmax[2];
            double
                        maxY = minmax[3];
            double
                        minX = minmax[0];
            double
                        minY = minmax[1];
            return new Dimension((int) (maxX - minX + 1), (int) (maxY - minY + 1));
      }
      
      /**
       *  Returns the java.awt.Dimension of a MoleculeSet
       *  See comment for center(IMoleculeSet setOfMolecules, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  setOfMolecules Of which the dimension should be returned
       *@return The java.awt.Dimension of this MoleculeSet
       */
00174       public static Dimension get2DDimension(IMoleculeSet setOfMolecules, HashMap renderingCoordinates) {
            double[] minmax = getMinMax(setOfMolecules, renderingCoordinates);
            double maxX = minmax[2];
            double
                        maxY = minmax[3];
            double
                        minX = minmax[0];
            double
                        minY = minmax[1];
            return new Dimension((int) (maxX - minX + 1), (int) (maxY - minY + 1));
      }


      /**
       *  Returns the minimum and maximum X and Y coordinates of the atoms in the
       *  AtomContainer. The output is returned as: <pre>
       *   minmax[0] = minX;
       *   minmax[1] = minY;
       *   minmax[2] = maxX;
       *   minmax[3] = maxY;
       * </pre>
       * See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  container  Description of the Parameter
       *@return            An four int array as defined above.
       */
00200       public static double[] getMinMax(IAtomContainer container, HashMap renderingCoordinates) {
            double maxX = Double.MIN_VALUE;
            double
                        maxY = Double.MIN_VALUE;
            double
                        minX = Double.MAX_VALUE;
            double
                        minY = Double.MAX_VALUE;
            for (int i = 0; i < container.getAtomCount(); i++) {
                  IAtom atom = container.getAtom(i);
                  if (renderingCoordinates.get(atom) != null) {
                        if (((Point2d)renderingCoordinates.get(atom)).x > maxX) {
                              maxX = ((Point2d)renderingCoordinates.get(atom)).x;
                        }
                        if (((Point2d)renderingCoordinates.get(atom)).x < minX) {
                              minX = ((Point2d)renderingCoordinates.get(atom)).x;
                        }
                        if (((Point2d)renderingCoordinates.get(atom)).y > maxY) {
                              maxY = ((Point2d)renderingCoordinates.get(atom)).y;
                        }
                        if (((Point2d)renderingCoordinates.get(atom)).y < minY) {
                              minY = ((Point2d)renderingCoordinates.get(atom)).y;
                        }
                  }
            }
            double[] minmax = new double[4];
            minmax[0] = minX;
            minmax[1] = minY;
            minmax[2] = maxX;
            minmax[3] = maxY;
            return minmax;
      }
      
      /**
       *  Returns the minimum and maximum X and Y coordinates of the molecules in the
       *  MoleculeSet. The output is returned as: <pre>
       *   minmax[0] = minX;
       *   minmax[1] = minY;
       *   minmax[2] = maxX;
       *   minmax[3] = maxY;
       * </pre>
       * See comment for center(IMoleculeSet setOfMolecules, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@return            An four int array as defined above.
       */
00245       public static double[] getMinMax(IMoleculeSet setOfMolecules, HashMap renderingCoordinates) {
            double maxX = Double.MIN_VALUE;
            double
                        maxY = Double.MIN_VALUE;
            double
                        minX = Double.MAX_VALUE;
            double
                        minY = Double.MAX_VALUE;
            for(int j = 0; j < setOfMolecules.getAtomContainerCount() ; j++){
                  IAtomContainer container = setOfMolecules.getAtomContainer(j);
                  for (int i = 0; i < container.getAtomCount(); i++) {
                        IAtom atom = container.getAtom(i);
                        if (renderingCoordinates.get(atom) != null) {
                              if (((Point2d)renderingCoordinates.get(atom)).x > maxX) {
                                    maxX = ((Point2d)renderingCoordinates.get(atom)).x;
                              }
                              if (((Point2d)renderingCoordinates.get(atom)).x < minX) {
                                    minX = ((Point2d)renderingCoordinates.get(atom)).x;
                              }
                              if (((Point2d)renderingCoordinates.get(atom)).y > maxY) {
                                    maxY = ((Point2d)renderingCoordinates.get(atom)).y;
                              }
                              if (((Point2d)renderingCoordinates.get(atom)).y < minY) {
                                    minY = ((Point2d)renderingCoordinates.get(atom)).y;
                              }
                        }
                  }
            }
            double[] minmax = new double[4];
            minmax[0] = minX;
            minmax[1] = minY;
            minmax[2] = maxX;
            minmax[3] = maxY;
            return minmax;
      }


      /**
       *  Translates a molecule from the origin to a new point denoted by a vector, using an external set of coordinates.
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  atomCon  molecule to be translated
       *@param  vector   dimension that represents the translation vector
       *@param   renderingCoordinates  The set of coordinates to use coming from RendererModel2D
       */
00290       public static void translate2D(IAtomContainer atomCon, Vector2d vector, HashMap renderingCoordinates) {
            java.util.Iterator atoms = atomCon.atoms();
            while (atoms.hasNext()) {
                  IAtom atom = (IAtom)atoms.next();
                  if (renderingCoordinates.get(atom) == null && atom.getPoint2d()!=null) {
                        renderingCoordinates.put(atom,new Point2d(atom.getPoint2d().x,atom.getPoint2d().y));
                  }
                  if (renderingCoordinates.get(atom) != null) {
                        ((Point2d)renderingCoordinates.get(atom)).add(vector);
                  } else {
                        logger.warn("Could not translate atom in 2D space");
                  }
            }
      }
      
      /**
       *  Translates a molecule from the origin to a new point denoted by a vector.
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  atomCon  molecule to be translated
       *@param  p        Description of the Parameter
       */
00312       public static void translate2DCentreOfMassTo(IAtomContainer atomCon, Point2d p, HashMap renderingCoordinates) {
            Point2d com = get2DCentreOfMass(atomCon, renderingCoordinates);
            Vector2d translation = new Vector2d(p.x - com.x, p.y - com.y);
            java.util.Iterator atoms = atomCon.atoms();
            while (atoms.hasNext()) {
                  IAtom atom = (IAtom)atoms.next();
                  if (renderingCoordinates.get(atom) != null) {
                        ((Point2d)renderingCoordinates.get(atom)).add(translation);
                  }
            }
      }

      
      /**
       *  Translates the geometric 2DCenter of the given
       *  AtomContainer container to the specified Point2d p.
       *
       *@param  container  AtomContainer which should be translated.
       *@param  p          New Location of the geometric 2D Center.
       *@see #get2DCenter
       *@see #translate2DCentreOfMassTo
       */
00334       public static void translate2DCenterTo(IAtomContainer container, Point2d p, HashMap renderingCoordinates) {
            Point2d com = get2DCenter(container, renderingCoordinates);
            Vector2d translation = new Vector2d(p.x - com.x, p.y - com.y);
            java.util.Iterator atoms = container.atoms();
            while (atoms.hasNext()) {
                  IAtom atom = (IAtom)atoms.next();
                  if (renderingCoordinates.get(atom) != null) {
                        ((Point2d)renderingCoordinates.get(atom)).add(translation);
                  }
            }
      }
      
      /**
       *  Calculates the center of mass for the <code>Atom</code>s in the
       *  AtomContainer for the 2D coordinates.
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  ac      AtomContainer for which the center of mass is calculated
       *@return         Description of the Return Value
       *@cdk.keyword    center of mass
       */
00355       public static Point2d get2DCentreOfMass(IAtomContainer ac, HashMap renderingCoordinates) {
            double x = 0.0;
            double y = 0.0;

            double totalmass = 0.0;

            java.util.Iterator atoms = ac.atoms();
            while (atoms.hasNext()) {
                  IAtom a = (IAtom) atoms.next();
                  double mass = a.getExactMass();
                  totalmass += mass;
                  x += mass * ((Point2d)renderingCoordinates.get(a)).x;
                  y += mass * ((Point2d)renderingCoordinates.get(a)).y;
            }

            return new Point2d(x / totalmass, y / totalmass);
      }


      /**
       *  Centers the molecule in the given area, using an external set of coordinates
       *  Attention: Many methods in this class working on coordinates exist in two versions: One with a HashMap as last parameter, one without
       *  this. The difference is as follows: The methods without the HashMap change the coordinates in the Atoms of the AtomContainer. The methods with the HashMaps
       *  expect in this HashMaps pairs of atoms and Point2ds. They work on the Point2ds associated with a particular atom and leave the atom itself
       *  unchanged. If there is no entry in the HashMap for an atom, they put the coordinates from the Atom in this HashMap and then work on the HashMap.
       *
       *
       *@param  atomCon  molecule to be centered
       *@param  areaDim  dimension in which the molecule is to be centered
       *@param   renderingCoordinates  The set of coordinates to use coming from RendererModel2D
       */
00386       public static void center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) {
            Dimension molDim = get2DDimension(atomCon, renderingCoordinates);
            int transX = (areaDim.width - molDim.width) / 2;
            int transY = (areaDim.height - molDim.height) / 2;
            translateAllPositive(atomCon,renderingCoordinates);
            translate2D(atomCon, new Vector2d(transX, transY),renderingCoordinates);
      }


      /**
       *  Calculates the center of the given atoms and returns it as a Point2d, using
       *  an external set of coordinates
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  atoms  The vector of the given atoms
       *@param   renderingCoordinates  The set of coordinates to use coming from RendererModel2D
       *@return        The center of the given atoms as Point2d
       *
       */
00405       public static Point2d get2DCenter(IAtom[] atoms, HashMap renderingCoordinates) {
            IAtom atom;
            double x = 0;
            double y = 0;
            for (int f = 0; f < atoms.length; f++) {
                  atom = atoms[f];
                  if (renderingCoordinates.get(atom) != null) {
                        x += ((Point2d)renderingCoordinates.get(atom)).x;
                        y += ((Point2d)renderingCoordinates.get(atom)).y;
                  }
            }
            return new Point2d(x / (double) atoms.length, y / (double) atoms.length);
      }


      /**
       *  Calculates the center of the given atoms and returns it as a Point2d, using
       *  an external set of coordinates
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  atoms  The Iterator of the given atoms
       *@param   renderingCoordinates  The set of coordinates to use coming from RendererModel2D
       *@return        The center of the given atoms as Point2d
       *
       */
00430       public static Point2d get2DCenter(Iterator atoms, HashMap renderingCoordinates) {
            IAtom atom;
            double x = 0;
            double y = 0;
            int length = 0;
            while (atoms.hasNext()) {
                  atom = (IAtom)atoms.next();
                  if (renderingCoordinates.get(atom) != null) {
                        x += ((Point2d)renderingCoordinates.get(atom)).x;
                        y += ((Point2d)renderingCoordinates.get(atom)).y;
                  }
                  ++length;
            }
            return new Point2d(x / (double) length, y / (double) length);
      }
      

      /**
       *  Returns the geometric center of all the atoms in the atomContainer.
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  container  Description of the Parameter
       **@param   renderingCoordinates  The set of coordinates to use coming from RendererModel2D
       *@return            the geometric center of the atoms in this atomContainer
       */
00455       public static Point2d get2DCenter(IAtomContainer container, HashMap renderingCoordinates) {
            double centerX = 0;
            double centerY = 0;
            double counter = 0;
            java.util.Iterator atoms = container.atoms();
            while (atoms.hasNext()) {
                  IAtom atom = (IAtom)atoms.next();
                  if (atom.getPoint2d() != null) {
                        centerX += ((Point2d)renderingCoordinates.get(atom)).x;
                        centerY += ((Point2d)renderingCoordinates.get(atom)).y;
                        counter++;
                  }
            }
        return new Point2d(centerX / (counter), centerY / (counter));
      }
      
      
      /**
       *  Writes the coordinates of the atoms participating the given bond into an
       *  array, using renderingCoordinates, using an external set of coordinates.
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  bond  The given bond
       *@param  renderingCoordinates  The set of coordinates to use coming from RendererModel2D
       *@return       The array with the coordinates
       */
00481       public static int[] getBondCoordinates(IBond bond, HashMap renderingCoordinates) {
            if (renderingCoordinates.get(bond.getAtom(0)) == null && bond.getAtom(0).getPoint2d()!=null) {
                  renderingCoordinates.put(bond.getAtom(0),new Point2d(bond.getAtom(0).getPoint2d().x,bond.getAtom(0).getPoint2d().y));
            }
            if (renderingCoordinates.get(bond.getAtom(1)) == null && bond.getAtom(1).getPoint2d()!=null) {
                  renderingCoordinates.put(bond.getAtom(1),new Point2d(bond.getAtom(1).getPoint2d().x,bond.getAtom(1).getPoint2d().y));
            }
            if (bond.getAtom(0).getPoint2d() == null || bond.getAtom(1).getPoint2d() == null) {
                  logger.error("getBondCoordinates() called on Bond without 2D coordinates!");
                  return new int[0];
            }
            int beginX = (int) ((Point2d)renderingCoordinates.get(bond.getAtom(0))).x;
            int endX = (int) ((Point2d)renderingCoordinates.get(bond.getAtom(1))).x;
            int beginY = (int) ((Point2d)renderingCoordinates.get(bond.getAtom(0))).y;
            int endY = (int) ((Point2d)renderingCoordinates.get(bond.getAtom(1))).y;
        return new int[]{beginX, beginY, endX, endY};
      }


    /**
     * Returns the atom of the given molecule that is closest to the given
     * coordinates, using an external set of coordinates.
     * See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
     *
     * @param xPosition            The x coordinate
     * @param yPosition            The y coordinate
     * @param renderingCoordinates The set of coordinates to use coming from RendererModel2D
     * @return The atom that is closest to the given coordinates
     */
00510     public static IAtom getClosestAtom(int xPosition, int yPosition, IChemModel model, IAtom ignore, HashMap renderingCoordinates) {
        IAtom closestAtom = null;
        IAtom currentAtom;
        double smallestMouseDistance = -1;
        double mouseDistance;
        double atomX;
        double atomY;

        List atomContainerList = ChemModelManipulator.getAllAtomContainers(model);
        Iterator iterator = atomContainerList.iterator();
        while(iterator.hasNext())
        {
            IAtomContainer ac = (IAtomContainer)iterator.next();
            for (int j = 0; j < ac.getAtomCount(); j++) {
                currentAtom = ac.getAtom(j);
                if (renderingCoordinates.get(currentAtom) == null && currentAtom.getPoint2d() != null) {
                    renderingCoordinates.put(currentAtom, new Point2d(currentAtom.getPoint2d().x, currentAtom.getPoint2d().y));
                }
                if (currentAtom != ignore && renderingCoordinates.get(currentAtom) != null) {
                    atomX = ((Point2d) renderingCoordinates.get(currentAtom)).x;
                    atomY = ((Point2d) renderingCoordinates.get(currentAtom)).y;
                    mouseDistance = Math.sqrt(Math.pow(atomX - xPosition, 2) + Math.pow(atomY - yPosition, 2));
                    if (mouseDistance < smallestMouseDistance || smallestMouseDistance == -1) {
                        smallestMouseDistance = mouseDistance;
                        closestAtom = currentAtom;
                    }
                }
            }
        }
        return closestAtom;
    }


      /**
       *  Returns the bond of the given molecule that is closest to the given
       *  coordinates.
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  xPosition  The x coordinate
       *@param  yPosition  The y coordinate
       *@param  atomCon    The molecule that is searched for the closest bond
       *@return            The bond that is closest to the given coordinates
       */
00553       public static IBond getClosestBond(int xPosition, int yPosition, IAtomContainer atomCon, HashMap renderingCoordinates) {
            Point2d bondCenter;
            IBond closestBond = null;

            double smallestMouseDistance = -1;
            double mouseDistance;
//          IBond[] bonds = atomCon.getBonds();
        Iterator bonds = atomCon.bonds();
        while (bonds.hasNext()) {
            IBond currentBond = (IBond) bonds.next();                   
                  bondCenter = get2DCenter(currentBond.atoms(),renderingCoordinates);
                  mouseDistance = Math.sqrt(Math.pow(bondCenter.x - xPosition, 2) + Math.pow(bondCenter.y - yPosition, 2));
                  if (mouseDistance < smallestMouseDistance || smallestMouseDistance == -1) {
                        smallestMouseDistance = mouseDistance;
                        closestBond = currentBond;
                  }
            }
            return closestBond;
      }


      /**
       *  Sorts a Vector of atoms such that the 2D distances of the atom locations
       *  from a given point are smallest for the first atoms in the vector
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  point  The point from which the distances to the atoms are measured
       *@param  atoms  The atoms for which the distances to point are measured
       *@param   renderingCoordinates  The set of coordinates to use coming from RendererModel2D
       */
00583       public static void sortBy2DDistance(IAtom[] atoms, Point2d point, HashMap renderingCoordinates) {
            double distance1;
            double distance2;
            IAtom atom1;
            IAtom atom2;
            boolean doneSomething;
            do {
                  doneSomething = false;
                  for (int f = 0; f < atoms.length - 1; f++) {
                        atom1 = atoms[f];
                        atom2 = atoms[f + 1];
                        if(renderingCoordinates.get(atom1)==null)
                              renderingCoordinates.put(atom1,atom1.getPoint2d());
                        if(renderingCoordinates.get(atom2)==null)
                              renderingCoordinates.put(atom2,atom2.getPoint2d());
                        distance1 = point.distance(((Point2d)renderingCoordinates.get(atom1)));
                        distance2 = point.distance(((Point2d)renderingCoordinates.get(atom2)));
                        if (distance2 < distance1) {
                              atoms[f] = atom2;
                              atoms[f + 1] = atom1;
                              doneSomething = true;
                        }
                  }
            } while (doneSomething);
      }

      
      /**
       *  Determines the scale factor for displaying a structure loaded from disk in
       *  a frame, using an external set of coordinates. An average of all bond length values is produced and a scale
       *  factor is determined which would scale the given molecule such that its
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  ac          The AtomContainer for which the ScaleFactor is to be
       *      calculated
       *@param  bondLength  The target bond length
       *@param   renderingCoordinates  The set of coordinates to use coming from RendererModel2D
       *@return             The ScaleFactor with which the AtomContainer must be
       *      scaled to have the target bond length
       */

00624       public static double getScaleFactor(IAtomContainer ac, double bondLength, HashMap renderingCoordinates) {
            java.util.Iterator atoms = ac.atoms();
            while (atoms.hasNext()) {
                  IAtom atom = (IAtom)atoms.next();
                  if (renderingCoordinates.get(atom) == null && atom.getPoint2d()!=null) {
                        renderingCoordinates.put(atom,new Point2d(atom.getPoint2d().x,atom.getPoint2d().y));
                  }
            }
            double currentAverageBondLength = getBondLengthAverage(ac,renderingCoordinates);
            if(currentAverageBondLength==0 || Double.isNaN(currentAverageBondLength))
                  return 1;
            return bondLength / currentAverageBondLength;
      }


      /**
       *  An average of all 2D bond length values is produced, using an external set of coordinates. Bonds which have
       *  Atom's with no coordinates are disregarded.
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  ac  The AtomContainer for which the average bond length is to be
       *      calculated
       *@param   renderingCoordinates  The set of coordinates to use coming from RendererModel2D
       *@return     the average bond length
       */
00649       public static double getBondLengthAverage(IAtomContainer ac, HashMap renderingCoordinates) {
            double bondLengthSum = 0;
        Iterator bonds = ac.bonds();
        int bondCounter = 0;
        while (bonds.hasNext()) {
            IBond bond = (IBond) bonds.next();
                  org.openscience.cdk.interfaces.IAtom atom1 = bond.getAtom(0);
                  org.openscience.cdk.interfaces.IAtom atom2 = bond.getAtom(1);
                  if (renderingCoordinates.get(atom1) != null &&
                              renderingCoordinates.get(atom2) != null) {
                        bondCounter++;
                        bondLengthSum += getLength2D(bond, renderingCoordinates);
                  }
            }
            return bondLengthSum / bondCounter;
      }


      /**
       *  Returns the geometric length of this bond in 2D space, using an external set of coordinates
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  bond  Description of the Parameter
       *@param   renderingCoordinates  The set of coordinates to use coming from RendererModel2D
       *@return       The geometric length of this bond
       */
00675       public static double getLength2D(IBond bond, HashMap renderingCoordinates) {
            if (bond.getAtom(0) == null ||
                        bond.getAtom(1) == null) {
                  return 0.0;
            }
            Point2d p1 = ((Point2d)renderingCoordinates.get(bond.getAtom(0)));
            Point2d p2 = ((Point2d)renderingCoordinates.get(bond.getAtom(1)));
            if (p1 == null || p2 == null) {
                  return 0.0;
            }
            return p1.distance(p2);
      }

      
      /**
       *  Determines the best alignment for the label of an atom in 2D space. It
       *  returns 1 if left aligned, and -1 if right aligned.
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  container  Description of the Parameter
       *@param  atom       Description of the Parameter
       *@return            The bestAlignmentForLabel value
       */
00698       public static int getBestAlignmentForLabel(IAtomContainer container, IAtom atom, HashMap renderingCoordinates) {
            List connectedAtoms = container.getConnectedAtomsList(atom);
            int overallDiffX = 0;
            for (int i = 0; i < connectedAtoms.size(); i++) {
                  IAtom connectedAtom = (IAtom)connectedAtoms.get(i);
                  overallDiffX = overallDiffX + (int) (((Point2d)renderingCoordinates.get(connectedAtom)).x - ((Point2d)renderingCoordinates.get(atom)).x);
            }
            if (overallDiffX <= 0) {
                  return 1;
            } else {
                  return -1;
            }
      }
      
      /**
       *  Gets the angle attribute of the GeometryTools class
       *
       *@param  xDiff  Description of the Parameter
       *@param  yDiff  Description of the Parameter
       *@return        The angle value
       */
00719       public static double getAngle(double xDiff, double yDiff) {
            return GeometryToolsInternalCoordinates.getAngle(xDiff, yDiff);
      }

      /**
       *  Gets the coordinates of two points (that represent a bond) and calculates
       *  for each the coordinates of two new points that have the given distance
       *  vertical to the bond.
       *
       *@param  coords  The coordinates of the two given points of the bond like this
       *      [point1x, point1y, point2x, point2y]
       *@param  dist    The vertical distance between the given points and those to
       *      be calculated
       *@return         The coordinates of the calculated four points
       */
00734       public static int[] distanceCalculator(int[] coords, double dist) {
            return GeometryToolsInternalCoordinates.distanceCalculator(coords, dist);
      }
      
      /**
       *  Determines if this AtomContainer contains 2D coordinates.
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  m  Description of the Parameter
       *@return    boolean indication that 2D coordinates are available
       */
00745       public static boolean has2DCoordinates(IAtomContainer m) {
            return GeometryToolsInternalCoordinates.has2DCoordinatesNew(m)>0;
      }
      
      /**
       *  Determines if this model contains 3D coordinates
       *
       *@param  ac  Description of the Parameter
       *@return    boolean indication that 3D coordinates are available
       */
00755       public static boolean has3DCoordinates(IChemModel model) {
            Iterator containers = ChemModelManipulator.getAllAtomContainers(model).iterator();
            while (containers.hasNext()) {
                  IAtomContainer ac = (IAtomContainer)containers.next();
                  boolean hasCoords = GeometryToolsInternalCoordinates.has3DCoordinates(ac); 
                  if (!hasCoords) return false; 
            }
            return true;
      }
            
      /**
       *  Determines if this model contains 3D coordinates
       *
       *@param  ac  Description of the Parameter
       *@return    boolean indication that 3D coordinates are available
       */
00771       public static boolean has3DCoordinates(IAtomContainer ac) {
            return GeometryToolsInternalCoordinates.has3DCoordinates(ac);
      }
      
      /**
       *  Determines if this AtomContainer contains 2D coordinates for some or all molecules.
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  ac  Description of the Parameter
       *@return    0 no 2d, 1=some, 2= for each atom
       */
00782       public static int has2DCoordinatesNew(IChemModel model) {
            Iterator containers = ChemModelManipulator.getAllAtomContainers(model).iterator();
            int oldCoords = -1;
            while (containers.hasNext()) {
                  IAtomContainer ac = (IAtomContainer)containers.next();
                  int hasCoords = GeometryToolsInternalCoordinates.has2DCoordinatesNew(ac); 
                  if (hasCoords == 1) return 1;
                  if (oldCoords != -1 && oldCoords != hasCoords) return 1;
                  oldCoords = hasCoords;
            }
            return oldCoords;
      }

      /**
       *  Determines if this AtomContainer contains 2D coordinates for some or all molecules.
       *  See comment for center(IAtomContainer atomCon, Dimension areaDim, HashMap renderingCoordinates) for details on coordinate sets
       *
       *@param  ac  Description of the Parameter
       *@return    0 no 2d, 1=some, 2= for each atom
       */
00802       public static int has2DCoordinatesNew(IAtomContainer ac) {
            return  GeometryToolsInternalCoordinates.has2DCoordinatesNew(ac);
      }
      
      public static void makeRenderingCoordinates(IMoleculeSet molset, HashMap renderingCoordinates){
            Iterator mols=molset.molecules();
            while(mols.hasNext()){
                  IAtomContainer ac=(IAtomContainer)mols.next();
                  java.util.Iterator atoms = ac.atoms();
                  while (atoms.hasNext()) {
                        IAtom atom = (IAtom)atoms.next();
                        renderingCoordinates.put(atom,new Point2d(atom.getPoint2d().x,atom.getPoint2d().y));
                  }
            }
      }
}



Generated by  Doxygen 1.6.0   Back to index