Blame c++/contourgl/contourbuilder.cpp

Ivan Mahonin faaf7d
/*
Ivan Mahonin faaf7d
    ......... 2015 Ivan Mahonin
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
    This program is free software: you can redistribute it and/or modify
Ivan Mahonin faaf7d
    it under the terms of the GNU General Public License as published by
Ivan Mahonin faaf7d
    the Free Software Foundation, either version 3 of the License, or
Ivan Mahonin faaf7d
    (at your option) any later version.
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
    This program is distributed in the hope that it will be useful,
Ivan Mahonin faaf7d
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Ivan Mahonin faaf7d
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Ivan Mahonin faaf7d
    GNU General Public License for more details.
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
    You should have received a copy of the GNU General Public License
Ivan Mahonin faaf7d
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
Ivan Mahonin faaf7d
*/
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
#include "contourbuilder.h"
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
using namespace std;
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
void ContourBuilder::build_simple(vector<Vector> &c) {
Ivan Mahonin faaf7d
	const float min_segment_length = 0.001f;
Ivan Mahonin faaf7d
	const float rounds = 10.f;
Ivan Mahonin faaf7d
	const float rounds2 = 1.f;
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	vector<Vector> back;
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	float angle = 360.f;
Ivan Mahonin faaf7d
	float offset = 0.25f/(rounds + 1.f);
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	// go front
Ivan Mahonin faaf7d
	while(true) {
Ivan Mahonin faaf7d
		float radius = angle/360.f/(rounds + 1.f);
Ivan Mahonin faaf7d
		float step = min_segment_length*180.f/M_PI/radius;
Ivan Mahonin faaf7d
		if (radius > 1.f - 2.f*offset) break;
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
		float fr = radius + offset;
Ivan Mahonin faaf7d
		float fx = fr*sinf(angle/180.f*M_PI);
Ivan Mahonin faaf7d
		float fy = fr*cosf(angle/180.f*M_PI);
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
		float br = radius - offset;
Ivan Mahonin faaf7d
		float bx = br*sinf(angle/180.f*M_PI);
Ivan Mahonin faaf7d
		float by = br*cosf(angle/180.f*M_PI);
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
		c.push_back(Vector(fx, fy));
Ivan Mahonin faaf7d
		back.push_back(Vector(bx, by));
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
		angle += step;
Ivan Mahonin faaf7d
	}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	float max_angle = angle;
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	while(true) {
Ivan Mahonin faaf7d
		float radius = max_angle/360.f/(rounds + 1.f)
Ivan Mahonin faaf7d
				     + (max_angle-angle)/360.f/rounds2;
Ivan Mahonin faaf7d
		float step = min_segment_length*180.f/M_PI/radius;
Ivan Mahonin faaf7d
		if (radius < 1.f/(rounds + 1.f))
Ivan Mahonin faaf7d
			break;
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
		float fr = radius + offset;
Ivan Mahonin faaf7d
		float fx = fr*sinf(angle/180.f*M_PI);
Ivan Mahonin faaf7d
		float fy = fr*cosf(angle/180.f*M_PI);
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
		float br = radius - offset;
Ivan Mahonin faaf7d
		float bx = br*sinf(angle/180.f*M_PI);
Ivan Mahonin faaf7d
		float by = br*cosf(angle/180.f*M_PI);
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
		c.push_back(Vector(fx, fy));
Ivan Mahonin faaf7d
		back.push_back(Vector(bx, by));
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
		angle += step;
Ivan Mahonin faaf7d
	}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	// go back
Ivan Mahonin faaf7d
	c.reserve(c.size() + back.size() + 1);
Ivan Mahonin faaf7d
	for(vector<Vector>::reverse_iterator ri = back.rbegin(); ri != back.rend(); ++ri)
Ivan Mahonin faaf7d
		c.push_back(*ri);
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	// close
Ivan Mahonin faaf7d
	c.push_back(c.front());
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin 93cbac
void ContourBuilder::build_car(Contour &c, const Vector &o, Real s) {
Ivan Mahonin faaf7d
	c.move_to(  Vector( 5, -1)*s + o);
Ivan Mahonin faaf7d
	c.line_to(  Vector( 4, -1)*s + o);
Ivan Mahonin faaf7d
	c.conic_to( Vector( 2, -1)*s + o, Vector( 0, -1)*s);
Ivan Mahonin faaf7d
	c.line_to(  Vector(-2, -1)*s + o);
Ivan Mahonin faaf7d
	c.conic_to( Vector(-4, -1)*s + o, Vector( 0, -1)*s);
Ivan Mahonin faaf7d
	c.line_to(  Vector(-5, -1)*s + o);
Ivan Mahonin faaf7d
	c.line_to(  Vector(-5,  1)*s + o);
Ivan Mahonin faaf7d
	c.line_to(  Vector(-4,  1)*s + o);
Ivan Mahonin faaf7d
	c.cubic_to( Vector(-1,  3)*s + o, Vector( 0,  2)*s, Vector( 4,  0)*s);
Ivan Mahonin faaf7d
	c.cubic_to( Vector( 3,  1)*s + o, Vector( 4,  0)*s, Vector( 2, -2)*s);
Ivan Mahonin faaf7d
	c.line_to(  Vector( 5,  1)*s + o);
Ivan Mahonin faaf7d
	c.close();
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
void ContourBuilder::build(Contour &c) {
Ivan Mahonin 93cbac
	Real scale = 0.8/5.0;
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	int count = 100;
Ivan Mahonin 93cbac
	Real size = (Real)(count + 2)/(Real)(count);
Ivan Mahonin 93cbac
	Real step = 2.0*size/(Real)(count + 1);
Ivan Mahonin 93cbac
	Real origin = step - size;
Ivan Mahonin 93cbac
	Real s = 2*size*scale/(Real)(count);
Ivan Mahonin faaf7d
	for(int i = 0; i < count; ++i)
Ivan Mahonin faaf7d
		for(int j = 0; j < count; ++j)
Ivan Mahonin faaf7d
			build_car(c, Vector(origin + i*step, origin + j*step), s);
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	count = 100;
Ivan Mahonin 93cbac
	size = (Real)(count + 2)/(Real)(count);
Ivan Mahonin 93cbac
	step = 2.0*size/(Real)(count + 1);
Ivan Mahonin faaf7d
	origin = step - size;
Ivan Mahonin 93cbac
	s = size*scale/(Real)(count);
Ivan Mahonin faaf7d
	for(int i = 0; i < count; ++i)
Ivan Mahonin faaf7d
		for(int j = 0; j < count; ++j)
Ivan Mahonin faaf7d
			build_car(c, Vector(origin + i*step, origin + j*step), s);
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	build_car(c, Vector::zero(), scale);
Ivan Mahonin faaf7d
	build_car(c, Vector::zero(), 0.5*scale);
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d