Box2D implemented its own convex hull algorithm, Graham just messes things up

--HG--
branch : box2d-update
This commit is contained in:
Bill Meltsner
2011-09-24 03:10:19 -04:00
parent 0d4569d28b
commit 08f894a98e
4 changed files with 6 additions and 300 deletions
+2 -16
View File
@@ -115,7 +115,6 @@
A946D7F910424E57002BF36C /* wrap_World.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A93E6B6A10420ACA007D418B /* wrap_World.cpp */; };
A946D7FA10424E57002BF36C /* wrap_RevoluteJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A93E6B6610420ACA007D418B /* wrap_RevoluteJoint.cpp */; };
A946D7FB10424E57002BF36C /* wrap_PrismaticJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A93E6B6210420ACA007D418B /* wrap_PrismaticJoint.cpp */; };
A946D7FC10424E57002BF36C /* GrahamScanConvexHull.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A93E6AF610420AC7007D418B /* GrahamScanConvexHull.cpp */; };
A946D7FE10424E57002BF36C /* wrap_MouseJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A93E6B5C10420ACA007D418B /* wrap_MouseJoint.cpp */; };
A946D7FF10424E57002BF36C /* wrap_Physics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A93E6B5E10420ACA007D418B /* wrap_Physics.cpp */; };
A946D80210424E57002BF36C /* PrismaticJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A93E6B0210420AC8007D418B /* PrismaticJoint.cpp */; };
@@ -442,8 +441,6 @@
A93E6AF210420AC7007D418B /* DistanceJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DistanceJoint.h; sourceTree = "<group>"; };
A93E6AF310420AC7007D418B /* GearJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GearJoint.cpp; sourceTree = "<group>"; };
A93E6AF410420AC7007D418B /* GearJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GearJoint.h; sourceTree = "<group>"; };
A93E6AF610420AC7007D418B /* GrahamScanConvexHull.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GrahamScanConvexHull.cpp; sourceTree = "<group>"; };
A93E6AF710420AC8007D418B /* GrahamScanConvexHull.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GrahamScanConvexHull.h; sourceTree = "<group>"; };
A93E6AFA10420AC8007D418B /* Joint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Joint.cpp; sourceTree = "<group>"; };
A93E6AFB10420AC8007D418B /* Joint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Joint.h; sourceTree = "<group>"; };
A93E6AFC10420AC8007D418B /* MouseJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MouseJoint.cpp; sourceTree = "<group>"; };
@@ -572,9 +569,9 @@
A96F417814127EFD0067FE9A /* b2EdgeAndCircleContact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2EdgeAndCircleContact.cpp; sourceTree = "<group>"; };
A96F417914127EFD0067FE9A /* b2EdgeAndCircleContact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2EdgeAndCircleContact.h; sourceTree = "<group>"; };
A96F417A14127EFD0067FE9A /* b2EdgeAndPolygonContact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2EdgeAndPolygonContact.cpp; sourceTree = "<group>"; };
A96F417B14127EFD0067FE9A /* b2EdgeAndPolygonContact.h */ = {isa = PBXFileReference; fileEncoding = 4; path = b2EdgeAndPolygonContact.h; sourceTree = "<group>"; };
A96F417B14127EFD0067FE9A /* b2EdgeAndPolygonContact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2EdgeAndPolygonContact.h; sourceTree = "<group>"; };
A96F417E14127FC20067FE9A /* b2EdgeShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2EdgeShape.cpp; sourceTree = "<group>"; };
A96F417F14127FC20067FE9A /* b2EdgeShape.h */ = {isa = PBXFileReference; fileEncoding = 4; path = b2EdgeShape.h; sourceTree = "<group>"; };
A96F417F14127FC20067FE9A /* b2EdgeShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2EdgeShape.h; sourceTree = "<group>"; };
A96F41811412AFB70067FE9A /* wrap_WeldJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_WeldJoint.cpp; sourceTree = "<group>"; };
A96F41821412AFC60067FE9A /* wrap_WeldJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_WeldJoint.h; sourceTree = "<group>"; };
A96F41841412AFEB0067FE9A /* WeldJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WeldJoint.cpp; sourceTree = "<group>"; };
@@ -1231,7 +1228,6 @@
A9B6432B13BF837800DC3C7E /* FrictionJoint.h */,
A93E6AF310420AC7007D418B /* GearJoint.cpp */,
A93E6AF410420AC7007D418B /* GearJoint.h */,
A93E6AF510420AC7007D418B /* graham */,
A93E6AFA10420AC8007D418B /* Joint.cpp */,
A93E6AFB10420AC8007D418B /* Joint.h */,
A93E6AFC10420AC8007D418B /* MouseJoint.cpp */,
@@ -1302,15 +1298,6 @@
path = box2d;
sourceTree = "<group>";
};
A93E6AF510420AC7007D418B /* graham */ = {
isa = PBXGroup;
children = (
A93E6AF610420AC7007D418B /* GrahamScanConvexHull.cpp */,
A93E6AF710420AC8007D418B /* GrahamScanConvexHull.h */,
);
path = graham;
sourceTree = "<group>";
};
A93E6B7410420ACB007D418B /* sound */ = {
isa = PBXGroup;
children = (
@@ -1730,7 +1717,6 @@
A946D7F910424E57002BF36C /* wrap_World.cpp in Sources */,
A946D7FA10424E57002BF36C /* wrap_RevoluteJoint.cpp in Sources */,
A946D7FB10424E57002BF36C /* wrap_PrismaticJoint.cpp in Sources */,
A946D7FC10424E57002BF36C /* GrahamScanConvexHull.cpp in Sources */,
A946D7FE10424E57002BF36C /* wrap_MouseJoint.cpp in Sources */,
A946D7FF10424E57002BF36C /* wrap_Physics.cpp in Sources */,
A946D80210424E57002BF36C /* PrismaticJoint.cpp in Sources */,
+4 -24
View File
@@ -20,9 +20,6 @@
#include "Physics.h"
// Convex Hull Scan
#include "graham/GrahamScanConvexHull.h"
// LOVE
#include <common/math.h>
#include "wrap_Body.h"
@@ -102,35 +99,18 @@ namespace box2d
love::luax_assert_argc(L, 2 * 3);
b2PolygonShape* s = new b2PolygonShape();
std::vector<point2d> points(s->m_vertexCount);
std::vector<point2d> convex_hull;
b2Vec2 * vecs = new b2Vec2[vcount];
for(int i = 0;i<vcount;i++)
{
float x = (float)lua_tonumber(L, -2);
float y = (float)lua_tonumber(L, -1);
point2d tmp(x, y);
points.push_back(tmp);
vecs[i] = (Physics::scaleDown(b2Vec2(x, y)));
lua_pop(L, 2);
}
// Compute convex hull.
GrahamScanConvexHull()(points, convex_hull);
int count = convex_hull.size();
if(count < 3)
return luaL_error(L, "Polygon degenerated to less than three points.");
b2Vec2 * vecs = new b2Vec2[count];
for (int i = 0; i < count; i++) {
vecs[i].Set(convex_hull[i].x, convex_hull[i].y);
vecs[i] = Physics::scaleDown(vecs[i]);
}
s->Set(vecs, count);
s->Set(vecs, vcount);
PolygonShape * p = new PolygonShape(s);
delete[] vecs;
@@ -1,123 +0,0 @@
#include "GrahamScanConvexHull.h"
#include <cmath>
#include <iterator>
bool GrahamScanConvexHull::operator()(const std::vector < point2d >& pnt, std::vector< point2d >& final_hull)
{
final_hull.clear();
if (pnt.size() <= 3)
{
std::copy(pnt.begin(), pnt.end(), std::back_inserter(final_hull));
return true;
}
unsigned int j = 0;
gs_point2d tmp_pnt;
for(unsigned int i = 0; i < pnt.size(); i++)
{
point.push_back(gs_point2d(pnt[i].x,pnt[i].y,0.0));
if (point[i].y < point[j].y)
j = i;
else if (point[i].y == point[j].y)
if (point[i].x < point[j].x)
j = i;
}
tmp_pnt = point[0];
point[0] = point[j];
point[j] = tmp_pnt;
anchor = point[0];
for (unsigned int i = 1; i < point.size(); i++)
{
point[i].angle = cartesian_angle(point[i].x - anchor.x, point[i].y - anchor.y);
}
sort(++point.begin(),point.end(),GSPoint2DCompare(&anchor));
graham_scan(final_hull);
return true;
}
void GrahamScanConvexHull::graham_scan(std::vector< point2d >& final_hull)
{
const std::size_t HEAD = 0;
const std::size_t PRE_HEAD = 1;
std::deque<gs_point2d> pnt_queue;
pnt_queue.push_front(point[0]);
pnt_queue.push_front(point[1]);
unsigned int i = 2;
while(i < point.size())
{
if (pnt_queue.size() > 1)
{
if (orientation(pnt_queue[PRE_HEAD],pnt_queue[HEAD],point[i]) == counter_clock_wise)
pnt_queue.push_front(point[i++]);
else
pnt_queue.pop_front();
}
else
pnt_queue.push_front(point[i++]);
}
for(std::deque<gs_point2d>::iterator it = pnt_queue.begin(); it != pnt_queue.end(); it++)
{
final_hull.push_back(point2d((*it).x, (*it).y));
}
}
inline double GrahamScanConvexHull::cartesian_angle(double x, double y)
{
if ((x > 0.0) && (y > 0.0)) return (atan( y / x) * _180DivPI);
else if ((x < 0.0) && (y > 0.0)) return (atan(-x / y) * _180DivPI) + 90.0;
else if ((x < 0.0) && (y < 0.0)) return (atan( y / x) * _180DivPI) + 180.0;
else if ((x > 0.0) && (y < 0.0)) return (atan(-x / y) * _180DivPI) + 270.0;
else if ((x == 0.0) && (y > 0.0)) return 90.0;
else if ((x < 0.0) && (y == 0.0)) return 180.0;
else if ((x == 0.0) && (y < 0.0)) return 270.0;
else
return 0.0;
}
inline int GrahamScanConvexHull::orientation(const gs_point2d& p1, const gs_point2d& p2, const gs_point2d& p3)
{
return orientation(p1.x,p1.y,p2.x,p2.y,p3.x,p3.y);
}
inline int GrahamScanConvexHull::orientation(const double x1, const double y1,
const double x2, const double y2,
const double px, const double py)
{
double orin = (x2 - x1) * (py - y1) - (px - x1) * (y2 - y1);
if (is_equal(orin,0.0))
return 0; /* Orientaion is neutral aka collinear */
else if (orin < 0.0)
return -1; /* Orientaion is to the right-hand side */
else
return +1; /* Orientaion is to the left-hand side */
}
inline bool GrahamScanConvexHull::is_equal(const double v1, const double& v2, const double epsilon)
{
double diff = v1 - v2;
return (-epsilon <= diff) && (diff <= epsilon);
}
@@ -1,137 +0,0 @@
/*
**************************************************************************
* Class: Graham Scan Convex Hull *
* By Arash Partow - 2001 *
* URL: http://www.partow.net *
* *
* Copyright Notice: *
* Free use of this library is permitted under the guidelines and *
* in accordance with the most current version of the Common Public *
* License. *
* http://www.opensource.org/licenses/cpl.php *
* *
**************************************************************************
*/
#ifndef INCLUDE_GRAHAMSCANCONVEXHULL_H
#define INCLUDE_GRAHAMSCANCONVEXHULL_H
#include <iostream>
#include <deque>
#include <vector>
#include <algorithm>
#include <math.h>
#include <vector>
struct point2d
{
point2d(double _x = 0.0 , double _y = 0.0) : x(_x), y(_y){}
double x;
double y;
};
class ConvexHull
{
public:
virtual ~ConvexHull(){};
virtual bool operator()(const std::vector<point2d>& pnt, std::vector<point2d>& final_hull) = 0;
};
struct gs_point2d
{
public:
gs_point2d(double _x = 0.0, double _y = 0.0, double _angle = 0.0) : x(_x), y(_y), angle(_angle){}
double x;
double y;
double angle;
};
const double _180DivPI = 57.295779513082320876798154814105000;
const int counter_clock_wise = +1;
const int clock_wise = -1;
class GSPoint2DCompare
{
public:
GSPoint2DCompare(gs_point2d* _anchor):anchor(_anchor){};
bool operator()(const gs_point2d& p1, const gs_point2d& p2)
{
if (p1.angle < p2.angle) return true;
else if (p1.angle > p2.angle) return false;
else if (is_equal(p1,p2)) return false;
else if (lay_distance(anchor->x, anchor->y, p1.x, p1.y) < lay_distance(anchor->x, anchor->y, p2.x, p2.y))
return true;
else
return false;
}
private:
inline bool is_equal(const gs_point2d p1, gs_point2d p2)
{
return is_equal(p1.x,p2.x) && is_equal(p1.y,p2.y);
}
inline bool is_equal(const double v1, const double& v2, const double epsilon = 1.0e-12)
{
double diff = v1 - v2;
return (-epsilon <= diff) && (diff <= epsilon);
}
inline double lay_distance(const double& x1, const double& y1, const double& x2, const double& y2)
{
double dx = (x1 - x2);
double dy = (y1 - y2);
return (dx * dx + dy * dy);
}
gs_point2d* anchor;
};
class GrahamScanConvexHull : public ConvexHull
{
public:
GrahamScanConvexHull(){};
~GrahamScanConvexHull(){};
virtual bool operator()(const std::vector < point2d >& pnt, std::vector< point2d >& final_hull);
private:
void graham_scan(std::vector< point2d >& final_hull);
inline double cartesian_angle(double x, double y);
inline int orientation(const gs_point2d& p1,
const gs_point2d& p2,
const gs_point2d& p3);
inline int orientation(const double x1, const double y1,
const double x2, const double y2,
const double px, const double py);
inline bool is_equal(const double v1, const double& v2, const double epsilon = 1.0e-12);
std::vector<gs_point2d> point;
gs_point2d anchor;
};
#endif