User 870ab5b546
26-08-2014 18:19:04
Hi,
I'm having problems with generating images of approximately equal sizes. I thinkt he problem has to do with shortcut groups, but that may not be the case.
The first figure shows a single figure that should show the same size in all three, but doesn't. The differences are no shortcut groups vs. Me shortcut groups vs. Ph shortcut groups.
The second figure shows a series of different figures that have been rendered in wildly disparate sizes, even though they are all approximately the same size in a Marvin window.
Here's the code we have been using to determine the optimal size to display a figure:
private static int[] getBestAppletSize(Molecule mol, boolean isLewis,
boolean showMapping, boolean fixedBondLength) {
final String SELF = "MolString.getBestAppletSize: ";
int[] dims = new int[] {OPT_WIDTH, OPT_WIDTH};
final int MAX_SCALE = fixedBondLength ? 30 : 40; // largest scale that looks OK
final int MIN_SCALE = 16; // smallest scale that looks OK
try {
if (mol.getDim() == 0) ChemUtils.clean2D(mol);
final MolPrinter printer = new MolPrinter(mol);
printer.setLonePairsVisible(true);
printer.setRendering(WIREFRAME_RENDERING_S);
printer.setImplicitH(isLewis ? IMPLICITH_ALL_S
: IMPLICITH_HETEROTERM_S);
printer.setScale(MAX_SCALE);
final Rectangle boundingRect = printer.getBoundingRectangle(
mol.getDocument().getAllMolecules());
// determine appropriate width
if (boundingRect.width < OPT_WIDTH || fixedBondLength) {
// use width and height at standard scale
dims[0] = boundingRect.width;
dims[1] = boundingRect.height;
} else {
final double smallerScale = ((double) (MAX_SCALE * OPT_WIDTH))
/ (double) boundingRect.width;
if (smallerScale > ((double) MIN_SCALE)) {
debugPrint(SELF + "scaling down to scale ", smallerScale);
// use optimum width
dims[0] = OPT_WIDTH;
dims[1] = (boundingRect.height * OPT_WIDTH)
/ boundingRect.width;
} else {
debugPrint(SELF + "scaling down to scale ", MIN_SCALE);
// use width that gives minimum bond length
dims[0] = (boundingRect.width * MIN_SCALE) / MAX_SCALE;
dims[1] = (boundingRect.height * MIN_SCALE) / MAX_SCALE;
} // if scale
} // if boundingRect.width
} catch (Exception e2) {
Utils.alwaysPrint(SELF + "got an exception on:\n", mol);
e2.printStackTrace();
}
return dims;
} // getBestAppletSize(Molecule, boolean, boolean, boolean)
The values of OPT_WIDTH is 250.
And here's how we use the applet dimensions to generate images:
/** Gets the molecule's image as a string.
* @param format SVG or PNG URI
* @param molStr the MRV of a molecule
* @param qFlags flags affecting the image
* @return the molecule's image as a String
*/
private static String getImage(String format, String molStr, long qFlags) {
final String SELF = "MolString.getImage: ";
String imageData = "";
if (!Utils.isEmpty(molStr)) try {
debugPrint(SELF + "molStr:\n", molStr);
final boolean isLewis = molStr.contains("Lewis ");
final Molecule mol = MolImporter.importMol(molStr);
final int[] dims = getBestAppletSize(mol, isLewis);
final String opts =
getImageOptsString(format, dims, qFlags, isLewis);
// workaround for bug in displaying lone pairs in JChem 6.1
MDocument mDoc = mol.getDocument();
if (mDoc == null) mDoc = new MDocument(mol);
if (Question.showLonePairs(qFlags)) toBinFormat(mDoc, opts);
// generates the lone pairs for printing later
imageData = (PNG.equals(format)
? new StringBuilder().append("data:image/")
.append(PNG).append(";base64,")
.append(Base64Coder.encode(toBinFormat(mDoc, opts)))
.toString()
: Utils.bytesToString(toBinFormat(mDoc, opts))
.replaceAll("\"clipPath1\"", "\"clipPath2\""));
debugPrint(SELF + "generated image src URI with options ", opts,
"; isLewis = ", isLewis);
debugPrintMRV(SELF + "image data:\n", imageData);
} catch (MolFormatException e) {
System.out.println(SELF + "caught MolFormatException: ");
e.printStackTrace();
} // try
return imageData;
} // getImage(String, String, long)
/** Prepares a string representing options for image formation.
* @param imgType the type of image (SVG or PNG)
* @param dims dimensions of the image
* @param qFlags flags affecting the image
* @param isLewis whether the image is a LewisSketch image
* @return the options as a string
*/
private static String getImageOptsString(String imgType, int[] dims,
long qFlags, boolean isLewis) {
final StringBuilder optsBld = new StringBuilder()
.append(imgType).append(':');
if (SVG.equals(imgType)) optsBld.append("headless,");
optsBld.append('w').append(dims[0]).append(",h").append(dims[1]);
if (!isLewis && !Question.badValenceInvisible(qFlags)) {
optsBld.append(",valenceErrorVisible");
} // if should show valence errors
optsBld.append(",H_").append(
Question.showNoHydrogens(qFlags) || isLewis ? "off"
: Question.showHeteroHydrogens(qFlags) ? "hetero"
: Question.showAllHydrogens(qFlags) ? "all"
: "heteroterm")
.append(",cv_").append(Question.showAllCarbons(qFlags)
|| isLewis ? "on" : "inChain");
if (Question.showLonePairs(qFlags)) optsBld.append(",lp");
if (Question.showMapping(qFlags)) optsBld.append(",amap");
if (Question.showRSLabels(qFlags)) {
optsBld.append(",chiral_all");
} // if should show RS labels
return optsBld.toString();
} // getImageOptsString(String, int[], long, boolean)
This is longstanding code, but I noticed the problem fairly recently.
Any ideas what could be going wrong? Let me know if you need more information.