From 1928a1812bb296bb3fd09b9a0084e30048332fa6 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 23 Nov 2023 09:15:38 +0100
Subject: [PATCH] Ellipse: check at 7*7 points

---
 Base/Axis/Bin.cpp       |  5 +++++
 Base/Axis/Bin.h         |  1 +
 Device/Mask/Ellipse.cpp | 15 ++++++++++-----
 3 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/Base/Axis/Bin.cpp b/Base/Axis/Bin.cpp
index c6461fcbf14..d731b4a9000 100644
--- a/Base/Axis/Bin.cpp
+++ b/Base/Axis/Bin.cpp
@@ -43,6 +43,11 @@ Bin1D::Bin1D(double lower, double upper)
     }
 }
 
+double Bin1D::atFraction(double fraction) const
+{
+    return m_lower * (1 - fraction) + m_upper * fraction;
+}
+
 std::optional<Bin1D> Bin1D::clipped_or_nil(double lower, double upper) const
 {
     ASSERT(lower <= upper);
diff --git a/Base/Axis/Bin.h b/Base/Axis/Bin.h
index 0efd1201f01..6651b02fffb 100644
--- a/Base/Axis/Bin.h
+++ b/Base/Axis/Bin.h
@@ -33,6 +33,7 @@ public:
     double upperBound() const { return m_upper; }
     double center() const { return (m_lower + m_upper) / 2; }
     double binSize() const { return m_upper - m_lower; }
+    double atFraction(double fraction) const;
 
     std::optional<Bin1D> clipped_or_nil(double lower, double upper) const;
 
diff --git a/Device/Mask/Ellipse.cpp b/Device/Mask/Ellipse.cpp
index 13ea40d4392..c9d38dac4b8 100644
--- a/Device/Mask/Ellipse.cpp
+++ b/Device/Mask/Ellipse.cpp
@@ -37,17 +37,22 @@ Ellipse::Ellipse(double xcenter, double ycenter, double xradius, double yradius,
 
 bool Ellipse::contains(double x, double y) const
 {
-    double u = std::cos(m_theta) * (x - m_xc) + std::sin(m_theta) * (y - m_yc);
-    double v = -std::sin(m_theta) * (x - m_xc) + std::cos(m_theta) * (y - m_yc);
+    double u = std::cos(m_theta) * (x - m_xc) - std::sin(m_theta) * (y - m_yc);
+    double v = std::sin(m_theta) * (x - m_xc) + std::cos(m_theta) * (y - m_yc);
     double d = (u / m_xr) * (u / m_xr) + (v / m_yr) * (v / m_yr);
     return d <= 1;
 }
 
-//! Returns true if area defined by two bins is inside or on border of ellipse;
-//! more precisely, if mid point of two bins satisfy this condition.
 bool Ellipse::contains(const Bin1D& binx, const Bin1D& biny) const
 {
-    return contains(binx.center(), biny.center());
+    // The overlap of an ellipse and a rectangle, in full generality, requires quite
+    // a complicated algorithm. We therefore content ourselves with a check for n*n points.
+    const int n = 7;
+    for (int ix = 0; ix < n; ++ix)
+	for (int iy = 0; iy < n; ++iy)
+	    if (contains(binx.atFraction(ix / (n - 1.)), biny.atFraction(iy / (n - 1.))))
+		return true;
+    return false;
 }
 
 void Ellipse::print(std::ostream& ostr) const
-- 
GitLab