Package org.openscience.jchempaint.controller

Source Code of org.openscience.jchempaint.controller.ChainModule

/*
* Copyright (C) 2010  Conni Wagner <conni75@users.sourceforge.net>
*               2012  Ralf Stephan <ralf@ark.in-berlin.de>
*
* 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 I ask is that proper credit is given for my 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.jchempaint.controller;

import javax.vecmath.Point2d;

import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IBond;
import org.openscience.cdk.interfaces.IChemModel;
import org.openscience.cdk.interfaces.IChemObject;
import org.openscience.cdk.interfaces.IChemObjectBuilder;
import org.openscience.cdk.tools.manipulator.ChemModelManipulator;
import org.openscience.jchempaint.renderer.JChemPaintRendererModel;
import org.openscience.jchempaint.renderer.Renderer;

/**
* Adds a bond at direction that is dragged.
*
*/
public class ChainModule extends ControllerModuleAdapter {

    Point2d start;
    Point2d dest;
    IAtom source = null;// either atom at mouse down or new atom
    IAtom merge = null;
    private double bondLength;
    private String ID;


    /**
     * Constructor for the ChainModule.
     *
     * @param chemModelRelay   The current chemModelRelay.
     */
    public ChainModule(IChemModelRelay chemModelRelay) {
        super( chemModelRelay );
    }

    private IChemObjectBuilder getBuilder() {
        return chemModelRelay.getIChemModel().getBuilder();
    }

    @Override
    public void mouseClickedDown( Point2d worldCoord ) {

        start = null;
        dest = null;
        source = null;
        bondLength = Renderer.calculateAverageBondLength( chemModelRelay.getIChemModel() );

        // in case we are starting on an empty canvas
        if(bondLength==0|| Double.isNaN(bondLength))
            bondLength=1.5;
       
        start = new Point2d(worldCoord);
        IAtom closestAtom = chemModelRelay.getClosestAtom(worldCoord);
        IBond closestBond = chemModelRelay.getClosestBond( worldCoord );

        IChemObject singleSelection = getHighlighted( worldCoord,
                                                      closestAtom,
                                                      closestBond );

        if(singleSelection instanceof IAtom ) {
            source =  (IAtom) getHighlighted(worldCoord, closestAtom);

            if(source == null) {
                source = getBuilder().newInstance(IAtom.class, chemModelRelay.getController2DModel().getDrawElement(), start );
            }
            else {
                // Take the true (x,y) of the atom, not the click point
                // otherwise it's very hard to draw a regular ring
                start = closestAtom.getPoint2d();
            }

        }
    }

  @Override
    public void mouseDrag( Point2d worldCoordFrom, Point2d worldCoordTo ) {
        chemModelRelay.clearPhantoms();
        //how many bonds do we want?
        double distance = start.distance(worldCoordTo);
        int numberofbonds = (int)(distance / (bondLength*.8660254)); // constant is sqrt(3)/4
        if(numberofbonds>0){
          //add start atom
          IAtomContainer phantoms = getBuilder().newInstance(IAtomContainer.class);
          IAtom startAtom;
          if(source==null){
            startAtom = getBuilder().newInstance(IAtom.class, chemModelRelay.getController2DModel().getDrawElement(), start );
          }else{
            startAtom=source;
          }  
          phantoms.addAtom(startAtom);
          //make atoms and bonds as needed
          for(int i=0;i<numberofbonds;i++){
            IAtom nextAtom = getBuilder().newInstance(IAtom.class, chemModelRelay.getController2DModel().getDrawElement(), new Point2d(startAtom.getPoint2d().x+bondLength, startAtom.getPoint2d().y));
            phantoms.addAtom(nextAtom);
            phantoms.addBond(getBuilder().newInstance(IBond.class, startAtom, nextAtom, IBond.Order.SINGLE));
            startAtom = nextAtom;
          }
         
          // The algorithm is 1. calc point a bondlength away in the mouse direction
          // 2. calc point rotating the above 30° down, then the same 30° up
          // 3. chain the points alternatively
            Point2d point = new Point2d(worldCoordTo);
            Point2d center = new Point2d(start);
            double dx = (point.x - center.x)/numberofbonds;
            double dy = (point.y - center.y)/numberofbonds;
            double angle = Math.PI / 6;
            double cosangle = Math.cos(angle);
            double sinangle = Math.sin(angle);
            double firstx = dx*cosangle - dy*sinangle;
            double firsty = dx*sinangle + dy*cosangle;
            double secx = dx*cosangle + dy*sinangle;
            double secy = -dx*sinangle + dy*cosangle;
        Point2d p1 = new Point2d(start);
        phantoms.getAtom(0).setPoint2d(p1);
        double currx = p1.x;
        double curry = p1.y;
            for(int i=1; i<phantoms.getAtomCount(); i++){
            Point2d p = new Point2d(currx,curry);
              if(i % 2 == 1){
                p.x += firstx;
                p.y += firsty;
              }else{
                p.x += secx;
                p.y += secy;
                }
              currx = p.x;
              curry = p.y;
            phantoms.getAtom(i).setPoint2d(p);
            }
            chemModelRelay.setPhantoms(phantoms);
            chemModelRelay.setPhantomText(""+phantoms.getAtomCount(), worldCoordTo);
            IAtom closestAtom = chemModelRelay.getClosestAtom(phantoms.getAtom(phantoms.getAtomCount()-1));
            chemModelRelay.getRenderer().getRenderer2DModel().getMerge().remove(merge);
            merge =  (IAtom) getHighlighted(phantoms.getAtom(phantoms.getAtomCount()-1).getPoint2d(), closestAtom);
            if(merge!=null){
              chemModelRelay.getRenderer().getRenderer2DModel().getMerge().put(merge,phantoms.getAtom(phantoms.getAtomCount()-1));
              chemModelRelay.getPhantoms().getConnectedBondsList(phantoms.getAtom(phantoms.getAtomCount()-1)).get(0).setAtom(merge,1);
              phantoms.removeAtom(phantoms.getAtomCount()-1);
            }
        }
        chemModelRelay.updateView();
    }

    @Override
    public void mouseClickedUp( Point2d worldCoord ) {
        JChemPaintRendererModel model = chemModelRelay.getRenderer().getRenderer2DModel();
        double d = model.getSelectionRadius() / model.getScale();
      if (start.distance(worldCoord) < 4*d)
        return;
      IAtomContainer fromContainer = null, toContainer = null;
      IChemModel chemModel = chemModelRelay.getChemModel();
      if(source != null){
      fromContainer = ChemModelManipulator.getRelevantAtomContainer(chemModel, source);
      if (chemModelRelay.getPhantoms().getAtomCount() > 0)
        chemModelRelay.getPhantoms().removeAtom(0);
      if (merge != null)
          toContainer = ChemModelManipulator.getRelevantAtomContainer(chemModel, merge);
        chemModelRelay.addFragment(getBuilder().newInstance(IAtomContainer.class,
            chemModelRelay.getPhantoms()),
            fromContainer, toContainer==fromContainer ? null : toContainer);
      } else {
      if (merge != null)
            toContainer = ChemModelManipulator.getRelevantAtomContainer(chemModel, merge);
        chemModelRelay.addFragment(getBuilder().newInstance(IAtomContainer.class,
            chemModelRelay.getPhantoms()),
            null, toContainer);
      }
        if (merge != null)
          chemModelRelay.updateAtom(merge);
    if (source != null)
      chemModelRelay.updateAtom(source);
          chemModelRelay.clearPhantoms();
          chemModelRelay.setPhantomText(null, null);
          chemModelRelay.getRenderer().getRenderer2DModel().getMerge().clear();
    }

    public String getDrawModeString() {
        return "Draw Bond Chain";
    }
   
    public String getID() {
        return ID;
    }

    public void setID(String ID) {
        this.ID=ID;
    }
}
TOP

Related Classes of org.openscience.jchempaint.controller.ChainModule

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.