PageRenderTime 74ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/test/test_triangle.rb

https://github.com/toshi0328/gmath3D
Ruby | 318 lines | 245 code | 49 blank | 24 comment | 16 complexity | c1791eb23aa2bcd243a27dfd2f086f68 MD5 | raw file
  1. $LOAD_PATH.unshift(File.dirname(__FILE__))
  2. require 'helper'
  3. include GMath3D
  4. MiniTest::Unit.autorun
  5. class TriangleTestCase < MiniTest::Unit::TestCase
  6. def setup
  7. @triangle = Triangle.new( Vector3.new(1,2,2), Vector3.new(1,4,2), Vector3.new(-1,3,0))
  8. @triangle_default = Triangle.new()
  9. end
  10. def test_initialize
  11. assert_equal(Vector3.new(1,2,2), @triangle.vertices[0])
  12. assert_equal(Vector3.new(1,4,2), @triangle.vertices[1])
  13. assert_equal(Vector3.new(-1,3,0), @triangle.vertices[2])
  14. assert_equal(Vector3.new(0,0,0), @triangle_default.vertices[0])
  15. assert_equal(Vector3.new(1,0,0), @triangle_default.vertices[1])
  16. assert_equal(Vector3.new(0,1,0), @triangle_default.vertices[2])
  17. end
  18. def test_equals
  19. assert(@triangle != nil)
  20. assert(@triangle != "string")
  21. shallow_copied = @triangle
  22. assert(@triangle.equal?(shallow_copied))
  23. assert(@triangle == shallow_copied)
  24. assert_equal(@triangle, Triangle.new( Vector3.new(1.0,2.0,2.0), Vector3.new(1.0,4.0,2.0), Vector3.new(-1.0,3.0,0.0)))
  25. assert(@triangle == Triangle.new( Vector3.new(1.0,2.0,2.0), Vector3.new(1.0,4.0,2.0), Vector3.new(-1.0,3.0,0.0)))
  26. assert(@triangle != Triangle.new( Vector3.new(1.0,2.0,2.0), Vector3.new(1.0,4.0,2.0), Vector3.new(-1.0,3.0,0.5)))
  27. end
  28. def test_clone
  29. shallow_copied = @triangle
  30. shallow_copied.vertices[2].x = 1
  31. assert(@triangle == shallow_copied)
  32. assert(@triangle.equal?(shallow_copied))
  33. assert_equal(1, @triangle.vertices[2].x)
  34. assert_equal(1, shallow_copied.vertices[2].x)
  35. cloned =@triangle.clone
  36. assert(@triangle == cloned)
  37. assert(!@triangle.equal?(cloned))
  38. cloned.vertices[2].x = -10
  39. assert_equal(-10, cloned.vertices[2].x)
  40. assert_equal(1, @triangle.vertices[2].x) # original never changed in editing cloned one.
  41. end
  42. def test_to_s
  43. assert_equal("Triangle[[1, 2, 2], [1, 4, 2], [-1, 3, 0]]", @triangle.to_s)
  44. end
  45. def test_box
  46. box1 = @triangle.box
  47. box2 = @triangle_default.box
  48. assert_equal(Vector3.new(-1,2,0), box1.min_point)
  49. assert_equal(Vector3.new(1,4,2), box1.max_point)
  50. assert_equal(Vector3.new(0,0,0) , box2.min_point)
  51. assert_equal(Vector3.new(1,1,0) , box2.max_point)
  52. end
  53. def test_point
  54. assert_equal(@triangle.vertices[0], @triangle.point( Array.new([1,0,0])))
  55. assert_equal(@triangle.vertices[1], @triangle.point( Array.new([0,1,0])))
  56. assert_equal(@triangle.vertices[2], @triangle.point( Array.new([0,0,1])))
  57. #on edge
  58. assert_equal(Vector3.new(1,3,2), @triangle.point( Array.new([0.5,0.5,0])))
  59. assert_equal(Vector3.new(0,3.5,1), @triangle.point( Array.new([0,0.5,0.5])))
  60. assert_equal(Vector3.new(0,2.5,1), @triangle.point( Array.new([0.5,0,0.5])))
  61. #inside
  62. assert_equal(Vector3.new(0, 3, 1), @triangle.point( Array.new([0.25,0.25,0.5])))
  63. assert_equal(@triangle.center, @triangle.point( Array.new([1.0/3.0,1.0/3.0,1.0/3.0])))
  64. end
  65. def test_edges
  66. edges = @triangle.edges
  67. assert_equal(@triangle.vertices[0], edges[0].start_point)
  68. assert_equal(@triangle.vertices[1], edges[0].end_point)
  69. assert_equal(@triangle.vertices[1], edges[1].start_point)
  70. assert_equal(@triangle.vertices[2], edges[1].end_point)
  71. assert_equal(@triangle.vertices[2], edges[2].start_point)
  72. assert_equal(@triangle.vertices[0], edges[2].end_point)
  73. end
  74. def test_area
  75. assert_in_delta(Math::sqrt(8), @triangle.area, @triangle.tolerance)
  76. assert_in_delta(0.5, @triangle_default.area, @triangle_default.tolerance)
  77. end
  78. def test_normal
  79. assert_equal( Vector3.new(-1,0,1).normalize(), @triangle.normal )
  80. assert_equal( Vector3.new(0,0,1) ,@triangle_default.normal )
  81. end
  82. def test_reverse
  83. current_normal = @triangle.normal()
  84. reversed_normal = @triangle.reverse().normal()
  85. assert( current_normal.parallel?(reversed_normal) )
  86. assert( !current_normal.same_direction?(reversed_normal) )
  87. end
  88. def test_center
  89. center = @triangle.center
  90. assert_in_delta( 0.333333333333333, center.x, @triangle.tolerance)
  91. assert_in_delta( 3.0, center.y, @triangle.tolerance)
  92. assert_in_delta( 1.333333333333333, center.z, @triangle.tolerance)
  93. barycentric_coordinate = @triangle.barycentric_coordinate(center)
  94. assert_in_delta( 1.0/3.0, barycentric_coordinate[0], @triangle.tolerance)
  95. assert_in_delta( 1.0/3.0, barycentric_coordinate[1], @triangle.tolerance)
  96. assert_in_delta( 1.0/3.0, barycentric_coordinate[2], @triangle.tolerance)
  97. end
  98. def test_barycentric_coordinate
  99. # on vertex
  100. coord = @triangle.barycentric_coordinate( @triangle.vertices[1])
  101. assert_equal( 3, coord.size )
  102. assert_in_delta( 0, coord[0], @triangle.tolerance)
  103. assert_in_delta( 1, coord[1], @triangle.tolerance)
  104. assert_in_delta( 0, coord[2], @triangle.tolerance)
  105. # on edge
  106. coord = @triangle.barycentric_coordinate( Vector3.new(1,3,2) )
  107. assert_in_delta( 0.5, coord[0], @triangle.tolerance)
  108. assert_in_delta( 0.5, coord[1], @triangle.tolerance)
  109. assert_in_delta( 0, coord[2], @triangle.tolerance)
  110. # inside case
  111. coord = @triangle.barycentric_coordinate( Vector3.new(0,3,1) )
  112. assert_in_delta( 1.0, coord[0] + coord[1] + coord[2], @triangle.tolerance)
  113. assert_in_delta( 0.25, coord[0], @triangle.tolerance)
  114. assert_in_delta( 0.25, coord[1], @triangle.tolerance)
  115. assert_in_delta( 0.5, coord[2], @triangle.tolerance)
  116. # outside case
  117. coord = @triangle_default.barycentric_coordinate( Vector3.new(2,0,0) )
  118. assert_in_delta( -1.0, coord[0], @triangle.tolerance)
  119. assert_in_delta( 2.0, coord[1], @triangle.tolerance)
  120. assert_in_delta( 0.0, coord[2], @triangle.tolerance)
  121. # outside case
  122. coord = @triangle.barycentric_coordinate( Vector3.new(3,3,4) )
  123. assert_in_delta( 1.0, coord[0], @triangle.tolerance)
  124. assert_in_delta( 1.0, coord[1], @triangle.tolerance)
  125. assert_in_delta( -1.0, coord[2], @triangle.tolerance)
  126. #invalid argument
  127. assert_raises ArgumentError do
  128. coord = @triangle.barycentric_coordinate( 3 )
  129. end
  130. assert_raises ArgumentError do
  131. coord = @triangle.barycentric_coordinate( nil )
  132. end
  133. end
  134. def test_contains
  135. check_point = @triangle.center + @triangle.normal*3.0
  136. assert( !@triangle.contains?( check_point) )
  137. assert( @triangle.contains?( @triangle.center) )
  138. assert( @triangle.contains?( Vector3.new( 1,3,2)))
  139. assert( @triangle.contains?( Vector3.new(-1,3,0)))
  140. assert( @triangle_default.contains?( Vector3.new( 0.5, 0.5, 0.0 ) ))
  141. assert( !@triangle_default.contains?( Vector3.new( -1.0, 2.0, 0.0 )))
  142. assert( !@triangle_default.contains?( Vector3.new( 1.0, 1.0, 0.0 )))
  143. end
  144. def test_distance_to_point
  145. # on inside
  146. check_point = @triangle.center + @triangle.normal*3.0
  147. distance, point_on_triangle = @triangle.distance(check_point)
  148. assert_in_delta(3.0, distance, @triangle.tolerance)
  149. assert_equal(@triangle.center, point_on_triangle)
  150. # on vertex
  151. distance, point_on_triangle = @triangle_default.distance(Vector3.new(-1,-1,0.5))
  152. assert_in_delta(Math::sqrt(2.25), distance, @triangle_default.tolerance)
  153. assert_equal(@triangle_default.vertices[0], point_on_triangle)
  154. # on edge
  155. distance, point_on_triangle = @triangle.distance( Vector3.new(2,3,2))
  156. assert_in_delta(1, distance, @triangle_default.tolerance)
  157. assert_equal(Vector3.new(1,3,2), point_on_triangle)
  158. # contains to inside
  159. distance, point_on_triangle = @triangle_default.distance(@triangle_default.center)
  160. assert_in_delta(0, distance, @triangle_default.tolerance)
  161. assert_equal(@triangle_default.center, point_on_triangle)
  162. end
  163. def test_distance_to_line
  164. # on inside
  165. line = Line.new(Vector3.new(0,3,-1), Vector3.new(0,0,4))
  166. distance, point_on_triangle, point_on_line, param_on_line = @triangle.distance(line)
  167. assert_equal(0, distance)
  168. assert_equal(Vector3.new(0,3,1), point_on_triangle)
  169. assert_equal(Vector3.new(0,3,1), point_on_line)
  170. assert_in_delta(0.5, param_on_line, line.tolerance)
  171. # on edge
  172. line = Line.new(Vector3.new(1,3,-1), Vector3.new(0,0,4))
  173. distance, point_on_triangle, point_on_line, param_on_line = @triangle.distance(line)
  174. assert_equal(0, distance)
  175. assert_equal(Vector3.new(1,3,2), point_on_triangle)
  176. assert_equal(Vector3.new(1,3,2), point_on_line)
  177. assert_in_delta(0.75, param_on_line, line.tolerance)
  178. # on vertex
  179. line = Line.new(Vector3.new(-1,3,0), Vector3.new(1,1,2))
  180. distance, point_on_triangle, point_on_line, param_on_line = @triangle.distance(line)
  181. assert_equal(0, distance)
  182. assert_equal(Vector3.new(-1,3,0), point_on_triangle)
  183. assert_equal(Vector3.new(-1,3,0), point_on_line)
  184. assert_in_delta(0.0, param_on_line, line.tolerance)
  185. # closest point is out of triangle1
  186. line = Line.new(Vector3.new(2,3,0), Vector3.new(0,0,4))
  187. distance, point_on_triangle, point_on_line, param_on_line = @triangle.distance(line)
  188. assert_equal(1, distance)
  189. assert_equal(Vector3.new(1,3,2), point_on_triangle)
  190. assert_equal(Vector3.new(2,3,2), point_on_line)
  191. assert_in_delta(0.5, param_on_line, line.tolerance)
  192. # closest point is out of triangle2
  193. line = Line.new(Vector3.new(-2,3,-1), Vector3.new(0,0,1))
  194. distance, point_on_triangle, point_on_line, param_on_line = @triangle.distance(line)
  195. assert_equal(1, distance)
  196. assert_equal(Vector3.new(-1,3,0), point_on_triangle)
  197. assert_equal(Vector3.new(-2,3,0), point_on_line)
  198. assert_in_delta(1, param_on_line, line.tolerance)
  199. # parallel case
  200. line = Line.new(Vector3.new(1,0,4), Vector3.new(0,6,0))
  201. distance, point_on_triangle, point_on_line, param_on_line = @triangle.distance(line)
  202. assert_equal(2, distance)
  203. assert_equal(nil, point_on_triangle)
  204. assert_equal(nil, point_on_line)
  205. assert_equal(nil, param_on_line)
  206. end
  207. def test_distance_to_plane
  208. # intersect case
  209. plane = Plane.new(Vector3.new(0,0,1), Vector3.new(1,0,0))
  210. distance, intersect_line, point_on_triangle, point_on_plane = @triangle.distance(plane)
  211. assert_equal( 0, distance )
  212. point1 = Vector3.new(0,2.5,1)
  213. point2 = Vector3.new(0,3.5,1)
  214. assert( FiniteLine.new(point1, point2) == intersect_line || FiniteLine.new(point2, point1) == intersect_line)
  215. assert_equal( nil, point_on_triangle )
  216. assert_equal( nil, point_on_plane )
  217. # contains edge
  218. plane = Plane.new(Vector3.new(1,0,1), Vector3.new(-1,0,0))
  219. distance, intersect_line, point_on_triangle, point_on_plane = @triangle.distance(plane)
  220. assert_equal( 0, distance )
  221. point1 = Vector3.new(1,2,2)
  222. point2 = Vector3.new(1,4,2)
  223. assert( FiniteLine.new(point1, point2) == intersect_line || FiniteLine.new(point2, point1) == intersect_line)
  224. assert_equal( nil, point_on_triangle )
  225. assert_equal( nil, point_on_plane )
  226. # contains vertex
  227. plane = Plane.new(Vector3.new(-1,0,1), Vector3.new(1,0,0))
  228. distance, intersect_line, point_on_triangle, point_on_plane = @triangle.distance(plane)
  229. assert_equal( 0, distance )
  230. assert_equal( nil, intersect_line)
  231. assert_equal( Vector3.new(-1,3,0), point_on_triangle )
  232. assert_equal( Vector3.new(-1,3,0), point_on_plane )
  233. # closeing point is outside of triangle
  234. plane = Plane.new(Vector3.new(-2,0,0), Vector3.new(-1,0,0))
  235. distance, intersect_line, point_on_triangle, point_on_plane = @triangle.distance(plane)
  236. assert_equal( 1, distance )
  237. assert_equal( nil, intersect_line)
  238. assert_equal( Vector3.new(-1,3,0), point_on_triangle )
  239. assert_equal( Vector3.new(-2,3,0), point_on_plane )
  240. # parallel to plane
  241. plane = Plane.new(Vector3.new(0,0,4), Vector3.new(0,0,1))
  242. distance, intersect_line, point_on_triangle, point_on_plane = @triangle_default.distance(plane)
  243. assert_equal( 4, distance )
  244. assert_equal( nil, intersect_line)
  245. assert_equal( nil, point_on_triangle )
  246. assert_equal( nil, point_on_plane )
  247. # parallel to edge
  248. plane = Plane.new(Vector3.new(3.5,0,3), Vector3.new(-1,0,0))
  249. distance, closest_line, point_on_triangle, point_on_plane = @triangle.distance(plane)
  250. assert_equal( 2.5, distance )
  251. point1 = Vector3.new(1,2,2)
  252. point2 = Vector3.new(1,4,2)
  253. assert( FiniteLine.new(point1, point2) == closest_line || FiniteLine.new(point2, point1) == closest_line)
  254. assert_equal( nil, point_on_triangle )
  255. assert_equal( nil, point_on_plane )
  256. end
  257. def test_angle
  258. triangle1 = Triangle.new( Vector3.new(0,0,1), Vector3.new(Math.sqrt(3.0),0,1), Vector3.new(0,1,1))
  259. triangle2 = Triangle.new( Vector3.new(1,0,0), Vector3.new(0,0,1), Vector3.new(1,1,1))
  260. assert_equal(nil, triangle1.angle(-1))
  261. assert_equal(nil, triangle1.angle(3))
  262. assert_in_delta(90.0*Math::PI/180.0, triangle1.angle(0), triangle1.tolerance)
  263. assert_in_delta(30.0*Math::PI/180.0, triangle1.angle(1), triangle1.tolerance)
  264. assert_in_delta(60.0*Math::PI/180.0, triangle1.angle(2), triangle1.tolerance)
  265. assert_in_delta(60.0*Math::PI/180.0, triangle2.angle(0), triangle1.tolerance)
  266. assert_in_delta(60.0*Math::PI/180.0, triangle2.angle(1), triangle1.tolerance)
  267. assert_in_delta(60.0*Math::PI/180.0, triangle2.angle(2), triangle1.tolerance)
  268. end
  269. end