Skip to content

Commit 8c6dd38

Browse files
committed
Charges should be delocalised in the middle of the ring, e.g. cyclopentadiene.
1 parent c7f3dc1 commit 8c6dd38

File tree

2 files changed

+64
-8
lines changed

2 files changed

+64
-8
lines changed

display/renderbasic/src/main/java/org/openscience/cdk/renderer/generators/standard/StandardDonutGenerator.java

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,16 @@
3232
import org.openscience.cdk.interfaces.IRingSet;
3333
import org.openscience.cdk.renderer.RendererModel;
3434
import org.openscience.cdk.renderer.elements.ElementGroup;
35+
import org.openscience.cdk.renderer.elements.GeneralPath;
3536
import org.openscience.cdk.renderer.elements.IRenderingElement;
3637
import org.openscience.cdk.renderer.elements.OvalElement;
38+
import org.openscience.cdk.renderer.generators.BasicSceneGenerator;
3739
import org.openscience.cdk.renderer.generators.standard.StandardGenerator.DelocalisedDonutsBondDisplay;
3840
import org.openscience.cdk.renderer.generators.standard.StandardGenerator.ForceDelocalisedBondDisplay;
3941

4042
import javax.vecmath.Point2d;
4143
import java.awt.Color;
44+
import java.awt.Font;
4245
import java.util.HashSet;
4346
import java.util.Set;
4447

@@ -48,19 +51,25 @@ final class StandardDonutGenerator {
4851

4952
// bonds involved in donuts!
5053
private final Set<IBond> bonds = new HashSet<>();
54+
// atoms with delocalised charge
55+
private final Set<IAtom> atoms = new HashSet<>();
5156
private final boolean forceDelocalised;
5257
private final boolean delocalisedDonuts;
5358
private final double dbSpacing;
59+
private final double scale;
5460
private final Color fgColor;
61+
private final Font font;
5562
private final IAtomContainer mol;
5663

57-
public StandardDonutGenerator(IAtomContainer mol, RendererModel model) {
64+
public StandardDonutGenerator(IAtomContainer mol, Font font, RendererModel model) {
65+
this.mol = mol;
66+
this.font = font;
5867
this.forceDelocalised = model.get(ForceDelocalisedBondDisplay.class);
5968
this.delocalisedDonuts = model.get(DelocalisedDonutsBondDisplay.class);
6069
this.dbSpacing = model.get(StandardGenerator.BondSeparation.class);
70+
this.scale = model.get(BasicSceneGenerator.Scale.class);
6171
this.fgColor = model.get(StandardGenerator.AtomColor.class).getAtomColor(
6272
mol.getBuilder().newInstance(IAtom.class, "C"));
63-
this.mol = mol;
6473
}
6574

6675
private boolean canDelocalise(final IAtomContainer ring) {
@@ -89,11 +98,42 @@ IRenderingElement generate() {
8998
for (IBond bond : ring.bonds()) {
9099
bonds.add(bond);
91100
}
101+
int charge = 0;
102+
int unpaired = 0;
103+
for (IAtom atom : ring.atoms()) {
104+
Integer q = atom.getFormalCharge();
105+
if (q == null || q == 0) {
106+
continue;
107+
}
108+
int nCyclic = 0;
109+
for (IBond bond : mol.getConnectedBondsList(atom))
110+
if (bond.isInRing())
111+
nCyclic++;
112+
if (nCyclic > 2)
113+
continue;
114+
atoms.add(atom);
115+
charge += atom.getFormalCharge();
116+
}
92117
Point2d p2 = GeometryUtil.get2DCenter(ring);
118+
119+
if (charge != 0) {
120+
String qText = charge < 0 ? "–" : "+";
121+
if (charge < -1)
122+
qText = Math.abs(charge) + qText;
123+
else if (charge > +1)
124+
qText = Math.abs(charge) + qText;
125+
126+
TextOutline qSym = new TextOutline(qText, font);
127+
qSym = qSym.resize(1 / scale, -1 / scale);
128+
qSym = qSym.translate(p2.x - qSym.getCenter().getX(),
129+
p2.y - qSym.getCenter().getY());
130+
group.add(GeneralPath.shapeOf(qSym.getOutline(), fgColor));
131+
}
132+
93133
double s = GeometryUtil.getBondLengthMedian(ring);
94134
double n = ring.getBondCount();
95135
double r = s / (2 * Math.tan(Math.PI / n));
96-
group.add(new OvalElement(p2.x, p2.y, r - dbSpacing,
136+
group.add(new OvalElement(p2.x, p2.y, r - 1.5*dbSpacing,
97137
false, fgColor));
98138
}
99139
return group;
@@ -102,4 +142,8 @@ IRenderingElement generate() {
102142
boolean isDelocalised(IBond bond) {
103143
return bonds.contains(bond);
104144
}
145+
146+
boolean isChargeDelocalised(IAtom atom) {
147+
return atoms.contains(atom);
148+
}
105149
}

display/renderbasic/src/main/java/org/openscience/cdk/renderer/generators/standard/StandardGenerator.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,14 @@ public IRenderingElement generate(IAtomContainer container, RendererModel parame
211211

212212
ElementGroup annotations = new ElementGroup();
213213

214-
StandardDonutGenerator donutGenerator = new StandardDonutGenerator(container, parameters);
214+
StandardDonutGenerator donutGenerator;
215+
donutGenerator = new StandardDonutGenerator(container, font, parameters);
215216
IRenderingElement donuts = donutGenerator.generate();
216217

217-
AtomSymbol[] symbols = generateAtomSymbols(container, symbolRemap, visibility, parameters, annotations, foreground, stroke);
218+
AtomSymbol[] symbols = generateAtomSymbols(container, symbolRemap,
219+
visibility, parameters,
220+
annotations, foreground,
221+
stroke, donutGenerator);
218222
IRenderingElement[] bondElements;
219223
bondElements = StandardBondGenerator.generateBonds(container, symbols,
220224
parameters, stroke,
@@ -367,7 +371,8 @@ private AtomSymbol[] generateAtomSymbols(IAtomContainer container,
367371
RendererModel parameters,
368372
ElementGroup annotations,
369373
Color foreground,
370-
double stroke) {
374+
double stroke,
375+
StandardDonutGenerator donutGen) {
371376

372377
final double scale = parameters.get(BasicSceneGenerator.Scale.class);
373378
final double annDist = parameters.get(AnnotationDistance.class)
@@ -424,9 +429,16 @@ private AtomSymbol[] generateAtomSymbols(IAtomContainer container,
424429

425430
if (remapped) {
426431
symbols[i] = atomGenerator.generateAbbreviatedSymbol(symbolRemap.get(atom), hPosition);
427-
} else {
432+
} else if (donutGen.isChargeDelocalised(atom)) {
433+
Integer charge = atom.getFormalCharge();
434+
atom.setFormalCharge(0);
435+
// can't think of a better way to handle this without API
436+
// change to symbol visibility
437+
if (atom.getAtomicNumber() != 6)
438+
symbols[i] = atomGenerator.generateSymbol(container, atom, hPosition, parameters);
439+
atom.setFormalCharge(charge);
440+
} else
428441
symbols[i] = atomGenerator.generateSymbol(container, atom, hPosition, parameters);
429-
}
430442

431443
if (symbols[i] != null) {
432444

0 commit comments

Comments
 (0)