/* (C) 2012 Claudio Rocchini - CC BY 3.0 */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <vector> #include <algorithm> const double PI = 3.1415926535897932384626433832795; inline double drand() { return double(rand())/RAND_MAX; } class point2 { public: double x,y; point2() {} point2( double nx, double ny ): x(nx),y(ny) {} }; class seed { public: point2 p; // seed position double a; // main angle double l[2]; // extents }; class inter { // intersection public: int i,j; double ti; double tj; inline inter(); inline inter( int ni, int nj, double nti, double ntj ) : i(ni),j(nj),ti(nti),tj(ntj) {} inline bool operator< ( const inter & ii ) const { return fabs(ti)<fabs(ii.ti); } }; bool intersects( const seed & s1, const seed & s2, double & t1, double & t2 ) { double dx1 = cos(s1.a); double dy1 = sin(s1.a); double dx2 = cos(s2.a); double dy2 = sin(s2.a); const double de = dx1*dy2-dy1*dx2; if(fabs(de)<1e-8) return false; double ox1 = s1.p.x; double oy1 = s1.p.y; double ox2 = s2.p.x; double oy2 = s2.p.y; t1 = (-ox1*dy2+ox2*dy2+dx2*oy1-dx2*oy2)/de; t2 = ( dx1*oy1-dx1*oy2-dy1*ox1+dy1*ox2)/de; return t1<s1.l[0] && t1>-s1.l[1] && t2<s2.l[0] && t2>-s2.l[1]; } int main() { const double SX = 800; const double SY = 800; const int N = 256; int i,j; static seed seeds[N]; std::vector<inter> inters; std::vector<inter>::iterator ii; for(i=0;i<N;++i) { seeds[i].p.x = drand()*SX; seeds[i].p.y = drand()*SY; seeds[i].a = PI*drand(); // ortho version: drand()>= 0.5 ? 0 : PI/2; seeds[i].l[0] = SX*10; seeds[i].l[1] = SX*10; } for(i=0;i<N-1;++i) for(j=i+1;j<N;++j) { double t1,t2; if(intersects(seeds[i],seeds[j],t1,t2)) { inters.push_back( inter(i,j,t1,t2) ); inters.push_back( inter(j,i,t2,t1) ); } } std::sort(inters.begin(),inters.end()); for(ii=inters.begin();ii!=inters.end();++ii) { // compute intersection on time if(ii->ti < seeds[ii->i].l[0] && ii->ti > -seeds[ii->i].l[1] && ii->tj < seeds[ii->j].l[0] && ii->tj > -seeds[ii->j].l[1]) { if( fabs(ii->ti) > fabs(ii->tj) ) { if(ii->ti>0) seeds[ii->i].l[0] = ii->ti; else seeds[ii->i].l[1] = -ii->ti; } } } for(i=0;i<N;++i) { // page clipping seed s; s.p.x = 0; s.p.y = 0; s.a = 0; s.l[0] = SX; s.l[1] = 0; double t1,t2; if(intersects(seeds[i],s,t1,t2)) { if(t1>0) seeds[i].l[0] = t1; else seeds[i].l[1] = -t1; } s.p.y = SY; if(intersects(seeds[i],s,t1,t2)) { if(t1>0) seeds[i].l[0] = t1; else seeds[i].l[1] = -t1; } s.p.x = 0; s.p.y = 0; s.l[0] = SY; s.l[1] = 0; s.a = PI/2; if(intersects(seeds[i],s,t1,t2)) { if(t1>0) seeds[i].l[0] = t1; else seeds[i].l[1] = -t1; } s.p.x = SX; if(intersects(seeds[i],s,t1,t2)) { if(t1>0) seeds[i].l[0] = t1; else seeds[i].l[1] = -t1; } } FILE * fo = fopen("gilbert.svg","w"); // output the results fprintf(fo, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.0\" width=\"%g\" height=\"%g\" id=\"%s\">\n" ,SX,SY,"girlbert" ); fprintf(fo,"<g style=\"stroke:#000000;stroke-width:2;stroke-linecap:round;fill:none\">\n"); for(i=0;i<N;++i){ fprintf(fo,"<line x1=\"%6.2f\" y1=\"%6.2f\" x2=\"%6.2f\" y2=\"%6.2f\"/>\n" ,seeds[i].p.x+seeds[i].l[0]*cos(seeds[i].a) ,seeds[i].p.y+seeds[i].l[0]*sin(seeds[i].a) ,seeds[i].p.x+seeds[i].l[1]*cos(seeds[i].a+PI) ,seeds[i].p.y+seeds[i].l[1]*sin(seeds[i].a+PI) ); } fprintf(fo,"</g>\n"); fprintf(fo,"</svg>\n"); fclose(fo); return 0; }