// more attractive and avoid tilted rings
//
Map<IAtom, IAtom> mergeMap = model.getMerge();
it = model.getMerge().keySet().iterator();
if (it.hasNext()) {
IAtomContainer movedAtomContainer = renderer.getRenderer2DModel()
.getSelection().getConnectedAtomContainer();
if (movedAtomContainer != null) {
IAtom atomA = (IAtom) it.next();
IAtom atomB = mergeMap.get(atomA);
Vector2d shift = new Vector2d();
shift.sub(atomB.getPoint2d(), atomA.getPoint2d());
for (IAtom shiftAtom : movedAtomContainer.atoms()) {
shiftAtom.getPoint2d().add(shift);
}
}
}
List<IAtom> mergedAtoms = new ArrayList<IAtom>();
List<IAtomContainer> containers = new ArrayList<IAtomContainer>();
List<IAtomContainer> droppedContainers = new ArrayList<IAtomContainer>();
List<List<IBond>> removedBondss = new ArrayList<List<IBond>>();
List<Map<IBond, Integer>> bondsWithReplacedAtoms = new ArrayList<Map<IBond, Integer>>();
List<IAtom> mergedPartnerAtoms = new ArrayList<IAtom>();
// Done shifting, now the actual merging.
it = model.getMerge().keySet().iterator();
while (it.hasNext()) {
List<IBond> removedBonds = new ArrayList<IBond>();
Map<IBond, Integer> bondsWithReplacedAtom = new HashMap<IBond, Integer>();
IAtom mergedAtom = (IAtom) it.next();
mergedAtoms.add(mergedAtom);
IAtom mergedPartnerAtom = model.getMerge().get(mergedAtom);
mergedPartnerAtoms.add(mergedPartnerAtom);
IAtomContainer container1 = ChemModelManipulator
.getRelevantAtomContainer(chemModel, mergedAtom);
containers.add(container1);
IAtomContainer container2 = ChemModelManipulator
.getRelevantAtomContainer(chemModel, mergedPartnerAtom);
// If the atoms are in different atom containers till now, we merge
// the atom containers first.
if (container1 != container2) {
container1.add(container2);
chemModel.getMoleculeSet().removeAtomContainer(container2);
droppedContainers.add(container2);
} else {
droppedContainers.add(null);
}
// Handle the case of a bond between mergedAtom and mergedPartnerAtom.
// This bond should be removed.
IBond rb = container1.getBond(mergedAtom, mergedPartnerAtom);
if (rb != null) {
container1.removeBond(rb);
removedBonds.add(rb);
}
// In the next loop we remove bonds that are redundant, that is
// to say bonds that exist on both sides of the parts to be merged
// and would cause duplicate bonding in the end result.
for (IAtom atom : container1.atoms()) {
if (!atom.equals(mergedAtom)) {
if (container1.getBond(mergedAtom, atom) != null) {
if (model.getMerge().containsKey(atom)) {
for (IAtom atom2 : container2.atoms()) {
if (!atom2.equals(mergedPartnerAtom)) {
if (container1.getBond(mergedPartnerAtom,
atom2) != null) {
if (model.getMerge().get(atom).equals(
atom2)) {
IBond redundantBond = container1
.getBond(atom, mergedAtom);
container1
.removeBond(redundantBond);
removedBonds.add(redundantBond);
}
}
}
}
}
}
}
}
removedBondss.add(removedBonds);
// After the removal of redundant bonds, the actual merge is done.
// One half of atoms in the merge map are removed and their bonds
// are mapped to their replacement atoms.
for (IBond bond : container1.bonds()) {
if (bond.contains(mergedAtom)) {
if (bond.getAtom(0).equals(mergedAtom)) {
bond.setAtom(mergedPartnerAtom, 0);
bondsWithReplacedAtom.put(bond, 0);
} else {
bond.setAtom(mergedPartnerAtom, 1);
bondsWithReplacedAtom.put(bond, 1);
}
}
}
container1.removeAtom(mergedAtom);
updateAtom(mergedPartnerAtom);
bondsWithReplacedAtoms.add(bondsWithReplacedAtom);
}
Map<Integer, Map<Integer, Integer>> oldRGroupHash = null;
Map<Integer, Map<Integer, Integer>> newRGroupHash = null;
if (rGroupHandler != null) {
try {
oldRGroupHash = rGroupHandler.makeHash();
rGroupHandler.adjustAtomContainers(chemModel.getMoleculeSet());
newRGroupHash = rGroupHandler.makeHash();
} catch (CDKException e) {
unsetRGroupHandler();
for (IAtomContainer atc : droppedContainers) {
atc.setProperty(CDKConstants.TITLE, null);
}
e.printStackTrace();
}
}
// Undo section to undo/redo the merge
IUndoRedoFactory factory = getUndoRedoFactory();
UndoRedoHandler handler = getUndoRedoHandler();
if (movedDistance != null && factory != null && handler != null) {
// we look if anything has been moved which was not merged
IAtomContainer undoRedoContainer = getIChemModel().getBuilder()
.newInstance(IAtomContainer.class);
if (renderer.getRenderer2DModel().getSelection()
.getConnectedAtomContainer() != null) {
undoRedoContainer.add(renderer.getRenderer2DModel()
.getSelection().getConnectedAtomContainer());
}
Iterator<IAtom> it2 = mergeMap.keySet().iterator();
while (it2.hasNext()) {
IAtom remove = it2.next();
undoRedoContainer.removeAtom(remove);
}
IUndoRedoable moveundoredo = getUndoRedoFactory().getMoveAtomEdit(
undoRedoContainer, movedDistance, "Move atom");
IUndoRedoable undoredo = factory.getMergeMoleculesEdit(mergedAtoms,
containers, droppedContainers, removedBondss,