Skip to content

Commit cc2c77f

Browse files
committed
Improve layout of nested sgroups, first calculate the hierarchical tree.
1 parent f8a595d commit cc2c77f

File tree

1 file changed

+59
-11
lines changed

1 file changed

+59
-11
lines changed

tool/sdg/src/main/java/org/openscience/cdk/layout/StructureDiagramGenerator.java

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,13 @@
108108
*/
109109
public class StructureDiagramGenerator {
110110

111-
static final double DEFAULT_BOND_LENGTH = 1.5;
111+
static final double DEFAULT_BOND_LENGTH = 1.5;
112+
static final double SGROUP_BRACKET_PADDING_FACTOR = 0.5;
112113
private static final Vector2d DEFAULT_BOND_VECTOR = new Vector2d(0, 1);
113114
private static final IdentityTemplateLibrary DEFAULT_TEMPLATE_LIBRARY = IdentityTemplateLibrary.loadFromResource("custom-templates.smi")
114115
.add(IdentityTemplateLibrary.loadFromResource("chebi-ring-templates.smi"));
115116
private static final double RAD_30 = Math.toRadians(-30);
116-
private static final ILoggingTool logger = LoggingToolFactory.createLoggingTool(StructureDiagramGenerator.class);
117+
private static final ILoggingTool logger = LoggingToolFactory.createLoggingTool(StructureDiagramGenerator.class);
117118

118119
public static final Comparator<IAtomContainer> LARGEST_FIRST_COMPARATOR = new Comparator<IAtomContainer>() {
119120
@Override
@@ -1170,12 +1171,42 @@ private void generateFragmentCoordinates(IAtomContainer mol, List<IAtomContainer
11701171
Set<IAtom> afixbackup = new HashSet<>(afix);
11711172
Set<IBond> bfixbackup = new HashSet<>(bfix);
11721173

1174+
List<Sgroup> sgroups = mol.getProperty(CDKConstants.CTAB_SGROUPS);
1175+
11731176
// generate the sub-layouts
11741177
for (IAtomContainer fragment : frags) {
11751178
setMolecule(fragment, false, afix, bfix);
11761179
generateCoordinates(DEFAULT_BOND_VECTOR, true, true);
11771180
lengthenIonicBonds(ionicBonds, fragment);
1178-
limits.add(getAprxBounds(fragment));
1181+
double[] aprxBounds = getAprxBounds(fragment);
1182+
1183+
if (sgroups != null && sgroups.size() > 0) {
1184+
boolean hasBracket = false;
1185+
for (Sgroup sgroup : sgroups) {
1186+
if (!hasBrackets(sgroup))
1187+
continue;
1188+
boolean contained = true;
1189+
Set<IAtom> aset = sgroup.getAtoms();
1190+
for (IAtom atom : sgroup.getAtoms()) {
1191+
if (!aset.contains(atom))
1192+
contained = false;
1193+
}
1194+
if (contained) {
1195+
hasBracket = true;
1196+
break;
1197+
}
1198+
}
1199+
1200+
if (hasBracket) {
1201+
// consider potential Sgroup brackets
1202+
aprxBounds[0] -= SGROUP_BRACKET_PADDING_FACTOR * bondLength;
1203+
aprxBounds[1] -= SGROUP_BRACKET_PADDING_FACTOR * bondLength;
1204+
aprxBounds[2] += SGROUP_BRACKET_PADDING_FACTOR * bondLength;
1205+
aprxBounds[3] += SGROUP_BRACKET_PADDING_FACTOR * bondLength;
1206+
}
1207+
}
1208+
1209+
limits.add(aprxBounds);
11791210
}
11801211

11811212
// restore
@@ -2613,6 +2644,12 @@ private static int numRingBonds(IAtomContainer mol, IAtom atom) {
26132644
return cnt;
26142645
}
26152646

2647+
private void updateMinMax(double[] minmax, Point2d p) {
2648+
minmax[0] = Math.min(p.x, minmax[0]);
2649+
minmax[1] = Math.min(p.y, minmax[1]);
2650+
minmax[2] = Math.max(p.x, minmax[2]);
2651+
minmax[3] = Math.max(p.y, minmax[3]);
2652+
}
26162653

26172654
/**
26182655
* Place and update brackets for polymer Sgroups.
@@ -2625,6 +2662,7 @@ private void placeSgroupBrackets(IAtomContainer mol) {
26252662

26262663
// index all crossing bonds
26272664
final Multimap<IBond,Sgroup> bondMap = HashMultimap.create();
2665+
final Multimap<Sgroup,Sgroup> childMap = HashMultimap.create();
26282666
final Map<IBond,Integer> counter = new HashMap<>();
26292667
for (Sgroup sgroup : sgroups) {
26302668
if (!hasBrackets(sgroup))
@@ -2633,19 +2671,16 @@ private void placeSgroupBrackets(IAtomContainer mol) {
26332671
bondMap.put(bond, sgroup);
26342672
counter.put(bond, 0);
26352673
}
2674+
for (Sgroup parent : sgroup.getParents())
2675+
childMap.put(parent, sgroup);
26362676
}
26372677
sgroups = new ArrayList<>(sgroups);
2638-
// place child sgroups first
2678+
// place child sgroups first, or those with less total children
26392679
Collections.sort(sgroups,
26402680
new Comparator<Sgroup>() {
26412681
@Override
26422682
public int compare(Sgroup o1, Sgroup o2) {
2643-
if (o1.getParents().isEmpty() != o2.getParents().isEmpty()) {
2644-
if (o1.getParents().isEmpty())
2645-
return +1;
2646-
return -1;
2647-
}
2648-
return 0;
2683+
return Integer.compare(childMap.get(o1).size(), childMap.get(o2).size());
26492684
}
26502685
});
26512686

@@ -2684,7 +2719,20 @@ public int compare(Sgroup o1, Sgroup o2) {
26842719
for (IAtom atom : atoms)
26852720
tmp.addAtom(atom);
26862721
double[] minmax = GeometryUtil.getMinMax(tmp);
2687-
double padding = 0.7 * bondLength;
2722+
2723+
// if a child Sgroup also has brackets, account for that in our
2724+
// bounds calculation
2725+
for (Sgroup child : childMap.get(sgroup)) {
2726+
List<SgroupBracket> brackets = child.getValue(SgroupKey.CtabBracket);
2727+
if (brackets != null) {
2728+
for (SgroupBracket bracket : brackets) {
2729+
updateMinMax(minmax, bracket.getFirstPoint());
2730+
updateMinMax(minmax, bracket.getSecondPoint());
2731+
}
2732+
}
2733+
}
2734+
2735+
double padding = SGROUP_BRACKET_PADDING_FACTOR * bondLength;
26882736
sgroup.addBracket(new SgroupBracket(minmax[0] - padding, minmax[1] - padding,
26892737
minmax[0] - padding, minmax[3] + padding));
26902738
sgroup.addBracket(new SgroupBracket(minmax[2] + padding, minmax[1] - padding,

0 commit comments

Comments
 (0)