Flatland

Documentation

SourceForge.net Logo

quad-circle.cpp

Go to the documentation of this file.
00001 // Summary: Test for quad-circle intersection and generate contacts.
00002 // Copyright: 2007  Philip Rideout.  All rights reserved.
00003 // License: see bsd-license.txt
00004 
00005 #include <flatland/shapes.hpp>
00006 #include <flatland/intersection.hpp>
00007 
00008 bool Flatland::Intersection::TestCircleQuad(const Geometry &c, const Geometry &q)
00009 {
00010     return TestQuadCircle(q, c);
00011 }
00012 
00013 bool Flatland::Intersection::TestQuadCircle(const Geometry &g1, const Geometry &g2)
00014 {
00015     assert(g1.GetShape() == Shape::Quad);
00016     assert(g2.GetShape() == Shape::Circle);
00017     const Quad &q = static_cast<const Quad&>(g1);
00018     const Circle &c = static_cast<const Circle&>(g2);
00019 
00020     bool onborder = false;
00021     vec2 l, t;
00022 
00023     vec2 p = c.Center() - q.Center();
00024     l.x = q.Extent(0);
00025     t.x = dot(p, q.Axis(0));
00026     if (t.x < -l.x) { t.x = -l.x; onborder = true; }
00027     if (t.x >  l.x) { t.x =  l.x; onborder = true; }
00028 
00029     l.y = q.Extent(1);
00030     t.y = dot(p, q.Axis(1));
00031     if (t.y < -l.y) { t.y = -l.y; onborder = true; }
00032     if (t.y >  l.y) { t.y =  l.y; onborder = true; }
00033 
00034     if (!onborder)
00035         return true;
00036 
00037     vec2 qq, r;
00038     vec2 a(q.Axis(0).x, q.Axis(1).x);
00039     vec2 b(q.Axis(0).y, q.Axis(1).y);
00040     qq.x = dot(t, a);
00041     qq.y = dot(t, b);
00042     r = p - qq;
00043     float depth = c.Radius() - r.length();
00044     return depth >= 0;
00045 }
00046 
00047 void Flatland::Intersection::FindCircleQuad(const Geometry &c, const Geometry &q, ContactList &contacts)
00048 {
00049     contacts.ToggleNormalInversion();
00050     FindQuadCircle(q, c, contacts);
00051     contacts.ToggleNormalInversion();
00052 }
00053 
00054 void Flatland::Intersection::FindQuadCircle(const Geometry &g1, const Geometry &g2, ContactList &contacts)
00055 {
00056     assert(g1.GetShape() == Shape::Quad);
00057     assert(g2.GetShape() == Shape::Circle);
00058     const Quad &q = static_cast<const Quad&>(g1);
00059     const Circle &c = static_cast<const Circle&>(g2);
00060 
00061     bool onborder = false;
00062     vec2 l, t;
00063 
00064     vec2 p = c.Center() - q.Center();
00065     l.x = q.Extent(0);
00066     t.x = dot(p, q.Axis(0));
00067     if (t.x < -l.x) { t.x = -l.x; onborder = true; }
00068     if (t.x >  l.x) { t.x =  l.x; onborder = true; }
00069 
00070     l.y = q.Extent(1);
00071     t.y = dot(p, q.Axis(1));
00072     if (t.y < -l.y) { t.y = -l.y; onborder = true; }
00073     if (t.y >  l.y) { t.y =  l.y; onborder = true; }
00074 
00075     if (!onborder)
00076     {
00077         // circle center is inside quad. find closest face to `t'
00078         float min_distance = l.x - fabsf(t.x);
00079         vec2 normal = t.x < 0 ? -q.Axis(0) : q.Axis(0);
00080 
00081         float face_distance = l.y - fabsf(t.y);
00082         if (face_distance < min_distance)
00083         {
00084             min_distance = face_distance;
00085             normal = t.y < 0 ? q.Axis(1) : -q.Axis(1);
00086         }
00087 
00088         float depth = min_distance + c.Radius();
00089         contacts.AddContact(c.Center(), normal, depth);
00090     }
00091 
00092     vec2 qq, r;
00093     vec2 a(q.Axis(0).x, q.Axis(1).x);
00094     vec2 b(q.Axis(0).y, q.Axis(1).y);
00095     qq.x = dot(t, a);
00096     qq.y = dot(t, b);
00097     r = p - qq;
00098 
00099     float distance = r.length();
00100     float depth = c.Radius() - distance;
00101     if (depth < 0)
00102         return;
00103 
00104     if (distance)
00105         r.normalize();
00106     else
00107         r = vec2(1, 0);
00108 
00109     contacts.AddContact(qq + q.Center(), -r, depth);
00110 }

Generated on Sat Jan 13 17:20:21 2007 for Flatland by doxygen 1.5.1