Compare commits

..

2 Commits

4 changed files with 158 additions and 68 deletions

View File

@ -98,100 +98,8 @@ void Display::show()
} }
} }
void Display::update () void Display::setCurrentLine()
{ {
unsigned int curStep = (m_step > 5) ? ((m_step - 2) % 4 + 2) : (m_step % 6); // skip init and first step after first run
if (m_stepSize == 0 && curStep > 0)
{
std::cout << "any key to continue with next step...";
std::cin.get();
}
std::string text = "(" + std::to_string(m_step) + ") step " + std::to_string(curStep) + ": ";
if (curStep == 1)
{
// first step: select min - max x coordinates
m_textStatus.setString(text + "select min - max x coordinates...");
// if use AklToussaint heuristic
if (m_useAkl)
{
sf::Vector2f topLeft(WIDTH, HEIGHT);
sf::Vector2f topRight(0, HEIGHT);
sf::Vector2f botLeft(WIDTH, 0);
sf::Vector2f botRight(0, 0);
for (auto& pt : m_points)
{
sf::Vector2f pos = pt.getPosition();
float x = pos.x;
float y = pos.y;
// TODO: only check explicit x and y seperate!
if (x < topLeft.x && y < topLeft.y) topLeft = pos;
if (x > topRight.x && y < topLeft.y) topRight = pos;
if (x < botLeft.x && y > botLeft.y) botLeft = pos;
if (x > botRight.x && y > botRight.y) botRight = pos;
}
m_hull.setPrimitiveType(sf::LineStrip);
m_hull.append(sf::Vertex(topLeft, sf::Color::Blue));
m_hull.append(sf::Vertex(topRight, sf::Color::Blue));
m_hull.append(sf::Vertex(botRight, sf::Color::Blue));
m_hull.append(sf::Vertex(botLeft, sf::Color::Blue));
m_hull.append(sf::Vertex(topLeft, sf::Color::Blue));
}
else
{
sf::Vector2f left(WIDTH, HEIGHT);
sf::Vector2f right(0, 0);
int i_left = WIDTH;
int i_right = 0;
size_t points = m_points.size();
for (size_t i = 0; i < points; ++i)
{
sf::Vector2f pos = m_points[i].getPosition();
float x = pos.x;
if (x < left.x)
{
i_left = i;
left = pos;
}
if (x > right.x)
{
i_right = i;
right = pos;
}
}
// adding starting points from most x to left
if (i_left < i_right)
{
std::swap(i_left, i_right);
}
for (int i = 0; i < 2; ++i)
{
int pos = (i == 0) ? i_left : i_right;
m_points[pos].setFillColor(sf::Color::Blue);
m_hullPoints.push_back(m_points[pos]);
m_points.erase(m_points.begin() + pos);
}
m_lines.push_back(Line(Point(left.x, left.y), Point(right.x, right.y)));
m_lines.push_back(Line(Point(right.x, right.y), Point(left.x, left.y))); // add first line in both directions to work with "right side"
m_curLineIdx = 1;
m_curLine = m_lines[1];
// TODO: split points and use map
}
}
else if (curStep == 2)
{
// second step: split board
m_textStatus.setString(text + "split board...");
// get current line with points
while (m_curLineIdx == -1) while (m_curLineIdx == -1)
{ {
size_t lines = m_lines.size(); size_t lines = m_lines.size();
@ -199,7 +107,14 @@ void Display::update ()
{ {
std::cout << "## no more open lines -> fin!" << std::endl; std::cout << "## no more open lines -> fin!" << std::endl;
m_points.clear(); m_points.clear();
if (m_points.size() == 0) m_textStatus.setString(text + "finished calculating convex hull in " + std::to_string((m_step / 4 + 1)) + " cycles");
if (m_points.size() == 0)
{
unsigned int curStep = (m_step > 5) ? ((m_step - 2) % 4 + 2) : (m_step % 6); // skip init and first step after first run
std::string text = "(" + std::to_string(m_step) + ") step " + std::to_string(curStep) + ": ";
m_textStatus.setString(text + "finished calculating convex hull in " + std::to_string((m_step / 4 + 1)) + " cycles");
}
return; return;
} }
@ -236,6 +151,163 @@ void Display::update ()
m_lines[m_curLineIdx].to().x(), m_lines[m_curLineIdx].to().y()) > 0 ? sf::Color::Red : sf::Color::Green); m_lines[m_curLineIdx].to().x(), m_lines[m_curLineIdx].to().y()) > 0 ? sf::Color::Red : sf::Color::Green);
} }
} }
void Display::update ()
{
unsigned int curStep = (m_step > 5) ? ((m_step - 2) % 4 + 2) : (m_step % 6); // skip init and first step after first run
if (m_stepSize == 0 && curStep > 0)
{
std::cout << "any key to continue with next step...";
std::cin.get();
}
std::string text = "(" + std::to_string(m_step) + ") step " + std::to_string(curStep) + ": ";
if (curStep == 1)
{
// first step: select min - max x coordinates
m_textStatus.setString(text + "select min - max x coordinates...");
// if use AklToussaint heuristic
if (m_useAkl)
{
sf::Vector2f left(WIDTH, HEIGHT);
sf::Vector2f right(0, HEIGHT);
sf::Vector2f bot(0, 0);
sf::Vector2f top(0, HEIGHT);
// index to find points
int i_left = WIDTH;
int i_right = 0;
int i_top = HEIGHT;
int i_bot = 0;
size_t points = m_points.size();
for (size_t i = 0; i < points; ++i)
{
sf::Vector2f pos = m_points[i].getPosition();
float x = pos.x;
float y = pos.y;
if (x < left.x)
{
left = pos;
i_left = i;
}
if (x > right.x)
{
right = pos;
i_right = i;
}
if (y < top.y)
{
top = pos;
i_top = i;
}
if (y > bot.y)
{
bot = pos;
i_bot = i;
}
}
// adding edge points to hull
m_points[i_left].setFillColor(sf::Color::Blue);
m_hullPoints.push_back(m_points[i_left]);
m_points[i_top].setFillColor(sf::Color::Blue);
m_hullPoints.push_back(m_points[i_top]);
m_points[i_right].setFillColor(sf::Color::Blue);
m_hullPoints.push_back(m_points[i_right]);
m_points[i_bot].setFillColor(sf::Color::Blue);
m_hullPoints.push_back(m_points[i_bot]);
// building lines between edge points
Point pt1(left.x, left.y);
Point pt2(top.x, top.y);
Point pt3(right.x, right.y);
Point pt4(bot.x, bot.y);
m_lines.push_back(Line(pt1, pt2));
m_lines.push_back(Line(pt2, pt3));
m_lines.push_back(Line(pt3, pt4));
m_lines.push_back(Line(pt4, pt1));
// remove points in calculated rectangle
for (int i = points - 1; i >= 0; i--)
{
Point pt(m_points[i].getPosition().x, m_points[i].getPosition().y);
if (IsPointInRectangle(pt, pt1, pt2, pt3, pt4))
{
std::cout << "remove pt inside triangle -> " << i << " with pos: " << pt.x() << ", " << pt.y() << std::endl;
m_points.erase(m_points.begin() + i);
}
// TODO: ugly workaround - remove hull points
else if ((pt.x() == pt1.x() && pt.y() == pt1.y()) ||
(pt.x() == pt2.x() && pt.y() == pt2.y()) ||
(pt.x() == pt3.x() && pt.y() == pt3.y()) ||
(pt.x() == pt4.x() && pt.y() == pt4.y()))
{
m_points.erase(m_points.begin() + i);
}
}
setCurrentLine();
}
else
{
sf::Vector2f left(WIDTH, HEIGHT);
sf::Vector2f right(0, 0);
int i_left = WIDTH;
int i_right = 0;
size_t points = m_points.size();
for (size_t i = 0; i < points; ++i)
{
sf::Vector2f pos = m_points[i].getPosition();
float x = pos.x;
if (x < left.x)
{
i_left = i;
left = pos;
}
if (x > right.x)
{
i_right = i;
right = pos;
}
}
// TODO: split points and use map
// adding starting points from most x to left
if (i_left < i_right)
{
std::swap(i_left, i_right);
}
for (int i = 0; i < 2; ++i)
{
int idx = (i == 0) ? i_left : i_right;
m_points[idx].setFillColor(sf::Color::Blue);
m_hullPoints.push_back(m_points[idx]);
m_points.erase(m_points.begin() + idx);
}
m_lines.push_back(Line(Point(left.x, left.y), Point(right.x, right.y)));
m_lines.push_back(Line(Point(right.x, right.y), Point(left.x, left.y))); // add first line in both directions to work with "right side"
// set current line just by taking the only one (in one direction)
m_curLineIdx = 1;
m_curLine = m_lines[1];
}
}
else if (curStep == 2)
{
// second step: split board
m_textStatus.setString(text + "split board...");
// get current line with points
setCurrentLine();
}
else if (curStep == 3) else if (curStep == 3)
{ {
// get line with more than one point -> or use m_curLine // get line with more than one point -> or use m_curLine

View File

@ -33,7 +33,7 @@ private:
//std::vector<sf::Vertex> m_hull; //std::vector<sf::Vertex> m_hull;
std::vector<sf::CircleShape> m_hullPoints; std::vector<sf::CircleShape> m_hullPoints;
sf::VertexArray m_hull; //sf::VertexArray m_hull;
//sf::ConvexShape m_convex; // shape for convex hull -> does not fit because points have to be aligned already //sf::ConvexShape m_convex; // shape for convex hull -> does not fit because points have to be aligned already
//std::map<Line, std::vector<Point> > m_pointsForLine; //std::map<Line, std::vector<Point> > m_pointsForLine;
@ -44,6 +44,8 @@ private:
int m_curLineIdx = -1; // or just use index int m_curLineIdx = -1; // or just use index
unsigned int m_step = 0; unsigned int m_step = 0;
void setCurrentLine();
void update(); void update();
void render(sf::RenderWindow &); void render(sf::RenderWindow &);

View File

@ -58,8 +58,11 @@ public:
{ {
std::list<Point> points; std::list<Point> points;
//srand(static_cast <unsigned> (time(0))); #ifdef _DEBUG
srand(static_cast <unsigned> (0)); // fixed seed for testing srand(static_cast <unsigned> (0)); // fixed seed for testing
#else
srand(static_cast <unsigned> (time(0)));
#endif
float x = 0; float x = 0;
float y = 0; float y = 0;

View File

@ -22,4 +22,17 @@ static bool IsPointInTriangle(const Point &pt, const Point &p1, const Point &p2,
return !(has_neg && has_pos); return !(has_neg && has_pos);
} }
static bool IsPointInRectangle(const Point& pt, const Point& p1, const Point& p2, const Point& p3, const Point& p4)
{
float d1 = sign(pt, p1, p2);
float d2 = sign(pt, p2, p3);
float d3 = sign(pt, p3, p4);
float d4 = sign(pt, p4, p1);
bool has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0) || (d4 < 0);
bool has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0) || (d4 > 0);
return !(has_neg && has_pos);
}
#endif // UTILITY_H #endif // UTILITY_H