26void toPoly(
D2<SBasis> const &f, std::list<Point> &p,
double tol,
bool include_first=
true){
30 if ( include_first ){ p.push_back( f.
at0() );}
40 if (bds_max<tol/4) dt = 1;
41 else dt = 2*std::sqrt( tol / bds_max );
53 assert ( f.size() >0 && f[0].size() >0 );
56 for (
unsigned i = 0; i<f.size(); i++){
57 for (
unsigned j = 0; j<f[i].size(); j++){
58 toPoly(f[i][j],res,tol, j==0);
60 if ( f[i].segs.front().at0() != f[i].segs.back().at1() ){
61 res.push_back( f[i].segs.front().at0() );
63 if ( i>0 ) res.push_back( f[0][0].at0() );
70 double abaa1 =
cross( b0-a0, a1-a0);
71 double abab1 =
cross( b0-a0, b1-a0);
72 double abaa0 =
cross( b1-a1, a0-a1);
73 double abab0 =
cross( b1-a1, b0-a1);
74 if ( abaa1 * abab1 < -tol && abaa0 * abab0 < -tol ){
75 c = a1 - (b1-a1) * abaa1/(abab1-abaa1);
81 if ( abaa1 == 0 &&
dot( a0-a1, b0-a1 ) < 0 ) {
85 if ( abab1 == 0 &&
dot( a0-b1, b0-b1 ) < 0 ) {
89 if ( abaa0 == 0 &&
dot( a1-a0, b1-a0 ) < 0 ) {
93 if ( abab0 == 0 &&
dot( a1-b0, b1-b0 ) < 0 ) {
103 std::list<Point>::iterator b0 = loop.begin(),a0,b1,a1;
104 if ( b0 == loop.end() )
return;
107 if ( b0 == loop.end() )
return;
109 while ( b0 != loop.end() ){
112 if ( b1 != loop.end() ) {
115 if ( b1 != loop.end() ) {
118 while ( b1 != loop.end() ){
120 if (
c != (*a0) &&
c != (*b0) ){
124 std::list<Point> loop_piece;
125 loop_piece.insert(loop_piece.begin(), b0, a1 );
126 loop_piece.reverse();
127 loop.erase( b0, a1 );
128 loop.splice( a1, loop_piece );
150void triangulate(std::list<Point> &pts, std::vector<Triangle> &tri,
bool clockwise =
false,
double tol=.001){
152 while ( !pts.empty() && pts.front() == pts.back() ){ pts.pop_back(); }
153 if ( pts.size() < 3 )
return;
155 pts.push_back(pts.front()); pts.pop_front();
156 std::list<Point>::iterator a,b,
c,m;
157 int sign = (clockwise ? -1 : 1 );
162 if ( pts.size() == 3 ) {
167 abc.area =
sign *(
cross((*b) - (*a),(*
c) - (*b))/2) ;
175 while(
c != pts.end() ){
176 double abac =
cross((*b)-(*a),(*
c)-(*a));
177 if ( fabs(abac)<tol &&
dot( *b-*a, *
c-*b ) <= 0) {
185 while ( m != pts.end() && !found && m!=a){
186 bool pointing_inside;
187 double abam =
cross((*b)-(*a),(*m)-(*a));
188 double bcbm =
cross((*
c)-(*b),(*m)-(*b));
189 if (
sign * abac > 0 ){
190 pointing_inside = (
sign * abam >= 0 ) && (
sign * bcbm >= 0 );
192 pointing_inside = (
sign * abam >=0 ) || (
sign * bcbm >=0);
194 if ( pointing_inside ){
195 std::list<Point>::iterator p=
c,q=++p;
197 while ( q != pts.end() && !
intersect(*b,*m,*p,*q,inter) ){
201 if ( q == pts.end() ){
211 std::list<Point>pts_beg;
214 pts_beg.splice(pts_beg.begin(), pts, b, m);
229 double x = std::rand();
233class RandomGenerator {
237 ~RandomGenerator(){};
239 void set_generator(
double (*rand_func)());
240 void resetRandomizer();
248 std::vector<Triangle> triangles;
249 std::vector<double> areas;
252RandomGenerator::RandomGenerator(){
253 seed = start_seed = 10;
257 seed = start_seed = 10;
259 setDomain(f_in, tol);
263 std::list<Point> p =
toPoly( f, tol);
265 if ( p.size()<3)
return;
267 std::list<Point>::iterator a = p.begin(), b=a;
270 tot_area += ((*b)[
X]-(*a)[
X]) * ((*b)[
Y]+(*a)[
Y])/2;
273 bool clockwise = tot_area < 0;
274 triangles = std::vector<Triangle>();
276 areas = std::vector<double>(triangles.size(),0.);
278 for (
unsigned i = 0; i<triangles.size(); i++){
279 cumul += triangles[i].area;
284void RandomGenerator::resetRandomizer(){
287Point RandomGenerator::pt(){
288 if (areas.empty())
return Point(0,0);
289 double pick_area = rand()*areas.back();
290 std::vector<double>::iterator picked = std::lower_bound( areas.begin(), areas.end(), pick_area);
291 unsigned i = picked - areas.begin();
292 double x = (*rand)();
293 double y = (*rand)();
300 res = triangles[i].a;
301 res += x * ( triangles[i].b - triangles[i].a );
302 res += y * ( triangles[i].c - triangles[i].a );
305double RandomGenerator::area(){
306 if (areas.empty())
return 0;
309void RandomGenerator::set_generator(
double (*f)()){
321class RandomToy:
public Toy {
329 std::ostringstream *notify,
330 int width,
int height,
bool save, std::ostringstream *timer_stream)
override {
332 for(
unsigned i=0; i<NB_SLIDER; i++){
333 adjuster[i].
pos[
X] = 30+i*20;
334 if (adjuster[i].pos[
Y]<100) adjuster[i].
pos[
Y] = 100;
335 if (adjuster[i].pos[
Y]>400) adjuster[i].
pos[
Y] = 400;
338 cairo_set_line_width (cr, .5);
342 double tol = (400-adjuster[0].
pos[
Y])/300.*5+0.05;
343 double tau = (400-adjuster[1].
pos[
Y])/300.;
351 b1_handle.
pts.back() = b2_handle.
pts.front();
352 b1_handle.
pts.front() = b2_handle.
pts.back();
356 cairo_set_line_width(cr, 0.3);
360 cairo_set_line_width (cr, .5);
371 Point centroid_tmp(0,0);
379 cairo_set_line_width (cr, .5);
387 std::list<Point> p =
toPoly( f, tol);
390 for (std::list<Point>::iterator pt = p.begin(); pt!=p.end(); ++pt){
394 cairo_set_line_width (cr, 3);
398 if ( p.size()<3)
return;
400 std::list<Point>::iterator a = p.begin(), b=a;
403 tot_area += ((*b)[
X]-(*a)[
X]) * ((*b)[
Y]+(*a)[
Y])/2;
406 bool clockwise = tot_area < 0;
408 std::vector<Triangle> tri;
413 for (
unsigned i=0; i<tri.size(); i++){
418 cairo_set_line_width (cr, .5);
430 RandomGenerator rdm = RandomGenerator(B, tol);
431 for(
int i = 0; i < rdm.area()/5*tau; i++) {
442 for(
int i = 0; i <
SIZE; i++) {
458 for(
unsigned i = 0; i < NB_SLIDER; i++) {
460 handles.push_back(&(adjuster[i]));
465int main(
int argc,
char **argv) {
466 init(argc, argv,
new RandomToy);
Conversion between Bezier control points and SBasis curves.
static int constexpr SIZE
Adaptor that creates 2D functions from 1D ones.
Point valueAt(double t) const
CPoint min() const
Get the corner of the rectangle with smallest coordinate values.
CPoint max() const
Get the corner of the rectangle with largest coordinate values.
Range of real numbers that is never empty.
Function that interpolates linearly between two values.
Range of real numbers that can be empty.
Function defined as discrete pieces.
void continuousConcat(const Piecewise< T > &other)
output_type lastValue() const
output_type firstValue() const
void concat(const Piecewise< T > &other)
Two-dimensional point that doubles as a vector.
void push_back(double x, double y)
Geom::D2< Geom::SBasis > asBezier()
std::vector< Geom::Point > pts
vector< Handle * > handles
virtual void save(FILE *f)
virtual void draw(cairo_t *cr, std::ostringstream *notify, int w, int h, bool save, std::ostringstream *timing_stream)
Lifts one dimensional objects into 2D.
Various utility functions.
OptInterval bounds_local(Bezier const &b, OptInterval const &i)
static float sign(double number)
Returns +1 for positive numbers, -1 for negative numbers, and 0 otherwise.
std::vector< Geom::Piecewise< Geom::D2< Geom::SBasis > > > split_at_discontinuities(Geom::Piecewise< Geom::D2< Geom::SBasis > > const &pwsbin, double tol=.0001)
Bezier integral(Bezier const &a)
Bezier derivative(Bezier const &a)
Piecewise< SBasis > cross(Piecewise< D2< SBasis > > const &a, Piecewise< D2< SBasis > > const &b)
T dot(D2< T > const &a, D2< T > const &b)
Point unit_vector(Point const &a)
D2< T > rot90(D2< T > const &a)
std::vector< Point > intersect(const xAx &C1, const xAx &C2)
void cairo_line_to(cairo_t *cr, Geom::Point p1)
void cairo_d2_pw_sb(cairo_t *cr, Geom::D2< Geom::Piecewise< Geom::SBasis > > const &p)
void draw_handle(cairo_t *cr, Geom::Point h)
void cairo_move_to(cairo_t *cr, Geom::Point p1)
void cairo_d2_sb(cairo_t *cr, Geom::D2< Geom::SBasis > const &p)
void triangulate(std::list< Point > &pts, std::vector< Triangle > &tri, bool clockwise=false, double tol=.001)
void toPoly(D2< SBasis > const &f, std::list< Point > &p, double tol, bool include_first=true)
void uncross(std::list< Point > &loop)
double my_rand_generator()
two-dimensional geometric operators.
Polynomial in symmetric power basis (S-basis)
void cairo_set_source_rgba(cairo_t *cr, colour c)
void init(int argc, char **argv, Toy *t, int width=600, int height=600)