SFML community forums
Help => Graphics => Topic started by: Mangocheese on March 22, 2010, 02:07:27 pm
-
Hello,
Is there any way to test if a point is within a polygon shape?
Also,
When a sprite is rotated, does it rotate the bounding box aswell?
Thanks!
-
As far as I know :
- No
- No, the bounding box is an horizontal rectangle with the sprite in it
For your first point, this method check if a point is inside a polygon. Coords is a vector containing the points of the polygon. A point is a simple two values structure. This is done with a vector test : saying that if each edge of the polygon has the point to the right, the point is inside the polygon :
////////////////////////////////////////////////////////////
/// Check if a point is inside the polygon's area
////////////////////////////////////////////////////////////
template <typename T>
bool sfPoly<T>::Contains(T X, T Y) const
{
for (unsigned int i=0;i<Coords.size()-2;i+=2)
{
if (((Y-Coords[i+1])*(Coords[i+2]-Coords[i]) - (X-Coords[i])*(Coords[i+3]-Coords[i+1]))<0)
{
return (false);
}
}
//The last test is special
unsigned int j = Coords.size();
if (((Y-Coords[j-1])*(Coords[0]-Coords[j-2]) - (X-Coords[j-2])*(Coords[1]-Coords[j-1]))<0)
{
return (false);
}
return (true);
}
-
Thanks, that piece of code helped out a lot!
-
However I think it's a must add in case polygon class becomes independent of it's drawable representation on SFML2 :wink:
-
I've done a bit of research and created some code (with help from http://local.wasp.uwa.edu.au/~pbourke/geometry/insidepoly/).
Below is my code, sloppy as it is, it does the trick. I hope it is helpful to those who need it. For this code, I found that I had to add the point twice into the vector. Can anyone refine the process, or am I on the right track?
#include <SFML/Graphics.hpp>
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
const double pi = 3.14;
const double twopi = 6.28;
struct Point
{
int x, y;
};
bool InsidePolygon(vector<Point> Poly, int sides, Point mouseCoods);
double Angle2D(double x1, double y1, double x2, double y2);
int main()
{
sf::RenderWindow App(sf::VideoMode(800,600,32), "Inside Polygon Test");
App.SetFramerateLimit(60);
sf::Event appEvent;
vector<Point> vPolygon;
sf::Shape Polygon;
while(App.IsOpened())
{
while(App.GetEvent(appEvent))
{
if(appEvent.Type == sf::Event::Closed)
{
App.Close();
}
if(appEvent.Type == sf::Event::MouseButtonPressed)
{
if(appEvent.MouseButton.Button == sf::Mouse::Left)
{
Point temp;
temp.x = appEvent.MouseButton.X;
temp.y = appEvent.MouseButton.Y;
if(InsidePolygon(vPolygon, vPolygon.size(), temp))
{
cout << "Inside." << endl;
}
}
if(appEvent.MouseButton.Button == sf::Mouse::Right)
{
Point temp;
temp.x = appEvent.MouseButton.X;
temp.y = appEvent.MouseButton.Y;
Polygon.AddPoint(temp.x, temp.y);
vPolygon.push_back(temp);
vPolygon.push_back(temp);
}
}
}
App.Clear();
App.Draw(Polygon);
App.Display();
}
return 0;
}
bool InsidePolygon(vector<Point> Poly, int sides, Point mouseCoods)
{
int i;
double angle=0;
Point p1,p2;
for (i=0;i<sides;i++) {
p1.x = Poly[i].x - mouseCoods.x;
p1.y = Poly[i].y - mouseCoods.y;
p2.x = Poly[(i+1)%sides].x - mouseCoods.x;
p2.y = Poly[(i+1)%sides].y - mouseCoods.y;
angle += Angle2D(p1.x,p1.y,p2.x,p2.y);
}
if (abs(angle) < pi)
return(FALSE);
else
return(TRUE);
}
double Angle2D(double x1, double y1, double x2, double y2)
{
double dtheta,theta1,theta2;
theta1 = atan2(y1,x1);
theta2 = atan2(y2,x2);
dtheta = theta2 - theta1;
while (dtheta > pi)
dtheta -= twopi;
while (dtheta < -pi)
dtheta += twopi;
return(dtheta);
}
Thanks. :D
-
Thanks from me as well.