stackBackup.len = visitAdj(visited, stackBackup.xs, begIdx, endIdx); final int begCnt = numFixedMoved(stackBackup.xs, stackBackup.len); if (begCnt > 0) { Arrays.fill(visited, false); stackBackup.len = visitAdj(visited, stackBackup.xs, endIdx, begIdx); final int endCnt = numFixedMoved(stackBackup.xs, stackBackup.len); if (endCnt > 0) continue; stackBackup.len = visitAdj(visited, stackBackup.xs, endIdx, begIdx); final int endCnt = numFixedMoved(stackBackup.xs, stackBackup.len); if (endCnt > 0) { Arrays.fill(visited, false); stackBackup.len = visitAdj(visited, stackBackup.xs, begIdx, endIdx); final int begCnt = numFixedMoved(stackBackup.xs, stackBackup.len); if (begCnt > 0) continue; backupCoords(backup, stackBackup); reflect(stackBackup, beg, end); congestion.update(visited, stackBackup.xs, stackBackup.len); restoreCoords(stackBackup, backup); congestion.update(visited, stackBackup.xs, stackBackup.len); congestion.score = min;
double bendScore = bend(pair, bendStack, buffer1, bendVisit); double stretchScore = stretch(pair, stretchStack, buffer2, stretchVisit); restoreCoords(bendStack, buffer1); congestion.update(bendStack.xs, bendStack.len); break; restoreCoords(stretchStack, buffer2); congestion.update(stretchStack.xs, stretchStack.len); break;
/** * Refine the 2D coordinates of a layout to reduce overlap and congestion. */ public void refine() { for (int i = 1; i <= MAX_ITERATIONS; i++) { final List<AtomPair> pairs = findCongestedPairs(); if (pairs.isEmpty()) break; final double min = congestion.score(); // rotation: flipping around sigma bonds rotate(pairs); // rotation improved, so try more rotation, we may have caused // new conflicts that can be resolved through more rotations if (congestion.score() < min) continue; // inversion: terminal atoms can be placed inside rings // which is preferable to bending or stretching invert(pairs); if (congestion.score() < min) continue; // bending or stretching: least favourable but sometimes // the only way. We try either and use the best bendOrStretch(pairs); if (congestion.score() < min) continue; break; } }
/** * Special case congestion minimisation, rotate terminals bonds around ring * systems so they are inside the ring. * * @param pairs congested atom pairs */ void invert(Collection<AtomPair> pairs) { for (AtomPair pair : pairs) { if (congestion.contribution(pair.fst, pair.snd) < MIN_SCORE) continue; if (fusionPointInversion(pair)) continue; if (macroCycleInversion(pair)) continue; } }
continue; Arrays.fill(visited, false); stackBackup.len = visit(visited, stackBackup.xs, v, idxs.get(bond.getOther(atom)), 0); perp.normalize(); double score = congestion.score(); backupCoords(backup, stackBackup); reflect(stackBackup, new Point2d(a.x - perp.y, a.y + perp.x), new Point2d(a.x + perp.y, a.y - perp.x)); congestion.update(visited, stackBackup.xs, stackBackup.len); if (percDiff(score, congestion.score()) >= IMPROVEMENT_PERC_THRESHOLD) { return true; restoreCoords(stackBackup, backup);
stack.len = visit(visited, stack.xs, endIdx, begIdx, 0); else stack.len = visit(visited, stack.xs, begIdx, endIdx, 0); backupCoords(backup, stack); if (begPriority < endPriority) stretch(stack, end, beg, pair.attempt * STRETCH_STEP); else stretch(stack, beg, end, pair.attempt * STRETCH_STEP); if (percDiff(score, congestion.score()) >= IMPROVEMENT_PERC_THRESHOLD && congestion.score() < min) { backupCoords(coords, stack); min = congestion.score(); stackBackup.copyFrom(stack); restoreCoords(stack, backup); congestion.update(visited, stack.xs, stack.len); congestion.score = score;
LayoutRefiner refiner = new LayoutRefiner(molecule, afix, bfix); refiner.refine();
if (contribution >= MIN_SCORE || contribution >= maybeCrossed && haveCrossingBonds(u, v)) { makeAtmBndQueues(path, seqAt, bndAt);
/** * Check if any of the bonds adjacent to u, v (not bonded) are crossing. * * @param u an atom (idx) * @param v another atom (idx) * @return there are crossing bonds */ private boolean haveCrossingBonds(int u, int v) { int[] us = adjList[u]; int[] vs = adjList[v]; for (int u1 : us) { for (int v1 : vs) { if (u1 == v || v1 == u || u1 == v1) continue; if (isCrossed(atoms[u].getPoint2d(), atoms[u1].getPoint2d(), atoms[v].getPoint2d(), atoms[v1].getPoint2d())) return true; } } return false; }
/** * Internal - makes atom (seq) and bond priority queues for resolving * overlap. Only (acyclic - but not really) atoms and bonds in the shortest * path between the two atoms can resolve an overlap. We create prioritised * sequences of atoms/bonds where the more central in the shortest path. * * @param path shortest path between atoms * @param seqAt prioritised atoms, first atom is the middle of the path * @param bndAt prioritised bonds, first bond is the middle of the path */ private void makeAtmBndQueues(int[] path, int[] seqAt, IBond[] bndAt) { int len = path.length; int i = (len - 1) / 2; int j = i + 1; int nSeqAt = 0; int nBndAt = 0; if (isOdd((path.length))) { seqAt[nSeqAt++] = path[i--]; bndAt[nBndAt++] = bondMap.get(path[j], path[j - 1]); } bndAt[nBndAt++] = bondMap.get(path[i], path[i + 1]); while (i > 0 && j < len - 1) { seqAt[nSeqAt++] = path[i--]; seqAt[nSeqAt++] = path[j++]; bndAt[nBndAt++] = bondMap.get(path[i], path[i + 1]); bndAt[nBndAt++] = bondMap.get(path[j], path[j - 1]); } }
continue; Arrays.fill(visited, false); stackBackup.len = visit(visited, stackBackup.xs, v, idxs.get(bond.getOther(atom)), 0); perp.normalize(); double score = congestion.score(); backupCoords(backup, stackBackup); reflect(stackBackup, new Point2d(a.x - perp.y, a.y + perp.x), new Point2d(a.x + perp.y, a.y - perp.x)); congestion.update(visited, stackBackup.xs, stackBackup.len); if (percDiff(score, congestion.score()) >= IMPROVEMENT_PERC_THRESHOLD) { return true; restoreCoords(stackBackup, backup);
stack.len = visit(visited, stack.xs, endIdx, begIdx, 0); else stack.len = visit(visited, stack.xs, begIdx, endIdx, 0); backupCoords(backup, stack); if (begPriority < endPriority) stretch(stack, end, beg, pair.attempt * STRETCH_STEP); else stretch(stack, beg, end, pair.attempt * STRETCH_STEP); if (percDiff(score, congestion.score()) >= IMPROVEMENT_PERC_THRESHOLD && congestion.score() < min) { backupCoords(coords, stack); min = congestion.score(); stackBackup.copyFrom(stack); restoreCoords(stack, backup); congestion.update(visited, stack.xs, stack.len); congestion.score = score;
/** * Special case congestion minimisation, rotate terminals bonds around ring * systems so they are inside the ring. * * @param pairs congested atom pairs */ void invert(Collection<AtomPair> pairs) { for (AtomPair pair : pairs) { if (congestion.contribution(pair.fst, pair.snd) < MIN_SCORE) continue; if (fusionPointInversion(pair)) continue; if (macroCycleInversion(pair)) continue; } }
LayoutRefiner refiner = new LayoutRefiner(molecule, afix, bfix); refiner.refine();
if (contribution >= MIN_SCORE || contribution >= maybeCrossed && haveCrossingBonds(u, v)) { makeAtmBndQueues(path, seqAt, bndAt);
/** * Check if any of the bonds adjacent to u, v (not bonded) are crossing. * * @param u an atom (idx) * @param v another atom (idx) * @return there are crossing bonds */ private boolean haveCrossingBonds(int u, int v) { int[] us = adjList[u]; int[] vs = adjList[v]; for (int u1 : us) { for (int v1 : vs) { if (u1 == v || v1 == u || u1 == v1) continue; if (isCrossed(atoms[u].getPoint2d(), atoms[u1].getPoint2d(), atoms[v].getPoint2d(), atoms[v1].getPoint2d())) return true; } } return false; }
/** * Internal - makes atom (seq) and bond priority queues for resolving * overlap. Only (acyclic - but not really) atoms and bonds in the shortest * path between the two atoms can resolve an overlap. We create prioritised * sequences of atoms/bonds where the more central in the shortest path. * * @param path shortest path between atoms * @param seqAt prioritised atoms, first atom is the middle of the path * @param bndAt prioritised bonds, first bond is the middle of the path */ private void makeAtmBndQueues(int[] path, int[] seqAt, IBond[] bndAt) { int len = path.length; int i = (len - 1) / 2; int j = i + 1; int nSeqAt = 0; int nBndAt = 0; if (isOdd((path.length))) { seqAt[nSeqAt++] = path[i--]; bndAt[nBndAt++] = bondMap.get(path[j], path[j - 1]); } bndAt[nBndAt++] = bondMap.get(path[i], path[i + 1]); while (i > 0 && j < len - 1) { seqAt[nSeqAt++] = path[i--]; seqAt[nSeqAt++] = path[j++]; bndAt[nBndAt++] = bondMap.get(path[i], path[i + 1]); bndAt[nBndAt++] = bondMap.get(path[j], path[j - 1]); } }
stackBackup.len = visitAdj(visited, stackBackup.xs, begIdx, endIdx); final int begCnt = numFixedMoved(stackBackup.xs, stackBackup.len); if (begCnt > 0) { Arrays.fill(visited, false); stackBackup.len = visitAdj(visited, stackBackup.xs, endIdx, begIdx); final int endCnt = numFixedMoved(stackBackup.xs, stackBackup.len); if (endCnt > 0) continue; stackBackup.len = visitAdj(visited, stackBackup.xs, endIdx, begIdx); final int endCnt = numFixedMoved(stackBackup.xs, stackBackup.len); if (endCnt > 0) { Arrays.fill(visited, false); stackBackup.len = visitAdj(visited, stackBackup.xs, begIdx, endIdx); final int begCnt = numFixedMoved(stackBackup.xs, stackBackup.len); if (begCnt > 0) continue; backupCoords(backup, stackBackup); reflect(stackBackup, beg, end); congestion.update(visited, stackBackup.xs, stackBackup.len); restoreCoords(stackBackup, backup); congestion.update(visited, stackBackup.xs, stackBackup.len); congestion.score = min;
/** * Refine the 2D coordinates of a layout to reduce overlap and congestion. */ public void refine() { for (int i = 1; i <= MAX_ITERATIONS; i++) { final List<AtomPair> pairs = findCongestedPairs(); if (pairs.isEmpty()) break; final double min = congestion.score(); // rotation: flipping around sigma bonds rotate(pairs); // rotation improved, so try more rotation, we may have caused // new conflicts that can be resolved through more rotations if (congestion.score() < min) continue; // inversion: terminal atoms can be placed inside rings // which is preferable to bending or stretching invert(pairs); if (congestion.score() < min) continue; // bending or stretching: least favourable but sometimes // the only way. We try either and use the best bendOrStretch(pairs); if (congestion.score() < min) continue; break; } }
double bendScore = bend(pair, bendStack, buffer1, bendVisit); double stretchScore = stretch(pair, stretchStack, buffer2, stretchVisit); restoreCoords(bendStack, buffer1); congestion.update(bendStack.xs, bendStack.len); break; restoreCoords(stretchStack, buffer2); congestion.update(stretchStack.xs, stretchStack.len); break;