github.com/pavlo67/common@v0.5.3/common/mathlib/plane/points_test.go (about)

     1  package plane
     2  
     3  import (
     4  	"math"
     5  	"testing"
     6  
     7  	"github.com/pavlo67/common/common/mathlib"
     8  
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  func TestRotateByAngle(t *testing.T) {
    13  	type args struct {
    14  		p        Point2
    15  		addAngle XToYAngle
    16  	}
    17  	tests := []struct {
    18  		name string
    19  		args args
    20  		want Point2
    21  	}{
    22  		{
    23  			name: "0+pi",
    24  			args: args{p: Point2{1, 0}, addAngle: math.Pi},
    25  			want: Point2{-1, 0},
    26  		},
    27  		{
    28  			name: "pi+0",
    29  			args: args{p: Point2{-1, 0}, addAngle: 0},
    30  			want: Point2{-1, 0},
    31  		},
    32  		{
    33  			name: "0-pi/2",
    34  			args: args{p: Point2{1, 0}, addAngle: -math.Pi / 2},
    35  			want: Point2{0, -1},
    36  		},
    37  		{
    38  			name: "pi/4+pi/2",
    39  			args: args{p: Point2{1, 1}, addAngle: math.Pi / 2},
    40  			want: Point2{-1, 1},
    41  		},
    42  		{
    43  			name: "3*pi/4+pi/2",
    44  			args: args{p: Point2{-1, 1}, addAngle: math.Pi / 2},
    45  			want: Point2{-1, -1},
    46  		},
    47  		{
    48  			name: "5*pi/4-pi/2",
    49  			args: args{p: Point2{-1, -1}, addAngle: -math.Pi / 2},
    50  			want: Point2{-1, 1},
    51  		},
    52  	}
    53  	for _, tt := range tests {
    54  		t.Run(tt.name, func(t *testing.T) {
    55  			if got := tt.args.p.RotateByAngle(tt.args.addAngle); got.DistanceTo(tt.want) > mathlib.Eps {
    56  				t.Errorf("RotateByAngle() = %v, wantDistance %v", got, tt.want)
    57  			}
    58  		})
    59  	}
    60  }
    61  
    62  func TestRotateWithRatio(t *testing.T) {
    63  	type args struct {
    64  		p     Point2
    65  		ratio float64
    66  	}
    67  	tests := []struct {
    68  		name string
    69  		args args
    70  		want Point2
    71  	}{
    72  		{
    73  			name: "pi/4*1",
    74  			args: args{p: Point2{1, 1}, ratio: 1},
    75  			want: Point2{1, 1},
    76  		},
    77  		{
    78  			name: "pi/4*3",
    79  			args: args{p: Point2{1, 1}, ratio: 3},
    80  			want: Point2{-1, 1},
    81  		},
    82  		{
    83  			name: "pi/4*5",
    84  			args: args{p: Point2{1, 1}, ratio: 5},
    85  			want: Point2{-1, -1},
    86  		},
    87  		{
    88  			name: "pi/4*7",
    89  			args: args{p: Point2{1, 1}, ratio: 7},
    90  			want: Point2{1, -1},
    91  		},
    92  
    93  		{
    94  			name: "5*pi/4*2",
    95  			args: args{p: Point2{-1, -1}, ratio: 2},
    96  			want: Point2{0, 1.4142135623730951},
    97  		},
    98  		{
    99  			name: "5*pi/4*3",
   100  			args: args{p: Point2{-1, -1}, ratio: 3},
   101  			want: Point2{1, -1},
   102  		},
   103  
   104  		{
   105  			name: "pi/2*1",
   106  			args: args{p: Point2{0, 1}, ratio: 1},
   107  			want: Point2{0, 1},
   108  		},
   109  		{
   110  			name: "pi/2*2",
   111  			args: args{p: Point2{0, 1}, ratio: 2},
   112  			want: Point2{-1, 0},
   113  		},
   114  		{
   115  			name: "pi/2*3",
   116  			args: args{p: Point2{0, 1}, ratio: 3},
   117  			want: Point2{0, -1},
   118  		},
   119  		{
   120  			name: "pi/2*4",
   121  			args: args{p: Point2{0, 1}, ratio: 4},
   122  			want: Point2{1, 0},
   123  		},
   124  		{
   125  			name: "pi*1",
   126  			args: args{p: Point2{-1, 0}, ratio: 1},
   127  			want: Point2{-1, 0},
   128  		},
   129  		{
   130  			name: "pi*2",
   131  			args: args{p: Point2{-1, 0}, ratio: 2},
   132  			want: Point2{1, 0},
   133  		},
   134  	}
   135  	for _, tt := range tests {
   136  		t.Run(tt.name, func(t *testing.T) {
   137  			if got := tt.args.p.RotateWithRatio(tt.args.ratio); got.DistanceTo(tt.want) > mathlib.Eps {
   138  				t.Errorf("RotateByAngle() = %v, wantDistance %v", got, tt.want)
   139  			}
   140  		})
   141  	}
   142  }
   143  
   144  func TestTurnAroundAxis(t *testing.T) {
   145  	type args struct {
   146  		p    Point2
   147  		axis Segment
   148  	}
   149  	tests := []struct {
   150  		name string
   151  		args args
   152  		want Point2
   153  	}{
   154  		{
   155  			name: "Oy/Ox",
   156  			args: args{p: Point2{0, 1}, axis: Segment{Point2{0, 0}, Point2{1, 0}}},
   157  			want: Point2{0, -1},
   158  		},
   159  		{
   160  			name: "Ox/Oy",
   161  			args: args{p: Point2{-1, 1}, axis: Segment{Point2{0, -5}, Point2{0, 1}}},
   162  			want: Point2{1, 1},
   163  		},
   164  		{
   165  			name: "Oy/45",
   166  			args: args{p: Point2{0, 1}, axis: Segment{Point2{-3, -3}, Point2{0, 0}}},
   167  			want: Point2{1, 0},
   168  		},
   169  		{
   170  			name: "Oy/45-1",
   171  			args: args{p: Point2{0, 1}, axis: Segment{Point2{-3, -4}, Point2{0, -1}}},
   172  			want: Point2{2, -1},
   173  		},
   174  		{
   175  			name: "Ox/-45",
   176  			args: args{p: Point2{1, 0}, axis: Segment{Point2{0, 0}, Point2{1, -1}}},
   177  			want: Point2{0, -1},
   178  		},
   179  	}
   180  	for _, tt := range tests {
   181  		t.Run(tt.name, func(t *testing.T) {
   182  			if got := tt.args.axis.TurnAroundAxis(tt.args.p); got.DistanceTo(tt.want) > mathlib.Eps {
   183  				t.Errorf("TurnAroundAxis() = %v, wantDistance %v", got, tt.want)
   184  			}
   185  		})
   186  	}
   187  }
   188  
   189  func TestAngle2(t *testing.T) {
   190  	type args struct {
   191  		v0 Point2
   192  		v1 Point2
   193  	}
   194  	tests := []struct {
   195  		name string
   196  		args args
   197  		want float64
   198  	}{
   199  		{args: args{v0: Point2{X: 1, Y: 0}, v1: Point2{X: 1, Y: 0}}, want: 0},
   200  		{args: args{v0: Point2{X: 1, Y: 0}, v1: Point2{X: 1, Y: 1}}, want: math.Pi / 4},
   201  		{args: args{v0: Point2{X: 1, Y: 0}, v1: Point2{X: 0, Y: 1}}, want: math.Pi / 2},
   202  		{args: args{v0: Point2{X: 1, Y: 0}, v1: Point2{X: -1, Y: 1}}, want: 3 * math.Pi / 4},
   203  		{args: args{v0: Point2{X: 1, Y: 0}, v1: Point2{X: -1, Y: 0}}, want: math.Pi},
   204  		{args: args{v0: Point2{X: 1, Y: 0}, v1: Point2{X: -1, Y: -1}}, want: -3 * math.Pi / 4},
   205  		{args: args{v0: Point2{X: 1, Y: 0}, v1: Point2{X: 0, Y: -1}}, want: -math.Pi / 2},
   206  		{args: args{v0: Point2{X: 1, Y: 0}, v1: Point2{X: 1, Y: -1}}, want: -math.Pi / 4},
   207  	}
   208  	for _, tt := range tests {
   209  		t.Run(tt.name, func(t *testing.T) {
   210  			if got := tt.args.v0.AnglesDelta(tt.args.v1); math.Abs(got-tt.want) > mathlib.Eps {
   211  				t.Errorf("AnglesDelta() = %v, wantDistance %v", got, tt.want)
   212  			}
   213  		})
   214  	}
   215  }
   216  
   217  func TestRotation(t *testing.T) {
   218  	type args struct {
   219  		p Point2
   220  	}
   221  	tests := []struct {
   222  		name string
   223  		args args
   224  		want XToYAngle
   225  	}{
   226  		{args: args{p: Point2{X: 0, Y: 0}}, want: XToYAngle(math.NaN())},
   227  		{args: args{p: Point2{X: 1, Y: 0}}, want: 0},
   228  		{args: args{p: Point2{X: 1, Y: 1}}, want: math.Pi / 4},
   229  		{args: args{p: Point2{X: 0, Y: 1}}, want: math.Pi / 2},
   230  		{args: args{p: Point2{X: -1, Y: 1}}, want: 3 * math.Pi / 4},
   231  		{args: args{p: Point2{X: -1, Y: 0}}, want: math.Pi},
   232  		{args: args{p: Point2{X: 1, Y: -1}}, want: -math.Pi / 4},
   233  		{args: args{p: Point2{X: 0, Y: -1}}, want: -math.Pi / 2},
   234  		{args: args{p: Point2{X: -1, Y: -1}}, want: -3 * math.Pi / 4},
   235  	}
   236  	for _, tt := range tests {
   237  		t.Run(tt.name, func(t *testing.T) {
   238  			if got := tt.args.p.XToYAngleFromOx(); math.Abs(float64(got-tt.want)) > mathlib.Eps {
   239  				t.Errorf("XToYAngleFromOy() = %v, wantDistance %v", got, tt.want)
   240  			}
   241  		})
   242  	}
   243  }
   244  
   245  //func TestAngle1(t *testing.T) {
   246  //	type args struct {
   247  //		p Point2
   248  //	}
   249  //	tests := []struct {
   250  //		name string
   251  //		args args
   252  //		wantDistance float64
   253  //	}{
   254  //		{args: args{p: Point2{Position: 0, Y: 0}}, wantDistance: math.NaN()},
   255  //		{args: args{p: Point2{Position: 1, Y: 0}}, wantDistance: 0},
   256  //		{args: args{p: Point2{Position: 1, Y: 1}}, wantDistance: math.Pi / 4},
   257  //		{args: args{p: Point2{Position: 0, Y: 1}}, wantDistance: math.Pi / 2},
   258  //		{args: args{p: Point2{Position: -1, Y: 1}}, wantDistance: 3 * math.Pi / 4},
   259  //		{args: args{p: Point2{Position: -1, Y: 0}}, wantDistance: math.Pi},
   260  //		{args: args{p: Point2{Position: 1, Y: -1}}, wantDistance: -math.Pi / 4},
   261  //		{args: args{p: Point2{Position: 0, Y: -1}}, wantDistance: -math.Pi / 2},
   262  //		{args: args{p: Point2{Position: -1, Y: -1}}, wantDistance: -3 * math.Pi / 4},
   263  //	}
   264  //	for _, tt := range tests {
   265  //		t.Run(tt.name, func(t *testing.T) {
   266  //			if got := Angle1(tt.args.p); math.Abs(got-tt.wantDistance) > Eps {
   267  //				t.Errorf("XToYAngleFromOy() = %v, wantDistance %v", got, tt.wantDistance)
   268  //			}
   269  //		})
   270  //	}
   271  //}
   272  
   273  func TestDistanceToLine(t *testing.T) {
   274  	tests := []struct {
   275  		name string
   276  		p    Point2
   277  		line Segment
   278  		want float64
   279  	}{
   280  		{
   281  			name: "1",
   282  			p:    Point2{38, 57.5},
   283  			line: Segment{Point2{11.666666666666666, 38.666666666666664}, Point2{165.33333333333331, 38.5}},
   284  			want: 18.861883338267475,
   285  		},
   286  		{
   287  			name: "2",
   288  			p:    Point2{25.333333333333332, 4.666666666666667},
   289  			line: Segment{Point2{11.666666666666666, 38.666666666666664}, Point2{165.33333333333331, 38.5}},
   290  			want: 33.98515716183312,
   291  		},
   292  		{
   293  			name: "3",
   294  			p:    Point2{25.333333333333332, 4.5},
   295  			line: Segment{Point2{11.666666666666666, 38.5}, Point2{165.33333333333331, 38.5}},
   296  			want: 34,
   297  		},
   298  		{
   299  			name: "4",
   300  			p:    Point2{25.3, 4.5},
   301  			line: Segment{Point2{11, 38.5}, Point2{11, 48.5}},
   302  			want: 14.3,
   303  		},
   304  		{
   305  			name: "5",
   306  			p:    Point2{1, 1},
   307  			line: Segment{Point2{2, 2}, Point2{2, 4}},
   308  			want: 1,
   309  		},
   310  		{
   311  			name: "5",
   312  			p:    Point2{1, 1},
   313  			line: Segment{Point2{2, 2}, Point2{0, 0}},
   314  			want: 0,
   315  		},
   316  		{
   317  			name: "5",
   318  			p:    Point2{1, 1},
   319  			line: Segment{Point2{2, 2}, Point2{2, 2}},
   320  			want: math.NaN(),
   321  		},
   322  		{
   323  			name: "6",
   324  			p:    Point2{0, 1},
   325  			line: Segment{{}, {2, 2}},
   326  			want: math.Sqrt(2) / 2,
   327  		},
   328  	}
   329  	for _, tt := range tests {
   330  		t.Run(tt.name, func(t *testing.T) {
   331  			got := tt.p.DistanceToLine(tt.line)
   332  			if math.IsNaN(tt.want) {
   333  				require.Truef(t, math.IsNaN(got), "wanted: %f, gotten: %f", tt.want, got)
   334  			} else {
   335  				require.Truef(t, math.Abs(got-tt.want) < mathlib.Eps, "wanted: %f, gotten: %f", tt.want, got)
   336  			}
   337  		})
   338  	}
   339  }