PageRenderTime 48ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/src/PolygonCollisionDetection.as

https://github.com/Lindi/Collision-Detection
ActionScript | 739 lines | 459 code | 119 blank | 161 comment | 70 complexity | d3a57992c4d8e9ed18cf550c910aaa9a MD5 | raw file
  1. package
  2. {
  3. import flash.display.Sprite;
  4. import flash.events.Event;
  5. import flash.events.MouseEvent;
  6. import flash.events.TimerEvent;
  7. import flash.utils.Timer;
  8. import flash.utils.getTimer;
  9. import geometry.AABB;
  10. import geometry.Polygon2d;
  11. import geometry.Vector2d;
  12. import physics.PolygonDistance;
  13. import physics.lcp.LcpSolver;
  14. [SWF(width='400',height='400')]
  15. public class PolygonCollisionDetection extends Sprite
  16. {
  17. private var polygons:Vector.<Polygon2d> = new Vector.<Polygon2d>(2,true);
  18. private var aabbs:Vector.<AABB> = new Vector.<AABB>(2,true);
  19. private var velocity:Vector.<Vector2d> = new Vector.<Vector2d>(2,true);
  20. private var currentPolygon:int = -1 ;
  21. private var offset:Vector2d ;
  22. private var solution:Object ;
  23. public function PolygonCollisionDetection()
  24. {
  25. super();
  26. init( );
  27. }
  28. private function init( ):void
  29. {
  30. // Create a polygon
  31. var random:int = int( Math.random() * 30 );
  32. var centroid:Vector2d = new Vector2d( stage.stageWidth/4, stage.stageHeight/2 - random ) ;
  33. polygons[0] = createPolygon( centroid );
  34. // Create another polygon, and make sure they don't intersect
  35. random = int( Math.random() * 30 );
  36. centroid = new Vector2d( 3 * stage.stageWidth/4, stage.stageHeight/2 + random ) ;
  37. polygons[1] = createPolygon( centroid );
  38. // Give each polygon a velocity
  39. var dx:Number, dy:Number ;
  40. dx = 20 + int( Math.random() * 10 ) * ( 1 - 2 * int( Math.random() * 2 ));
  41. dy = 20 + int( Math.random() * 10 ) * ( 1 - 2 * int( Math.random() * 2 ));
  42. velocity[0] = new Vector2d( dx, dy );
  43. do
  44. {
  45. dx = 20 + int( Math.random() * 10 ) * ( 1 - 2 * int( Math.random() * 2 ));
  46. dy = 20 + int( Math.random() * 10 ) * ( 1 - 2 * int( Math.random() * 2 ));
  47. } while ( dx == velocity[0].x || dy == velocity[0].y )
  48. velocity[1] = new Vector2d( dx, dy );
  49. // Calculate distance
  50. calculateDistance();
  51. // Draw the polygons
  52. draw( polygons );
  53. // Listen for mouse up
  54. addEventListener( Event.ENTER_FRAME, frame );
  55. }
  56. private function calculateDistance( ):void
  57. {
  58. var solution:Object = PolygonDistance.distance( polygons[0].clone(), polygons[1].clone());
  59. if ( solution.status == LcpSolver.FOUND_SOLUTION )
  60. {
  61. this.solution = solution ;
  62. } else
  63. {
  64. this.solution = null ;
  65. }
  66. }
  67. private function click( event:Event ):void
  68. {
  69. // TODO: Make sure to determine their AABBs intersect
  70. var polygonsIntersect:Boolean = SeparatingAxes.testIntersection( polygons[0], polygons[1] );
  71. // Calculate the distance
  72. calculateDistance();
  73. // Store the two closest points
  74. var a:Vector2d = new Vector2d( solution.Z[0], solution.Z[1] );
  75. var b:Vector2d = new Vector2d( solution.Z[2], solution.Z[3] );
  76. // Calculate the distance between them
  77. var distance:Number = b.Subtract( a ).length ;
  78. // Minimum distance threshold
  79. var threshold:Number = 5.0 ;
  80. // If the polygons are close enough together ...
  81. if ( distance < threshold )
  82. {
  83. collisionResponse( a, b );
  84. }
  85. // Draw the polygons
  86. draw( polygons, 0xaaaaaa );
  87. }
  88. /**
  89. * Separate the axis-aligned bounding boxes if
  90. * the polygons intersect
  91. */
  92. private function separateAABBs():void
  93. {
  94. // Separate the AABBs
  95. var intersection:AABB = new AABB();
  96. aabbs[0].findIntersection( aabbs[1], intersection );
  97. var w:Number = intersection.width ;
  98. var h:Number = intersection.height ;
  99. var d:Number = Math.sqrt( w * w + h * h ) ;
  100. // Move each polygon apart by half this distance
  101. var v:Vector2d = velocity[0].clone();
  102. v.normalize();
  103. // Move them both half the distance
  104. // Move polygon 0
  105. var centroid:Vector2d = polygons[0].centroid.Add( v.Negate().ScaleBy( d/2 ));
  106. updateCentroid( polygons[0], centroid ) ;
  107. //velocity[0] = v.Negate().ScaleBy( velocity[0].length ) ;
  108. // Move polygon 1
  109. v = velocity[1].clone();
  110. v.normalize();
  111. centroid = polygons[1].centroid.Add( v.Negate().ScaleBy( d/2 ));
  112. updateCentroid( polygons[1], centroid ) ;
  113. //velocity[1] = v.Negate().ScaleBy( velocity[1].length ) ;
  114. }
  115. /**
  116. * Enter frame handler
  117. * @param event
  118. *
  119. */
  120. private function frame( event:Event ):void
  121. {
  122. // Update the velocities of each polygon
  123. updateCentroid( polygons[0], polygons[0].centroid.Add( velocity[0] ));
  124. updateCentroid( polygons[1], polygons[1].centroid.Add( velocity[1] ));
  125. // Update the axis-aligned bounding boxes
  126. updateAABBs( ) ;
  127. // Do collision detection with stage edges
  128. for ( var i:int = 0; i < polygons.length; i++ )
  129. {
  130. // Grab a polygon
  131. var polygon:Polygon2d = polygons[i];
  132. polygon.moved = false ;
  133. // Get the AABB
  134. var aabb:AABB = aabbs[i] ;
  135. var offstage:Boolean = ( aabb.xmin <= 0 )
  136. || ( aabb.xmax >= stage.stageWidth )
  137. || ( aabb.ymin <= 0 )
  138. || ( aabb.ymax >= stage.stageHeight );
  139. // Get the centroid
  140. var centroid:Vector2d = polygon.centroid.clone() ;
  141. if ( aabb.xmin <= 0 )
  142. {
  143. if ( velocity[i].dot( new Vector2d( 1, 0 )) < 0 )
  144. {
  145. velocity[i].x = -velocity[i].x ;
  146. centroid.x -= aabb.xmin ;
  147. polygon.moved = true ;
  148. }
  149. }
  150. if ( aabb.xmax >= stage.stageWidth )
  151. {
  152. if ( velocity[i].dot( new Vector2d( -1, 0 )) < 0 )
  153. {
  154. velocity[i].x = -velocity[i].x ;
  155. centroid.x -= ( aabb.xmax - stage.stageWidth ) ;
  156. polygon.moved = true ;
  157. }
  158. }
  159. if ( aabb.ymin <= 0 )
  160. {
  161. if ( velocity[i].dot( new Vector2d( 0, 1 )) < 0 )
  162. {
  163. velocity[i].y = -velocity[i].y ;
  164. centroid.y -= aabb.ymin ;
  165. polygon.moved = true ;
  166. }
  167. }
  168. if ( aabb.ymax >= stage.stageHeight )
  169. {
  170. if ( velocity[i].dot( new Vector2d( 0, -1 )) < 0 )
  171. {
  172. velocity[i].y = -velocity[i].y ;
  173. centroid.x -= ( aabb.ymax - stage.stageHeight ) ;
  174. polygon.moved = true ;
  175. }
  176. }
  177. updateCentroid( polygon, centroid );
  178. }
  179. // Get the axis-aligned bounding boxes
  180. for ( i = 0; i < polygons.length; i++ )
  181. {
  182. // Grab a polygon
  183. polygon = polygons[i];
  184. // Get the AABB
  185. aabbs[i] = getAABB( polygon ) ;
  186. }
  187. // Do their AABBs intersect?
  188. var aabbsIntersect:Boolean = aabbs[0].findIntersection( aabbs[1] ) ;
  189. var color:Number = ( aabbsIntersect ? 0xff0000 : 0x000000 ) ;
  190. // Do the collision response here ...
  191. if ( aabbsIntersect )
  192. {
  193. if ( SeparatingAxes.testIntersection( polygons[0], polygons[1] ))
  194. separateAABBs();
  195. // Calculate the distance
  196. calculateDistance();
  197. // Store the two closest points
  198. var a:Vector2d = new Vector2d( solution.Z[0], solution.Z[1] );
  199. var b:Vector2d = new Vector2d( solution.Z[2], solution.Z[3] );
  200. // Calculate the distance between them
  201. var distance:Number = b.Subtract( a ).length ;
  202. // Minimum distance threshold
  203. var threshold:Number = 5.0 ;
  204. // If the polygons are close enough together ...
  205. if ( distance < threshold )
  206. {
  207. collisionResponse( a, b );
  208. updateCentroid( polygons[0], polygons[0].centroid.Add( velocity[0] ));
  209. updateCentroid( polygons[1], polygons[1].centroid.Add( velocity[1] ));
  210. }
  211. }
  212. // Update the axis-aligned bounding boxes
  213. updateAABBs( ) ;
  214. // Draw the polygons
  215. draw( polygons, color );
  216. }
  217. /**
  218. * Update the axis-aligned bounding boxes
  219. * of the polygons
  220. *
  221. */
  222. private function updateAABBs( ):void
  223. {
  224. // Get the axis-aligned bounding boxes
  225. for ( var i:int = 0; i < polygons.length; i++ )
  226. {
  227. // Get the AABB
  228. aabbs[i] = getAABB( polygons[i] ) ;
  229. }
  230. }
  231. /**
  232. * Respond to the collision of the polygons. Vectors a and b
  233. * are the two closest points between the polygon.
  234. * @param a - The point on polygon a closest to polygon b
  235. * @param b - The poing on polygon b closest to polygon a
  236. *
  237. */
  238. private function collisionResponse( a:Vector2d, b:Vector2d ):void
  239. {
  240. // Move the polygons together
  241. // TODO: return a vector of velocities from this function
  242. // and translate point a and b by the respective velocities
  243. movePolygonsTogether( a, b );
  244. // velocity[0].negate() ;
  245. // velocity[1].negate() ;
  246. // // Update the velocities of each polygon
  247. // updateCentroid( polygons[0], polygons[0].centroid.Add( velocity[0] ));
  248. // updateCentroid( polygons[1], polygons[1].centroid.Add( velocity[1] ));
  249. //// a.add( velocity[0] );
  250. //// b.add( velocity[1] );
  251. // return ;
  252. // Determine which closest point lies on an edge
  253. var index:int = -1;
  254. var edge:Vector2d ;
  255. var normal:Vector2d ;
  256. var polygon:Polygon2d ;
  257. var c:Vector2d, d:Vector2d, v:Vector2d ;
  258. // If the polygon a's closest point is not a vertex and
  259. // polygon b's closest point is a vertext ...
  260. if ( !isVertex( polygons[0], a ) && isVertex( polygons[1], b ))
  261. {
  262. // Grab the edge normal on polygon a that is closest to point a
  263. polygon = polygons[0] ;
  264. index = getClosestEdgeNormalIndex( polygons[0], a );
  265. normal = polygons[0].getNormal( index );
  266. // Resolve the collision with polygon1 colliding into polygon0
  267. v = resolveCollision( polygons[1], velocity[1].Subtract( velocity[0] ), normal );
  268. if ( v != null )
  269. {
  270. v.normalize();
  271. v.scale( velocity[1].length );
  272. updateCentroid( polygons[1], polygons[1].centroid.Add( v ));
  273. velocity[1] = v ;
  274. }
  275. // Resolve the collision with polygon0 colliding into polygon1
  276. polygon = polygons[1] ;
  277. normal = b.Subtract( polygons[1].centroid );
  278. v = resolveCollision( polygons[0], velocity[0].Subtract( velocity[1] ), normal );
  279. if ( v != null )
  280. {
  281. v.normalize();
  282. v.scale( velocity[0].length );
  283. updateCentroid( polygons[0], polygons[0].centroid.Add( v ));
  284. velocity[0] = v ;
  285. }
  286. // If polygon a's closest point is a vertex and
  287. // polygon b's closest point is not a vertex
  288. } else if ( isVertex( polygons[0], a ) && !isVertex( polygons[1], b ))
  289. {
  290. // Grab the edge normal closest to point b
  291. polygon = polygons[1] ;
  292. index = getClosestEdgeNormalIndex( polygons[1], b );
  293. normal = polygons[1].getNormal( index );
  294. // Resolve the collision with polygon0 colliding into polygon1
  295. v = resolveCollision( polygons[0], velocity[0].Subtract( velocity[1] ), normal );
  296. if ( v != null )
  297. {
  298. v.normalize();
  299. v.scale( velocity[0].length );
  300. updateCentroid( polygons[0], polygons[0].centroid.Add( v ));
  301. velocity[0] = v ;
  302. }
  303. // Resolve the collision with polygon1 colliding into polygon0
  304. polygon = polygons[0] ;
  305. normal = a.Subtract( polygons[0].centroid );
  306. v = resolveCollision( polygons[1], velocity[1].Subtract( velocity[0] ), normal );
  307. if ( v != null )
  308. {
  309. v.normalize();
  310. v.scale( velocity[1].length );
  311. updateCentroid( polygons[1], polygons[1].centroid.Add( v ));
  312. velocity[1] = v ;
  313. }
  314. } else if ( isVertex( polygons[0], a ) && isVertex( polygons[1], b ))
  315. {
  316. // Two vertices
  317. // Grab the edge normal closest to point b
  318. polygon = polygons[1] ;
  319. normal = b.Subtract( a ) ;
  320. // Resolve the collision with polygon0 colliding into polygon1
  321. v = resolveCollision( polygons[0], velocity[0].Subtract( velocity[1] ), normal );
  322. if ( v != null )
  323. {
  324. v.normalize();
  325. v.scale( velocity[0].length );
  326. updateCentroid( polygons[0], polygons[0].centroid.Add( v ));
  327. velocity[0] = v ;
  328. }
  329. // Grab the edge normal closest to point a
  330. polygon = polygons[0] ;
  331. normal.negate();
  332. // Resolve the collision with polygon1 colliding into polygon0
  333. v = resolveCollision( polygons[1], velocity[1].Subtract( velocity[0] ), normal );
  334. if ( v != null )
  335. {
  336. v.normalize();
  337. v.scale( velocity[1].length );
  338. updateCentroid( polygons[1], polygons[1].centroid.Add( v ));
  339. velocity[1] = v ;
  340. }
  341. } else if ( !isVertex( polygons[1], b ) && !isVertex( polygons[1], b ))
  342. {
  343. // Two edges
  344. // Resolve the collision with polygon1 colliding into polygon0
  345. polygon = polygons[0] ;
  346. normal = a.Subtract( polygons[0].centroid );
  347. v = resolveCollision( polygons[1], velocity[1].Subtract( velocity[0] ), normal );
  348. if ( v != null )
  349. {
  350. v.normalize();
  351. v.scale( velocity[1].length );
  352. updateCentroid( polygons[1], polygons[1].centroid.Add( v ));
  353. velocity[1] = v ;
  354. }
  355. // Resolve the collision with polygon0 colliding into polygon1
  356. polygon = polygons[1] ;
  357. v = resolveCollision( polygons[0], velocity[0].Subtract( velocity[1] ), normal );
  358. if ( v != null )
  359. {
  360. v.normalize();
  361. v.scale( velocity[0].length );
  362. updateCentroid( polygons[0], polygons[0].centroid.Add( v ));
  363. velocity[0] = v ;
  364. }
  365. }
  366. }
  367. /**
  368. * Moves both polygons half of the closest distance between them
  369. * @param a - The point on polygon a that's closest to polygon b
  370. * @param b - The point on polygon b that's closest to polygon a
  371. *
  372. */
  373. private function movePolygonsTogether( a:Vector2d, b:Vector2d ):Vector.<Vector2d>
  374. {
  375. // Create a collection of velocities
  376. var velocity:Vector.<Vector2d> = new Vector.<Vector2d>(2,true);
  377. // Initialize some temp variables
  378. var d:Vector2d ;
  379. var index:int ;
  380. var v:Vector2d, m:Vector2d;
  381. // Calculate the mid-point between a and b
  382. var x:Number = ( b.x + a.x )/ 2 ;
  383. var y:Number = ( b.y + a.y )/ 2 ;
  384. m = new Vector2d( x, y );
  385. // Get the vector from polygon a's centroit the point
  386. // that's closest to polygon b
  387. d = a.Subtract( polygons[0].centroid );
  388. // Get the vertex that's closest to the polygon in a given direction
  389. index = Polygon2d.getExtremeIndex( polygons[1], d );
  390. velocity[0] = v = polygons[1].getVertex( index ).Subtract( polygons[0].centroid );
  391. // Move the polygon in the velocity direction such
  392. // that it moves half the distance between a and b in the b - a direction
  393. d = m.Subtract( a );
  394. v.normalize();
  395. v.scale( d.length );
  396. updateCentroid( polygons[0], polygons[0].centroid.Add( v ));
  397. // Get the second polygon's velocity
  398. d = b.Subtract( polygons[1].centroid );
  399. index = Polygon2d.getExtremeIndex( polygons[0], d );
  400. velocity[1] = v = polygons[0].getVertex( index ).Subtract( polygons[1].centroid );
  401. // Move the polygon in the velocity direction such
  402. // that is moves half the distance between a and b in the b - a direction
  403. d = m.Subtract( b );
  404. v.normalize();
  405. v.scale( d.length );
  406. updateCentroid( polygons[1], polygons[1].centroid.Add( v ));
  407. // Return the velocities
  408. return velocity ;
  409. }
  410. /**
  411. * Calculates the velocity of a polygon after collision
  412. * @param polygon - the colliding polygon
  413. * @param relativeVelocity - the difference between the velocity of the colliding polygon
  414. * and the velocity of the 'collidee'
  415. * @param normal - this must be normalized
  416. *
  417. */
  418. private function resolveCollision( polygon:Polygon2d, relativeVelocity:Vector2d, normal:Vector2d ):Vector2d
  419. {
  420. // normal must be unit-length and outward facing
  421. normal.normalize();
  422. // Make sure the dot product between the normal and the relative velocity is negative
  423. // The dot product of the relative velocity and the outward facing normal yields
  424. // the component of the relative velocity in the normal direction
  425. var dp:Number = relativeVelocity.dot( normal );
  426. if ( dp < 0 )
  427. {
  428. // Get the perpendicular to the normal
  429. var perp:Vector2d = normal.perp() ;
  430. // The dot product between the relative velocity and the perp to the normal should be positive
  431. if ( relativeVelocity.dot( perp ) < 0 )
  432. {
  433. perp.negate();
  434. }
  435. // Subtract the component of the relative velocity in the
  436. // normal direction from the normal perpendicular
  437. var normalComponent:Vector2d = normal.ScaleBy( dp );
  438. return perp.Subtract( normalComponent );
  439. }
  440. return null ;
  441. }
  442. public function updateCentroid( polygon:Polygon2d, centroid:Vector2d ):void
  443. {
  444. // Update the vertices
  445. var vertices:Vector.<Vector2d> = polygon.vertices ;
  446. for ( var j:int = 0; j < vertices.length; j++ )
  447. {
  448. var vertex:Vector2d = vertices[j] ;
  449. vertex.x -= polygon.centroid.x ;
  450. vertex.y -= polygon.centroid.y ;
  451. vertex.x += centroid.x ;
  452. vertex.y += centroid.y ;
  453. }
  454. polygon.centroid = centroid ;
  455. polygon.updateLines();
  456. }
  457. /**
  458. * Returns true if the closest point
  459. * @param polygon
  460. * @param closestPoint
  461. * @return
  462. *
  463. */
  464. private function isVertex( polygon:Polygon2d, closestPoint:Vector2d ):Boolean
  465. {
  466. var vertices:Vector.<Vector2d> = polygon.vertices ;
  467. for ( var i:int = 0; i < vertices.length; i++ )
  468. {
  469. var vertex:Vector2d = vertices[i] ;
  470. var diff:Vector2d = closestPoint.Subtract( vertex );
  471. if ( diff.length < .00001 )
  472. {
  473. return true ;
  474. }
  475. }
  476. return false ;
  477. }
  478. private function getVertexIndex( polygon:Polygon2d, closestPoint:Vector2d ):int
  479. {
  480. var vertices:Vector.<Vector2d> = polygon.vertices ;
  481. for ( var i:int = 0; i < vertices.length; i++ )
  482. {
  483. var vertex:Vector2d = vertices[i] ;
  484. var diff:Vector2d = closestPoint.Subtract( vertex );
  485. if ( diff.length < .00001 )
  486. {
  487. return i ;
  488. }
  489. }
  490. return -1 ;
  491. }
  492. /**
  493. * Returns the edge normal that's closest to the given point
  494. * @return
  495. *
  496. */
  497. private function getClosestEdgeNormal( polygon:Polygon2d, point:Vector2d ):Vector2d
  498. {
  499. return polygon.getNormal( getClosestEdgeNormalIndex( polygon, point ) ) ;
  500. }
  501. /**
  502. * Returns the edge normal index that's closest to the given point
  503. * @return
  504. *
  505. */
  506. private function getClosestEdgeNormalIndex( polygon:Polygon2d, point:Vector2d ):int
  507. {
  508. var vertices:Vector.<Vector2d> = polygon.vertices ;
  509. var dist:Number = Number.MAX_VALUE ;
  510. var index:int ;
  511. for ( var i:int = 0; i < vertices.length; i++ )
  512. {
  513. var b:Vector2d = vertices[(i + 1) % vertices.length];
  514. var a:Vector2d = vertices[i] ;
  515. var edge:Vector2d = b.Subtract( a ) ;
  516. edge.normalize();
  517. var u:Vector2d = point.Subtract( a );
  518. u.normalize();
  519. var d:Number = Math.abs( edge.dot( u ) - 1.0 );
  520. if ( d < dist )
  521. {
  522. index = i ;
  523. dist = d;
  524. }
  525. }
  526. return index ;
  527. }
  528. private function isInside( polygon:Polygon2d, point:Vector2d ):Boolean
  529. {
  530. for ( var j:int = 0; j < polygon.vertices.length; j++)
  531. {
  532. if ( polygon.normals[j].dot( point.Subtract( polygon.vertices[j] )) > 0 )
  533. {
  534. return false ;
  535. }
  536. }
  537. return true ;
  538. }
  539. /**
  540. * Returs the axis-aligned bounding box (AABB) of a given polygon
  541. * @param polygon
  542. * @return
  543. *
  544. */
  545. private function getAABB( polygon:Polygon2d ):AABB
  546. {
  547. var xmin:Number = Number.MAX_VALUE ;
  548. var ymin:Number = Number.MAX_VALUE ;
  549. var xmax:Number = Number.MIN_VALUE ;
  550. var ymax:Number = Number.MIN_VALUE ;
  551. for each ( var vertex:Vector2d in polygon.vertices )
  552. {
  553. xmin = Math.min( xmin, vertex.x );
  554. xmax = Math.max( xmax, vertex.x );
  555. ymin = Math.min( ymin, vertex.y );
  556. ymax = Math.max( ymax, vertex.y );
  557. }
  558. var aabb:AABB = new AABB( xmin, ymin, xmax, ymax );
  559. return aabb ;
  560. }
  561. private function draw( polygons:Vector.<Polygon2d>, color:Number = 0x000000 ):void
  562. {
  563. graphics.clear();
  564. if ( solution != null )
  565. {
  566. graphics.lineStyle( 2, 0xff0000 );
  567. graphics.moveTo( solution.Z[0], solution.Z[1] );
  568. graphics.lineTo( solution.Z[2], solution.Z[3] );
  569. }
  570. for ( var i:int = 0; i < polygons.length; i++ )
  571. {
  572. var polygon:Polygon2d = polygons[i] ;
  573. graphics.lineStyle( 2, color );
  574. for ( var j:int = 0, k:int = -1; j < polygon.vertices.length; k = j++ )
  575. {
  576. var a:Vector2d = polygon.getVertex( k ) ;
  577. var b:Vector2d = polygon.getVertex( j ) ;
  578. graphics.moveTo( a.x, a.y );
  579. graphics.lineTo( b.x, b.y );
  580. }
  581. var aabb:AABB = aabbs[i] ;
  582. if ( aabb != null )
  583. {
  584. graphics.lineStyle( .5, 0x0000ff ) ;
  585. graphics.drawRect( aabb.xmin, aabb.ymin, aabb.width, aabb.height ) ;
  586. }
  587. }
  588. }
  589. /**
  590. * Creates a polygon with a number of vertices between
  591. * 3 and 6 ;
  592. *
  593. */
  594. private function createPolygon( centroid:Vector2d ):Polygon2d
  595. {
  596. // Create a polygon
  597. var polygon:Polygon2d = new Polygon2d( );
  598. // The polygon should have at least 3 and at most six points
  599. var points:int = 3 + int( Math.random() * 3 );
  600. // Add points to the polygon
  601. var angle:Number = ( Math.PI / 180 ) * ( 360 / points ) ;
  602. var scale:Number = 40 ;
  603. for ( var i:int = 0; i < points; i++ )
  604. {
  605. var alpha:Number = angle * i ;
  606. var x:Number = Math.cos( alpha ) - Math.sin( alpha ) ;
  607. var y:Number = Math.sin( alpha ) + Math.cos( alpha ) ;
  608. polygon.addVertex( new Vector2d(( x * scale ) + centroid.x, ( y * scale ) + centroid.y ));
  609. }
  610. // Order the polygon vertices counter-clockwise
  611. polygon.orderVertices();
  612. // Create the collection of polygon edges
  613. polygon.updateLines();
  614. // Create a true
  615. polygon.createTree();
  616. // Return the polygon
  617. return polygon ;
  618. }
  619. }
  620. }