package com.chemhack.jsMolEditor.client.controller; import com.chemhack.jsMolEditor.client.model.Molecule; import com.chemhack.jsMolEditor.client.model.Atom; import com.chemhack.jsMolEditor.client.model.Bond; import com.chemhack.jsMolEditor.client.math.Vector2D; import com.chemhack.jsMolEditor.client.jre.emulation.java.awt.geom.Point2D; import com.chemhack.jsMolEditor.client.renderer.GeometryTools; public class MoleculePlacer { public static Point2D calcNewAtomPlace(Atom targetAtom, double bondLength) { Molecule molecule = targetAtom.getMolecule(); int neighbors = targetAtom.countNeighbors(); Point2D newPlace = new Point2D(); switch (neighbors) { case 0: newPlace.setLocation(targetAtom.getX() + bondLength, targetAtom.getY()); break; case 1: Atom onlyNeighbor = targetAtom.getNeighbors()[0]; Vector2D onlyVector = new Vector2D(onlyNeighbor.getX() - targetAtom.getX(), onlyNeighbor.getY() - targetAtom.getY()); Vector2D newVector1 = onlyVector.rotate(Math.toRadians(120))[0]; Vector2D newVector2 = onlyVector.rotate(Math.toRadians(120))[1]; Point2D moleculeCenter = GeometryTools.getGeometryCenter(molecule); Vector2D compareVector = new Vector2D(moleculeCenter.x - targetAtom.getX(), moleculeCenter.y - targetAtom.getY()); double angle1 = compareVector.angle(newVector1); double angle2 = compareVector.angle(newVector2); Vector2D newVector; newVector = (angle1 > angle2) ? newVector1 : newVector2; newVector.setLength(bondLength); newPlace.setLocation(targetAtom.getX() + newVector.x, targetAtom.getY() + newVector.y); break; case 2: Atom neighbor1 = targetAtom.getNeighbors()[0]; Atom neighbor2 = targetAtom.getNeighbors()[1]; Vector2D vector1 = new Vector2D(neighbor1.getX() - targetAtom.getX(), neighbor1.getY() - targetAtom.getY()); Vector2D vector2 = new Vector2D(neighbor2.getX() - targetAtom.getX(), neighbor2.getY() - targetAtom.getY()); vector1.normalize(); vector2.normalize(); Vector2D vector3 = new Vector2D(vector1.x + vector2.x, vector1.y + vector2.y); vector3.setLength(bondLength); newPlace.setLocation(targetAtom.getX() - vector3.x, targetAtom.getY() - vector3.y); break; default: double maxAngel = 0; Vector2D targetVector = null; for (Atom neighborD1 : targetAtom.getNeighbors()) { double currentMinAngel = Math.PI; //find out the nearest bond Vector2D currentNeighboringVector = new Vector2D(); for (Atom neighborD2 : targetAtom.getNeighbors()) { if (neighborD1 != neighborD2) { Vector2D vectorD1 = new Vector2D(neighborD1.getX() - targetAtom.getX(), neighborD1.getY() - targetAtom.getY()); Vector2D vectorD2 = new Vector2D(neighborD2.getX() - targetAtom.getX(), neighborD2.getY() - targetAtom.getY()); double currentAngel = vectorD1.angle(vectorD2); if (currentAngel < currentMinAngel) { currentMinAngel = currentAngel; currentNeighboringVector.x = vectorD1.x + vectorD2.x; currentNeighboringVector.y = vectorD1.y + vectorD2.y; currentNeighboringVector.setLength(bondLength); } } } if (currentMinAngel > maxAngel) { targetVector = currentNeighboringVector; maxAngel = currentMinAngel; } } newPlace.setLocation(targetAtom.getX() + targetVector.x, targetAtom.getY() + targetVector.y); break; } return newPlace; } public static void placeRingOnCurrentBond(Bond currentBond, double bondLength, int ringSize, boolean isBenzene) { } // public static void placeRingOnWhiteSpace(double x,double y,Molecule molecule, double bondLength, int ringSize, boolean isBenzene) { // Vector2D vector = new Vector2D(0, bondLength); // Atom targetAtom=molecule.addAtom("C",x,y,0); // System.out.println(vector); // System.out.println(targetAtom.getX()); // System.out.println(targetAtom.getY()); // doRingPlace(bondLength, ringSize, isBenzene, molecule, vector, targetAtom); // } public static void placeRingOnCurrentAtom(Atom targetAtom, double bondLength, int ringSize, boolean isBenzene) { Vector2D vector = new Vector2D(0, -1); doRingPlace(bondLength, ringSize, isBenzene, targetAtom.getMolecule(), vector, targetAtom); } public static void placeRingOnCurrentAtom(Atom targetAtom, double bondLength, int ringSize, boolean isBenzene, Atom lastAtom) { Vector2D vector = new Vector2D(targetAtom.getX() - lastAtom.getX(), targetAtom.getY() - lastAtom.getY()); doRingPlace(bondLength, ringSize, isBenzene, targetAtom.getMolecule(), vector, targetAtom); } public static Atom placeNewRing(Atom targetAtom, double bondLength, int ringSize, boolean isBenzene) { Point2D firtAtomPlace = calcNewAtomPlace(targetAtom, bondLength); Point2D targetAtomPlace = new Point2D(targetAtom.getX(), targetAtom.getY()); Molecule molecule = targetAtom.getMolecule(); Vector2D vector = new Vector2D(firtAtomPlace.x - targetAtomPlace.x, firtAtomPlace.y - targetAtomPlace.y); Atom firstRingAtom = molecule.addAtom("C", firtAtomPlace.x, firtAtomPlace.y, 0); doRingPlace(bondLength, ringSize, isBenzene, molecule, vector, firstRingAtom); return firstRingAtom; } private static void doRingPlace(double bondLength, int ringSize, boolean isBenzene, Molecule molecule, Vector2D vector, Atom firstRingAtom) { double radical = (bondLength / 2) / (Math.sin(Math.toRadians(180 / ringSize))); vector.setLength(radical); Point2D ringCenter = new Point2D(firstRingAtom.getX() + vector.x, firstRingAtom.getY() + vector.y); Vector2D reverseVector = new Vector2D(-vector.x, -vector.y); int bondOrder = 1; Atom lastAtom = firstRingAtom; for (int i = 1; i < ringSize; i++) { double angle = i * ((double) 360) / ringSize; Vector2D turnedVector; if (angle < 180) { turnedVector = reverseVector.rotate(Math.toRadians(angle))[0]; } else if (angle > 180) { turnedVector = reverseVector.rotate(Math.toRadians(360 - angle))[1]; } else { turnedVector = vector; } turnedVector.setLength(radical); Atom newAtom = molecule.addAtom("C", ringCenter.x + turnedVector.x, ringCenter.y + turnedVector.y, 0); molecule.connect(lastAtom, newAtom, bondOrder); lastAtom = newAtom; if (isBenzene) { bondOrder = bondOrder == 1 ? 2 : 1; } } molecule.connect(lastAtom, firstRingAtom, bondOrder); } }