gamnit and related: improve doc
[nit.git] / lib / geometry / points_and_lines.nit
1 # This file is part of NIT (http://www.nitlanguage.org).
2 #
3 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Interfaces and classes to represent basic geometry needs.
18 module points_and_lines is serialize
19
20 import serialization
21
22 # Abstract 2d point, strongly linked to its implementation `Point`
23 interface IPoint[N: Numeric]
24
25 # Horizontal coordinate
26 fun x: N is abstract
27
28 # Vertical coordinate
29 fun y: N is abstract
30
31 redef fun to_s do return "({x}, {y})"
32
33 # Distance with `other`
34 #
35 # ~~~
36 # var p0 = new Point[Float](0.0, 0.0)
37 # var p1 = new Point[Float](2.0, 3.0)
38 # assert p0.dist(p1).is_approx(3.6, 0.01)
39 # ~~~
40 #
41 # TODO 3D implementation.
42 fun dist(other: Point[Numeric]): N
43 do
44 return x.value_of(dist2(other).to_f.sqrt)
45 end
46
47 # Square of the distance with `other`
48 #
49 # May be used as an approximation to compare distance between two points.
50 #
51 # ~~~
52 # var p0 = new Point[Float](0.0, 0.0)
53 # var p1 = new Point[Float](2.0, 3.0)
54 # assert p0.dist2(p1) == 13.0
55 # ~~~
56 #
57 # TODO 3D implementation.
58 fun dist2(other: Point[Numeric]): N
59 do
60 var dx = other.x.sub(x)
61 var dy = other.y.sub(y)
62 var s = (dx.mul(dx)).add(dy.mul(dy))
63 return x.value_of(s)
64 end
65
66 # Linear interpolation between `self` and `other` at `p` out of `1.0`
67 #
68 # ~~~
69 # var p0 = new Point[Float](0.0, 0.0)
70 # var p1 = new Point[Float](2.0, 3.0)
71 # assert p0.lerp(p1, 0.0) == p0
72 # assert p0.lerp(p1, 1.0) == p1
73 # assert p0.lerp(p1, 0.5) == new Point[Float](1.0, 1.5)
74 # ~~~
75 #
76 # TODO 3D implementation.
77 fun lerp(other: Point[Numeric], p: Float): Point[N]
78 do
79 var xx = x.to_f + (other.x.to_f - x.to_f).to_f * p
80 var yy = y.to_f + (other.y.to_f - y.to_f).to_f * p
81 return new Point[N](x.value_of(xx), y.value_of(yy))
82 end
83
84 redef fun ==(o) do return o isa IPoint[Numeric] and o.x == x and o.y == y
85 end
86
87 # 2D point with `x` and `z`
88 class Point[N: Numeric]
89 super IPoint[N]
90
91 redef var x: N is writable
92 redef var y: N is writable
93 end
94
95 # Abstract 3d point, strongly linked to its implementation `Point3d`
96 interface IPoint3d[N: Numeric]
97 super IPoint[N]
98
99 # Depth coordinate
100 fun z: N is abstract
101
102 redef fun to_s do return "({x}, {y}, {z})"
103 end
104
105 # 3D point with `x`, `y` and `z`
106 class Point3d[N: Numeric]
107 super IPoint3d[N]
108 super Point[N]
109
110 redef var z: N is writable
111 end
112
113 # Abstract 2D line segment between two ordered points
114 interface ILine[N: Numeric]
115 # The type of points that ends the segment
116 type P: IPoint[N]
117
118 # Point at the left-end of the segment
119 fun point_left: P is abstract
120
121 # Point at the right-end of the segment
122 fun point_right: P is abstract
123
124 redef fun to_s do return "{point_left}--{point_right}"
125 end
126
127 # 2D line segment between two ordered points
128 class Line[N: Numeric]
129 super ILine[N]
130
131 redef var point_left
132 redef var point_right
133
134 init
135 do
136 var a = point_left
137 var b = point_right
138 if a.x > b.x then
139 point_left = b
140 point_right = a
141 end
142 end
143 end
144
145 # Abstract 3D line segment between two ordered points
146 interface ILine3d[N: Numeric]
147 super ILine[N]
148
149 redef type P: IPoint3d[N]
150 end
151
152 # 3D line segment between two ordered points
153 class Line3d[N: Numeric]
154 super Line[N]
155 super ILine3d[N]
156 end