@@ -139,6 +139,26 @@ public function testArcToBezierCurvesDoesNotDegenerateAtExactRadiusTolerance():
139139 self ::assertNotSame ([[20.0 , 30.0 , 20.0 , 30.0 , 20.0 , 30.0 ]], $ curves );
140140 }
141141
142+ public function testArcToBezierCurvesDoesNotDegenerateAtExactRadiusYTolerance (): void
143+ {
144+ $ converter = new SvgArcConverter ();
145+
146+ $ curves = $ converter ->arcToBezierCurves (
147+ 0.0 ,
148+ 0.0 ,
149+ 2.0e-10 ,
150+ 1.0e-10 ,
151+ 0.0 ,
152+ 0 ,
153+ 1 ,
154+ 20.0 ,
155+ 30.0 ,
156+ );
157+
158+ self ::assertNotSame ([], $ curves );
159+ self ::assertNotSame ([[20.0 , 30.0 , 20.0 , 30.0 , 20.0 , 30.0 ]], $ curves );
160+ }
161+
142162 public function testArcToBezierCurvesUsesSweepAndLargeArcFlagsToChooseDifferentSolutions (): void
143163 {
144164 $ converter = new SvgArcConverter ();
@@ -285,6 +305,94 @@ public function testCalculatePrimeCoordinatesMatchesExpectedRotatedValues(): voi
285305 self ::assertSame ([-21.213203435596427 , 21.213203435596423 ], $ primeCoordinates );
286306 }
287307
308+ public function testNormalizeArcRadiiReturnsSameInstanceWhenScaleEqualsOne (): void
309+ {
310+ $ converter = new SvgArcConverter ();
311+ $ params = new ArcParams (
312+ 0.0 ,
313+ 0.0 ,
314+ 20.0 ,
315+ 0.0 ,
316+ 10.0 ,
317+ 99.0 ,
318+ 1.0 ,
319+ 0.0 ,
320+ 0 ,
321+ 1 ,
322+ );
323+
324+ $ normalized = self ::invokePrivateMethod ($ converter , 'normalizeArcRadii ' , [$ params ]);
325+
326+ self ::assertSame ($ params , $ normalized );
327+ }
328+
329+ public function testNormalizeArcRadiiScalesRotatedArcUsingExpectedFactors (): void
330+ {
331+ $ converter = new SvgArcConverter ();
332+ $ params = new ArcParams (
333+ 0.0 ,
334+ 10.0 ,
335+ 60.0 ,
336+ 30.0 ,
337+ 15.0 ,
338+ 8.0 ,
339+ cos (deg2rad (45.0 )),
340+ sin (deg2rad (45.0 )),
341+ 1 ,
342+ 1 ,
343+ );
344+
345+ $ normalized = self ::invokePrivateMethod ($ converter , 'normalizeArcRadii ' , [$ params ]);
346+
347+ self ::assertNotSame ($ params , $ normalized );
348+ self ::assertEqualsWithDelta (38.77015604817706 , $ normalized ->radiusX , 0.0001 );
349+ self ::assertEqualsWithDelta (20.677416559027762 , $ normalized ->radiusY , 0.0001 );
350+ }
351+
352+ public function testCalculateArcCenterRespectsSweepDirection (): void
353+ {
354+ $ converter = new SvgArcConverter ();
355+ $ counterClockwise = new ArcParams (10.0 , 0.0 , 0.0 , 10.0 , 10.0 , 10.0 , 1.0 , 0.0 , 0 , 0 );
356+ $ clockwise = new ArcParams (10.0 , 0.0 , 0.0 , 10.0 , 10.0 , 10.0 , 1.0 , 0.0 , 0 , 1 );
357+ $ degenerate = new ArcParams (0.0 , 0.0 , 0.0 , 0.0 , 10.0 , 20.0 , cos (deg2rad (30.0 )), sin (deg2rad (30.0 )), 0 , 1 );
358+
359+ self ::assertSame (
360+ [10.0 , 10.0 ],
361+ self ::invokePrivateMethod ($ converter , 'calculateArcCenter ' , [$ counterClockwise ]),
362+ );
363+ self ::assertSame (
364+ [0.0 , 0.0 ],
365+ self ::invokePrivateMethod ($ converter , 'calculateArcCenter ' , [$ clockwise ]),
366+ );
367+ self ::assertSame (
368+ [0.0 , 0.0 ],
369+ self ::invokePrivateMethod ($ converter , 'calculateArcCenter ' , [$ degenerate ]),
370+ );
371+ }
372+
373+ public function testCalculateArcAnglesReturnsExpectedSweepAdjustedDelta (): void
374+ {
375+ $ converter = new SvgArcConverter ();
376+ $ counterClockwise = new ArcParams (10.0 , 0.0 , 0.0 , 10.0 , 10.0 , 10.0 , 1.0 , 0.0 , 0 , 0 );
377+ $ clockwise = new ArcParams (10.0 , 0.0 , 0.0 , 10.0 , 10.0 , 10.0 , 1.0 , 0.0 , 0 , 1 );
378+
379+ $ counterClockwiseAngles = self ::invokePrivateMethod (
380+ $ converter ,
381+ 'calculateArcAngles ' ,
382+ [$ counterClockwise , 10.0 , 10.0 ],
383+ );
384+ $ clockwiseAngles = self ::invokePrivateMethod (
385+ $ converter ,
386+ 'calculateArcAngles ' ,
387+ [$ clockwise , 0.0 , 0.0 ],
388+ );
389+
390+ self ::assertEqualsWithDelta (-0.7853981633974483 , $ counterClockwiseAngles [0 ], 0.0001 );
391+ self ::assertEqualsWithDelta (-M_PI , $ counterClockwiseAngles [1 ], 0.0001 );
392+ self ::assertEqualsWithDelta (-0.7853981633974483 , $ clockwiseAngles [0 ], 0.0001 );
393+ self ::assertEqualsWithDelta (M_PI , $ clockwiseAngles [1 ], 0.0001 );
394+ }
395+
288396 public function testGenerateArcCurvesUsesSingleSegmentBelowNinetyDegrees (): void
289397 {
290398 $ converter = new SvgArcConverter ();
0 commit comments