Skip to content

ofRectangle::inside(): include points on the edge (fixes #4871, clean version of #8475) - #8584

Merged
danoli3 merged 2 commits into
openframeworks:masterfrom
danoli3:ofrectangle-inside-inclusive
Oct 13, 2026
Merged

danoli3 merged 2 commits into
openframeworks:masterfrom
danoli3:ofrectangle-inside-inclusive

Conversation

@danoli3

@danoli3 danoli3 commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Clean version of #8475, fixing the issues raised there. Fixes #4871.

Change

What it fixes

intersects(p0, p1) checks whether either endpoint is inside(), then checks for crossings with each edge. With exclusive bounds it missed segments that only touch the boundary:

ofRectangle r(0, 0, 100, 100);
r.intersects({20, 100}, {60, 100});   // along part of the bottom edge: false on master
r.intersects({0, 50}, {-50, 50});     // touching the left edge from outside: false on master
r.intersects({100, 100}, {150, 150}); // touching a corner from outside: false on master

The exact segment from #4871, ({0, 50}, {50, 0}), already returns true on master, because ofLineSegmentIntersection counts an endpoint lying on an edge. The cases above still fail on master.

Tested (macOS, make RunDebug, as in CI)

master this PR
ofRectangleTests 16 / 133 failed 133 / 133 passed

Behaviour change

inside() now returns true for points on the edge, and inside(rect) returns true for a rectangle that shares an edge, including an identical rectangle.

Callers that use inside() for mouse hit-testing (ofxGui, ofEasyCam) now also count the edge pixel. Adjacent ofxGui controls that share an edge can both match a click exactly on the shared edge. intersects(ofRectangle) is unchanged: rectangles that only share an edge still don't intersect.


Original description from #8475 (by @Jarvis-BOT-Equilateral-AI)

Problem

Issue #4871 reported that ofRectangle::intersects() returns false for certain line segments that should intersect the rectangle.

Failing test case:

ofRectangle(0, 0, 100, 100).intersects(ofPoint(0, 50), ofPoint(50, 0))
// Returns false, but should return true

Both endpoints (0, 50) and (50, 0) lie exactly on the rectangle's boundaries, but inside() was using exclusive boundary checks (> and <) which incorrectly classified boundary points as outside.

Solution

Changed ofRectangle::inside() from exclusive to inclusive boundary checks:

Before:

return p.x > getMinX() && p.y > getMinY() &&
       p.x < getMaxX() && p.y < getMaxY();

After:

return p.x >= getMinX() && p.y >= getMinY() &&
       p.x <= getMaxX() && p.y <= getMaxY();

This is a minimal 2-character change that fixes the entire class of boundary-related bugs. In computational geometry, boundary points are typically considered "inside" closed shapes. The intersects() method already handles line-edge crossing detection, so recognizing boundary points as inside provides complete intersection coverage.

Testing

Added comprehensive unit tests in tests/types/rectangleTests/ covering:

All tests follow the existing OpenFrameworks ofxUnitTests framework pattern.

Impact

Standards Applied

This fix follows the C++ Geometric Algorithms Standard from Equilateral AI:

  • Use inclusive boundaries (>=, <=) for containment tests
  • Treat boundary points as inside closed shapes
  • Ensure symmetry in intersection detection

Full standard: https://github.com/Equilateral-AI/equilateral-open-standards/blob/main/cpp-geometric-algorithms-standard.md


🤖 Generated with assistance from Equilateral AI

This contribution was created with AI assistance and reviewed by human engineers.
Our agents follow the standards documented at:
https://github.com/Equilateral-AI/equilateral-open-standards

Our Contribution Policy: https://github.com/Equilateral-AI/equilateral-open-standards/blob/main/EQUILATERAL-AI-OSS-CONTRIBUTION-POLICY.md

Opt-out: If you prefer not to receive AI-assisted contributions,
please email james.ford@equilateral.ai

Co-Authored-By: Jarvis (Equilateral AI) jarvis@equilateral.ai

inside() used exclusive bounds (> and <), so points exactly on an edge
or corner were outside. intersects(p0, p1) relies on inside() for its
endpoints, so a segment whose endpoints both lie on the boundary, e.g.

    ofRectangle(0, 0, 100, 100).intersects({0, 50}, {50, 0})

returned false. inside() now uses inclusive bounds (>= and <=).

Cherry-picked from openframeworks#8475 (a674147).
The inside() docs said points on the edge are outside; update them to
match the inclusive bounds.

Add the tests from openframeworks#8475 to the existing tests/types/ofRectangleTests
app (it already has addons.make with ofxUnitTests) instead of a new
rectangleTests folder, which could not find ofxUnitTests.h. Corner and
edge names now use OF's y-down coordinates.

Also test segments that lie along part of an edge or touch the
rectangle from outside, which intersects(p0, p1) missed before; the
exact segment from openframeworks#4871 already passes on master because
ofLineSegmentIntersection counts endpoints on an edge. intersects(rect)
is unchanged: rectangles sharing only an edge still do not intersect.
@danoli3

danoli3 commented Oct 12, 2026

Copy link
Copy Markdown
Member Author

updated and merged with Qwen

@danoli3
danoli3 merged commit 80fa60d into openframeworks:master Oct 13, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ofRectangle::intersects(const ofPoint& p0, const ofPoint& p1) fails in one case.

2 participants