Skip to content

Commit 20a3f98

Browse files
committed
Protect overlap tracker from crash when computing intersection in edge cases.
In rare occasions, the overlap tracker generates a NPE when computing polyon intersection. This is a bug that originates from the GPCJ library at this place: https://github.com/ChristianLutz/gpcj/blob/master/gpcj/src/main/java/com/seisw/util/geom/Clip.java#L1604 It is unclear why this happens reproducibly. The faulty polygons are perfectly fine as far as we cam judge them. This commit introduces a safeguard. If such an error happens, we default to computing the interesection with the bounding box instead of the polygons. Fix #334
1 parent e6d1853 commit 20a3f98

1 file changed

Lines changed: 41 additions & 5 deletions

File tree

src/main/java/fiji/plugin/trackmate/tracking/overlap/OverlapTracker.java

Lines changed: 41 additions & 5 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>.
@@ -23,6 +23,7 @@
2323

2424
import static fiji.plugin.trackmate.tracking.overlap.OverlapTrackerFactory.BASE_ERROR_MESSAGE;
2525

26+
import java.awt.Color;
2627
import java.util.ArrayList;
2728
import java.util.Arrays;
2829
import java.util.Collections;
@@ -213,7 +214,7 @@ public boolean process()
213214
for ( final Spot target : targetGeometries.keySet() )
214215
{
215216
final Polygon2D targetPoly = targetGeometries.get( target );
216-
futures.add( executors.submit( new FindBestSourceTask( target, targetPoly, sourceGeometries, minIoU ) ) );
217+
futures.add( executors.submit( new FindBestSourceTask( target, targetPoly, sourceGeometries, minIoU, enlargeFactor, logger ) ) );
217218
}
218219

219220
// Get results.
@@ -345,12 +346,18 @@ private static final class FindBestSourceTask implements Callable< IoULink >
345346

346347
private final double minIoU;
347348

348-
public FindBestSourceTask( final Spot target, final Polygon2D targetPoly, final Map< Spot, Polygon2D > sourceGeometries, final double minIoU )
349+
private final double scale;
350+
351+
private final Logger logger;
352+
353+
public FindBestSourceTask( final Spot target, final Polygon2D targetPoly, final Map< Spot, Polygon2D > sourceGeometries, final double minIoU, final double scale, final Logger logger )
349354
{
350355
this.target = target;
351356
this.targetPoly = targetPoly;
352357
this.sourceGeometries = sourceGeometries;
353358
this.minIoU = minIoU;
359+
this.scale = scale;
360+
this.logger = logger;
354361
}
355362

356363
@Override
@@ -362,7 +369,36 @@ public IoULink call() throws Exception
362369
for ( final Spot spot : sourceGeometries.keySet() )
363370
{
364371
final Polygon2D sourcePoly = sourceGeometries.get( spot );
365-
final double intersection = Math.abs( Polygons2D.intersection( targetPoly, sourcePoly ).area() );
372+
double intersection;
373+
try
374+
{
375+
intersection = Math.abs( Polygons2D.intersection( targetPoly, sourcePoly ).area() );
376+
}
377+
catch ( final NullPointerException e )
378+
{
379+
/*
380+
* Sometimes the intersection computation fails with NPE.
381+
* The code crashes here:
382+
*
383+
* https://github.com/ChristianLutz/gpcj/blob/master/gpcj/
384+
* src/main/java/com/seisw/util/geom/Clip.java#L1604
385+
*
386+
* The issue is not with the polygons, they are good. It's a
387+
* bug in the Clip algorithm that doesn't handle certain
388+
* edge cases.
389+
*
390+
* When this happens, we catch the error, and compute an
391+
* approximation of the intersection with the bounding
392+
* boxes.
393+
*/
394+
logger.log( "Error trying to compute intersection between spots "
395+
+ spot.ID() + " and " + target.ID() + "\n"
396+
+ "Approximating with the bounding box.\n", Color.ORANGE.darker() );
397+
final Rectangle2D sourceRectangle = toBoundingBox( spot, scale );
398+
final Rectangle2D targetRectangle = toBoundingBox( target, scale );
399+
final Polygon2D approxIntersection = Polygons2D.intersection( sourceRectangle, targetRectangle );
400+
intersection = Math.abs( approxIntersection.area() );
401+
}
366402
if ( intersection == 0. )
367403
continue;
368404

0 commit comments

Comments
 (0)