ShapeRoi handles "open" ("line-like") rois incorrectly, most notably
when performing set arithmetic using functions such as or() (union),
or and() (intersection) (and others)....

If people think that it makes sense to address this and
that this is the right approach, I will try to finish up
a replacement version of ShapeRoi.java (following the
draft ShapeRoi2).

Currently ShapeRoi2 is supposed to work correctly for the
“basic” ShapeRoi operations, and generally behave no worse
than ShapeRoi. (Constructing a ShapeRoi2 from aShape is not expected to work properly with this version.)

Please let me know if you find any issues with the core
functionality of ShapeRoi2.

Here are two test images that illustrate some of the
problems with ShapeRoi and compare ShapeRoi with a
draft of the proposed fix.

The first image shows ShapeRoi performing correct set
arithmetic with closed rois (in this case EllipseRois):

The orange outlines are boundaries drawn byroi.drawPixels (ip). The cyan solid shapes are
from ip.fill (roi).

The next three rows (rows 4 through 6) are again classical,ShapeRoi, and ShapeRoi2, now illustrating set arithmetic.
Classical rois don’t do set arithmetic, so they are just
the two rois drawn on top of one another to guide the eye.

For the ShapeRoi and ShapeRoi2 rows (rows 5 and 6), the
five columns (of boundary / interior pairs) are the results
of the or() (union), and() (intersection), xor()
(symmetric difference), and the two orders of not() (A-B
and B-A) operations.

In the first image everything works as expected. In the
second image, the Line roi displays correctly as the
classical Line and as the fixed ShapeRoi2 constructed
from the Line. But when a ShapeRoi is constructed fromLine, it displays only with drawPixels(), not withfill(), and vanishes entirely when used in set arithmetic.

Here is the jython script that generates these (and other)
test images:

Add it to a directory from which Fiji / ImageJ loads classes.
(I put it in the plugins directory.)

For completeness, the code for ShapeRoi2.java appears below.
(It is renamed and posted as ShapeRoi2_java.tif to get by the
forum limitations.) It is almost entirely copy-pasted from the
original ShapeRoi.java, with changes isolated to theroiToShape() method, primarily in the newif (!roi.isArea()) if-block.

@mountain_man I would not try to “fix” ShapeRoi, which has had this behavior for many years and would break some existing extensions if changed. Instead, I encourage you to check out the imglib2-roi library:

Shape-based regions of interest in the net.imglib2.roi.geom package.

Both real-space and integer-space ROIs, including conversion between them.

Composition of ROIs including and, or, xor and subtract.

Open, closed and unspecified boundary types.

Deep equality comparison.

Easy iteration of contained points.

No dependency on Java AWT classes.

This work was discussed and directed here on the forum a couple of years ago; see:

Hello,
I am working on adding support for 2D ROIs to ImageJ-OMERO. In order to do this, I will need to expand the ImgLib2-Roi API. My basic plan for doing this is outlined below. @ctrueden, @tpietzsch, @dietzc, @axtimwalde, @joshmoore please let me know your thoughts on this plan, and if you have any questions/concerns regarding it.
Overview
Create the below classes:
a. BinaryMask
b. Composite (OMERO allows for ROIs which are a union of shapes, this would be the equiavalent to that)
c. Re…

Thank you for your quick turn-around in the daily build. I have
updated my ImageJ to 1.52q47 and I now see good “set
arithmetic” with ShapeRoi.

One note: The changes to the roi system (not just ShapeRoi)
seem to have changed the “definition” of Line slightly, causing
it to contain one less point than before (basically [a, b) instead
of [a, b]).

For some reason the new ShapeRoi draws roi boundaries
(Roi.drawPixels (ip)) more thickly than do the “classical”Rois.

In lines_intersecting_q47.png (the second to last image) (the
new) ShapeRoi draws a non-empty boundary for an empty
intersection. (The image name is confusing because the
“change in definition” of Line has caused what had been
two Lines that intersected in one point (pixel) to become a
“missed intersection”.)

These nuances notwithstanding, I will mark Wayne’s post as
the solution, because it fixes the original issue.