📄 atomplacer.java
字号:
// startAngle = Math.PI/placedNeighbours.getAtomCount();// } logger.debug("After check: distributePartners->startAngle: " + startAngle); populatePolygonCorners(atomsToDraw, renderingCoordinates==null ? new Point2d(atom.getPoint2d()) : ((Point2d)renderingCoordinates.get(atom)), startAngle, addAngle, radius); } /** * Places the atoms in a linear chain. Expects the first atom to be placed and * places the next atom according to initialBondVector. The rest of the chain * is placed such that it is as linear as possible (in the overall result, the * angles in the chain are set to 120 Deg.) * *@param ac The AtomContainer containing the chain atom to be * placed *@param initialBondVector The Vector indicating the direction of the first * bond *@param bondLength Description of the Parameter */ public void placeLinearChain(IAtomContainer ac, Vector2d initialBondVector, double bondLength) { IMolecule withh = ac.getBuilder().newMolecule(ac); // BUGFIX - withh does not have cloned cloned atoms, so changes are // reflected in our atom container. If we're using implicit hydrogens // the correct counts need saving and restoring int[] numh = new int[ac.getAtomCount()]; for (int i = 0, n = ac.getAtomCount(); i < n; i ++) { numh[i] = ac.getAtom(i).getHydrogenCount(); }// SDG should lay out what it gets and not fiddle with molecules// during layout so this was // removed during debugging. Before you put this in again, contact// er@doktor-steinbeck.de // if(GeometryTools.has2DCoordinatesNew(ac)==2){// try{// new HydrogenAdder().addExplicitHydrogensToSatisfyValency(withh);// }catch(Exception ex){// logger.warn("Exception in hydrogen adding. This could mean that cleanup does not respect E/Z: ", ex.getMessage());// logger.debug(ex);// }// new HydrogenPlacer().placeHydrogens2D(withh, bondLength);// } logger.debug("Placing linear chain of length " + ac.getAtomCount()); Vector2d bondVector = initialBondVector; IAtom atom = null; Point2d atomPoint = null; IAtom nextAtom = null; for (int f = 0; f < ac.getAtomCount() - 1; f++) { atom = ac.getAtom(f); nextAtom = ac.getAtom(f + 1); atomPoint = new Point2d(atom.getPoint2d()); bondVector.normalize(); bondVector.scale(bondLength); atomPoint.add(bondVector); nextAtom.setPoint2d(atomPoint); nextAtom.setFlag(CDKConstants.ISPLACED, true); boolean trans=false; if(GeometryTools.has2DCoordinatesNew(ac)==2){ try{ if(f>2 && BondTools.isValidDoubleBondConfiguration(withh,withh.getBond(withh.getAtom(f-2),withh.getAtom(f-1)))){ trans=BondTools.isCisTrans(withh.getAtom(f-3),withh.getAtom(f-2),withh.getAtom(f-1),withh.getAtom(f-0),withh); } }catch(Exception ex){ logger.debug("Excpetion in detecting E/Z. This could mean that cleanup does not respect E/Z"); } bondVector = getNextBondVector(nextAtom, atom, GeometryToolsInternalCoordinates.get2DCenter(molecule),trans); }else{ bondVector = getNextBondVector(nextAtom, atom, GeometryToolsInternalCoordinates.get2DCenter(molecule),true); } } // BUGFIX part 2 - restore hydrogen counts for (int i = 0, n = ac.getAtomCount(); i < n; i ++) { ac.getAtom(i).setHydrogenCount(numh[i]); } } /** * Returns the next bond vector needed for drawing an extended linear chain of * atoms. It assumes an angle of 120 deg for a nice chain layout and * calculates the two possible placments for the next atom. It returns the * vector pointing farmost away from a given start atom. * *@param atom An atom for which the vector to the next atom to * draw is calculated *@param previousAtom The preceding atom for angle calculation *@param distanceMeasure A point from which the next atom is to be farmost * away *@param trans if true E (trans) configurations are built, false makes Z (cis) configurations *@return A vector pointing to the location of the next atom * to draw */ public Vector2d getNextBondVector(IAtom atom, IAtom previousAtom, Point2d distanceMeasure, boolean trans) { if (logger.isDebugEnabled()) { logger.debug("Entering AtomPlacer.getNextBondVector()"); logger.debug("Arguments are atom: " + atom + ", previousAtom: " + previousAtom + ", distanceMeasure: " + distanceMeasure); } double angle = GeometryTools.getAngle(previousAtom.getPoint2d().x - atom.getPoint2d().x, previousAtom.getPoint2d().y - atom.getPoint2d().y); double addAngle = Math.toRadians(120); if(!trans) addAngle=Math.toRadians(60); if (shouldBeLinear(atom, molecule)) addAngle = Math.toRadians(180); angle += addAngle; Vector2d vec1 = new Vector2d(Math.cos(angle), Math.sin(angle)); Point2d point1 = new Point2d(atom.getPoint2d()); point1.add(vec1); double distance1 = point1.distance(distanceMeasure); angle += addAngle; Vector2d vec2 = new Vector2d(Math.cos(angle), Math.sin(angle)); Point2d point2 = new Point2d(atom.getPoint2d()); point2.add(vec2); double distance2 = point2.distance(distanceMeasure); if (distance2 > distance1) { logger.debug("Exiting AtomPlacer.getNextBondVector()"); return vec2; } logger.debug("Exiting AtomPlacer.getNextBondVector()"); return vec1; } /** * Populates the corners of a polygon with atoms. Used to place atoms in a * geometrically regular way around a ring center or another atom. If this is * used to place the bonding partner of an atom (and not to draw a ring) we * want to place the atoms such that those with highest "weight" are placed * farmost away from the rest of the molecules. The "weight" mentioned here is * calculated by a modified morgan number algorithm. * *@param atomsToDraw All the atoms to draw *@param startAngle A start angle, giving the angle of the most clockwise * atom which has already been placed *@param addAngle An angle to be added to startAngle for each atom from * atomsToDraw *@param rotationCenter The center of a ring, or an atom for which the * partners are to be placed *@param radius The radius of the polygon to be populated: bond * length or ring radius */ public void populatePolygonCorners(Vector atomsToDraw, Point2d rotationCenter, double startAngle, double addAngle, double radius) { IAtom connectAtom = null; double angle = startAngle; double newX; double newY; double x; double y; logger.debug("populatePolygonCorners->startAngle: ", Math.toDegrees(angle)); Vector points = new Vector(); //IAtom atom = null; logger.debug(" centerX:", rotationCenter.x); logger.debug(" centerY:", rotationCenter.y); logger.debug(" radius :", radius); for (int i = 0; i < atomsToDraw.size(); i++) { angle = angle + addAngle; if (angle >= 2.0 * Math.PI) { angle -= 2.0 * Math.PI; } logger.debug("populatePolygonCorners->angle: ", Math.toDegrees(angle)); x = Math.cos(angle) * radius; y = Math.sin(angle) * radius; newX = x + rotationCenter.x; newY = y + rotationCenter.y; logger.debug(" newX:", newX); logger.debug(" newY:", newY); points.addElement(new Point2d(newX, newY)); if (logger.isDebugEnabled()) try { logger.debug("populatePolygonCorners->connectAtom: " + (molecule.getAtomNumber(connectAtom) + 1) + " placed at " + connectAtom.getPoint2d()); } catch (Exception exc) { //nothing to catch here. This is just for logging } } for (int i = 0; i < atomsToDraw.size(); i++) { connectAtom = (IAtom) atomsToDraw.elementAt(i); connectAtom.setPoint2d((Point2d) points.elementAt(i)); connectAtom.setFlag(CDKConstants.ISPLACED, true); } } /** * Populates the corners of a polygon with atoms. Used to place atoms in a * geometrically regular way around a ring center or another atom. If this is * used to place the bonding partner of an atom (and not to draw a ring) we * want to place the atoms such that those with highest "weight" are placed * farmost away from the rest of the molecules. The "weight" mentioned here is * calculated by a modified morgan number algorithm. * *@param atomsToDraw All the atoms to draw *@param startAngle A start angle, giving the angle of the most clockwise * atom which has already been placed *@param addAngle An angle to be added to startAngle for each atom from * atomsToDraw *@param rotationCenter The center of a ring, or an atom for which the * partners are to be placed *@param radius The radius of the polygon to be populated: bond * length or ring radius */ public void populatePolygonCorners(Vector atomsToDraw, Point2d rotationCenter, double startAngle, double addAngle, double radius, HashMap renderingCoordinates) { IAtom connectAtom = null; double angle = startAngle; double newX; double newY; double x; double y; logger.debug("populatePolygonCorners->startAngle: ", Math.toDegrees(angle)); Vector points = new Vector(); //IAtom atom = null; logger.debug(" centerX:", rotationCenter.x); logger.debug(" centerY:", rotationCenter.y); logger.debug(" radius :", radius); for (int i = 0; i < atomsToDraw.size(); i++) { angle = angle + addAngle; if (angle >= 2.0 * Math.PI) { angle -= 2.0 * Math.PI; } logger.debug("populatePolygonCorners->angle: ", Math.toDegrees(angle)); x = Math.cos(angle) * radius; y = Math.sin(angle) * radius; newX = x + rotationCenter.x; newY = y + rotationCenter.y; logger.debug(" newX:", newX); logger.debug(" newY:", newY); points.addElement(new Point2d(newX, newY)); if (logger.isDebugEnabled()) try { logger.debug("populatePolygonCorners->connectAtom: " + (molecule.getAtomNumber(connectAtom) + 1) + " placed at " + connectAtom.getPoint2d()); } catch (Exception exc) { //nothing to catch here. This is just for logging } } for (int i = 0; i < atomsToDraw.size(); i++) { connectAtom = (IAtom) atomsToDraw.elementAt(i); if(renderingCoordinates!=null) renderingCoordinates.put(connectAtom, points.elementAt(i)); connectAtom.setPoint2d((Point2d)points.elementAt(i)); connectAtom.setFlag(CDKConstants.ISPLACED, true); } } /** * Partition the bonding partners of a given atom into placed (coordinates * assinged) and not placed. * *@param atom The atom whose bonding partners are to be * partitioned *@param unplacedPartners A vector for the unplaced bonding partners to go in *@param placedPartners A vector for the placed bonding partners to go in */ public void partitionPartners(IAtom atom, IAtomContainer unplacedPartners, IAtomContainer placedPartners) { java.util.List atoms = molecule.getConnectedAtomsList(atom); for (int i = 0; i < atoms.size(); i++) { IAtom curatom = (IAtom)atoms.get(i); if (curatom.getFlag(CDKConstants.ISPLACED)) { placedPartners.addAtom(curatom); } else { unplacedPartners.addAtom(curatom); } } } /** * Search an aliphatic molecule for the longest chain. This is the method to * be used if there are no rings in the molecule and you want to layout the * longest chain in the molecule as a starting point of the structure diagram * generation. * *@param molecule The molecule * to be search for the longest unplaced chain *@return An * AtomContainer holding the longest chain. *@exception org.openscience.cdk.exception.NoSuchAtomException Description of * the Exception */ public IAtomContainer getInitialLongestChain(IMolecule molecule) throws org.openscience.cdk.exception.CDKException { logger.debug("Start of getInitialLongestChain()"); double[][] conMat = ConnectionMatrix.getMatrix(molecule); logger.debug("Computing all-pairs-shortest-pathes"); int[][] apsp = PathTools.computeFloydAPSP(conMat); int maxPathLength = 0; int bestStartAtom = -1; int bestEndAtom = -1; IAtom atom = null; IAtom startAtom = null; //IAtom endAtom = null; for (int f = 0; f < apsp.length; f++) { atom = molecule.getAtom(f); if (molecule.getConnectedBondsCount(atom) == 1) { for (int g = 0; g < apsp.length; g++) { if (apsp[f][g] > maxPathLength) { maxPathLength = apsp[f][g]; bestStartAtom = f; bestEndAtom = g; } } } } logger.debug("Longest chaing in molecule is of length " + maxPathLength + " between atoms " + (bestStartAtom+1) + " and " + (bestEndAtom+1) ); startAtom = molecule.getAtom(bestStartAtom); //endAtom = molecule.getAtomAt(bestEndAtom); IAtomContainer path = molecule.getBuilder().newAtomContainer(); path.addAtom(startAtom); path = getLongestUnplacedChain(molecule, startAtom); //PathTools.depthFirstTargetSearch(molecule, startAtom, endAtom, path); logger.debug("End of getInitialLongestChain()"); return path; } /** * Search a molecule for the longest unplaced, aliphatic chain in it. If an * aliphatic chain encounters an unplaced ring atom, the ring atom is also
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -