Merge pull request #23 from pierre-dejoue/master

Improvement to the testbed application
This commit is contained in:
Jan Niklas Hasse 2020-11-20 11:38:31 +01:00 committed by GitHub
commit 4515f65f5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 174 additions and 121 deletions

View File

@ -92,3 +92,15 @@
251.07143 621.11218 251.07143 621.11218
250.53571 649.1479 250.53571 649.1479
268.1955 654.36208 268.1955 654.36208
HOLE
325 437
320 423
329 413
332 423
HOLE
320.72342 480
338.90617 465.96863
347.99754 480.61584
329.8148 510.41534
339.91632 480.11077
334.86556 478.09046

9
testbed/data/steiner.dat Normal file
View File

@ -0,0 +1,9 @@
0 0
10 0
10 10
0 10
STEINER
2 2
8 2
8 8
2 8

View File

@ -33,12 +33,15 @@
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <algorithm> #include <algorithm>
#include <cassert>
#include <cstdlib> #include <cstdlib>
#include <ctime> #include <ctime>
#include <exception>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <iterator> #include <iterator>
#include <list> #include <list>
#include <numeric>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <vector> #include <vector>
@ -46,6 +49,12 @@
using namespace std; using namespace std;
using namespace p2t; using namespace p2t;
bool ParseFile(string filename, vector<Point*>& out_polyline, vector<vector<Point*>>& out_holes,
vector<Point*>& out_steiner);
void GenerateRandomPointDistribution(size_t num_points, double min, double max,
vector<Point*>& out_polyline,
vector<vector<Point*>>& out_holes,
vector<Point*>& out_steiner);
void Init(); void Init();
void ShutDown(int return_code); void ShutDown(int return_code);
void MainLoop(const double zoom); void MainLoop(const double zoom);
@ -56,13 +65,9 @@ double StringToDouble(const std::string& s);
double Random(double (*fun)(double), double xmin, double xmax); double Random(double (*fun)(double), double xmin, double xmax);
double Fun(double x); double Fun(double x);
/// Dude hole examples double rotate_y = 0.0,
vector<Point*> CreateHeadHole(); rotate_z = 0.0;
vector<Point*> CreateChestHole(); const double rotations_per_tick = 0.2;
float rotate_y = 0,
rotate_z = 0;
const float rotations_per_tick = .2;
/// Screen center x /// Screen center x
double cx = 0.0; double cx = 0.0;
@ -74,7 +79,9 @@ vector<Triangle*> triangles;
/// Triangle map /// Triangle map
list<Triangle*> map; list<Triangle*> map;
/// Polylines /// Polylines
vector< vector<Point*> > polylines; vector<Point*> polyline;
vector<vector<Point*>> holes;
vector<Point*> steiner;
/// Draw the entire triangle map? /// Draw the entire triangle map?
bool draw_map = false; bool draw_map = false;
@ -83,18 +90,18 @@ bool random_distribution = false;
GLFWwindow* window = NULL; GLFWwindow* window = NULL;
template <class C> void FreeClear( C & cntr ) { template <class C> void FreeClear(C& cntr)
for ( typename C::iterator it = cntr.begin(); {
it != cntr.end(); ++it ) { for (typename C::iterator it = cntr.begin(); it != cntr.end(); ++it) {
delete * it; delete *it;
} }
cntr.clear(); cntr.clear();
} }
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
string filename;
int num_points = 0; size_t num_points = 0u;
double max, min; double max, min;
double zoom; double zoom;
@ -105,58 +112,30 @@ int main(int argc, char* argv[])
return 1; return 1;
} }
if(string(argv[1]) == "random") { if (string(argv[1]) == "random") {
num_points = atoi(argv[2]); num_points = atoi(argv[2]);
random_distribution = true; random_distribution = true;
char* pEnd; char* pEnd;
max = strtod(argv[3], &pEnd); max = strtod(argv[3], &pEnd);
min = -max; min = -max;
cx = cy = 0; cx = cy = 0.0;
zoom = atof(argv[4]); zoom = atof(argv[4]);
} else { } else {
zoom = atof(argv[4]); filename = string(argv[1]);
cx = atof(argv[2]); cx = atof(argv[2]);
cy = atof(argv[3]); cy = atof(argv[3]);
zoom = atof(argv[4]);
} }
vector<p2t::Point*> polyline; if (random_distribution) {
GenerateRandomPointDistribution(num_points, min, max, polyline, holes, steiner);
if(random_distribution) {
// Create a simple bounding box
polyline.push_back(new Point(min,min));
polyline.push_back(new Point(min,max));
polyline.push_back(new Point(max,max));
polyline.push_back(new Point(max,min));
} else { } else {
// Load pointset from file // Load pointset from file
if (!ParseFile(filename, polyline, holes, steiner)) {
// Parse and tokenize data file return 2;
string line;
ifstream myfile(argv[1]);
if (myfile.is_open()) {
while (!myfile.eof()) {
getline(myfile, line);
if (line.size() == 0) {
break;
}
istringstream iss(line);
vector<string> tokens;
copy(istream_iterator<string>(iss), istream_iterator<string>(),
back_inserter<vector<string> >(tokens));
double x = StringToDouble(tokens[0]);
double y = StringToDouble(tokens[1]);
polyline.push_back(new Point(x, y));
num_points++;
}
myfile.close();
} else {
cout << "File not opened" << endl;
} }
} }
cout << "Number of constrained edges = " << polyline.size() << endl;
polylines.push_back(polyline);
Init(); Init();
/* /*
@ -173,29 +152,14 @@ int main(int argc, char* argv[])
CDT* cdt = new CDT(polyline); CDT* cdt = new CDT(polyline);
/* /*
* STEP 2: Add holes or Steiner points if necessary * STEP 2: Add holes or Steiner points
*/ */
for (const auto& hole : holes) {
string s(argv[1]); assert(!hole.empty());
if(s.find("dude.dat", 0) != string::npos) { cdt->AddHole(hole);
// Add head hole }
vector<Point*> head_hole = CreateHeadHole(); for (const auto& s : steiner) {
num_points += head_hole.size(); cdt->AddPoint(s);
cdt->AddHole(head_hole);
// Add chest hole
vector<Point*> chest_hole = CreateChestHole();
num_points += chest_hole.size();
cdt->AddHole(chest_hole);
polylines.push_back(head_hole);
polylines.push_back(chest_hole);
} else if (random_distribution) {
max-=(1e-4);
min+=(1e-4);
for(int i = 0; i < num_points; i++) {
double x = Random(Fun, min, max);
double y = Random(Fun, min, max);
cdt->AddPoint(new Point(x, y));
}
} }
/* /*
@ -207,27 +171,115 @@ int main(int argc, char* argv[])
triangles = cdt->GetTriangles(); triangles = cdt->GetTriangles();
map = cdt->GetMap(); map = cdt->GetMap();
const size_t points_in_holes =
std::accumulate(holes.cbegin(), holes.cend(), size_t(0),
[](size_t cumul, const vector<Point*>& hole) { return cumul + hole.size(); });
cout << "Number of points = " << num_points << endl; cout << "Number of primary constrained edges = " << polyline.size() << endl;
cout << "Number of holes = " << holes.size() << endl;
cout << "Number of constrained edges in holes = " << points_in_holes << endl;
cout << "Number of Steiner points = " << steiner.size() << endl;
cout << "Total number of points = " << (polyline.size() + points_in_holes + steiner.size())
<< endl;
cout << "Number of triangles = " << triangles.size() << endl; cout << "Number of triangles = " << triangles.size() << endl;
cout << "Elapsed time (ms) = " << dt*1000.0 << endl; cout << "Elapsed time (ms) = " << dt * 1000.0 << endl;
MainLoop(zoom); MainLoop(zoom);
// Cleanup // Cleanup
delete cdt; delete cdt;
FreeClear(polyline);
// Free points for (vector<Point*>& hole : holes) {
for(int i = 0; i < polylines.size(); i++) { FreeClear(hole);
vector<Point*> poly = polylines[i];
FreeClear(poly);
} }
FreeClear(steiner);
ShutDown(0); ShutDown(0);
return 0; return 0;
} }
bool ParseFile(string filename, vector<Point*>& out_polyline, vector<vector<Point*>>& out_holes,
vector<Point*>& out_steiner)
{
enum ParserState {
Polyline,
Hole,
Steiner,
};
ParserState state = Polyline;
vector<Point*>* hole = nullptr;
try {
string line;
ifstream myfile(filename);
if (myfile.is_open()) {
while (!myfile.eof()) {
getline(myfile, line);
if (line.empty()) {
break;
}
istringstream iss(line);
vector<string> tokens;
copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter(tokens));
if (tokens.empty()) {
break;
} else if (tokens.size() == 1u) {
const auto token = tokens[0];
if (token == "HOLE") {
state = Hole;
out_holes.emplace_back();
hole = &out_holes.back();
} else if (token == "STEINER") {
state = Steiner;
} else {
throw runtime_error("Invalid token [" + token + "]");
}
} else {
double x = StringToDouble(tokens[0]);
double y = StringToDouble(tokens[1]);
switch (state) {
case Polyline:
out_polyline.push_back(new Point(x, y));
break;
case Hole:
assert(hole != nullptr);
hole->push_back(new Point(x, y));
break;
case Steiner:
out_steiner.push_back(new Point(x, y));
break;
default:
assert(0);
}
}
}
} else {
throw runtime_error("File not opened");
}
} catch (exception& e) {
cerr << "Error parsing file: " << e.what() << endl;
return false;
}
return true;
}
void GenerateRandomPointDistribution(size_t num_points, double min, double max,
vector<Point*>& out_polyline,
vector<vector<Point*>>& out_holes, vector<Point*>& out_steiner)
{
out_polyline.push_back(new Point(min, min));
out_polyline.push_back(new Point(min, max));
out_polyline.push_back(new Point(max, max));
out_polyline.push_back(new Point(max, min));
max -= (1e-4);
min += (1e-4);
for (int i = 0; i < num_points; i++) {
double x = Random(Fun, min, max);
double y = Random(Fun, min, max);
out_steiner.push_back(new Point(x, y));
}
}
void Init() void Init()
{ {
const int window_width = 800, const int window_width = 800,
@ -267,7 +319,7 @@ void MainLoop(const double zoom)
// calculate time elapsed, and the amount by which stuff rotates // calculate time elapsed, and the amount by which stuff rotates
double current_time = glfwGetTime(), double current_time = glfwGetTime(),
delta_rotate = (current_time - old_time) * rotations_per_tick * 360; delta_rotate = (current_time - old_time) * rotations_per_tick * 360.0;
old_time = current_time; old_time = current_time;
// escape to quit, arrow keys to rotate view // escape to quit, arrow keys to rotate view
@ -306,8 +358,8 @@ void ResetZoom(double zoom, double cx, double cy, double width, double height)
glLoadIdentity(); glLoadIdentity();
// Reset ortho view // Reset ortho view
glOrtho(left, right, bottom, top, 1, -1); glOrtho(left, right, bottom, top, 1.0, -1.0);
glTranslatef(-cx, -cy, 0); glTranslated(-cx, -cy, 0.0);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glLoadIdentity(); glLoadIdentity();
@ -333,20 +385,25 @@ void Draw(const double zoom)
glColor3f(1, 0, 0); glColor3f(1, 0, 0);
glBegin(GL_LINE_LOOP); glBegin(GL_LINE_LOOP);
glVertex2f(a.x, a.y); glVertex2d(a.x, a.y);
glVertex2f(b.x, b.y); glVertex2d(b.x, b.y);
glVertex2f(c.x, c.y); glVertex2d(c.x, c.y);
glEnd(); glEnd();
} }
// green // green
glColor3f(0, 1, 0); glColor3f(0, 1, 0);
vector<vector<Point*>*> polylines;
polylines.push_back(&polyline);
for (vector<Point*>& hole : holes) {
polylines.push_back(&hole);
}
for(int i = 0; i < polylines.size(); i++) { for(int i = 0; i < polylines.size(); i++) {
vector<Point*> poly = polylines[i]; const vector<Point*>& poly = *polylines[i];
glBegin(GL_LINE_LOOP); glBegin(GL_LINE_LOOP);
for(int j = 0; j < poly.size(); j++) { for(int j = 0; j < poly.size(); j++) {
glVertex2f(poly[j]->x, poly[j]->y); glVertex2d(poly[j]->x, poly[j]->y);
} }
glEnd(); glEnd();
} }
@ -368,20 +425,20 @@ void DrawMap(const double zoom)
ConstrainedColor(t.constrained_edge[2]); ConstrainedColor(t.constrained_edge[2]);
glBegin(GL_LINES); glBegin(GL_LINES);
glVertex2f(a.x, a.y); glVertex2d(a.x, a.y);
glVertex2f(b.x, b.y); glVertex2d(b.x, b.y);
glEnd( ); glEnd( );
ConstrainedColor(t.constrained_edge[0]); ConstrainedColor(t.constrained_edge[0]);
glBegin(GL_LINES); glBegin(GL_LINES);
glVertex2f(b.x, b.y); glVertex2d(b.x, b.y);
glVertex2f(c.x, c.y); glVertex2d(c.x, c.y);
glEnd( ); glEnd( );
ConstrainedColor(t.constrained_edge[1]); ConstrainedColor(t.constrained_edge[1]);
glBegin(GL_LINES); glBegin(GL_LINES);
glVertex2f(c.x, c.y); glVertex2d(c.x, c.y);
glVertex2f(a.x, a.y); glVertex2d(a.x, a.y);
glEnd( ); glEnd( );
} }
} }
@ -397,31 +454,6 @@ void ConstrainedColor(bool constrain)
} }
} }
vector<Point*> CreateHeadHole() {
vector<Point*> head_hole;
head_hole.push_back(new Point(325, 437));
head_hole.push_back(new Point(320, 423));
head_hole.push_back(new Point(329, 413));
head_hole.push_back(new Point(332, 423));
return head_hole;
}
vector<Point*> CreateChestHole() {
vector<Point*> chest_hole;
chest_hole.push_back(new Point(320.72342,480));
chest_hole.push_back(new Point(338.90617,465.96863));
chest_hole.push_back(new Point(347.99754,480.61584));
chest_hole.push_back(new Point(329.8148,510.41534));
chest_hole.push_back(new Point(339.91632,480.11077));
chest_hole.push_back(new Point(334.86556,478.09046));
return chest_hole;
}
double StringToDouble(const std::string& s) double StringToDouble(const std::string& s)