diff --git a/src/geom/SpanSet.cc b/src/geom/SpanSet.cc index 6ec16ffdd..2a7512411 100644 --- a/src/geom/SpanSet.cc +++ b/src/geom/SpanSet.cc @@ -727,16 +727,18 @@ std::shared_ptr SpanSet::intersect(SpanSet const& other) const { return std::make_shared(this->_spanVector); } std::vector tempVec; - auto otherIter = other.begin(); + auto otherBeginIter = other.begin(); for (auto const& spn : _spanVector) { - while (otherIter != other.end() && otherIter->getY() <= spn.getY()) { + while(otherBeginIter != other.end() && otherBeginIter->getY() < spn.getY()) { + ++otherBeginIter; + } + for (auto otherIter = otherBeginIter; otherIter != other.end() && otherIter->getY() <= spn.getY(); ++otherIter) { if (spansOverlap(spn, *otherIter)) { auto newMin = std::max(spn.getMinX(), otherIter->getMinX()); auto newMax = std::min(spn.getMaxX(), otherIter->getMaxX()); auto newSpan = Span(spn.getY(), newMin, newMax); tempVec.push_back(newSpan); } - ++otherIter; } } return std::make_shared(std::move(tempVec)); @@ -758,12 +760,15 @@ std::shared_ptr SpanSet::intersectNot(SpanSet const& other) const { * or with other containing this b1| a1| a2| b2| */ std::vector tempVec; - auto otherIter = other.begin(); + auto otherBeginIter = other.begin(); for (auto const& spn : _spanVector) { bool added = false; bool spanStarted = false; int spanBottom = 0; - while (otherIter != other.end() && otherIter->getY() <= spn.getY()) { + while(otherBeginIter != other.end() && otherBeginIter->getY() < spn.getY()) { + ++otherBeginIter; + } + for (auto otherIter = otherBeginIter; otherIter != other.end() && otherIter->getY() <= spn.getY(); ++otherIter) { if (spansOverlap(spn, *otherIter)) { added = true; /* To handle one span containing the other, the spans will be added @@ -806,7 +811,6 @@ std::shared_ptr SpanSet::intersectNot(SpanSet const& other) const { if (otherIter->getMaxX() > spn.getMaxX()) { break; } - ++otherIter; } // Check if a span has been started but not finished, if that is the case that means there are // no further spans on this row to consider and the span should be closed and added diff --git a/tests/test_spanSets.py b/tests/test_spanSets.py index 79d1915de..e84a74ffe 100644 --- a/tests/test_spanSets.py +++ b/tests/test_spanSets.py @@ -252,6 +252,20 @@ def testIntersection(self): for expected, val in zip(expectedYRange, spanSetIntersectMask): self.assertEqual(expected, val.getY()) + def testIntersectionWithGap(self): + # This test was created in DM-47945 to fix a bug where the + # intersection of two spansets where multiple spans have the same + # y-value would fail. + spans1 = afwGeom.SpanSet([afwGeom.Span(1, 0, 3), afwGeom.Span(1, 5, 7)]) + spans2 = afwGeom.SpanSet([afwGeom.Span(1, 2, 6)]) + intersection = spans1.intersect(spans2) + trueIntersection = afwGeom.SpanSet([afwGeom.Span(1, 2, 3), afwGeom.Span(1, 5, 6)]) + + self.assertEqual(len(intersection), 2) + + for a, b in zip(intersection, trueIntersection): + self.assertEqual(a, b) + def testIntersectNot(self): firstSpanSet, secondSpanSet = self.makeOverlapSpanSets() @@ -322,6 +336,20 @@ def testIntersectNot(self): targetSpanSet.contains(point): self.assertTrue(resultSpanSet.contains(point)) + def testIntersectNotWithGap(self): + # This test was created in DM-47945 to fix a bug where the + # intersection of two spansets where multiple spans have the same + # y-value would fail. + spans1 = afwGeom.SpanSet([afwGeom.Span(1, 0, 3), afwGeom.Span(1, 5, 7)]) + spans2 = afwGeom.SpanSet([afwGeom.Span(1, 2, 6)]) + intersectNot = spans1.intersectNot(spans2) + trueIntersectNot = afwGeom.SpanSet([afwGeom.Span(1, 0, 1), afwGeom.Span(1, 7, 7)]) + + self.assertEqual(len(intersectNot), 2) + + for a, b in zip(intersectNot, trueIntersectNot): + self.assertEqual(a, b) + def testUnion(self): firstSpanSet, secondSpanSet = self.makeOverlapSpanSets()