<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Doswa &#187; Computational Geometry</title>
	<atom:link href="http://doswa.com/blog/category/computational-geometry/feed/" rel="self" type="application/rss+xml" />
	<link>http://doswa.com/blog</link>
	<description>Programming, physics, mathematics</description>
	<lastBuildDate>Sat, 28 Aug 2010 16:20:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Line Segment to Circle Collision/Intersection Detection</title>
		<link>http://doswa.com/blog/2009/07/13/circle-segment-intersectioncollision/</link>
		<comments>http://doswa.com/blog/2009/07/13/circle-segment-intersectioncollision/#comments</comments>
		<pubDate>Mon, 13 Jul 2009 18:15:08 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[Computational Geometry]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Physics]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://doswa.com/?p=158</guid>
		<description><![CDATA[Style and Notation All variables are represented in italics except in the diagrams and Python code. Vectors are shown in bold except in the diagrams and Python code. The notation &#124;a&#124; is used to represent the length of a vector &#8230; <a href="http://doswa.com/blog/2009/07/13/circle-segment-intersectioncollision/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h2>Style and Notation</h2>
<ul>
<li>All variables are represented in italics except in the diagrams and Python code.</li>
<li>Vectors are shown in bold except in the diagrams and Python code.</li>
<li>The notation |<em>a</em>| is used to represent the length of a vector named <strong><em>a</em></strong>.</li>
</ul>
<h2>Introduction to the problem</h2>
<p>Start by defining a few points (vectors from the world origin):<br />
<a href="http://doswa.com/blog/wp-content/uploads/2009/07/2.png"><img class="alignnone size-full wp-image-162" title="2" src="http://doswa.com/blog/wp-content/uploads/2009/07/2.png" alt="2" width="275" height="192" /></a></p>
<p>Now, from these points, you can easily calculate two useful values, the segment vector, <strong><em>seg_v</em></strong> (from <strong><em>seg_a</em></strong> to <strong><em>seg_b</em></strong>) and the position of <strong><em>circ_pos</em></strong> relative to <strong><em>seg_a</em></strong>, <strong><em>pt_v</em></strong>.</p>
<p><a href="http://doswa.com/blog/wp-content/uploads/2009/07/3.png"></a><a href="http://doswa.com/blog/wp-content/uploads/2009/07/31.png"><img class="alignnone size-full wp-image-166" title="31" src="http://doswa.com/blog/wp-content/uploads/2009/07/31.png" alt="31" width="275" height="192" /></a></p>
<p><strong><em>seg_v</em></strong> = <strong><em>seg_b</em></strong> &#8211; <strong><em>seg_a</em></strong></p>
<p><strong><em>pt_v</em></strong> = <strong><em>circ_pos</em></strong> &#8211; <strong><em>seg_a</em></strong></p>
<h2>Closest point to the circle&#8217;s center on the segment<em><br />
</em></h2>
<p>The next step is to find the closest point to the circle&#8217;s center on the segment (labeled &#8220;<strong><em>closest</em></strong>&#8221; on the diagram). To do this, we must project <strong><em>pt_v</em></strong> onto <strong><em>seg_v</em></strong>:</p>
<p><a href="http://doswa.com/blog/wp-content/uploads/2009/07/4.png"><img class="alignnone size-full wp-image-167" title="4" src="http://doswa.com/blog/wp-content/uploads/2009/07/4.png" alt="4" width="275" height="192" /></a></p>
<p>To project on vector onto another, take the dot product of the vector and the unit vector of the projection target. That is:</p>
<p><center><img src="http://doswa.com/blog/wp-content/cache/tex_d317daa71d17b12f8188376628d58ba8.png" align="absmiddle" class="tex" alt="|proj\_v| = \textbf{pt\_v} \cdot \frac{\textbf{seg\_v}}{|seg\_v|}" /></center></p>
<p>Note that this dot product returns a scalar value (the length of <strong><em>proj_v</em></strong>), not a vector.</p>
<p>&#8211;</p>
<p>We now need to take a small break from the main goal and look into a special case: the ends of the segment. If |<em>proj_v</em>| is less than <em>0</em> or greater than |<em>seg_v</em>|, the closest point to <strong><em>circ_pos</em></strong> on the segment will be one of the segment&#8217;s endpoints. That is:<br />
<code>if |<em>proj_v</em>| &lt; 0: <strong><em>closest</em></strong> = <strong><em>seg_a</em></strong><br />
if |<em>proj_v</em>| &gt; |<em>seg_v</em>|: <em><strong>c</strong><strong>losest</strong></em> = <strong><em>seg_b</em></strong></code></p>
<p>&#8211;</p>
<p>Next, calculate the actual <strong><em>proj_v</em></strong> vector, rather than just its length (|<em>proj_v</em>|). To do this, simply multiply by the <strong><em>seg_v</em></strong> unit vector:</p>
<p><center><img src="http://doswa.com/blog/wp-content/cache/tex_2bc551d3368e2e85233c77ffd0ab9665.png" align="absmiddle" class="tex" alt="\textbf{proj\_v} = |proj\_v| \frac{\textbf{seg\_v}}{|seg\_v|}" /></center></p>
<p>The only thing left to do is to convert this into world coordinates (rather than coordinates relative to <strong><em>seg_a</em></strong>) to get the closest point:</p>
<p><strong><em>closest</em></strong> = <strong><em>seg_a</em></strong> + <strong><em>proj_v</em></strong></p>
<h2>Checking for a intersection</h2>
<p>Now that we&#8217;ve calculated the closest point on the segment (the variable &#8220;<strong><em>closest</em></strong>&#8220;), we can check if the circle and segment intersect. To do this, first find the vector from <strong><em>closest</em></strong> to <strong><em>circ_pos</em></strong>:</p>
<p><strong><em>dist_v</em></strong> = <strong><em>circ_pos</em></strong> &#8211; <strong><em>closest</em></strong></p>
<p>If the length of this vector is less than the circle&#8217;s radius, the circle and segment are intersecting:<br />
<code>if |<em>dist_v</em>| &lt; <em>circ_rad: </em>They are intersecting<br />
else: They are not intersecting</code></p>
<h2>Collision response</h2>
<p>A useful bit of data in collision response is the amount of overlap between two shapes and the direction a shape must be moved in order to resolve the collision. This can be represented as a vector that points in the same direction as <strong><em>dist_v</em></strong> whose length is equal to the difference between <em>circ_rad</em> and |<em>dist_v</em>|.</p>
<p><center><img src="http://doswa.com/blog/wp-content/cache/tex_8339fdad8e95d59472dda12890ebb6ab.png" align="absmiddle" class="tex" alt="\textbf{offset} = (circ\_rad - |dist\_v|) \frac{\textbf{dist\_v}}{|dist\_v|}" /></center></p>
<h2>Python implementation</h2>
<p>Here is a Python implementation of everything in this post. For the sake of clarity, I avoided optimizations. <tt>vec</tt> is assumed to be a fully implemented 2d vector class.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> closest_point_on_seg<span style="color: black;">&#40;</span>seg_a, seg_b, circ_pos<span style="color: black;">&#41;</span>:
	seg_v = seg_b - seg_a
	pt_v = circ_pos - seg_a
	<span style="color: #ff7700;font-weight:bold;">if</span> seg_v.<span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span>= <span style="color: #ff4500;">0</span>:
		<span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">ValueError</span>, <span style="color: #483d8b;">&quot;Invalid segment length&quot;</span>
	seg_v_unit = seg_v / seg_v.<span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
	proj = pt_v.<span style="color: black;">dot</span><span style="color: black;">&#40;</span>seg_v_unit<span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">if</span> proj <span style="color: #66cc66;">&lt;</span>= <span style="color: #ff4500;">0</span>:
		<span style="color: #ff7700;font-weight:bold;">return</span> seg_a.<span style="color: #dc143c;">copy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">if</span> proj <span style="color: #66cc66;">&gt;</span>= seg_v.<span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
		<span style="color: #ff7700;font-weight:bold;">return</span> seg_b.<span style="color: #dc143c;">copy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
	proj_v = seg_v_unit <span style="color: #66cc66;">*</span> proj
	closest = proj_v + seg_a
	<span style="color: #ff7700;font-weight:bold;">return</span> closest
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> segment_circle<span style="color: black;">&#40;</span>seg_a, seg_b, circ_pos, circ_rad<span style="color: black;">&#41;</span>:
	closest = closest_point_on_seg<span style="color: black;">&#40;</span>seg_a, seg_b, circ_pos<span style="color: black;">&#41;</span>
	dist_v = circ_pos - closest
	<span style="color: #ff7700;font-weight:bold;">if</span> dist_v.<span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span> circ_rad:
		<span style="color: #ff7700;font-weight:bold;">return</span> vec<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">if</span> dist_v.<span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span>= <span style="color: #ff4500;">0</span>:
		<span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">ValueError</span>, <span style="color: #483d8b;">&quot;Circle's center is exactly on segment&quot;</span>
	offset = dist_v / dist_v.<span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: black;">&#40;</span>circ_rad - dist_v.<span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">return</span> offset</pre></div></div>

<h2>Similar algorithms</h2>
<p>Collisions involving <a href="http://mathworld.wolfram.com/Stadium.html">stadiums</a> (a type of rounded rectangle) can be calculated in a similar manner. A stadium is essentially a line segment with a radius.</p>
<p>A stadium-point collision is the same as a segment-circle collision with a circle whose radius is equal to the stadium&#8217;s radius.</p>
<p>A stadium-circle collision is the same as a segment-circle collision with a circle whose radius is equal to the sum of the original circle&#8217;s radius and the stadium&#8217;s radius.</p>
<h2>Download</h2>
<p><a href="http://doswa.com/projects/segment_circle/segment_circle.zip">segment_circle.zip</a> &#8211; An implementation in Python and <a href="http://cython.org">Cython</a>.</p>
<h2>Conclusion</h2>
<p>If you find this post useful or have any questions, please leave a comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://doswa.com/blog/2009/07/13/circle-segment-intersectioncollision/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
