Raw File
LowcrossingMatchings.cpp
#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>
#include <assert.h>
#include <algorithm> 
#include <time.h>
#include <cmath>
#include <chrono>
#include <random>
#include <math.h>
#include <Eigen/Dense>
#include <thread>

using namespace std;
using namespace Eigen;

#define _uindex unsigned long long //64 bits
#define _sindex long long int      //64 bits
#define _float  double

struct myEdge;
struct myVec;
struct myPlane;

_uindex _NUMTHREADS = 24;
_uindex _N_DEFAULT = 5000;
_uindex _D_DEFAULT = 4;
_uindex _THRESHOLD = 0;

_uindex GLOBAL_N;
_uindex GLOBAL_D;
string GLOBAL_DISTRIB;
string GLOBAL_FILENAME;
_uindex _LOG2_N;
_uindex _LOGe_N;
_uindex _pow1dim_N;
_uindex _EDGE_SAMPLED_SEARCH_RADIUS;
_uindex _PLANE_SAMPLED_SEARCH_RADIUS;
_uindex _EDGES_SAMPLED_PER_VERTEX_INITIAL;
_uindex _PLANES_SAMPLED_TOTAL_INITIAL;
_uindex _EDGES_SAMPLED_PER_ITERATION;
_uindex _PLANES_SAMPLED_PER_ITERATION;
_float	_PROPORTION_ITERATIONS;

std::random_device rd;
std::default_random_engine generator(rd());
std::uniform_int_distribution<_uindex> distribution;

void generateCyclicPolytope(vector<myVec> & input, _uindex);
void generateBoxRandom(vector<myVec> & input, _uindex);
void generateUniformRandomGrid(vector<myVec> &, _uindex, _uindex);
void generateCircle(vector<myVec> & input, _uindex);
void generateSineCurve(vector<myVec> & input, _uindex);
void saveFile(vector<myVec> &, string & fname);
void saveFile(vector<myEdge *> & output, string & fname);



/*

OUR STRUCTURES

*/

struct myVec				// structure for points
{
	vector<_float> coordinates;
	vector<myEdge *> vE; // pointers to all incident active edges 

	myVec() {}
	myVec(vector<_float> & q) { coordinates.reserve(q.size());  for (size_t i = 0; i < q.size(); i++) coordinates.push_back(q[i]); }
	void clearEdges() { vE.clear(); }
};



struct myEdge 		// structure for edges
{
	myVec *p1, *p2;
	_uindex intersection_count; // its weight is (1/2)^intersection_count
	_uindex index_sampling;		// index in the set of all active edges
	_sindex index;				// index in the set of edges of the same weight
	_sindex thread;				// index of the thread working with this edge.

	myEdge(myVec *f1 = nullptr, myVec* f2 = nullptr) : p1(f1), p2(f2) {}
};

_float dot(vector<_float> & p, vector<_float> & q)	//dot product of two vectors
{
	assert(p.size() == q.size());
	_float sum = 0.0f;
	for (size_t i = 0; i < p.size(); i++) sum += p[i] * q[i];
	return sum;
}

struct myPlane 			// structure for hyperplanes
{
	vector<_float> N; 				// vector orthogonal to the plane
	_float dist;					// dot product of N and a point on the plane
	_uindex intersection_count;		// plane has weight 2^intersection_count
	_sindex index;					// index in the set of planes with the same weight

	myPlane() { intersection_count = 0; }

	myPlane(vector<myVec *> & points)  // constructing a hyperplane through points
	{
		_uindex _D = points[0]->coordinates.size();
		intersection_count = 0;
		MatrixXd A(_D, _D);
		for (size_t i = 0; i < _D; i++)
			for (size_t j = 0; j < _D; j++)
				A(i, j) = points[i]->coordinates[j];
		VectorXd b(_D);
		for (size_t i = 0; i < _D; i++) b(i) = 1.0f;
		//VectorXd ans = A.colPivHouseholderQr().solve(b);
		VectorXd ans = A.partialPivLu().solve(b);
		N.reserve(_D);
		for (size_t i = 0; i < _D; i++) N.push_back(ans(i));
		dist = 1.0f;
	}
	bool side(myVec * & q) { return ((dot(N, q->coordinates) > dist) ? 1 : 0); }
	bool intersectEdge(myEdge * & e) { return (side(e->p1) ^ side(e->p2)); }
	bool intersectEdge(myVec * & p1, myVec * & p2) { return (side(p1) ^ side(p2)); }
};

_uindex max_crossing(vector<myEdge *> & edges, vector<myPlane *> & planes) // computes max crossing number of 'edges' with respect to 'planes'
{
	vector<_uindex> S(planes.size(), 0);
	for (size_t i = 0; i < planes.size(); i += 5)
		for (size_t j = 0; j < edges.size(); j++)
			if (planes[i]->intersectEdge(edges[j])) S[i]++;
	return *max_element(S.begin(), S.end());
}



void setParameters(vector<myVec *>  input)
{
	assert(input.size());
	_uindex _N = input.size();
	_uindex _D = input[0]->coordinates.size();

	_LOG2_N = ((_uindex)log2(_N)) + 1;
	_LOGe_N = ((_uindex)log(_N)) + 1;
	_pow1dim_N = ((_uindex)pow(_N, 1.0f / ((_float)_D))) + 1;

	_EDGE_SAMPLED_SEARCH_RADIUS = ((_uindex) 2.0f * _LOG2_N) + 1;
	_PLANE_SAMPLED_SEARCH_RADIUS = ((_uindex) 2.0f * _LOG2_N) + 1;

	_EDGES_SAMPLED_PER_VERTEX_INITIAL = ((_uindex) 4 * _LOG2_N) + 1;
	_PLANES_SAMPLED_TOTAL_INITIAL = ((_uindex)_N * _LOG2_N) + 1;


	_EDGES_SAMPLED_PER_ITERATION = ((_uindex)  10 *_pow1dim_N * pow(_LOG2_N, 2) ) + 1;
	_PLANES_SAMPLED_PER_ITERATION = ((_uindex)  1 * _pow1dim_N * pow(_LOG2_N, 2) ) + 1;

	_PROPORTION_ITERATIONS = 0.25f;
}

struct myTimer {
	std::chrono::time_point<std::chrono::high_resolution_clock> _currtime;
	myTimer() {}
	void start() { _currtime = std::chrono::high_resolution_clock::now(); }
	double end() {
		std::chrono::duration<double, std::micro> timer_algo_delta = std::chrono::high_resolution_clock::now() - _currtime;
		return timer_algo_delta.count() / 1000000.0f;
	}
};



struct myEdges {		// structure for the edge set
	vector<vector<myEdge *>> CE;    // edges partitioned by weight for weighted sampling
	vector<myEdge *> CE_sampling;   // the list of active edges from which to uniformly sample
	_uindex minCE_index;

	myEdges() {}
	myEdges(vector<myEdge *> & input_edges, _uindex thread_no = 0) { CE_sampling = input_edges; init_weights(thread_no); }
	myEdges(vector<myVec *> & input, size_t num, _uindex thread_no) { sample_initial_edges(input, num, CE_sampling); init_weights(thread_no); }

	void init_weights(_uindex thread_no) {
		CE = vector<vector<myEdge *>>(CE_sampling.size(), vector<myEdge *>());
		CE[0] = CE_sampling;
		for (size_t i = 0; i < CE[0].size(); i++) {
			CE[0][i]->p1->vE.push_back(CE[0][i]);
			CE[0][i]->p2->vE.push_back(CE[0][i]);
			CE[0][i]->index = i;
			CE[0][i]->index_sampling = i;
			CE[0][i]->intersection_count = 0;
			CE[0][i]->thread = thread_no;
		}
		minCE_index = 0;
	}

	void sample_initial_edges(vector<myVec *> & input, size_t num, vector<myEdge *> & output)	 // uniformly samples 'num' many edges per vertex
	{
		output.reserve(input.size() * num);
		for (size_t i = 0; i < input.size(); i++)
			for (size_t j = 0; j < num; j++) {
				size_t k;
				do {
					k = distribution(generator) % input.size();
				} while (k == i);
				output.push_back(new myEdge(input[i], input[k]));
			}
	}

	myEdge * weighted_sample_edge() // samples one edge according to current weights
	{
		_uindex curr_sum;
		_uindex W;	// total weight of edges
		_uindex	p;

		_uindex max_edge_index = min(minCE_index + _EDGE_SAMPLED_SEARCH_RADIUS, (_uindex)(CE.size() - 1));

		W = 0;
		p = 1;
		for (size_t i = max_edge_index; i >= minCE_index; i--) {
			W += CE[i].size() * p;
			p <<= 1;
			if (i == 0) break;
		}
		p >>= 1;

		_uindex r = distribution(generator) % W;
		curr_sum = 0;
		for (size_t i = minCE_index; i <= max_edge_index; i++) {
			curr_sum += CE[i].size() * p;
			if (curr_sum > r)
				return CE[i][distribution(generator) % CE[i].size()];
			p >>= 1;
		}
		return nullptr;
	}

	myEdge * sample_edge() // samples one edge uniformly at random
	{
		return CE_sampling[distribution(generator) % CE_sampling.size()]; 
	}



	void increment_weight(myEdge *e)
	{
		CE[e->intersection_count][e->index] = CE[e->intersection_count].back();
		CE[e->intersection_count][e->index]->index = e->index;
		CE[e->intersection_count].pop_back();
		e->intersection_count++;
		if (CE.size() <= e->intersection_count) CE.push_back(vector<myEdge *>());
		CE[e->intersection_count].push_back(e);
		e->index = CE[e->intersection_count].size() - 1;

		while (CE[minCE_index].empty())  minCE_index++;
	}

	void deleteEdge(myEdge * & e)
	{
		if (e->index < 0) return;

		vector<myEdge *> & E_e = CE[e->intersection_count];
		assert(e->index < E_e.size());

		E_e[e->index] = E_e.back();
		E_e[e->index]->index = e->index;
		E_e.pop_back();
		e->index = -1;

		CE_sampling[e->index_sampling] = CE_sampling.back();
		CE_sampling[e->index_sampling]->index_sampling = e->index_sampling;
		CE_sampling.pop_back();

		while (CE[minCE_index].empty())  minCE_index++;
	}



	void test_hyperplane(myPlane *h, _uindex num)	// sample num many edges and for each, increment its weight if it is crossed by h
	{
		for (size_t i = 0; i < num; i++) {
			myEdge *e = sample_edge();
			if (h->intersectEdge(e)) increment_weight(e);
		}
	}
};

struct myPlanes 		// structure for hyperplane set
{
	vector<vector<myPlane *>> CH;	//  hyperplanes partitioned by weight for weighted sampling
	vector<myPlane *> CH_sampling;	// vector of all test hyperplanes
	_uindex maxCH_index;

	myPlanes() {}
	myPlanes(vector<myPlane *> & input_planes) { CH_sampling = input_planes;  init_weights(); }
	myPlanes(vector<myVec *> & input, size_t num) { sample_initial_hyperplanes(input, num, CH_sampling); init_weights(); }

	void init_weights() {
		CH = vector<vector<myPlane *>>(CH_sampling.size(), vector<myPlane *>());
		CH[0] = CH_sampling;
		for (size_t i = 0; i < CH[0].size(); i++) {
			CH[0][i]->index = i;
			CH[0][i]->intersection_count = 0;
		}
		maxCH_index = 0;
	}

	void sample_initial_hyperplanes(vector<myVec *> & input, size_t num, vector<myPlane *> & output)	 // samples 'num' many hyperplanes through input points
	{
		output.resize(num);
		_uindex _D = input[0]->coordinates.size();
		vector<myVec *> plane(_D);
		for (size_t j = 0; j < num; j++) {
			for (size_t k = 0; k < _D; k++)  plane[k] = input[distribution(generator) % input.size()];
			output[j] = new myPlane(plane);
		}
	}

	

	myPlane * weighted_sample_plane()	// samples one hyplerplane according to current weights
	{
		_uindex curr_sum;
		_uindex W = 0;
		_uindex	p = 1;

		_uindex min_plane_index = (maxCH_index > _PLANE_SAMPLED_SEARCH_RADIUS) ? maxCH_index - _PLANE_SAMPLED_SEARCH_RADIUS : 0;

		for (size_t i = min_plane_index; i <= maxCH_index; i++) {
			W += CH[i].size() * p;
			p <<= 1;
		}
		p >>= 1;

		_uindex r = distribution(generator) % W;
		curr_sum = 0;
		for (size_t i = maxCH_index; i >= min_plane_index; i--) {
			curr_sum += CH[i].size() * p;
			if (curr_sum > r)
				return CH[i][distribution(generator) % CH[i].size()];
			p >>= 1;
			if (i == 0) break;
		}
		return nullptr;
	}

	myPlane * sample_plane() // samples one hyperplane uniformly
	{
		return CH_sampling[distribution(generator) % CH_sampling.size()]; 
	}

	void increment_weight(myPlane *h) 
	{
		CH[h->intersection_count][h->index] = CH[h->intersection_count].back();
		CH[h->intersection_count][h->index]->index = h->index;
		CH[h->intersection_count].pop_back();
		h->intersection_count++;
		if (CH.size() <= h->intersection_count) CH.push_back(vector<myPlane *>());
		CH[h->intersection_count].push_back(h);
		h->index = CH[h->intersection_count].size() - 1;

		if (!CH[maxCH_index + 1].empty())  maxCH_index++;
	}

	
	void add_max_planes(vector<myPlane *> & output) 
	{
		for (size_t i = 0; i < CH[maxCH_index].size(); i++)
			output.push_back(CH[maxCH_index][i]);
	}

	void test_edge(myEdge *e, _uindex num)	// sample num many hyperplanes and for each, increment its weight if it crosses e
	{
		for (size_t r = 0; r < num; r++) 
		{
			myPlane *h = sample_plane();
			if (h->intersectEdge(e)) increment_weight(h);
		}
	}
};



myEdge * weighted_sample_edge(vector<myEdges *> & presamplededges)
{
	myEdge *e = nullptr;
	while (!e)
		e = presamplededges[distribution(generator) % presamplededges.size()]->weighted_sample_edge();
	return e;
}

myPlane * weighted_sample_plane(vector<myPlanes *> &  testplanes)
{
	myPlane *h = nullptr;
	while (!h)
		h = testplanes[distribution(generator) % testplanes.size()]->weighted_sample_plane();
	return h;
}




/*

MATCHING ALGORITHM

*/

void computeMatching_iteration(vector<myVec *> & input, vector<myPlanes *> & testplanes, vector<myEdge *> & output, vector<myPlane *> & heavy_planes)
{
	setParameters(input);

	_uindex num_edgethreads = min((_uindex)(_EDGES_SAMPLED_PER_ITERATION / 2000.0f + 1), _NUMTHREADS);

	vector<myEdges *> presamplededges(num_edgethreads);


	for (size_t i = 0; i < input.size(); i++) input[i]->clearEdges();
	for (size_t t = 0; t < testplanes.size(); t++) testplanes[t]->init_weights();

	for (size_t t = 0; t < presamplededges.size(); t++) presamplededges[t] = new myEdges(input, (_uindex)(_EDGES_SAMPLED_PER_VERTEX_INITIAL / (_float)presamplededges.size()+1), t);

	_uindex num_iterations = (_uindex)(input.size() * _PROPORTION_ITERATIONS);

	_uindex curr_threshold = (_uindex)(0.5f * num_iterations); // number of initial warm-up iterations
	

	for (size_t i = 0; i < num_iterations + curr_threshold; i++) {

		if (i == curr_threshold)	// initalize plane weights after warm-up
			for (size_t t = 0; t < testplanes.size(); t++) testplanes[t]->init_weights();

		myEdge *random_edge = weighted_sample_edge(presamplededges);
		myPlane *random_hyperplane = weighted_sample_plane(testplanes);
		assert(random_edge); assert(random_hyperplane);

		vector<thread> Threads;

		for (size_t t = 0; t < presamplededges.size(); t++)
			Threads.push_back(thread(&myEdges::test_hyperplane, presamplededges[t], random_hyperplane, (_uindex)(_EDGES_SAMPLED_PER_ITERATION / (_float)presamplededges.size())));

		if (i >= curr_threshold) 
		{
			for (size_t t = 0; t < testplanes.size(); t++)
				Threads.push_back(thread(&myPlanes::test_edge, testplanes[t], random_edge, (_uindex)(_PLANES_SAMPLED_PER_ITERATION / (_float)testplanes.size())));
		}

		for (size_t t = 0; t < Threads.size(); t++) Threads[t].join();


		if (i >= curr_threshold)
		{
			for (size_t k = 0; k < random_edge->p1->vE.size(); k++)
				presamplededges[random_edge->p1->vE[k]->thread]->deleteEdge(random_edge->p1->vE[k]);
			for (size_t k = 0; k < random_edge->p2->vE.size(); k++)
				presamplededges[random_edge->p2->vE[k]->thread]->deleteEdge(random_edge->p2->vE[k]);
			random_edge->p1->clearEdges();
			random_edge->p2->clearEdges();
			presamplededges[random_edge->thread]->deleteEdge(random_edge);
			output.push_back(random_edge);
		}
		

	}

	for (size_t t = 0; t < testplanes.size(); t++)
		testplanes[t]->add_max_planes(heavy_planes);

}

_uindex computeMatching(vector<myVec *> input, vector<myEdge *> & output, _float & timetaken)
{
	myTimer _t;
	//_float timer = 0.0f;

	setParameters(input);

	_uindex num_planethreads = min((_uindex)(_PLANES_SAMPLED_PER_ITERATION / 2000.0f + 1), _NUMTHREADS);

	vector<myPlanes *> testplanes(num_planethreads);

	//cout << "Started testplane generation.\n"; _t.start();

	for (size_t t = 0; t < testplanes.size(); t++)
		testplanes[t] = new myPlanes(input, (_uindex)(_PLANES_SAMPLED_TOTAL_INITIAL / (_float)testplanes.size()));

	//cout << "\tFinished testplane generation in time: " << _t.end() << endl;

	vector<myPlane *> heavy_planes;
	output.clear();

	size_t iters = 0;
	_t.start();
	while (input.size() >= 40) {

		//cout << "  Iteration " << ++iters << endl; _t.start();

		computeMatching_iteration(input, testplanes, output, heavy_planes);

		//cout << "  Finished in time: " << _t.end() << endl;
		//timer += _t.end(); 
		{
			size_t i = 0;
			while (i < input.size()) {
				if (!input[i]->vE.size()) {
					input[i] = input.back();
					input.pop_back();
				}
				else i++;
			}
		}
	}

	timetaken = _t.end();
	return max_crossing(output, heavy_planes);
}


int main(int argc, char **argv)
{
	_uindex _N = _N_DEFAULT;
	_uindex _D = _D_DEFAULT;
	bool output_tofile = false;
	string input_distrib = string("Uniform");

	_uindex crossing_number = 0;
	 _float timetaken = 0;	
			 
			 

	for (int i = 0; i < argc; i++)
	{
		string s = argv[i];
		if (s == "-N") _N = atoi(argv[++i]);
		else if (s == "-D") _D = atoi(argv[++i]);
		else if (s == "-I") input_distrib = string(argv[++i]);
		else if (s == "-T") _THRESHOLD = atoi(argv[++i]);
		else if (s == "-F") output_tofile = true;
		else if (s == "-THREADS") _NUMTHREADS = atoi(argv[++i]);
		else if (s == "-FN") GLOBAL_FILENAME = string(argv[++i]);
	}

	GLOBAL_N = _N;
	GLOBAL_D = _D;
	GLOBAL_DISTRIB = input_distrib;

		

		distribution = std::uniform_int_distribution<_uindex>(0, _N * _N * _N);
		srand((unsigned int)time(NULL));

		vector<myVec> vector_of_points(_N);

		if (input_distrib == "Moment") generateCyclicPolytope(vector_of_points, _D);
		else if (input_distrib == "Grid") generateUniformRandomGrid(vector_of_points, _N, _D);
		else if (input_distrib == "Circle") generateCircle(vector_of_points, _D);
		else if (input_distrib == "Sine") generateSineCurve(vector_of_points, _D);
		else { input_distrib = "Uniform"; generateBoxRandom(vector_of_points, _D);}

		vector<myVec *>  input(_N);
		for (size_t i = 0; i < _N; i++) input[i] = &vector_of_points[i];


		if (_THRESHOLD == 0) _THRESHOLD = (_uindex)(0.5f * _N);

		vector<myEdge *>  output;

		cout << input_distrib << ", n: " << _N << ", d: " << _D << endl;

		
				cout << "Started.\n";
				crossing_number = computeMatching(input, output, timetaken);
				cout << "\t Finished within  " << timetaken << ", crossing number: " <<  crossing_number << endl;

				ofstream fout("outputdata.txt", ofstream::app);
				fout <<  input_distrib << ", input size: " <<  _N << ", dim: " << _D << ", time: " << timetaken  << ", crossing nr: "<< crossing_number << endl;
				fout.close();

				



		if (output_tofile) {
			string pointsfile = "p-n" + to_string(_N) + "d" + to_string(_D)  + input_distrib + ".txt";
			saveFile(vector_of_points, pointsfile);
			string edgesfile = "e-n" + to_string(_N) + "d" + to_string(_D)  + input_distrib + ".txt";
			saveFile(output, edgesfile);
		}

		
}





void saveFile(vector<myVec> & points, string & fname)
{
	ofstream fout(fname);
	for (size_t i = 0; i < points.size(); i++)
	{
		for (size_t j = 0; j < points[i].coordinates.size(); j++)
			fout << points[i].coordinates[j] << " ";
		fout << endl;
	}
	fout.close();
}


void saveFile(vector<myEdge *> & output, string & fname)
{
	ofstream fout(fname);
	for (size_t i = 0; i < output.size(); i++)
	{
		for (size_t j = 0; j < output[i]->p1->coordinates.size(); j++)
			fout << output[i]->p1->coordinates[j] << " ";
		fout << endl;
		for (size_t j = 0; j < output[i]->p2->coordinates.size(); j++)
			fout << output[i]->p2->coordinates[j] << " ";
		fout << endl << endl;
	}
	fout.close();
}






void generateBoxRandom(vector<myVec> & vector_of_points, _uindex _D)
{
	for (size_t i = 0; i < vector_of_points.size(); i++)
		for (size_t j = 0; j < _D; j++) vector_of_points[i].coordinates.push_back(rand() / ((_float)RAND_MAX));
}

void generateUniformGrid(vector<myVec> & vector_of_points, _uindex _D, _uindex eachdim)
{
	if (_D == 0) {
		vector_of_points.push_back(myVec());
		return;
	}

	vector<myVec> vec_onelowerdim;
	generateUniformGrid(vec_onelowerdim, _D - 1, eachdim);
	_float onebyeachdim = 1.0f / (_float)eachdim;
	for (size_t i = 0; i < vec_onelowerdim.size(); i++) {
		for (size_t j = 0; j < eachdim; j++)
		{
			myVec p = vec_onelowerdim[i];
			p.coordinates.push_back(j * onebyeachdim);
			vector_of_points.push_back(p);
		}
	}
}

void generateUniformRandomGrid(vector<myVec> & vector_of_points, _uindex _N, _uindex _D)
{
	vector_of_points.clear();

	_uindex eachdim = ((_uindex)pow(_N, 1.0f / ((_float)_D))) + 1;
	_float onebyeachdim = 1.0f / (_float)eachdim;

	generateUniformGrid(vector_of_points, _D, eachdim);

	for (size_t i = 0; i < vector_of_points.size(); i++)
		for (size_t j = 0; j < vector_of_points[i].coordinates.size(); j++)
			vector_of_points[i].coordinates[j] += onebyeachdim * (rand() / ((_float)RAND_MAX));
}

void generateCyclicPolytope(vector<myVec> & vector_of_points, _uindex _D)
{
	_float _t = 0.0f;
	for (size_t i = 0; i < vector_of_points.size(); i++) {
		for (size_t j = 0; j < _D; j++) vector_of_points[i].coordinates.push_back(pow(_t + 0.1f * rand() / ((_float)RAND_MAX), j + 1));
		_t += 1.0f;
	}
}


void generateCircle(vector<myVec> & vector_of_points, _uindex _D)
{
	assert(_D == 2);
	size_t nby4 = (size_t)((_float)vector_of_points.size() / 4.0f);
	for (size_t i = 0; i < nby4; i++) {
		_float angle = (3.14f / 2.0f * i) / (_float)nby4;
		vector_of_points[i].coordinates.push_back(sin(angle));
		vector_of_points[i].coordinates.push_back(cos(angle));

		vector_of_points[i + nby4].coordinates.push_back(-sin(angle));
		vector_of_points[i + nby4].coordinates.push_back(cos(angle));

		vector_of_points[i + 2 * nby4].coordinates.push_back(sin(angle));
		vector_of_points[i + 2 * nby4].coordinates.push_back(-cos(angle));

		vector_of_points[i + 3 * nby4].coordinates.push_back(-sin(angle));
		vector_of_points[i + 3 * nby4].coordinates.push_back(-cos(angle));
	}
}

void generateSineCurve(vector<myVec> & vector_of_points, _uindex _D)
{
	assert(_D == 2);
	size_t nby4 = (size_t)((_float)vector_of_points.size() / 40.0f);
	for (size_t i = 0; i < vector_of_points.size(); i++) {
		_float angle = (3.14f / 2.0f * i) / (_float)nby4;
		vector_of_points[i].coordinates.push_back((float) 800.0f * i / vector_of_points.size());
		vector_of_points[i].coordinates.push_back(sin(angle));
	}
}
back to top