mirror of
https://github.com/jhasse/poly2tri.git
synced 2024-11-05 22:09:52 +01:00
Merge pull request #23 from pierre-dejoue/master
Improvement to the testbed application
This commit is contained in:
commit
4515f65f5b
@ -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
9
testbed/data/steiner.dat
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
0 0
|
||||||
|
10 0
|
||||||
|
10 10
|
||||||
|
0 10
|
||||||
|
STEINER
|
||||||
|
2 2
|
||||||
|
8 2
|
||||||
|
8 8
|
||||||
|
2 8
|
274
testbed/main.cc
274
testbed/main.cc
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user