Skip to content

Commit e7daba3

Browse files
authored
fix!: Remove middle intersection point on shared line segments in collision detection (#4004)
When two line segments were collinear and overlapping, `LineSegment.intersections` returned a single synthetic point: the average of the overlap's end points. For shape collision detection this meant that two shapes sharing an edge (for example two axis-aligned rectangles standing side by side) reported both the real corner points and an extra point in the middle of the shared edge. This PR changes the collinear-overlap case of `LineSegment.intersections` to return the actual end points of the overlapping section instead of their average. Segments that only touch in a single point still return that one point. As a result, collision detection on shared edges now only reports the end points of the shared segment, without the synthetic middle point. The dartdoc on `LineSegment.intersections` and `PolygonPolygonIntersections.intersect` has been updated to describe the new behavior, and the affected tests now assert the overlap end points.
1 parent 698f261 commit e7daba3

4 files changed

Lines changed: 19 additions & 27 deletions

File tree

packages/flame/lib/src/geometry/line.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class Line {
2727
final determinant = a * otherLine.b - otherLine.a * b;
2828
if (determinant == 0) {
2929
//The lines are parallel (potentially coincides) and have no intersection
30-
return [];
30+
return const [];
3131
}
3232
return [
3333
Vector2(

packages/flame/lib/src/geometry/line_segment.dart

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,11 @@ class LineSegment {
6464
return inflate(-amount);
6565
}
6666

67-
/// Returns an empty list if there are no intersections between the segments
68-
/// If the segments are concurrent, the intersecting point is returned as a
69-
/// list with a single point
67+
/// Returns an empty list if there are no intersections between the segments.
68+
/// If the segments intersect in a single point, that point is returned in a
69+
/// list with a single element.
70+
/// If the segments are collinear and overlap, the end points of the
71+
/// overlapping section are returned.
7072
List<Vector2> intersections(LineSegment otherSegment) {
7173
final result = toLine().intersections(otherSegment.toLine());
7274
if (result.isNotEmpty) {
@@ -86,14 +88,10 @@ class LineSegment {
8688
if (containsPoint(otherSegment.to)) otherSegment.to,
8789
};
8890
if (overlaps.isNotEmpty) {
89-
final sum = Vector2.zero();
90-
for (final overlap in overlaps) {
91-
sum.add(overlap);
92-
}
93-
return [sum..scale(1 / overlaps.length)];
91+
return overlaps.toList(growable: false);
9492
}
9593
}
96-
return [];
94+
return const [];
9795
}
9896

9997
/// Whether the given [point] lies in this line segment.

packages/flame/lib/src/geometry/shape_intersections.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ class PolygonPolygonIntersections
3131
extends Intersections<PolygonComponent, PolygonComponent> {
3232
/// Returns the intersection points of [polygonA] and [polygonB]
3333
/// The two polygons are required to be convex
34-
/// If they share a segment of a line, both end points and the center point of
35-
/// that line segment will be counted as collision points
34+
/// If they share a segment of a line, both end points of that segment will
35+
/// be counted as collision points
3636
@override
3737
List<Vector2> intersect(
3838
PolygonComponent polygonA,

packages/flame/test/collisions/collision_detection_test.dart

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -107,23 +107,21 @@ void main() {
107107
final segmentB = LineSegment(Vector2.all(0), Vector2.all(1));
108108
final intersection = segmentA.intersections(segmentB);
109109
expect(
110-
intersection.isNotEmpty,
111-
true,
112-
reason: 'Should have intersection at (0.5, 0.5)',
110+
intersection,
111+
unorderedEquals([Vector2.all(0), Vector2.all(1)]),
112+
reason: 'Should intersect at the end points of the overlap',
113113
);
114-
expect(intersection.first == Vector2.all(0.5), true);
115114
});
116115

117116
test('overlapping line segments', () {
118117
final segmentA = LineSegment(Vector2.all(0), Vector2.all(1));
119118
final segmentB = LineSegment(Vector2.all(0.5), Vector2.all(1.5));
120119
final intersection = segmentA.intersections(segmentB);
121120
expect(
122-
intersection.isNotEmpty,
123-
true,
124-
reason: 'Should intersect at (0.75, 0.75)',
121+
intersection,
122+
unorderedEquals([Vector2.all(0.5), Vector2.all(1)]),
123+
reason: 'Should intersect at the end points of the overlap',
125124
);
126-
expect(intersection.first == Vector2.all(0.75), true);
127125
});
128126

129127
test('one pixel overlap in different angles', () {
@@ -312,13 +310,12 @@ void main() {
312310
intersections,
313311
containsAll([
314312
Vector2(2.0, 2.0),
315-
Vector2(2.0, 1.5),
316313
Vector2(2.0, 1.0),
317314
]),
318315
reason: 'Does not have all the correct intersection points',
319316
);
320317
expect(
321-
intersections.length == 3,
318+
intersections.length == 2,
322319
true,
323320
reason: 'Wrong number of intersections',
324321
);
@@ -377,15 +374,13 @@ void main() {
377374
containsAll([
378375
Vector2(2, 0),
379376
Vector2(2, 2),
380-
Vector2(1, 0),
381377
Vector2(0, 0),
382-
Vector2(0, 1),
383378
Vector2(0, 2),
384379
]),
385380
reason: 'Does not have all the correct intersection points',
386381
);
387382
expect(
388-
intersections.length == 6,
383+
intersections.length == 4,
389384
true,
390385
reason: 'Wrong number of intersections',
391386
);
@@ -457,13 +452,12 @@ void main() {
457452
intersections,
458453
containsAll([
459454
Vector2(4, 0),
460-
Vector2(4, 2),
461455
Vector2(4, 4),
462456
]),
463457
reason: 'Missed intersections',
464458
);
465459
expect(
466-
intersections.length == 3,
460+
intersections.length == 2,
467461
true,
468462
reason: 'Wrong number of intersections',
469463
);

0 commit comments

Comments
 (0)