@@ -668,7 +668,184 @@ describe("Point unit tests", () => {
668
668
const result = point . sortPoints ( input ) ;
669
669
expect ( result ) . toEqual ( expected ) ;
670
670
} ) ;
671
+ } ) ;
672
+
673
+ describe ( "calculateMaxFilletRadius" , ( ) => {
674
+ const defaultTolerance = 1e-7 ; // Default tolerance for the function if not provided
675
+ const precision = 6 ; // Decimal places for toBeCloseTo assertions
676
+
677
+ // Helper to create input object matching the confusing naming convention
678
+ const createInput = ( p1 : Inputs . Base . Point3 , corner : Inputs . Base . Point3 , p2 : Inputs . Base . Point3 , tolerance : number = defaultTolerance ) : Inputs . Point . ThreePointsToleranceDto => ( {
679
+ start : p1 ,
680
+ center : p2 ,
681
+ end : corner ,
682
+ tolerance : tolerance
683
+ } ) ;
684
+
685
+ it ( "should calculate correct radius for a simple 90-degree corner (2D)" , ( ) => {
686
+ const geoP1 : Inputs . Base . Point3 = [ 5 , 0 , 0 ] ;
687
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
688
+ const geoP2 : Inputs . Base . Point3 = [ 0 , 3 , 0 ] ;
689
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
690
+ expect ( point . maxFilletRadius ( input ) ) . toBeCloseTo ( 3.0 , precision ) ;
691
+ } ) ;
692
+
693
+ it ( "should calculate correct radius for a symmetric 90-degree corner (2D)" , ( ) => {
694
+ const geoP1 : Inputs . Base . Point3 = [ 4 , 0 , 0 ] ;
695
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
696
+ const geoP2 : Inputs . Base . Point3 = [ 0 , 4 , 0 ] ;
697
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
698
+ expect ( point . maxFilletRadius ( input ) ) . toBeCloseTo ( 4.0 , precision ) ;
699
+ } ) ;
700
+
701
+ it ( "should calculate correct radius for an acute angle (60 degrees, 2D)" , ( ) => {
702
+ const geoP1 : Inputs . Base . Point3 = [ 5 , 0 , 0 ] ;
703
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
704
+ const geoP2 : Inputs . Base . Point3 = [ 5 * Math . cos ( Math . PI / 3 ) , 5 * Math . sin ( Math . PI / 3 ) , 0 ] ;
705
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
706
+ const expected = 5 * Math . tan ( Math . PI / 6 ) ;
707
+ expect ( point . maxFilletRadius ( input ) ) . toBeCloseTo ( expected , precision ) ;
708
+ } ) ;
709
+
710
+ it ( "should calculate correct radius for an obtuse angle (120 degrees, 2D)" , ( ) => {
711
+ const geoP1 : Inputs . Base . Point3 = [ 4 , 0 , 0 ] ;
712
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
713
+ const geoP2 : Inputs . Base . Point3 = [ 6 * Math . cos ( 2 * Math . PI / 3 ) , 6 * Math . sin ( 2 * Math . PI / 3 ) , 0 ] ;
714
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
715
+ const expected = 4 * Math . tan ( Math . PI / 3 ) ;
716
+ expect ( point . maxFilletRadius ( input ) ) . toBeCloseTo ( expected , precision ) ;
717
+ } ) ;
718
+
719
+ it ( "should return 0 for collinear points (0 degrees)" , ( ) => {
720
+ const geoP1 : Inputs . Base . Point3 = [ 5 , 0 , 0 ] ;
721
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
722
+ const geoP2 : Inputs . Base . Point3 = [ 10 , 0 , 0 ] ;
723
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
724
+ expect ( point . maxFilletRadius ( input ) ) . toBeCloseTo ( 0 , precision ) ;
725
+ } ) ;
726
+
727
+ it ( "should return 0 for collinear points (180 degrees)" , ( ) => {
728
+ const geoP1 : Inputs . Base . Point3 = [ 5 , 0 , 0 ] ;
729
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
730
+ const geoP2 : Inputs . Base . Point3 = [ - 3 , 0 , 0 ] ;
731
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
732
+ expect ( point . maxFilletRadius ( input ) ) . toBeCloseTo ( 0 , precision ) ;
733
+ } ) ;
734
+
735
+ it ( "should return 0 if one segment has near-zero length (P1=C)" , ( ) => {
736
+ const geoP1 : Inputs . Base . Point3 = [ defaultTolerance / 2 , 0 , 0 ] ; // Very close to C
737
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
738
+ const geoP2 : Inputs . Base . Point3 = [ 0 , 3 , 0 ] ;
739
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
740
+ expect ( point . maxFilletRadius ( input ) ) . toBeCloseTo ( 0 , precision ) ;
741
+ } ) ;
742
+
743
+ it ( "should return 0 if one segment has near-zero length (P2=C)" , ( ) => {
744
+ const geoP1 : Inputs . Base . Point3 = [ 5 , 0 , 0 ] ;
745
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
746
+ const geoP2 : Inputs . Base . Point3 = [ 0 , defaultTolerance / 3 , 0 ] ; // Very close to C
747
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
748
+ expect ( point . maxFilletRadius ( input ) ) . toBeCloseTo ( 0 , precision ) ;
749
+ } ) ;
750
+
751
+ it ( "should use the provided tolerance if specified" , ( ) => {
752
+ const customTolerance = 1e-4 ;
753
+ const geoP1 : Inputs . Base . Point3 = [ customTolerance / 2 , 0 , 0 ] ; // Near zero relative to custom tolerance
754
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
755
+ const geoP2 : Inputs . Base . Point3 = [ 0 , 3 , 0 ] ;
756
+ const input = createInput ( geoP1 , geoC , geoP2 , customTolerance ) ;
757
+ // Expect 0 because len1 < customTolerance
758
+ expect ( point . maxFilletRadius ( input ) ) . toBeCloseTo ( 0 , precision ) ;
759
+
760
+ const geoP1_ok : Inputs . Base . Point3 = [ customTolerance * 2 , 0 , 0 ] ; // OK relative to custom tolerance
761
+ const input_ok = createInput ( geoP1_ok , geoC , geoP2 , customTolerance ) ;
762
+ // Expect non-zero result here
763
+ expect ( point . maxFilletRadius ( input_ok ) ) . toBeGreaterThan ( 0 ) ;
764
+ } ) ;
765
+
766
+ it ( "should return 0 if all points coincide" , ( ) => {
767
+ const geoP1 : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
768
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
769
+ const geoP2 : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
770
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
771
+ expect ( point . maxFilletRadius ( input ) ) . toBeCloseTo ( 0 , precision ) ;
772
+ } ) ;
773
+
774
+ it ( "should calculate correct radius for a corner in 3D space" , ( ) => {
775
+ const geoP1 : Inputs . Base . Point3 = [ 1 , 1 , 0 ] ;
776
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
777
+ const geoP2 : Inputs . Base . Point3 = [ 0 , 2 , 0 ] ;
778
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
779
+ const expected = Math . sqrt ( 2 ) * Math . tan ( Math . PI / 8 ) ;
780
+ expect ( point . maxFilletRadius ( input ) ) . toBeCloseTo ( expected , precision ) ;
781
+ } ) ;
782
+ } ) ;
783
+
784
+ describe ( "calculateMaxFilletRadiusHalfLine" , ( ) => {
785
+ const defaultTolerance = 1e-7 ;
786
+ const precision = 6 ;
671
787
788
+ const createInput = ( p1 : Inputs . Base . Point3 , corner : Inputs . Base . Point3 , p2 : Inputs . Base . Point3 , tolerance : number = defaultTolerance ) : Inputs . Point . ThreePointsToleranceDto => ( {
789
+ start : p1 , center : p2 , end : corner , tolerance : tolerance
790
+ } ) ;
791
+
792
+ it ( "should calculate correct radius for a simple 90-degree corner (2D)" , ( ) => {
793
+ const geoP1 : Inputs . Base . Point3 = [ 5 , 0 , 0 ] ;
794
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
795
+ const geoP2 : Inputs . Base . Point3 = [ 0 , 3 , 0 ] ;
796
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
797
+ expect ( point . maxFilletRadiusHalfLine ( input ) ) . toBeCloseTo ( 1.5 , precision ) ;
798
+ } ) ;
799
+
800
+ it ( "should calculate correct radius for a symmetric 90-degree corner (2D)" , ( ) => {
801
+ const geoP1 : Inputs . Base . Point3 = [ 4 , 0 , 0 ] ;
802
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
803
+ const geoP2 : Inputs . Base . Point3 = [ 0 , 4 , 0 ] ;
804
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
805
+ expect ( point . maxFilletRadiusHalfLine ( input ) ) . toBeCloseTo ( 2.0 , precision ) ;
806
+ } ) ;
672
807
808
+ it ( "should calculate correct radius for an acute angle (60 degrees, 2D)" , ( ) => {
809
+ const geoP1 : Inputs . Base . Point3 = [ 6 , 0 , 0 ] ;
810
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
811
+ const geoP2 : Inputs . Base . Point3 = [ 4 * Math . cos ( Math . PI / 3 ) , 4 * Math . sin ( Math . PI / 3 ) , 0 ] ;
812
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
813
+ const expected = 2 * Math . tan ( Math . PI / 6 ) ;
814
+ expect ( point . maxFilletRadiusHalfLine ( input ) ) . toBeCloseTo ( expected , precision ) ;
815
+ } ) ;
816
+
817
+ it ( "should calculate correct radius for an obtuse angle (120 degrees, 2D)" , ( ) => {
818
+ const geoP1 : Inputs . Base . Point3 = [ 4 , 0 , 0 ] ;
819
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
820
+ const geoP2 : Inputs . Base . Point3 = [ 6 * Math . cos ( 2 * Math . PI / 3 ) , 6 * Math . sin ( 2 * Math . PI / 3 ) , 0 ] ;
821
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
822
+ const expected = 2 * Math . tan ( Math . PI / 3 ) ;
823
+ expect ( point . maxFilletRadiusHalfLine ( input ) ) . toBeCloseTo ( expected , precision ) ;
824
+ } ) ;
825
+
826
+ it ( "should return 0 for collinear points (0 degrees)" , ( ) => {
827
+ const geoP1 : Inputs . Base . Point3 = [ 5 , 0 , 0 ] ;
828
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
829
+ const geoP2 : Inputs . Base . Point3 = [ 10 , 0 , 0 ] ;
830
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
831
+ expect ( point . maxFilletRadiusHalfLine ( input ) ) . toBeCloseTo ( 0 , precision ) ;
832
+ } ) ;
833
+
834
+ it ( "should return 0 if one segment has near-zero length" , ( ) => {
835
+ const geoP1 : Inputs . Base . Point3 = [ 5 , 0 , 0 ] ;
836
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
837
+ const geoP2 : Inputs . Base . Point3 = [ 0 , defaultTolerance / 3 , 0 ] ;
838
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
839
+ expect ( point . maxFilletRadiusHalfLine ( input ) ) . toBeCloseTo ( 0 , precision ) ;
840
+ } ) ;
841
+
842
+ it ( "should calculate correct radius for a corner in 3D space" , ( ) => {
843
+ const geoP1 : Inputs . Base . Point3 = [ 1 , 1 , 0 ] ;
844
+ const geoC : Inputs . Base . Point3 = [ 0 , 0 , 0 ] ;
845
+ const geoP2 : Inputs . Base . Point3 = [ 0 , 2 , 0 ] ;
846
+ const input = createInput ( geoP1 , geoC , geoP2 ) ;
847
+ const expected = ( Math . sqrt ( 2 ) / 2.0 ) * Math . tan ( Math . PI / 8 ) ;
848
+ expect ( point . maxFilletRadiusHalfLine ( input ) ) . toBeCloseTo ( expected , precision ) ;
849
+ } ) ;
673
850
} ) ;
674
851
} ) ;
0 commit comments