@@ -90,6 +90,20 @@ TEST (LineTests, Contains)
9090 EXPECT_TRUE (l.contains (Point<float > (5 .0f , 5 .0f )));
9191 EXPECT_FALSE (l.contains (Point<float > (5 .0f , 6 .0f )));
9292 EXPECT_TRUE (l.contains (Point<float > (5 .001f , 5 .001f ), 0 .01f ));
93+
94+ // Test the specific case mentioned by the user
95+ EXPECT_TRUE (l.contains (Point<float > (5 .0f , 5 .1f ), 0 .2f ));
96+
97+ // Test edge cases with corrected distance calculation
98+ Line<float > l2 (0 .0f , 0 .0f , 10 .0f , 0 .0f ); // Horizontal line
99+ EXPECT_TRUE (l2.contains (Point<float > (5 .0f , 0 .1f ), 0 .2f ));
100+ EXPECT_FALSE (l2.contains (Point<float > (5 .0f , 0 .3f ), 0 .2f ));
101+
102+ // Test zero-length line edge case
103+ Line<float > zeroLine (5 .0f , 5 .0f , 5 .0f , 5 .0f );
104+ EXPECT_TRUE (zeroLine.contains (Point<float > (5 .0f , 5 .0f ), 0 .1f ));
105+ EXPECT_TRUE (zeroLine.contains (Point<float > (5 .05f , 5 .05f ), 0 .1f ));
106+ EXPECT_FALSE (zeroLine.contains (Point<float > (5 .2f , 5 .2f ), 0 .1f ));
93107}
94108
95109TEST (LineTests, PointAlong)
@@ -194,3 +208,152 @@ TEST (LineTests, StreamOutput)
194208 str << l;
195209 EXPECT_EQ (str, " 1, 2, 3, 4" );
196210}
211+
212+ // Additional missing tests
213+ TEST (LineTests, ExtendMethods)
214+ {
215+ Line<float > l (5 .0f , 0 .0f , 15 .0f , 0 .0f );
216+
217+ // Test extend method (non-const version)
218+ l.extend (5 .0f );
219+ EXPECT_EQ (l.getStart (), Point<float > (0 .0f , 0 .0f ));
220+ EXPECT_EQ (l.getEnd (), Point<float > (20 .0f , 0 .0f ));
221+
222+ // Test extendBefore method (non-const version)
223+ l.extendBefore (5 .0f );
224+ EXPECT_EQ (l.getStart (), Point<float > (-5 .0f , 0 .0f ));
225+ EXPECT_EQ (l.getEnd (), Point<float > (20 .0f , 0 .0f ));
226+
227+ // Test extendAfter method (non-const version)
228+ l.extendAfter (5 .0f );
229+ EXPECT_EQ (l.getStart (), Point<float > (-5 .0f , 0 .0f ));
230+ EXPECT_EQ (l.getEnd (), Point<float > (25 .0f , 0 .0f ));
231+ }
232+
233+ TEST (LineTests, TransformMethods)
234+ {
235+ Line<float > l (1 .0f , 2 .0f , 3 .0f , 4 .0f );
236+
237+ // Test transform method
238+ AffineTransform t = AffineTransform::translation (5 .0f , 6 .0f );
239+ l.transform (t);
240+ EXPECT_EQ (l.getStart (), Point<float > (6 .0f , 8 .0f ));
241+ EXPECT_EQ (l.getEnd (), Point<float > (8 .0f , 10 .0f ));
242+
243+ // Test transformed method
244+ Line<float > l2 (1 .0f , 2 .0f , 3 .0f , 4 .0f );
245+ AffineTransform t2 = AffineTransform::scaling (2 .0f );
246+ Line<float > transformed = l2.transformed (t2);
247+ EXPECT_EQ (transformed.getStart (), Point<float > (2 .0f , 4 .0f ));
248+ EXPECT_EQ (transformed.getEnd (), Point<float > (6 .0f , 8 .0f ));
249+
250+ // Original line should be unchanged
251+ EXPECT_EQ (l2.getStart (), Point<float > (1 .0f , 2 .0f ));
252+ EXPECT_EQ (l2.getEnd (), Point<float > (3 .0f , 4 .0f ));
253+ }
254+
255+ TEST (LineTests, EdgeCases)
256+ {
257+ // Test with zero-length line
258+ Line<float > zeroLine (5 .0f , 5 .0f , 5 .0f , 5 .0f );
259+ EXPECT_FLOAT_EQ (zeroLine.length (), 0 .0f );
260+ EXPECT_TRUE (zeroLine.contains (Point<float > (5 .0f , 5 .0f )));
261+
262+ // Test slope with vertical line
263+ Line<float > verticalLine (1 .0f , 1 .0f , 1 .0f , 5 .0f );
264+ EXPECT_FLOAT_EQ (verticalLine.slope (), 0 .0f ); // Vertical line has slope 0 in this implementation
265+
266+ // Test pointAlong with negative and > 1.0 values
267+ Line<float > l (0 .0f , 0 .0f , 10 .0f , 0 .0f );
268+ EXPECT_EQ (l.pointAlong (-0 .5f ), Point<float > (-5 .0f , 0 .0f ));
269+ EXPECT_EQ (l.pointAlong (2 .0f ), Point<float > (20 .0f , 0 .0f ));
270+
271+ // Test extend with negative values
272+ Line<float > l2 (10 .0f , 10 .0f , 20 .0f , 10 .0f );
273+ l2.extend (-5 .0f );
274+ EXPECT_EQ (l2.getStart (), Point<float > (15 .0f , 10 .0f ));
275+ EXPECT_EQ (l2.getEnd (), Point<float > (15 .0f , 10 .0f ));
276+
277+ // Test contains with tolerance on edge cases
278+ Line<float > l3 (0 .0f , 0 .0f , 10 .0f , 10 .0f );
279+ EXPECT_TRUE (l3.contains (Point<float > (0 .0f , 0 .0f )));
280+ EXPECT_TRUE (l3.contains (Point<float > (10 .0f , 10 .0f )));
281+ EXPECT_FALSE (l3.contains (Point<float > (5 .0f , 6 .0f )));
282+ EXPECT_TRUE (l3.contains (Point<float > (5 .0f , 5 .1f ), 0 .2f )); // Corrected: should be true with sufficient tolerance
283+ }
284+
285+ TEST (LineTests, TypeConversionEdgeCases)
286+ {
287+ // Test with extreme values
288+ Line<float > l (1 .9f , 2 .1f , 3 .9f , 4 .1f );
289+ auto rounded = l.roundToInt ();
290+ EXPECT_EQ (rounded.getStart (), Point<int > (2 , 2 ));
291+ EXPECT_EQ (rounded.getEnd (), Point<int > (4 , 4 ));
292+
293+ // Test with negative values
294+ Line<float > lNeg (-1 .7f , -2 .3f , -3 .1f , -4 .9f );
295+ auto roundedNeg = lNeg.roundToInt ();
296+ EXPECT_EQ (roundedNeg.getStart (), Point<int > (-2 , -2 ));
297+ EXPECT_EQ (roundedNeg.getEnd (), Point<int > (-3 , -5 ));
298+ }
299+
300+ TEST (LineTests, RotationEdgeCases)
301+ {
302+ // Test rotation with different angles
303+ Line<float > l (0 .0f , 0 .0f , 2 .0f , 0 .0f );
304+
305+ // 180 degree rotation
306+ auto rotated180 = l.rotateAtPoint (Point<float > (1 .0f , 0 .0f ), MathConstants<float >::pi);
307+ EXPECT_NEAR (rotated180.getStartX (), 2 .0f , tol);
308+ EXPECT_NEAR (rotated180.getStartY (), 0 .0f , tol);
309+ EXPECT_NEAR (rotated180.getEndX (), 0 .0f , tol);
310+ EXPECT_NEAR (rotated180.getEndY (), 0 .0f , tol);
311+
312+ // 270 degree rotation
313+ auto rotated270 = l.rotateAtPoint (Point<float > (0 .0f , 0 .0f ), -MathConstants<float >::halfPi);
314+ EXPECT_NEAR (rotated270.getStartX (), 0 .0f , tol);
315+ EXPECT_NEAR (rotated270.getStartY (), 0 .0f , tol);
316+ EXPECT_NEAR (rotated270.getEndX (), 0 .0f , tol);
317+ EXPECT_NEAR (rotated270.getEndY (), -2 .0f , tol);
318+ }
319+
320+ TEST (LineTests, ExtendWithDifferentDirections)
321+ {
322+ // Test extend with diagonal line
323+ Line<float > diagLine (0 .0f , 0 .0f , 3 .0f , 4 .0f ); // Length = 5
324+ auto extended = diagLine.extended (5 .0f );
325+ EXPECT_FLOAT_EQ (extended.length (), 15 .0f );
326+
327+ // Test extend before/after with diagonal line
328+ auto extendedBefore = diagLine.extendedBefore (5 .0f );
329+ auto extendedAfter = diagLine.extendedAfter (5 .0f );
330+ EXPECT_FLOAT_EQ (extendedBefore.length (), 10 .0f );
331+ EXPECT_FLOAT_EQ (extendedAfter.length (), 10 .0f );
332+ }
333+
334+ TEST (LineTests, ComplexTransformations)
335+ {
336+ Line<float > l (1 .0f , 1 .0f , 2 .0f , 2 .0f );
337+
338+ // Test combination of transformations
339+ AffineTransform complex = AffineTransform::translation (5 .0f , 5 .0f )
340+ .scaled (2 .0f )
341+ .rotated (MathConstants<float >::pi / 4 .0f );
342+
343+ Line<float > transformed = l.transformed (complex );
344+ EXPECT_FALSE (transformed.getStart () == l.getStart ());
345+ EXPECT_FALSE (transformed.getEnd () == l.getEnd ());
346+ }
347+
348+ TEST (LineTests, ApproximatelyEqual)
349+ {
350+ Line<float > l1 (1 .0f , 2 .0f , 3 .0f , 4 .0f );
351+ Line<float > l2 (1 .0000001f , 2 .0000001f , 3 .0000001f , 4 .0000001f );
352+ Line<float > l3 (1 .1f , 2 .1f , 3 .1f , 4 .1f );
353+
354+ // Test floating point precision
355+ EXPECT_TRUE (l1.getStart ().approximatelyEqualTo (l2.getStart ()));
356+ EXPECT_TRUE (l1.getEnd ().approximatelyEqualTo (l2.getEnd ()));
357+ EXPECT_FALSE (l1.getStart ().approximatelyEqualTo (l3.getStart ()));
358+ EXPECT_FALSE (l1.getEnd ().approximatelyEqualTo (l3.getEnd ()));
359+ }
0 commit comments