@@ -394,6 +394,17 @@ mod tests {
394394 ] ;
395395 let hull = arcline_convex_hull ( & arcs) ;
396396 assert_eq ! ( hull. len( ) , 4 ) ; // All segments should be on hull
397+
398+ // Write SVG for visualization
399+ use crate :: svg:: SVG ;
400+ let arcs2 = arcline_scale ( & arcs, 100.0 ) ;
401+ let hull2 = arcline_scale ( & hull, 100.0 ) ;
402+ let arcs3 = arcline_translate ( & arcs2, point ( 50.0 , 50.0 ) ) ;
403+ let hull3 = arcline_translate ( & hull2, point ( 50.0 , 50.0 ) ) ;
404+ let mut svg = SVG :: new ( 600.0 , 600.0 , Some ( "/tmp/test.svg" ) ) ;
405+ svg. arcline ( & arcs3, "blue" ) ;
406+ svg. arcline ( & hull3, "red" ) ;
407+ svg. write_stroke_width ( 0.1 ) ;
397408 }
398409
399410 #[ test]
@@ -423,6 +434,7 @@ mod tests {
423434 let ( _, start) = result. unwrap ( ) ;
424435 // Should find the bottommost point
425436 assert_eq ! ( start. y, 0.0 ) ;
437+ assert_eq ! ( start. x, 0.0 ) ;
426438 }
427439
428440 #[ test]
@@ -447,6 +459,17 @@ mod tests {
447459 assert ! ( hull_points. contains( & point( 0.0 , 1.0 ) ) ) ; // Top
448460 assert ! ( hull_points. contains( & point( -1.0 , 0.0 ) ) ) ; // Left
449461 assert ! ( hull_points. contains( & point( 0.0 , -1.0 ) ) ) ; // Bottom
462+
463+ // Write SVG for visualization
464+ use crate :: svg:: SVG ;
465+ let arcs2 = arcline_scale ( & arcs, 100.0 ) ;
466+ let hull2 = arcline_scale ( & hull, 100.0 ) ;
467+ let arcs3 = arcline_translate ( & arcs2, point ( 50.0 , 50.0 ) ) ;
468+ let hull3 = arcline_translate ( & hull2, point ( 50.0 , 50.0 ) ) ;
469+ let mut svg = SVG :: new ( 600.0 , 600.0 , Some ( "/tmp/test.svg" ) ) ;
470+ svg. arcline ( & arcs3, "blue" ) ;
471+ svg. arcline ( & hull3, "red" ) ;
472+ svg. write_stroke_width ( 0.1 ) ;
450473 }
451474
452475 #[ test]
@@ -468,6 +491,17 @@ mod tests {
468491 assert ! ( hull_points. contains( & point( 1.0 , 0.0 ) ) ) ;
469492 assert ! ( hull_points. contains( & point( 0.0 , 1.0 ) ) ) ;
470493 assert ! ( hull_points. contains( & point( -1.0 , 0.0 ) ) ) ;
494+
495+ // Write SVG for visualization
496+ use crate :: svg:: SVG ;
497+ let arcs2 = arcline_scale ( & arcs, 100.0 ) ;
498+ let hull2 = arcline_scale ( & hull, 100.0 ) ;
499+ let arcs3 = arcline_translate ( & arcs2, point ( 50.0 , 50.0 ) ) ;
500+ let hull3 = arcline_translate ( & hull2, point ( 50.0 , 50.0 ) ) ;
501+ let mut svg = SVG :: new ( 600.0 , 600.0 , Some ( "/tmp/test.svg" ) ) ;
502+ svg. arcline ( & arcs3, "blue" ) ;
503+ svg. arcline ( & hull3, "red" ) ;
504+ svg. write_stroke_width ( 0.1 ) ;
471505 }
472506
473507 #[ test]
@@ -515,6 +549,17 @@ mod tests {
515549 assert ! ( ( min_x - 0.0 ) . abs( ) < 1e-6 ) ;
516550 assert ! ( ( max_y - 2.0 ) . abs( ) < 1e-6 ) ;
517551 assert ! ( ( min_y - 0.0 ) . abs( ) < 1e-6 ) ;
552+
553+ // Write SVG for visualization
554+ use crate :: svg:: SVG ;
555+ let arcs2 = arcline_scale ( & arcs, 100.0 ) ;
556+ let hull2 = arcline_scale ( & hull, 100.0 ) ;
557+ let arcs3 = arcline_translate ( & arcs2, point ( 50.0 , 50.0 ) ) ;
558+ let hull3 = arcline_translate ( & hull2, point ( 50.0 , 50.0 ) ) ;
559+ let mut svg = SVG :: new ( 600.0 , 600.0 , Some ( "/tmp/test.svg" ) ) ;
560+ svg. arcline ( & arcs3, "blue" ) ;
561+ svg. arcline ( & hull3, "red" ) ;
562+ svg. write_stroke_width ( 0.1 ) ;
518563 }
519564
520565 #[ test]
@@ -526,7 +571,7 @@ mod tests {
526571 arcseg( point( 2.0 , 0.0 ) , point( 2.0 , 2.0 ) ) , // Right
527572 arcseg( point( 2.0 , 2.0 ) , point( 0.0 , 2.0 ) ) , // Top
528573 // Left side with concave arc (backward traversal = concave)
529- arc( point( 0.0 , 2 .0) , point( 0.0 , 0 .0) , point( 0.0 , 1.0 ) , 0.5 ) , // Concave indent
574+ arc( point( 0.0 , 0 .0) , point( 0.0 , 2 .0) , point( 0.0 , 1.0 ) , 0.5 ) , // Concave indent
530575 ] ;
531576
532577 let hull = arcline_convex_hull ( & arcs) ;
@@ -540,6 +585,17 @@ mod tests {
540585 assert ! ( hull_points. contains( & point( 2.0 , 0.0 ) ) ) ;
541586 assert ! ( hull_points. contains( & point( 2.0 , 2.0 ) ) ) ;
542587 assert ! ( hull_points. contains( & point( 0.0 , 2.0 ) ) ) ;
588+
589+ // Write SVG for visualization
590+ use crate :: svg:: SVG ;
591+ let arcs2 = arcline_scale ( & arcs, 100.0 ) ;
592+ let hull2 = arcline_scale ( & hull, 100.0 ) ;
593+ let arcs3 = arcline_translate ( & arcs2, point ( 50.0 , 50.0 ) ) ;
594+ let hull3 = arcline_translate ( & hull2, point ( 50.0 , 50.0 ) ) ;
595+ let mut svg = SVG :: new ( 600.0 , 600.0 , Some ( "/tmp/test.svg" ) ) ;
596+ svg. arcline ( & arcs3, "blue" ) ;
597+ svg. arcline ( & hull3, "red" ) ;
598+ svg. write_stroke_width ( 0.1 ) ;
543599 }
544600
545601 #[ test]
@@ -592,16 +648,134 @@ mod tests {
592648
593649 assert_eq ! ( hull. len( ) , 8 , "Expected 8 elements: 4 split arcs + 4 connecting segments" ) ;
594650
651+ // Write SVG for visualization
652+ use crate :: svg:: SVG ;
653+ let arcs2 = arcline_scale ( & arcs, 100.0 ) ;
654+ let hull2 = arcline_scale ( & hull, 100.0 ) ;
655+ let arcs3 = arcline_translate ( & arcs2, point ( 150.0 , 150.0 ) ) ;
656+ let hull3 = arcline_translate ( & hull2, point ( 150.0 , 150.0 ) ) ;
657+ let mut svg = SVG :: new ( 600.0 , 600.0 , Some ( "/tmp/test.svg" ) ) ;
658+ svg. arcline ( & arcs3, "blue" ) ;
659+ svg. arcline ( & hull3, "red" ) ;
660+ svg. write_stroke_width ( 0.1 ) ;
661+ }
595662
663+ #[ test]
664+ fn test_arcline_convex_hull_mixed_convex_concave_arcs ( ) {
665+ let arcs = vec ! [
666+ arc( point( 2.0 , 0.0 ) , point( 2.0 , 2.0 ) , point( 2.0 , 1.0 ) , 1.0 ) , // Convex arc
667+ arc( point( 2.0 , 2.0 ) , point( 0.0 , 2.0 ) , point( 1.0 , 2.0 ) , 1.0 ) , // Convex arc
668+ arc( point( 0.0 , 2.0 ) , point( 0.0 , 0.0 ) , point( 0.0 , 1.0 ) , 0.5 ) , // Concave arc (inward)
669+ arcseg( point( 0.0 , 0.0 ) , point( 2.0 , 0.0 ) ) , // Line segment
670+ ] ;
671+
672+ let hull = arcline_convex_hull ( & arcs) ;
673+ assert ! ( hull. len( ) >= 3 ) ;
674+
675+ // Write SVG for visualization
676+ use crate :: svg:: SVG ;
677+ let arcs2 = arcline_scale ( & arcs, 100.0 ) ;
678+ let hull2 = arcline_scale ( & hull, 100.0 ) ;
679+ let arcs3 = arcline_translate ( & arcs2, point ( 150.0 , 150.0 ) ) ;
680+ let hull3 = arcline_translate ( & hull2, point ( 150.0 , 150.0 ) ) ;
681+ let mut svg = SVG :: new ( 600.0 , 600.0 , Some ( "/tmp/test.svg" ) ) ;
682+ svg. arcline ( & arcs3, "blue" ) ;
683+ svg. arcline ( & hull3, "red" ) ;
684+ svg. write_stroke_width ( 0.1 ) ;
685+ }
686+
687+ #[ test]
688+ fn test_arcline_convex_hull_alternating_convex_concave ( ) {
689+ let arcs = vec ! [
690+ arc( point( 0.0 , 1.0 ) , point( 1.0 , 0.0 ) , point( 1.0 , 1.0 ) , 1.0 ) ,
691+ arc( point( 0.0 , 1.0 ) , point( -1.0 , 0.0 ) , point( -0.5 , 0.5 ) , 1.0 ) ,
692+ arc( point( 0.0 , -1.0 ) , point( -1.0 , 0.0 ) , point( -1.0 , -1.0 ) , 1.0 ) ,
693+ arc( point( 0.0 , -1.0 ) , point( 1.0 , 0.0 ) , point( 0.5 , -0.5 ) , 1.0 ) ,
694+ ] ;
695+
696+ let hull = arcline_convex_hull ( & arcs) ;
697+ assert ! ( hull. len( ) >= 2 ) ;
698+
699+ // Write SVG for visualization
700+ use crate :: svg:: SVG ;
701+ let arcs2 = arcline_scale ( & arcs, 100.0 ) ;
702+ let hull2 = arcline_scale ( & hull, 100.0 ) ;
703+ let arcs3 = arcline_translate ( & arcs2, point ( 150.0 , 150.0 ) ) ;
704+ let hull3 = arcline_translate ( & hull2, point ( 150.0 , 150.0 ) ) ;
705+ let mut svg = SVG :: new ( 600.0 , 600.0 , Some ( "/tmp/test.svg" ) ) ;
706+ svg. arcline ( & arcs3, "blue" ) ;
707+ svg. arcline ( & hull3, "red" ) ;
708+ svg. write_stroke_width ( 0.1 ) ;
709+ }
710+
711+ #[ test]
712+ fn test_arcline_convex_hull_with_line_segments ( ) {
713+ let arcs = vec ! [
714+ arcseg( point( 0.0 , 0.0 ) , point( 2.0 , 0.0 ) ) , // Bottom edge
715+ arc( point( 2.0 , 0.0 ) , point( 2.0 , 2.0 ) , point( 2.0 , 1.0 ) , 1.0 ) , // Right convex arc
716+ arcseg( point( 2.0 , 2.0 ) , point( 0.0 , 2.0 ) ) , // Top edge
717+ arc( point( 0.0 , 2.0 ) , point( 0.0 , 0.0 ) , point( 0.0 , 1.0 ) , 1.0 ) , // Left convex arc
718+ ] ;
719+
720+ let hull = arcline_convex_hull ( & arcs) ;
721+ assert_eq ! ( hull. len( ) , 4 ) ;
722+
723+ // Write SVG for visualization
724+ use crate :: svg:: SVG ;
725+ let arcs2 = arcline_scale ( & arcs, 100.0 ) ;
726+ let hull2 = arcline_scale ( & hull, 100.0 ) ;
727+ let arcs3 = arcline_translate ( & arcs2, point ( 150.0 , 150.0 ) ) ;
728+ let hull3 = arcline_translate ( & hull2, point ( 150.0 , 150.0 ) ) ;
729+ let mut svg = SVG :: new ( 600.0 , 600.0 , Some ( "/tmp/test.svg" ) ) ;
730+ svg. arcline ( & arcs3, "blue" ) ;
731+ svg. arcline ( & hull3, "red" ) ;
732+ svg. write_stroke_width ( 0.1 ) ;
733+ }
734+
735+ #[ test]
736+ fn test_arcline_convex_hull_three_convex_arcs ( ) {
737+ let arcs = vec ! [
738+ arc( point( 1.0 , 0.0 ) , point( 0.0 , 1.0 ) , point( 0.0 , 0.0 ) , 1.0 ) , // Convex
739+ arc( point( 0.0 , 1.0 ) , point( -1.0 , 0.0 ) , point( 0.0 , 0.0 ) , 1.0 ) , // Convex
740+ arc( point( -1.0 , 0.0 ) , point( 1.0 , 0.0 ) , point( 0.0 , 0.0 ) , 1.0 ) , // Convex (bottom)
741+ ] ;
742+
743+ let hull = arcline_convex_hull ( & arcs) ;
744+ assert ! ( hull. len( ) >= 3 ) ;
745+
746+ // Write SVG for visualization
747+ use crate :: svg:: SVG ;
748+ let arcs2 = arcline_scale ( & arcs, 100.0 ) ;
749+ let hull2 = arcline_scale ( & hull, 100.0 ) ;
750+ let arcs3 = arcline_translate ( & arcs2, point ( 150.0 , 150.0 ) ) ;
751+ let hull3 = arcline_translate ( & hull2, point ( 150.0 , 150.0 ) ) ;
752+ let mut svg = SVG :: new ( 600.0 , 600.0 , Some ( "/tmp/test.svg" ) ) ;
753+ svg. arcline ( & arcs3, "blue" ) ;
754+ svg. arcline ( & hull3, "red" ) ;
755+ svg. write_stroke_width ( 0.1 ) ;
756+ }
757+
758+ #[ test]
759+ fn test_arcline_convex_hull_segment_dominated ( ) {
760+ let arcs = vec ! [
761+ arcseg( point( 0.0 , 0.0 ) , point( 3.0 , 0.0 ) ) , // Long bottom
762+ arc( point( 3.0 , 0.0 ) , point( 3.0 , 1.0 ) , point( 3.0 , 0.5 ) , 0.5 ) , // Small convex
763+ arcseg( point( 3.0 , 1.0 ) , point( 0.0 , 1.0 ) ) , // Long top
764+ arc( point( 0.0 , 1.0 ) , point( 0.0 , 0.0 ) , point( 0.0 , 0.5 ) , 0.5 ) , // Small convex
765+ ] ;
766+
767+ let hull = arcline_convex_hull ( & arcs) ;
768+ assert_eq ! ( hull. len( ) , 4 ) ;
596769
597770 // Write SVG for visualization
598771 use crate :: svg:: SVG ;
599772 let arcs2 = arcline_scale ( & arcs, 100.0 ) ;
600773 let hull2 = arcline_scale ( & hull, 100.0 ) ;
601- let mut svg = SVG :: new ( 400.0 , 400.0 , Some ( "/tmp/hull_square_arcs.svg" ) ) ;
602- svg. arcline ( & arcs2, "blue" ) ;
603- svg. arcline ( & hull2, "red" ) ;
604- svg. write ( ) ;
774+ let arcs3 = arcline_translate ( & arcs2, point ( 150.0 , 150.0 ) ) ;
775+ let hull3 = arcline_translate ( & hull2, point ( 150.0 , 150.0 ) ) ;
776+ let mut svg = SVG :: new ( 600.0 , 600.0 , Some ( "/tmp/test.svg" ) ) ;
777+ svg. arcline ( & arcs3, "blue" ) ;
778+ svg. arcline ( & hull3, "red" ) ;
605779 svg. write_stroke_width ( 0.1 ) ;
606780 }
607781}
0 commit comments