1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Geometric computations around vectors and points for collision detection
22 # Get the distance between `p1` and `p2`
23 fun distance
(p1
, p2
: Point[Float]): Float
27 return ( x
* x
+ y
* y
).sqrt
30 # Get the magnitude (length) of `vector`
31 fun magnitude
(vector
: Point[Float]): Float do return ( vector
.x
* vector
.x
+ vector
.y
* vector
.y
).sqrt
33 # Get the unit vector of `vector`
34 fun unit_vector
(vector
: Point[Float]): Point[Float] do return new Point[Float](vector
.x
/ magnitude
(vector
), vector
.y
/ magnitude
(vector
))
36 # Get the dot product of vectors `v1` and `v2`
37 fun dot_product
(v1
, v2
: Point[Float]): Float do return v1
.x
* v2
.x
+ v1
.y
* v2
.y
39 # Get the vector between `start_point` and `end_point`
40 fun vector_between
(start_point
, end_point
: Point[Float]): Point[Float] do return new Point[Float](end_point
.x
- start_point
.x
, end_point
.y
- start_point
.y
)
42 # Returns the point on a line with endpoints `l1` and `l2` closest to `center`
43 fun point_closest_to_line
(center
, l1
, l2
: Point[Float]): Point[Float]
45 var luvector
= unit_vector
(vector_between
(l1
, l2
))
46 var l_to_ball
= vector_between
(l1
, center
)
48 var projection
= dot_product
(l_to_ball
, luvector
)
50 if projection
<= 0.0 then return l1
51 if projection
>= distance
(l1
, l2
) then return l2
52 return new Point[Float](l1
.x
+ luvector
.x
* projection
, l1
.y
+ luvector
.y
* projection
)
55 # Is the ball with the `center` and `radius` intersecting the line with the endpoints `l1` and `l2`?
56 fun is_intersecting
(center
, l1
, l2
: Point[Float], radius
: Float): Bool
58 var closest
= point_closest_to_line
(center
, l1
, l2
)
59 var distance
= distance
(center
, closest
)
60 return distance
< radius
63 # Bouncing function, returns the new point of the center of the ball
64 fun bounce
(center
, l1
, l2
, offset
: Point[Float]): Point[Float]
66 var bln
= bounce_line_normal
(center
, l1
, l2
)
67 var dot
= dot_product
(offset
, bln
)
68 return new Point[Float](offset
.x
- (2.0 * dot
* bln
.x
), offset
.y
- (2.0 * dot
* bln
.y
))
71 private fun bounce_line_normal
(center
, l1
, l2
: Point[Float]): Point[Float]
73 var p
= point_closest_to_line
(center
, l1
, l2
)
74 var v
= vector_between
(p
, center
)
78 # Rotate `p` around `center` through `angle`
79 fun rotate_point
(p
, center
: Point[Float], angle
: Float): Point[Float]
84 var nx
= c
* (p
.x
- center
.x
) - s
* (p
.y
- center
.y
) + center
.x
85 var ny
= s
* (p
.x
- center
.x
) + c
* (p
.y
- center
.y
) + center
.y
86 return new Point[Float](nx
, ny
)