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 }