Skip to content

Commit d63b3e3

Browse files
committed
Fix #270
1 parent 612a73b commit d63b3e3

1 file changed

Lines changed: 64 additions & 42 deletions

File tree

‎src/main/java/sc/fiji/snt/PathAndFillManager.java‎

Lines changed: 64 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
* it under the terms of the GNU General Public License as
99
* published by the Free Software Foundation, either version 3 of the
1010
* License, or (at your option) any later version.
11-
*
11+
*
1212
* This program is distributed in the hope that it will be useful,
1313
* but WITHOUT ANY WARRANTY; without even the implied warranty of
1414
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1515
* GNU General Public License for more details.
16-
*
16+
*
1717
* You should have received a copy of the GNU General Public
1818
* License along with this program. If not, see
1919
* <http://www.gnu.org/licenses/gpl-3.0.html>.
@@ -1476,17 +1476,28 @@ private void writePathToXML(final PrintWriter pw, final Path p) {
14761476
String startsString = "";
14771477
String endsString = "";
14781478
if (p.parentPath != null) {
1479-
final int startPathID = p.parentPath.getID();
1480-
// Find the nearest index for backward compatibility:
1481-
int nearestIndexOnStartPath = -1;
1482-
if (p.parentPath.size() > 0) {
1483-
nearestIndexOnStartPath = p.parentPath.indexNearestTo(p.getBranchPoint().x,
1484-
p.getBranchPoint().y, p.getBranchPoint().z);
1479+
// Guard: only write startson if the parent exists in the manager.
1480+
// A dangling parentPath (e.g. from a stale clone reference after deletion)
1481+
// would produce a startson ID that cannot be resolved on load, causing an NPE
1482+
// see https://github.com/morphonets/SNT/issues/270
1483+
if (getPathFromID(p.parentPath.getID()) == null) {
1484+
SNTUtils.log("Warning: path " + p.getID() + " ('" + p.getName() + "') has a parentPath (ID "
1485+
+ p.parentPath.getID() + ") not registered in the manager. "
1486+
+ "The branch relationship will not be saved to avoid a corrupt file.");
1487+
p.parentPath = null; // repair in-memory to keep state consistent
1488+
} else {
1489+
final int startPathID = p.parentPath.getID();
1490+
// Find the nearest index for backward compatibility:
1491+
int nearestIndexOnStartPath = -1;
1492+
if (p.parentPath.size() > 0) {
1493+
nearestIndexOnStartPath = p.parentPath.indexNearestTo(p.getBranchPoint().x,
1494+
p.getBranchPoint().y, p.getBranchPoint().z);
1495+
}
1496+
startsString = " startson=\"" + startPathID + "\"" + " startx=\"" + p.getBranchPoint().x + "\""
1497+
+ " starty=\"" + p.getBranchPoint().y + "\"" + " startz=\"" + p.getBranchPoint().z + "\"";
1498+
if (nearestIndexOnStartPath >= 0)
1499+
startsString += " startsindex=\"" + nearestIndexOnStartPath + "\"";
14851500
}
1486-
startsString = " startson=\"" + startPathID + "\"" + " startx=\"" + p.getBranchPoint().x + "\""
1487-
+ " starty=\"" + p.getBranchPoint().y + "\"" + " startz=\"" + p.getBranchPoint().z + "\"";
1488-
if (nearestIndexOnStartPath >= 0)
1489-
startsString += " startsindex=\"" + nearestIndexOnStartPath + "\"";
14901501
}
14911502
if (p.isPrimary())
14921503
pw.print(" primary=\"true\"");
@@ -2000,41 +2011,52 @@ public void endElement(final String uri, final String localName,
20002011

20012012
if (startID != null) {
20022013
final Path startPath = getPathFromID(startID);
2003-
if (startJoinPoint == null) {
2004-
// Then we have to get it from startIndexInteger:
2005-
startJoinPoint = startPath.getNodeWithoutChecks(startIndexInteger);
2014+
if (startPath == null) {
2015+
SNTUtils.log("Malformed traces file: startson=" + startID
2016+
+ " referenced by path " + p.getID() + " ('" + p.getName()
2017+
+ "') does not exist. Branch relationship skipped.");
2018+
} else {
2019+
if (startJoinPoint == null) {
2020+
// Then we have to get it from startIndexInteger:
2021+
startJoinPoint = startPath.getNodeWithoutChecks(startIndexInteger);
2022+
}
2023+
p.setBranchFrom(startPath, startJoinPoint);
20062024
}
2007-
p.setBranchFrom(startPath, startJoinPoint);
20082025
}
20092026
if (endID != null) {
20102027
Path endPath = getPathFromID(endID);
2011-
if (endJoinPoint == null) {
2012-
// Then we have to get it from endIndexInteger:
2013-
endJoinPoint = endPath.getNodeWithoutChecks(endIndexInteger);
2014-
}
2015-
// We no longer support end point joining, so we'll reverse everything
2016-
// and apply a 'start join';
2017-
SNTUtils.log("End joining no longer supported: Establishing a star-join' on reversed path");
2018-
Path pReversed = p.reversed();
2019-
// replace the path in all data structures...
2020-
allPaths.remove(p);
2021-
pathIdMap.remove(p.getID(), p);
2022-
pathNameMap.remove(p.getName(), p);
2023-
2024-
allPaths.add(pReversed);
2025-
pathIdMap.put(pReversed.getID(), pReversed);
2026-
pathNameMap.put(pReversed.getName(), pReversed);
2027-
2028-
pReversed.setBranchFrom(endPath, endJoinPoint);
2029-
2030-
for (final Path join : new ArrayList<>(p.connectedPaths)) {
2031-
if (join.getParentPath() == p) {
2032-
final PointInImage joinPoint = join.getBranchPoint();
2033-
join.detachFromParent();
2034-
join.setBranchFrom(pReversed, joinPoint);
2028+
if (endPath == null) {
2029+
SNTUtils.log("Malformed traces file: endson=" + endID
2030+
+ " referenced by path " + p.getID() + " ('" + p.getName()
2031+
+ "') does not exist. End-join skipped.");
2032+
} else {
2033+
if (endJoinPoint == null) {
2034+
// Then we have to get it from endIndexInteger:
2035+
endJoinPoint = endPath.getNodeWithoutChecks(endIndexInteger);
20352036
}
2036-
}
2037-
2037+
// We no longer support end point joining, so we'll reverse everything
2038+
// and apply a 'start join';
2039+
SNTUtils.log("End joining no longer supported: Establishing a star-join' on reversed path");
2040+
Path pReversed = p.reversed();
2041+
// replace the path in all data structures...
2042+
allPaths.remove(p);
2043+
pathIdMap.remove(p.getID(), p);
2044+
pathNameMap.remove(p.getName(), p);
2045+
2046+
allPaths.add(pReversed);
2047+
pathIdMap.put(pReversed.getID(), pReversed);
2048+
pathNameMap.put(pReversed.getName(), pReversed);
2049+
2050+
pReversed.setBranchFrom(endPath, endJoinPoint);
2051+
2052+
for (final Path join : new ArrayList<>(p.connectedPaths)) {
2053+
if (join.getParentPath() == p) {
2054+
final PointInImage joinPoint = join.getBranchPoint();
2055+
join.detachFromParent();
2056+
join.setBranchFrom(pReversed, joinPoint);
2057+
}
2058+
}
2059+
} // end null-check else
20382060
}
20392061
if (fittedID != null) {
20402062
p.fitted = getPathFromID(fittedID);

0 commit comments

Comments
 (0)