{"id":208,"date":"2011-11-29T07:27:19","date_gmt":"2011-11-29T14:27:19","guid":{"rendered":"http:\/\/sloanseaman.com\/wordpress\/?p=208"},"modified":"2012-04-10T10:51:45","modified_gmt":"2012-04-10T17:51:45","slug":"arc-collision","status":"publish","type":"post","link":"http:\/\/sloanseaman.com\/wordpress\/2011\/11\/29\/arc-collision\/","title":{"rendered":"Arc Collision"},"content":{"rendered":"<p>I&#8217;ve been working on an Android game for the past few months and at one point I needed to detect if a point (P) fell within the confines of an arc.  I was surprised to find that Android&#8217;s API&#8217;s didn&#8217;t have anything to support this.  After some Googling I still couldn&#8217;t find anything so I figured I&#8217;d post how I do it (partially in the hope that someone else might present a faster way ;)).<\/p>\n<p>First, lets look at our arc:<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/sloanseaman.com\/wordpress\/wp-content\/uploads\/2011\/11\/conebnw1.jpg\" style=\"width:180px;height:180px\"\/><\/p>\n<p>You can see that in my representation I actually have a cone (2d, not 3d) and I need to detect collision in the cone.  So, not only do I need to check if the P falls on the arc, but also if it is within the cone.  This means I have to things to check:<\/p>\n<ul>\n<li>Distance from start of cone (O) to end of arc<\/li>\n<li>If P is between the start and end of the arc (A and B)<\/li>\n<\/ul>\n<p\/>\n<h3>Range Check<\/h3>\n<p>Well, the distance part is rather easy, since I know position A and I know position O, I know the radius.  Now I just need to remember that an arc in my case is just a part of a uniform circle so the distance is really just the radius (r) of the circle. Basic math here:<\/p>\n<ul>\n<li>Known Diameter: r = D \/ 2<\/li>\n<li>Known Circumferance: r = C \/ (2 * PI)<\/li>\n<\/ul>\n<p>So now, if P is > 0 and P <= r, I know that P is in range.\n\n\n<p\/>\n<h3>Arc Collision<\/h3>\n<p>Next comes the check to see if P is between A and B.  For this we again need to remember that the arc is really just a slice of a circle.  So, the first thing we need to determine is the degree at which P is from O (lets call it dP).<\/p>\n<ul>\n<li>Take the position of O<\/li>\n<li>Take the position of P<\/li>\n<li>Use Math.atan(P.y-O.y, P.x-O.x)<small> (please note that I&#8217;m using a GFX library for this part, so this may not be 100% correct as I haven&#8217;t tested it)<\/small><\/li>\n<\/ul>\n<p>Now we know where P actually falls, degree wise, in relation to O.  All we have to test now is if P is between A and B.  But, that&#8217;s not as easy as you think. Sure, if A = 5 and B = 20 and dP = 10, we know it is in between.  What happens when A = 320 (remember that a circle goes to 360), B = 20, and dP = 10?  Well, the A < dP would fail because A > dP but for us, dP is still inside the arc.<br \/>\n<br \/>\nThis is what I came up with and, to be honest, where I&#8217;m hoping someone can tell me a better way (if there is one):<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nif (((B &lt; A) &amp;&amp;  ((A &lt;= dP &amp;&amp; dP &lt; 360) || (dP &lt;= B &amp;&amp; dP &gt;= 0)))\r\n    ||  ( A &lt;= dP &amp;&amp; dP &lt;= B))\r\n{\r\n    return true;\r\n}\r\nreturn false;                \r\n<\/pre>\n<p>Basically, if B < A that means that B has crossed over the 360\/0 point of the circle since A is greater that B.  If this has occurred then check if A <= dP while dP < 360 OR check if dP <= B while dP >= 0.   This covers any issues around the 360\/0 point on the circle.  If we don&#8217;t have the 360\/0 point issue its just a simple compare of A <= dP and dP < B.\n\n\n<p\/>\n<p>You now know if P is within your cone!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been working on an Android game for the past few months and at one point I needed to detect if a point (P) fell within the confines of an arc. I was surprised to find that Android&#8217;s API&#8217;s didn&#8217;t &hellip; <a href=\"http:\/\/sloanseaman.com\/wordpress\/2011\/11\/29\/arc-collision\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[10],"tags":[25,19],"_links":{"self":[{"href":"http:\/\/sloanseaman.com\/wordpress\/wp-json\/wp\/v2\/posts\/208"}],"collection":[{"href":"http:\/\/sloanseaman.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/sloanseaman.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/sloanseaman.com\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/sloanseaman.com\/wordpress\/wp-json\/wp\/v2\/comments?post=208"}],"version-history":[{"count":15,"href":"http:\/\/sloanseaman.com\/wordpress\/wp-json\/wp\/v2\/posts\/208\/revisions"}],"predecessor-version":[{"id":328,"href":"http:\/\/sloanseaman.com\/wordpress\/wp-json\/wp\/v2\/posts\/208\/revisions\/328"}],"wp:attachment":[{"href":"http:\/\/sloanseaman.com\/wordpress\/wp-json\/wp\/v2\/media?parent=208"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/sloanseaman.com\/wordpress\/wp-json\/wp\/v2\/categories?post=208"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/sloanseaman.com\/wordpress\/wp-json\/wp\/v2\/tags?post=208"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}