2727
2828import com .google .common .primitives .Ints ;
2929import org .openscience .cdk .config .Elements ;
30+ import org .openscience .cdk .geometry .GeometryUtil ;
3031import org .openscience .cdk .graph .Cycles ;
3132import org .openscience .cdk .interfaces .IAtom ;
3233import org .openscience .cdk .interfaces .IAtomContainer ;
5556import javax .vecmath .Vector2d ;
5657import java .awt .Color ;
5758import java .awt .Font ;
59+ import java .awt .Shape ;
5860import java .util .ArrayList ;
5961import java .util .Arrays ;
6062import java .util .Collections ;
6163import java .util .Comparator ;
6264import java .util .HashMap ;
65+ import java .util .HashSet ;
6366import java .util .List ;
6467import java .util .Map ;
68+ import java .util .Set ;
6569
6670import static org .openscience .cdk .interfaces .IBond .Order .SINGLE ;
6771import static org .openscience .cdk .interfaces .IBond .Order .UNSET ;
@@ -112,6 +116,7 @@ final class StandardBondGenerator {
112116 private final Color foreground , annotationColor ;
113117 private final boolean fancyBoldWedges , fancyHashedWedges ;
114118 private final double annotationDistance , annotationScale ;
119+ private final boolean aromaticDonuts = true ;
115120 private final Font font ;
116121 private final ElementGroup annotations ;
117122 private final boolean forceDelocalised ;
@@ -182,9 +187,37 @@ static IRenderingElement[] generateBonds(IAtomContainer container, AtomSymbol[]
182187 elements [i ] = bondGenerator .generate (bond );
183188 }
184189 }
190+ if (bondGenerator .aromaticDonuts ) {
191+ IRenderingElement donuts = bondGenerator .generateDonuts ();
192+ if (donuts != null ) {
193+ elements = Arrays .copyOf (elements , elements .length + 1 );
194+ elements [elements .length -1 ] = donuts ;
195+ }
196+ }
185197 return elements ;
186198 }
187199
200+ IRenderingElement generateDonuts () {
201+ ElementGroup group = new ElementGroup ();
202+ Set <IAtomContainer > rings = new HashSet <>(ringMap .values ());
203+ for (IAtomContainer ring : rings ) {
204+ if (ring .getBondCount () <= 8 ) {
205+ Point2d p2 = GeometryUtil .get2DCenter (ring );
206+ if (ring .getBondCount () == 5 ) {
207+ TextOutline to = new TextOutline ("–" , font ).resize (1 /scale , -1 /scale );
208+ to = to .translate (p2 .x -to .getCenter ().getX (),
209+ p2 .y -to .getCenter ().getY ());
210+ // group.add(GeneralPath.shapeOf(to.getOutline(), foreground));
211+ }
212+ double s = GeometryUtil .getBondLengthMedian (ring );
213+ double n = ring .getBondCount ();
214+ double r = s / (2 *Math .tan (Math .PI /n ));
215+ // group.add(new OvalElement(p2.x, p2.y, r-separation, false, foreground));
216+ }
217+ }
218+ return group ;
219+ }
220+
188221 /**
189222 * Generate a rendering element for a given bond.
190223 *
@@ -203,14 +236,23 @@ IRenderingElement generate(IBond bond) {
203236
204237 switch (order ) {
205238 case SINGLE :
206- if (bond .isAromatic () && forceDelocalised )
207- elem = generateDoubleBond (bond , true );
208- else
239+ // TODO check small ring!
240+ if (bond .isAromatic ()) {
241+ if (forceDelocalised && !aromaticDonuts ) {
242+ elem = generateDoubleBond (bond , true );
243+ } else
244+ elem = generateSingleBond (bond , atom1 , atom2 );
245+ } else
209246 elem = generateSingleBond (bond , atom1 , atom2 );
210247 break ;
211248 case DOUBLE :
212- elem = generateDoubleBond (bond ,
213- bond .isAromatic () && forceDelocalised );
249+ if (bond .isAromatic ()) {
250+ if (forceDelocalised && aromaticDonuts )
251+ elem = generateSingleBond (bond , atom1 , atom2 );
252+ else
253+ elem = generateDoubleBond (bond , forceDelocalised );
254+ } else
255+ elem = generateDoubleBond (bond , false );
214256 break ;
215257 case TRIPLE :
216258 elem = generateTripleBond (bond , atom1 , atom2 );
@@ -608,10 +650,10 @@ IRenderingElement generateWavyBond(final IAtom from, final IAtom to) {
608650 * Generates a double bond rendering element by deciding how best to display it.
609651 *
610652 * @param bond the bond to render
611- * @param dashed the second line should be dashed
653+ * @param arom the second line should be dashed
612654 * @return rendering element
613655 */
614- private IRenderingElement generateDoubleBond (IBond bond , boolean dashed ) {
656+ private IRenderingElement generateDoubleBond (IBond bond , boolean arom ) {
615657
616658 final boolean cyclic = ringMap .containsKey (bond );
617659
@@ -643,9 +685,9 @@ private IRenderingElement generateDoubleBond(IBond bond, boolean dashed) {
643685 final int wind1 = winding (atom1Bonds .get (0 ), bond );
644686 final int wind2 = winding (bond , atom2Bonds .get (0 ));
645687 if (wind1 > 0 ) {
646- return generateOffsetDoubleBond (bond , atom1 , atom2 , atom1Bonds .get (0 ), atom2Bonds , dashed );
688+ return generateOffsetDoubleBond (bond , atom1 , atom2 , atom1Bonds .get (0 ), atom2Bonds , arom );
647689 } else if (wind2 > 0 ) {
648- return generateOffsetDoubleBond (bond , atom2 , atom1 , atom2Bonds .get (0 ), atom1Bonds , dashed );
690+ return generateOffsetDoubleBond (bond , atom2 , atom1 , atom2Bonds .get (0 ), atom1Bonds , arom );
649691 } else {
650692 // special case, offset line is drawn on the opposite side for
651693 // when concave in macro cycle
@@ -654,7 +696,7 @@ private IRenderingElement generateDoubleBond(IBond bond, boolean dashed) {
654696 // a --- b
655697 // / \
656698 // -- x x --
657- return generateOffsetDoubleBond (bond , atom1 , atom2 , atom1Bonds .get (0 ), atom2Bonds , true , dashed );
699+ return generateOffsetDoubleBond (bond , atom1 , atom2 , atom1Bonds .get (0 ), atom2Bonds , true , arom );
658700 }
659701 } else if (!(hasDisplayedSymbol (atom1 ) && hasDisplayedSymbol (atom2 ))) {
660702 if (atom1Bonds .size () == 1 && atom2Bonds .isEmpty ())
@@ -672,7 +714,7 @@ else if (atom2Bonds.size() == 1)
672714 else
673715 return generateCenteredDoubleBond (bond , atom1 , atom2 , atom1Bonds , atom2Bonds );
674716 } else {
675- if (dashed ) {
717+ if (arom ) {
676718 return generateDashedBond (atom1 , atom2 );
677719 } else {
678720 return generateCenteredDoubleBond (bond , atom1 , atom2 , atom1Bonds , atom2Bonds );
@@ -1561,7 +1603,7 @@ static int winding(IBond bond1, IBond bond2) {
15611603 */
15621604 static Map <IBond , IAtomContainer > ringPreferenceMap (IAtomContainer container ) {
15631605
1564- final IRingSet relevantRings = Cycles .sssr (container ).toRingSet ();
1606+ final IRingSet relevantRings = Cycles .edgeShort (container ).toRingSet ();
15651607 final List <IAtomContainer > rings = AtomContainerSetManipulator .getAllAtomContainers (relevantRings );
15661608
15671609 Collections .sort (rings , new RingBondOffsetComparator ());
0 commit comments