get MRectanglePoint from MRectangle?

User 870ab5b546

11-05-2016 19:32:35

Hi, I want to take a MarvinJS/Sketch drawing that includes graphical arrows (MPolyline) that start and end at the corners or edge midpoints of various rectangles (MRectangle), and change the termini of the arrows so they start and end at different corners or edge midpoints of the same rectangles. The code I have so far is below.


final int[] posnConverter = new int[] {
MRectangle.P_SW, MRectangle.P_SE,
MRectangle.P_NE, MRectangle.P_NW,
MRectangle.P_S, MRectangle.P_E,
MRectangle.P_N, MRectangle.P_W};
final String[] posnStrs = new String[] {
"NW", "NE", "SE", "SW", "N", "E", "S", "W"};
for (int objIndex = 0; objIndex < mDoc.getObjectCount(); objIndex++) {
final MObject mObject = mDoc.getObject(objIndex);
if (isReactionArrow(mObject)) {
final MPolyline arrow = (MPolyline) mObject;
final MPoint[] arrowPts = arrow.getPoints();
for (int ptNum = 0; ptNum < 2; ptNum++) {
final boolean isTail = ptNum == 0;
final MPoint arrowPt = arrowPts[ptNum];
if (arrowPt instanceof MRectanglePoint) {
final MRectanglePoint arrowRectPt = (MRectanglePoint) arrowPt;
final MRectangle arrowRect = arrowRectPt.getParentRect();
final int arrowRectPosn = arrowRectPt.getPositionInRect();
final int newArrowRectPosn = posnConverter[arrowRectPosn];
final MRectanglePoint newArrowRectPt = (MRectanglePoint)
arrowRect.getPointRef(newArrowRectPosn, null);
arrowPts[ptNum] = newArrowRectPt;
arrow.setPoints(arrowPts);
} // if arrow starts or ends at box
} // for tail and head
} // if is reaction arrow
} // for each object in the MDocument

The code works pretty well, but there's a problem. Debugging output is below. Note that the termini of the MPolyline in the original document is fixed at MRectanglePoints, whereas in the modified document, the termini of the MPolyline are simply MPoints, with coordinates. The problem is that there appears to be no way to get an MRectanglePoint from an MRectangle; the method getPointRef() returns a simple MPoint, and casting the MPoint to an MRectanglePoint appears to have no effect. Can you either provide a method getRectanglePointRef(), or suggest another way that I can set the arrow termini to MRectanglePoints? I note that getting the MRectanglePoint might not be the only problem here; the MPolyline.setPoints() method might also not set the arrow's points to MRectanglePoints.


INFO: MolString.adjustArrowsAttachedToRectangles: original document:
<?xml version="1.0" encoding="UTF-8"?>
<cml xmlns="http://www.chemaxon.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.chemaxon.com/marvin/schema/mrvSchema_16_02_15.xsd" version="ChemAxon file format v16.02.15, generated by v16.4.25.0">
<MDocument>
<MChemicalStruct>
<molecule molID="m1">
<atomArray atomID="a1 a2 a3 a4 a5" elementType="C C C C C" x2="-4.440892098500626E-16 -1.2458133233668267 -0.7699999938399991 0.7699999938399995 1.2458133233668263" y2="4.351626657186987 3.4462933310963204 1.9817066761463469 1.9817066761463469 3.4462933310963204"/>
<bondArray>
<bond id="b1" atomRefs2="a1 a2" order="1"/>
<bond id="b2" atomRefs2="a1 a5" order="1"/>
<bond id="b3" atomRefs2="a2 a3" order="1"/>
<bond id="b4" atomRefs2="a3 a4" order="1"/>
<bond id="b5" atomRefs2="a4 a5" order="1"/>
</bondArray>
</molecule>
</MChemicalStruct>
<MRectangle id="o2" lineColor="#000000">
<MPoint x="-2.1250000000000004" y="0.625"/>
<MPoint x="2.3749999999999996" y="0.625"/>
<MPoint x="2.3749999999999996" y="5.541666666666666"/>
<MPoint x="-2.1250000000000004" y="5.541666666666666"/>
</MRectangle>
<MRectangle id="o3" lineColor="#000000">
<MPoint x="-2.375000000000001" y="-5.541666666666667"/>
<MPoint x="1.2083333333333321" y="-5.541666666666667"/>
<MPoint x="1.2083333333333321" y="-1.333333333333333"/>
<MPoint x="-2.375000000000001" y="-1.333333333333333"/>
</MRectangle>
<MPolyline id="o4" headLength="0.6" headWidth="0.4">
<MRectanglePoint pos="2" rectRef="o2"/>
<MRectanglePoint pos="1" rectRef="o3"/>
</MPolyline>
</MDocument>
</cml>

MolString.adjustArrowsAttachedToRectangles: new document:
<?xml version="1.0" encoding="UTF-8"?>
<cml xmlns="http://www.chemaxon.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.chemaxon.com/marvin/schema/mrvSchema_16_02_15.xsd" version="ChemAxon file format v16.02.15, generated by v16.4.25.0">
<MDocument>
<MChemicalStruct>
<molecule molID="m1">
<atomArray atomID="a1 a2 a3 a4 a5" elementType="C C C C C" x2="-4.440892098500626E-16 -1.2458133233668267 -0.7699999938399991 0.7699999938399995 1.2458133233668263" y2="4.351626657186987 3.4462933310963204 1.9817066761463469 1.9817066761463469 3.4462933310963204"/>
<bondArray>
<bond id="b1" atomRefs2="a1 a2" order="1"/>
<bond id="b2" atomRefs2="a1 a5" order="1"/>
<bond id="b3" atomRefs2="a2 a3" order="1"/>
<bond id="b4" atomRefs2="a3 a4" order="1"/>
<bond id="b5" atomRefs2="a4 a5" order="1"/>
</bondArray>
</molecule>
</MChemicalStruct>
<MRectangle id="o2" lineColor="#000000">
<MPoint x="-2.1250000000000004" y="0.625"/>
<MPoint x="2.3749999999999996" y="0.625"/>
<MPoint x="2.3749999999999996" y="5.541666666666666"/>
<MPoint x="-2.1250000000000004" y="5.541666666666666"/>
</MRectangle>
<MRectangle id="o3" lineColor="#000000">
<MPoint x="-2.375000000000001" y="-5.541666666666667"/>
<MPoint x="1.2083333333333321" y="-5.541666666666667"/>
<MPoint x="1.2083333333333321" y="-1.333333333333333"/>
<MPoint x="-2.375000000000001" y="-1.333333333333333"/>
</MRectangle>
<MPolyline id="o4" headLength="0.6" headWidth="0.4">
<MPoint x="2.3749999999999996" y="0.625"/>
<MPoint x="1.2083333333333321" y="-1.333333333333333"/>
</MPolyline>
</MDocument>
</cml>

User 870ab5b546

12-05-2016 14:08:00

I have also noticed that MRectanglePoint.getPositionInRect() doesn't return values that correspond to the constant field values for the rectangle positions. For example, the north point of a rectangle returns the value 4, even though MRectangle.P_N has the value 5.

ChemAxon cfb2ce1d3d

13-05-2016 14:43:48

Hello Bob,


The problem is in this line:


arrow.setPoints(arrowPts)

Unfortunately MRectanglePoint is swallowed within this method. We will examine the feasibility of a fix.


Until then you can work around it by



 


Attached see an example code (to make it more readable for myself refactored your code).


HTH


Regards


Zsolt

User 870ab5b546

13-05-2016 19:35:12

Thanks. It turns out that setting the arrow terminus to an MPoint with the correct coordinates, even if it is not the MRectanglePoint, still accomplishes what I need. But I will keep your code on the back burner in case I need it.


BTW, as I point out in a different thread, the values for the posnConverter need to be set as follows:


final int[] posnConverter = new int[] {
MRectangle.P_SW, MRectangle.P_SE,
MRectangle.P_NE, MRectangle.P_NW,
MRectangle.P_S - 1, MRectangle.P_E - 1,
MRectangle.P_N - 1, MRectangle.P_W - 1};

The reason is that getPositionInRect() returns values of 4–7 for the four edge midpoints, not the values of 5–8 given by the constants representing those positions.