User 870ab5b546
25-09-2012 01:44:15
I am processing the MObjects in the attached MRV document. I am looking to see if the endpoints of any arrows are near the midpoints of any other arrows. The code:
private void extractArrows() throws MechError {
final String SELF = "MechData.extractArrows: ";
arrows = new ArrayList<MechArrow>();
final List<MechArrow> branchedArrows = new ArrayList<MechArrow>();
final List<MechArrow> unsureArrows = new ArrayList<MechArrow>();
// search objects in MDoc for arrows
for (int objIndex = 0; objIndex < mechDoc.getObjectCount(); objIndex++) {
final MObject mObject = mechDoc.getObject(objIndex);
if (MolString.isLineOrRxnArrow(mObject)) {
if (MolString.isReactionArrow(mObject)) {
debugPrint(SELF + "examining arrow with object number ",
objIndex + 1);
final MechArrow arrow =
new MechArrow((MPolyline) mObject, objIndex);
final MPoint arrowTail = arrow.getPoint(TAIL);
if (arrowTail instanceof MRectanglePoint) { // box to box arrow
debugPrint(SELF + "arrow starts at box");
arrows.add(arrow);
} else if (arrowTail instanceof MMidPoint) {
// branched arrow
debugPrint(SELF + "arrow starts at arrow midpoint");
branchedArrows.add(arrow);
} else {
debugPrint(SELF + "arrow starts in space");
unsureArrows.add(arrow);
} // if arrow originates from another arrow
final MPoint arrowHead = arrow.getPoint(HEAD);
if (arrowHead instanceof MMidPoint)
fail(objIndex, "Reaction arrows may originate "
+ "from the midpoint of another arrow, "
+ "but they must point to a rectangle.");
} else { // line but not arrow
fail(objIndex, "Please connect your boxes with "
+ "reaction or resonance arrows, not with "
+ "straight lines.");
} // if is an arrow
} // if is a straight line or arrow
} // for each object in the MDocument
// see if any of the unassigned arrows are originating near the midpoint
// of another arrow
debugPrint(SELF + "assigning ", unsureArrows.size(),
" arrow(s) originating in space.");
for (int arrowNum = unsureArrows.size() - 1; arrowNum >= 0; arrowNum--) {
final MechArrow unsureArrow = unsureArrows.remove(arrowNum);
debugPrint(SELF + "finding origin of arrow ", arrowNum + 1,
" with object number ", unsureArrow.getObjectNumber() + 1);
final MPoint arrowTail = unsureArrow.getPoint(TAIL);
boolean foundMainArrow = false;
// search arrows known to originate at rectangles
for (MechArrow toRectArrow : arrows) {
if (onArrow(arrowTail, toRectArrow)) {
debugPrint(SELF + "arrow ", arrowNum + 1, " with object "
+ "number ", unsureArrow.getObjectNumber() + 1,
" has tail that originates on arrow with object "
+ "number ", toRectArrow.getObjectNumber() + 1,
"; this latter arrow originates at a rectangle.");
foundMainArrow = true;
unsureArrow.getArrow().setPoints(new MPoint[]
{toRectArrow.getPoint(MIDPT),
unsureArrow.getPoint(HEAD)});
branchedArrows.add(unsureArrow);
break;
} // if the unsure arrow originates at an arrow originating at a rectangle
} // for each arrow originating at a rectangle
// search arrows known to originate at other arrows
if (!foundMainArrow) for (MechArrow otherArrow : branchedArrows) {
if (onArrow(arrowTail, otherArrow)) {
debugPrint(SELF + "arrow ", arrowNum + 1, " with object "
+ "number ", unsureArrow.getObjectNumber() + 1,
" has tail that originates on arrow with object "
+ "number ", otherArrow.getObjectNumber() + 1,
"; this latter arrow originates at a branching "
+ "arrow.");
foundMainArrow = true;
unsureArrow.getArrow().setPoints(new MPoint[]
{otherArrow.getPoint(MIDPT),
unsureArrow.getPoint(HEAD)});
branchedArrows.add(unsureArrow);
break;
} // if the unsure arrow originates at an arrow originating at another arrow
} // for each arrow not originating at a rectangle
// search arrows with thus-far-unknown origins
if (!foundMainArrow) for (MechArrow otherArrow : unsureArrows) {
if (onArrow(arrowTail, otherArrow)) {
debugPrint(SELF + "arrow ", arrowNum + 1, " with object "
+ "number ", unsureArrow.getObjectNumber() + 1,
" has tail that originates on arrow with object "
+ "number ", otherArrow.getObjectNumber() + 1,
"; this latter arrow has an unknown origin.");
foundMainArrow = true;
unsureArrow.getArrow().setPoints(new MPoint[]
{otherArrow.getPoint(MIDPT),
unsureArrow.getPoint(HEAD)});
branchedArrows.add(unsureArrow);
break;
} // if the unsure arrow originates on an arrow originating in space
} // for each arrow not originating at a rectangle
if (!foundMainArrow) {
// assume it originates at a rectangle
arrows.add(unsureArrow);
} // if the unsure arrow doesn't originate at an arrow
} // for each unassigned arrow
removeBranchedArrows(branchedArrows);
setArrowEndpoints();
} // extractArrows()
private boolean onArrow(MPoint pt, MechArrow arrow) {
final String SELF = "MechData.onArrow: ";
debugPrint(SELF + "seeing if point is on arrow.");
final boolean onArrow =
VectorMath.pointOnLine(pt.getLocation(), arrow.getArrow());
debugPrint(SELF + "point is ", onArrow ? "" : "not ", "on arrow.");
return onArrow;
} // onArrow(MPoint, MechArrow)
public static boolean pointOnLine(DPoint3 p, MPolyline line) {
final String SELF = "VectorMath.pointOnLine: ";
debugPrint(SELF + "point = ", p, ", line = ", line);
final DPoint3 pt1 = line.getPoint(0).getLocation();
final DPoint3 pt2 = line.getPoint(1).getLocation();
final DPoint3 pt = new DPoint3(p.x, p.y, 0); // project onto XY plane
final DPoint3 vecTo1 = diff(new DPoint3(pt1.x, pt1.y, 0), pt);
final DPoint3 vecTo2 = diff(new DPoint3(pt2.x, pt2.y, 0), pt);
final int sumAngles = MathMethods.roundToInt(
toDegrees(Math.abs(angle(vecTo1, vecTo2))));
debugPrint(SELF + "sumAngles = ", sumAngles);
return MathMethods.inRange(sumAngles, new int[] {170, 190});
} // pointOnLine(DPoint3, MPolyline)
private static void debugPrint(Object... msg) {
Utils.printToLog(msg);
}
public static void printToLog(Object[] msg) {
printToLog(msg, SMILES);
} // alwaysPrint(Object[], String)
private static void printObject(Object obj, String format) {
if (obj == null) {
System.out.print("null");
...
} else if (obj instanceof DPoint3) {
System.out.print(((DPoint3) obj).toString());
} else if (obj instanceof MPoint) {
printObject(((MPoint) obj).getLocation(), format); // recursive call
} else if (obj instanceof MPolyline) {
printObject(((MPolyline) obj).getPoints(), format); // recursive call
} else if (obj instanceof Object[] || obj instanceof List) {
// includes multidimensional lists and arrays, e.g. int[][]
final boolean isList = obj instanceof List;
List list = null;
Object[] array = null;
int numItems;
if (isList) {
list = (List) obj;
numItems = list.size();
} else {
array = (Object[]) obj;
numItems = array.length;
} // if is list
System.out.print('[');
String divider = null;
for (int itemNum = 0; itemNum < numItems; itemNum++) {
final Object item =
(isList ? list.get(itemNum) : array[itemNum]);
if (itemNum == 0) divider = getDivider(item);
else System.out.print(divider);
printObject(item, format); // recursive call
} // for each object in the collection
System.out.print(']');
} else System.out.print(obj);
} // printObject(Object, String)
The error message:
MechData.extractArrows: arrow 3 with object number 7 has tail that originates on arrow with object number 6; this latter arrow has an unknown origin.
MechData.extractArrows: finding origin of arrow 2 with object number 6
MechData.onArrow: seeing if point is on arrow.
VectorMath.pointOnLine: point = DPoint3(-8.25, -11.65999984741211, 0.0), line = [DPoint3(0.27356451749801636, -5.380102157592773, 0.0), DPoint3(2.361952893937054, -8.997296931521465, 0.0)]
VectorMath.pointOnLine: sumAngles = 22
MechData.onArrow: point is not on arrow.
MechData.onArrow: seeing if point is on arrow.
VectorMath.pointOnLine: point = DPoint3(-8.25, -11.65999984741211, 0.0), line = [DPoint3(-9.085513567791546, -8.541820762000917, 0.0), DPoint3(-6.520300286938771, -18.129008231941995, 0.0)]
VectorMath.pointOnLine: sumAngles = 180
MechData.onArrow: point is on arrow.
MechData.extractArrows: arrow 2 with object number 6 has tail that originates on arrow with object number 7; this latter arrow originates at a branching arrow.
MechData.extractArrows: finding origin of arrow 1 with object number 5
MechData.onArrow: seeing if point is on arrow.
VectorMath.pointOnLine: point = DPoint3(-8.396491050720215, -1.4667165279388428, 0.0), line = [DPoint3(0.27356451749801636, -5.380102157592773, 0.0), DPoint3(2.361952893937054, -8.997296931521465, 0.0)]
VectorMath.pointOnLine: sumAngles = 11
MechData.onArrow: point is not on arrow.
MechData.onArrow: seeing if point is on arrow.
VectorMath.pointOnLine: point = DPoint3(-8.396491050720215, -1.4667165279388428, 0.0), line = [java.lang.StackOverflowError
at chemaxon.struc.graphics.MMidPoint.getLocation(MMidPoint.java:172)
at chemaxon.struc.MPoint.getLocation(MPoint.java:123)
at chemaxon.struc.graphics.MPolyline.getMidPointLocation(MPolyline.java:900)
at chemaxon.struc.graphics.MMidPoint.getFixedLocation(MMidPoint.java:206)
at chemaxon.struc.graphics.MMidPoint.getLocation(MMidPoint.java:175)
at chemaxon.struc.MPoint.getLocation(MPoint.java:123)
at chemaxon.struc.graphics.MPolyline.getMidPointLocation(MPolyline.java:900)
at chemaxon.struc.graphics.MMidPoint.getFixedLocation(MMidPoint.java:206)
at chemaxon.struc.graphics.MMidPoint.getLocation(MMidPoint.java:175)
at chemaxon.struc.MPoint.getLocation(MPoint.java:123)
at chemaxon.struc.graphics.MPolyline.getMidPointLocation(MPolyline.java:900)
at chemaxon.struc.graphics.MMidPoint.getFixedLocation(MMidPoint.java:206)
at chemaxon.struc.graphics.MMidPoint.getLocation(MMidPoint.java:175)
at chemaxon.struc.MPoint.getLocation(MPoint.java:123)
If I comment out the debugPrint line in pointOnLine(), I get a similar error message:
MechData.extractArrows: arrow 3 with object number 7 has tail that originates on arrow with object number 6; this latter arrow has an unknown origin.
MechData.extractArrows: finding origin of arrow 2 with object number 6
MechData.onArrow: seeing if point is on arrow.
VectorMath.pointOnLine: sumAngles = 22
MechData.onArrow: point is not on arrow.
MechData.onArrow: seeing if point is on arrow.
VectorMath.pointOnLine: sumAngles = 180
MechData.onArrow: point is on arrow.
MechData.extractArrows: arrow 2 with object number 6 has tail that originates on arrow with object number 7; this latter arrow originates at a branching arrow.
MechData.extractArrows: finding origin of arrow 1 with object number 5
MechData.onArrow: seeing if point is on arrow.
VectorMath.pointOnLine: sumAngles = 11
MechData.onArrow: point is not on arrow.
MechData.onArrow: seeing if point is on arrow.
java.lang.StackOverflowError
at chemaxon.struc.graphics.MMidPoint.getFixedLocation(MMidPoint.java:206)
at chemaxon.struc.graphics.MMidPoint.getLocation(MMidPoint.java:175)
at chemaxon.struc.MPoint.getLocation(MPoint.java:123)
at chemaxon.struc.graphics.MPolyline.getMidPointLocation(MPolyline.java:900)
at chemaxon.struc.graphics.MMidPoint.getFixedLocation(MMidPoint.java:206)
at chemaxon.struc.graphics.MMidPoint.getLocation(MMidPoint.java:175)
at chemaxon.struc.MPoint.getLocation(MPoint.java:123)
at chemaxon.struc.graphics.MPolyline.getMidPointLocation(MPolyline.java:900)
at chemaxon.struc.graphics.MMidPoint.getFixedLocation(MMidPoint.java:206)
at chemaxon.struc.graphics.MMidPoint.getLocation(MMidPoint.java:175)
at chemaxon.struc.MPoint.getLocation(MPoint.java:123)
at chemaxon.struc.graphics.MPolyline.getMidPointLocation(MPolyline.java:900)
at chemaxon.struc.graphics.MMidPoint.getFixedLocation(MMidPoint.java:206)
at chemaxon.struc.graphics.MMidPoint.getLocation(MMidPoint.java:175)
at chemaxon.struc.MPoint.getLocation(MPoint.java:123)