Package org.openscience.jchempaint.controller

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

/*
* Copyright (C) 2009 Stefan Kuhn <shk3@users.sourceforge.net>
*
* Contact: cdk-jchempaint@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 javax.vecmath.Vector2d;

import org.openscience.cdk.geometry.BondTools;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IAtomContainerSet;
import org.openscience.cdk.interfaces.IReaction;
import org.openscience.cdk.interfaces.IReactionSet;
import org.openscience.cdk.reaction.ReactionChain;
import org.openscience.cdk.tools.ILoggingTool;
import org.openscience.cdk.tools.LoggingToolFactory;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ReactionArrowModule extends ControllerModuleAdapter {

    protected static ILoggingTool logger =
            LoggingToolFactory.createLoggingTool(ReactionArrowModule.class);
    Point2d startPoint = null;
    protected String ID;

    /**
     * Constructor
     * @param chemModelRelay
     */
    public ReactionArrowModule(IChemModelRelay chemModelRelay) {
        super(chemModelRelay);
        logger.debug("constructor");
    }

    @Override
    public void mouseClickedDown(Point2d worldCoordFrom) {
        startPoint = worldCoordFrom;
    }

    @Override
    public void mouseClickedUp(Point2d endPoint) {
        //first, we get rid of the phantom arrow
        chemModelRelay.setPhantomArrow(null, null);
        chemModelRelay.updateView();
        //for each molecule, we need to look if the majority of
        // its atoms are to the left or right or on the arrow
        IAtomContainerSet moleculeSet = super.chemModelRelay.getChemModel().getMoleculeSet();
        if (moleculeSet.getAtomContainerCount() == 0 || (moleculeSet.getAtomContainerCount() == 1 && moleculeSet.getAtomContainer(0).getAtomCount() == 0)) {
            return;
        }
       
        final Vector2d unit = newUnitVector(startPoint, endPoint);
        final Vector2d perp = new Vector2d(unit.y, -unit.x);
       
        List<IAtomContainer> reactants = new ArrayList<IAtomContainer>(2);
        List<IAtomContainer> products = new ArrayList<IAtomContainer>(2);
       
        // determine the reactants and products of a reaction we do this by
        // taking the perpendicular vector and testing where atoms lie with
        // respect to the start and end of the arrow. The following diagram
        // may help visualise what the startPos and endPos values are.
        //
        // startPos < 0   startPos > 0
        //                       endPost < 0   endPost > 0
        //              ^                    ^
        //              |                    |
        //              --------------------->
        //
        for (IAtomContainer container : moleculeSet.atomContainers()) {
           
            // count the number of atoms before and after the arrow for this molecule
            int beforeStart = 0;
            int afterEnd = 0;
                      
            for (final IAtom atom : container.atoms()){
                final Point2d p = atom.getPoint2d();
               
                // sign( (Bx-Ax)*(Y-Ay) - (By-Ay)*(X-Ax) )
                final double endPos   = (perp.x) * (p.y - endPoint.y) - (perp.y) * (p.x - endPoint.x);
                final double startPos = (perp.x) * (p.y - startPoint.y) - (perp.y) * (p.x - startPoint.x);

                if (endPos > 0)
                    afterEnd++;
                if (startPos < 0)
                    beforeStart++;
            }

            if (beforeStart > afterEnd) {
                reactants.add(container);
            }
            else if (beforeStart < afterEnd) {
                products.add(container);
            } else {
                //TODO catalysts in general
            }
        }
       
        // don't create a new reaction
        if (reactants.isEmpty() && products.isEmpty())
            return;
       
        // do reaction creation
        IReactionSet reactionSet = super.chemModelRelay.getChemModel().getReactionSet();
        if (reactionSet == null) {
            reactionSet = new ReactionChain(); //reactionSet = super.chemModelRelay.getChemModel().getBuilder().newInstance(IReactionSet.class);
            super.chemModelRelay.getChemModel().setReactionSet(reactionSet);
        }
        IReaction reaction = moleculeSet.getBuilder().newInstance(IReaction.class);
        ((ReactionChain) reactionSet).addReaction(reaction, reactionSet.getReactionCount()); //reactionSet.addReaction(reaction);
        reaction.setID(ReactionHub.newReactionId(chemModelRelay));
       
        for (IAtomContainer reactant : reactants) {
            ReactionHub.makeReactantInExistingReaction((ControllerHub) super.chemModelRelay,
                                                       reaction.getID(),
                                                       cloneReactionParticipant(reactant),
                                                       reactant);
        }
        for (IAtomContainer product : products) {
            ReactionHub.makeProductInExistingReaction((ControllerHub) super.chemModelRelay,
                                                      reaction.getID(),
                                                      cloneReactionParticipant(product),
                                                      product);
        }
       
       
    }
   
    static Vector2d newUnitVector(Point2d a, Point2d b) {
        Vector2d v = new Vector2d(b.x - a.x,
                                  b.y - a.y);
        v.normalize();
        return v;
    }
   
    IAtomContainer cloneReactionParticipant(IAtomContainer org) {
        try {
            IAtomContainer cpy = (IAtomContainer) org.clone();
            if (org.getID() != null) {
                cpy.setID(org.getID());
            } else {
                cpy.setID("ac" + System.currentTimeMillis());
            }
            return cpy;
        } catch (CloneNotSupportedException e) {
            // never going to happen (should be suppressed)
            logger.error("Could not clone IAtomContainer: ", e.getMessage());
            logger.debug(e);
            throw new InternalError("Could not clone IAtomContainer: ", e);
        }
    }

    /**
     * On mouse drag, quasi-3D rotation around the center is done
     * (It isn't real 3D rotation because of truncation of transformation
     * matrix to 2x2)
     */
    @Override
    public void mouseDrag(Point2d worldCoordFrom, Point2d worldCoordTo) {
        chemModelRelay.setPhantomArrow(startPoint, worldCoordTo);
        chemModelRelay.updateView();
    }

    public String getDrawModeString() {
        return "Draw a reaction Arrow";
    }

    public String getID() {
        return ID;
    }

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

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

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.