26struct LevelCrossingOrder {
27 bool operator()(LevelCrossing a, LevelCrossing b) {
28 return a.pt[
Y] < b.pt[
Y];
34class LevelsCrossings:
public std::vector<LevelCrossings>{
36 LevelsCrossings():std::vector<LevelCrossings>(){};
37 LevelsCrossings(std::vector<std::vector<double> >
const ×,
40 for (
const auto & time : times){
42 for (
double j : time){
50 std::sort(lcs.begin(), lcs.end(), LevelCrossingOrder());
56 for (
unsigned i=0; i<
size(); i++){
57 for (
auto & j : (*this)){
62 void findFirstUnused(
unsigned &level,
unsigned &idx){
65 for (
unsigned i=0; i<
size(); i++){
66 for (
unsigned j=0; j<(*this)[i].size(); j++){
67 if (!(*
this)[i][j].used){
81 void step(
unsigned &level,
unsigned &idx,
int &direction){
82 std::cout <<
"Entering step: "<<level<<
","<<idx<<
", dir="<< direction<<
"\n";
84 if ( direction % 2 == 0 ){
86 if ( idx >= (*
this)[level].
size()-1 || (*
this)[level][idx+1].
used ) {
88 std::cout <<
"max end of level reached...\n";
93 if ( idx <= 0 || (*
this)[level][idx-1].
used ) {
95 std::cout <<
"min end of level reached...\n";
101 std::cout <<
"exit with: "<<level<<
","<<idx<<
", dir="<< direction<<
"\n";
104 double t = (*this)[level][idx].t;
105 double sign = ((*this)[level][idx].sign ? 1 : -1);
108 direction = (direction + 1)%4;
109 if (level ==
size()){
110 std::cout <<
"max level reached\n";
113 for (
unsigned j=0; j<(*this)[level].size(); j++){
114 double tj = (*this)[level][j].t;
115 if (
sign*(tj-t) > 0 ){
116 if( next_t == t ||
sign*(tj-next_t)<0 ){
124 std::cout <<
"no next time found\n";
129 if ( (*
this)[level][idx].
used ) {
131 std::cout <<
" reached a point already used\n";
134 std::cout <<
"exit with: "<<level<<
","<<idx<<
"\n";
147 std::vector<double>
result;
151 while (x<domain.
max()){
153 double rdm = 1+ ( (rand() % 100) - 50) /100.*randomness;
166 std::vector<Point>
result;
173 std::vector<double> levels =
generateLevels((*range), dy, growth, rdmness);
174 std::vector<std::vector<double> > times;
179 std::vector<std::vector<double> > cleaned_times(levels.size(),std::vector<double>());
180 for (
unsigned i=0; i<times.size(); i++){
181 if ( times[i].
size()>0 ){
182 double last_t = times[i][0]-1;
183 for (
unsigned j=0; j<times[i].size(); j++){
184 if (times[i][j]-last_t >0.000001){
185 last_t = times[i][j];
186 cleaned_times[i].push_back(last_t);
191 times = cleaned_times;
192 for (
unsigned i=0; i<times.size(); i++){
193 std::cout <<
"roots on level "<<i<<
": ";
194 for (
double j : times){
195 std::cout << j <<
" ";
200 LevelsCrossings lscs(times,f,dx);
202 lscs.findFirstUnused(i,j);
203 while ( i < lscs.size() ){
205 while ( i < lscs.size() ){
206 result.push_back(lscs[i][j].pt);
207 lscs[i][j].used =
true;
213 lscs.findFirstUnused(i,j);
222 double scale_bf = 1,
double scale_bb = 1,
223 double scale_tf = 1,
double scale_tb = 1){
234 Point new_pt = (pt0+pt1)/2;
235 double scale = (is_top ? scale_tf : scale_bf );
241 scale = (is_top ? scale_tb : scale_bb );
242 last_hdle = new_pt+(pt1-new_pt)*
scale;
264class HatchesToy:
public Toy {
272 std::ostringstream *notify,
273 int width,
int height,
bool save, std::ostringstream *timer_stream)
override {
274 for(
unsigned i=0; i<NB_SLIDER; i++){
275 adjuster[i].
pos[
X] = 30+i*20;
276 if (adjuster[i].pos[
Y]<100) adjuster[i].
pos[
Y] = 100;
277 if (adjuster[i].pos[
Y]>400) adjuster[i].
pos[
Y] = 400;
280 cairo_set_line_width (cr, .5);
284 double hatch_width = (400-adjuster[0].
pos[
Y])/300.*50;
285 double scale_topfront = (250-adjuster[1].
pos[
Y])/150.*5;
286 double scale_topback = (250-adjuster[2].
pos[
Y])/150.*5;
287 double scale_botfront = (250-adjuster[3].
pos[
Y])/150.*5;
288 double scale_botback = (250-adjuster[4].
pos[
Y])/150.*5;
289 double growth = 1+(250-adjuster[5].
pos[
Y])/150.*.1;
290 double rdmness = 1+(400-adjuster[6].
pos[
Y])/300.*.9;
291 double bend_amount = (250-adjuster[7].
pos[
Y])/300.*100.;
293 b1_handle.
pts.back() = b2_handle.
pts.front();
294 b1_handle.
pts.front() = b2_handle.
pts.back();
300 cairo_set_line_width(cr, 0.3);
301 cairo_set_source_rgb(cr, 0, 0, 0);
316 std::vector<Point> snakePoints;
317 snakePoints =
linearSnake(bentB, hatch_width, growth, rdmness);
324 smthSnake =
bend(smthSnake, -bending);
326 cairo_set_line_width (cr, 1.5);
330 if ( snakePoints.size() > 0 ){
331 Path snake(snakePoints.front());
332 for (
unsigned i=1; i<snakePoints.size(); i++){
339 cairo_set_line_width (cr, .5);
349 for(
int i = 0; i <
SIZE; i++) {
365 for(
unsigned i = 0; i < NB_SLIDER; i++) {
367 handles.push_back(&(adjuster[i]));
372int main(
int argc,
char **argv) {
373 init(argc, argv,
new HatchesToy);
Conversion between Bezier control points and SBasis curves.
static int constexpr SIZE
Bezier curve with compile-time specified order.
Adaptor that creates 2D functions from 1D ones.
Range of real numbers that is never empty.
Function that interpolates linearly between two values.
Range of real numbers that can be empty.
Sequence of contiguous curves, aka spline.
Function defined as discrete pieces.
output_type valueAt(double t) const
void continuousConcat(const Piecewise< T > &other)
void concat(const Piecewise< T > &other)
void setDomain(Interval dom)
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.
std::vector< double > generateLevels(Interval const &domain, double const width, double const growth, double randomness)
std::vector< LevelCrossing > LevelCrossings
Piecewise< D2< SBasis > > bend(Piecewise< D2< SBasis > > const &f, Piecewise< SBasis > bending)
Piecewise< D2< SBasis > > smoothSnake(std::vector< Point > const &linearSnake, double scale_bf=1, double scale_bb=1, double scale_tf=1, double scale_tb=1)
std::vector< Point > linearSnake(Piecewise< D2< SBasis > > const &f, double dy, double growth, double rdmness)
Various utility functions.
D2< Piecewise< SBasis > > make_cuts_independent(Piecewise< D2< SBasis > > const &a)
OptInterval bounds_exact(Bezier const &b)
static float sign(double number)
Returns +1 for positive numbers, -1 for negative numbers, and 0 otherwise.
Piecewise< D2< SBasis > > sectionize(D2< Piecewise< SBasis > > const &a)
SBasisOf< T > shift(SBasisOf< T > const &a, int sh)
D2< T > compose(D2< T > const &a, T const &b)
Bezier derivative(Bezier const &a)
std::vector< std::vector< double > > multi_roots(SBasis const &f, std::vector< double > const &levels, double htol=1e-7, double vtol=1e-7, double a=0, double b=1)
void cairo_line_to(cairo_t *cr, Geom::Point p1)
void cairo_move_to(cairo_t *cr, Geom::Point p1)
void cairo_d2_sb(cairo_t *cr, Geom::D2< Geom::SBasis > const &p)
void cairo_pw_d2_sb(cairo_t *cr, Geom::Piecewise< Geom::D2< Geom::SBasis > > const &p)
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)