56#include "../2geom/orphan-code/intersection-by-smashing.cpp"
71 std::vector<Interval> xdoms =
level_set( df[
X], 0., tol);
72 std::vector<Interval> ydoms =
level_set( df[
Y], 0., tol);
73 std::vector<Interval> doms;
75 for (
unsigned i=0; i<xdoms.size(); i++ ){
77 for (
unsigned j=0; j<ydoms.size(); j++ ){
81 doms.push_back( *inter );
86 if (doms[0].
min() > 0 ){
91 for (
unsigned i=0; i<doms.size(); i++ ){
95 result.cuts.push_back( doms[i].middle() );
99 double t = ( i+1 == doms.size() )? 1 : doms[i+1].min();
100 result.cuts.push_back( t );
110std::vector<Interval>
intersect( std::vector<Interval>
const &a, std::vector<Interval>
const &b){
111 std::vector<Interval>
result;
113 for (
unsigned i=0; i < a.size(); i++){
114 for (
unsigned j=0; j < b.size(); j++){
129 double signx = ( f[
X].
at0() > f[
X].
at1() )? -1 : 1;
130 double signy = ( f[
Y].
at0() > f[
Y].
at1() )? -1 : 1;
134 top.
cuts.insert( top.
cuts.end(), 2);
138 bot.
cuts.insert( bot.
cuts.begin(), - 1 );
141 top +=
Point(-tol*signx, tol);
142 bot +=
Point( tol*signx, -tol);
146 top +=
Point( 0, 2*tol);
147 bot +=
Point( 0, -2*tol);
177 std::vector<Interval> x_in_reg =
level_set( f[
X], region[
X] );
178 std::vector<Interval> y_in_reg =
level_set( f[
Y], region[
Y] );
184 if ( f.
size() == 0 )
return;
185 f.
cuts.insert( f.
cuts.begin(), f.
cuts.front() - paddle_width );
187 f.
cuts.insert( f.
cuts.end(), f.
cuts.back() + paddle_width );
199 double tol,
cairo_t *cr ,
bool draw_more_stuff=
false ){
201 std::vector<std::pair<Interval, Interval> > res;
206 bool swapresult =
false;
207 bool swapcoord =
false;
209 if ( draw_more_stuff ){
210 cairo_set_line_width (cr, 3);
219 if ( !draw_more_stuff ){
222 if ( !abounds || !bbounds )
return res;
223 abounds->expandBy(tol);
233 if ( dbbounds->min().length() > dabounds->min().length() ){
236 swap( dabounds, dbbounds );
241 double dxmin = std::min(
abs((*dabounds)[
X].
max()),
abs((*dabounds)[
X].
min()) );
242 double dymin = std::min(
abs((*dabounds)[
Y].
max()),
abs((*dabounds)[
Y].
min()) );
243 if ( (*dabounds)[
X].
max()*(*dabounds)[
X].
min() < 0 ) dxmin=0;
244 if ( (*dabounds)[
Y].
max()*(*dabounds)[
Y].
min() < 0 ) dymin=0;
245 assert (dxmin>=0 && dymin>=0);
254 Interval x_range_strict( aa[
X].at0(), aa[
X].at1() );
263 if ( draw_more_stuff ){
270 unsigned h = ( swapcoord ) ?
Y :
X;
271 dbg_rgn[h].concat ( dbg_x );
272 dbg_rgn[h].concat ( dbg_side[
X] + dbg_x.
lastValue() );
273 dbg_rgn[h].concat (
reverse(dbg_x) );
274 dbg_rgn[h].concat ( dbg_side[
X] + dbg_x.
firstValue() );
276 dbg_rgn[1-h].concat ( bot_ay );
277 dbg_rgn[1-h].concat ( dbg_side[
Y] + bot_ay.
lastValue() );
278 dbg_rgn[1-h].concat (
reverse(top_ay) );
281 cairo_set_line_width (cr, 1.);
287 if ( swapcoord ) swap( bbb[
X], bbb[
Y] );
291 cairo_set_line_width (cr, 1.);
299 std::vector<Interval> bx_in_ax_range =
level_set(bb[
X], ax_range );
302 std::vector<Interval> tbs;
303 for (
unsigned i=0; i<bx_in_ax_range.size(); i++){
307 bb_in[
X].setDomain( bx_in_ax_range[i] );
308 bb_in[
Y].setDomain( bx_in_ax_range[i] );
312 h = bb_in[
Y] -
compose( top_ay, bb_in[
X] );
314 std::vector<Interval> rts_lo =
level_set( h, level);
315 h = bb_in[
Y] -
compose( bot_ay, bb_in[
X] );
317 std::vector<Interval> rts_hi =
level_set( h, level);
319 std::vector<Interval> rts =
intersect( rts_lo, rts_hi );
320 tbs.insert(tbs.end(), rts.begin(), rts.end() );
323 std::vector<std::pair<Interval, Interval> >
result(tbs.size(),std::pair<Interval,Interval>());
332 for (
unsigned j=0; j<tbs.size(); j++){
333 result[j].second = tbs[j];
334 std::vector<Interval> tas;
344 h = top_b[
Y] -
compose( fat_y_of_x, top_b[
X] );
346 std::vector<Interval> rts_top =
level_set( h, level);
347 for (
unsigned idx=0; idx < rts_top.size(); idx++){
348 rts_top[idx] =
Interval( top_b[
X].valueAt( rts_top[idx].
min() ),
349 top_b[
X].valueAt( rts_top[idx].
max() ) );
351 assert( rts_top.size() == 1 );
353 h = bot_b[
Y] -
compose( fat_y_of_x, bot_b[
X] );
355 std::vector<Interval> rts_bot =
level_set( h, level);
356 for (
unsigned idx=0; idx < rts_bot.size(); idx++){
357 rts_bot[idx] =
Interval( bot_b[
X].valueAt( rts_bot[idx].
min() ),
358 bot_b[
X].valueAt( rts_bot[idx].
max() ) );
360 assert( rts_bot.size() == 1 );
364 printf(
"range(bbj[X]) = [%f, %f]; tol= %f\n", bbj[
X].at0(), bbj[
X].at1(), tol);
366 printf(
"rts_top = ");
367 for (
unsigned dbgi=0; dbgi<rts_top.size(); dbgi++){
368 printf(
"[%f,%f]U", rts_top[dbgi].
min(), rts_top[dbgi].
max() );
371 printf(
"rts_bot = ");
372 for (
unsigned dbgi=0; dbgi<rts_bot.size(); dbgi++){
373 printf(
"[%f,%f]U", rts_bot[dbgi].
min(), rts_bot[dbgi].
max() );
379 printf(
"intersection = ");
380 for (
unsigned dbgi=0; dbgi<rts_top.size(); dbgi++){
381 printf(
"[%f,%f]U", rts_top[dbgi].
min(), rts_top[dbgi].
max() );
385 if (rts_top.size() != 1){
386 printf(
"!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!\n");
387 rts_top[0].unionWith( rts_top[1] );
391 assert (rts_top.size() == 1);
394 if ( x_dom.
max() <= x_range_strict.
min() ){
395 tas.push_back(
Interval ( ( aa[
X].at0() < aa[
X].at1() ) ? 0 : 1 ) );
396 }
else if ( x_dom.
min() >= x_range_strict.
max() ){
397 tas.push_back(
Interval ( ( aa[
X].at0() < aa[
X].at1() ) ? 1 : 0 ) );
403 if ( tas.size() != 1 ){
404 printf(
"Error: preimage of [%f, %f] by x:[0,1]->[%f, %f] is ",
405 x_dom.
min(), x_dom.
max(), x_range_strict.
min(), x_range_strict.
max());
406 if ( tas.size() == 0 ){
409 printf(
"\n [%f,%f]", tas[0].
min(), tas[0].
max() );
410 for (
unsigned toto=1; toto<tas.size(); toto++){
411 printf(
" U [%f,%f]", tas[toto].
min(), tas[toto].
max() );
416 assert( tas.size()==1 );
417 result[j].first = tas.front();
421 for (
unsigned i=0; i<
result.size(); i++){
432class Intersector :
public Toy
435 void draw(
cairo_t *cr, std::ostringstream *notify,
436 int width,
int height,
bool save, std::ostringstream *timer_stream)
override
441 cairo_set_line_width (cr, .8);
447 Rect tolbytol( anchor.pos, anchor.pos );
448 tolbytol.expandBy( tol );
463 for (
unsigned i=0; i<Acuts.size(); i++){
465 cairo_set_line_width (cr, .2);
469 for (
unsigned j=0; j<Bcuts.size(); j++){
470 std::vector<std::pair<Interval, Interval> > my_intersections;
472 cairo_set_line_width (cr, .2);
480 std::vector<SmashIntersection> my_intersections;
483 for (
auto & my_intersection : my_intersections){
484 cairo_set_line_width (cr, 2.5);
488 cairo_set_line_width (cr, 2.5);
495 unsigned apiece( slidera.value()/100. * Acuts.size() );
496 unsigned bpiece( sliderb.value()/100. * Bcuts.size() );
499 for (
unsigned i=0; i<Acuts.size(); i++){
501 for (
unsigned j=0; j<Bcuts.size(); j++){
502 if ( toggle.on && (i != apiece || j != bpiece) )
continue;
504 std::vector<SmashIntersection> my_intersections;
506 bool draw_more = toggle.on && i == apiece && j == bpiece;
510 for (
unsigned k=0; k<my_intersections.size(); k++){
511 cairo_set_line_width (cr, 2.5);
515 cairo_set_line_width (cr, 2.5);
527 Intersector(
unsigned int _A_bez_ord,
unsigned int _B_bez_ord)
528 : A_bez_ord(_A_bez_ord), B_bez_ord(_B_bez_ord)
530 unsigned int total_handles = A_bez_ord + B_bez_ord;
531 for (
unsigned int i = 0; i < total_handles; ++i )
534 slider =
Slider(-4, 2, 0, 1.2,
"tolerance");
535 slider.geometry(
Point(30, 20), 250);
538 slidera =
Slider(0, 100, 1, 0.,
"piece on A");
539 slidera.geometry(
Point(300, 50), 250);
541 sliderb =
Slider(0, 100, 1, 0.,
"piece on B");
542 sliderb.geometry(
Point(300, 80), 250);
551 unsigned int A_bez_ord;
552 unsigned int B_bez_ord;
555 Slider slider,slidera,sliderb;
562 unsigned int A_bez_ord=4;
563 unsigned int B_bez_ord=4;
565 sscanf(argv[2],
"%d", &B_bez_ord);
567 sscanf(argv[1],
"%d", &A_bez_ord);
569 init( argc, argv,
new Intersector(A_bez_ord, B_bez_ord));
Path - a sequence of contiguous curves.
Conversion between Bezier control points and SBasis curves.
Adaptor that creates 2D functions from 1D ones.
Point valueAt(double t) const
bool intersects(CRect const &r) const
Check whether the rectangles have any common points.
Range of real numbers that is never empty.
Function that interpolates linearly between two values.
Range of real numbers that can be empty.
Axis-aligned rectangle that can be empty.
Function defined as discrete pieces.
void offsetDomain(double o)
output_type lastValue() const
std::vector< double > cuts
output_type firstValue() const
void setDomain(Interval dom)
Two-dimensional point that doubles as a vector.
Axis aligned, non-empty rectangle.
Polynomial in symmetric power basis.
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.
constexpr Coord infinity()
Get a value representing infinity.
static double exp_rescale(double x)
Various utility functions.
D2< Piecewise< SBasis > > make_cuts_independent(Piecewise< D2< SBasis > > const &a)
OptInterval bounds_exact(Bezier const &b)
Bezier reverse(const Bezier &a)
MultiDegree< n > max(MultiDegree< n > const &p, MultiDegree< n > const &q)
Returns the maximal degree appearing in the two arguments for each variables.
static void computeLinfinityNeighborhood(D2< SBasis > const &f, double tol, D2< Piecewise< SBasis > > &topside, D2< Piecewise< SBasis > > &botside)
std::vector< SmashIntersection > smash_intersect(D2< SBasis > const &a, D2< SBasis > const &b, double tol)
static void prolongateByConstants(Piecewise< SBasis > &f, double paddle_width)
D2< T > compose(D2< T > const &a, T const &b)
std::vector< SmashIntersection > monotonic_smash_intersect(D2< SBasis > const &a, D2< SBasis > const &b, double tol)
Bezier portion(const Bezier &a, double from, double to)
D2< SBasis > handles_to_sbasis(T const &handles, unsigned order)
Bezier derivative(Bezier const &a)
Piecewise< SBasis > pw_compose_inverse(SBasis const &f, SBasis const &g, unsigned order, double zero)
Piecewise< SBasis > min(SBasis const &f, SBasis const &g)
Return the more negative of the two functions pointwise.
std::vector< Interval > monotonicSplit(D2< SBasis > const &p)
OptInterval bounds_fast(Bezier const &b)
std::vector< Point > intersect(const xAx &C1, const xAx &C2)
std::vector< Interval > level_set(D2< SBasis > const &f, Rect region)
Point abs(Point const &b)
void cairo_rectangle(cairo_t *cr, Geom::Rect const &r)
void draw_cross(cairo_t *cr, Geom::Point h)
void cairo_d2_pw_sb(cairo_t *cr, Geom::D2< Geom::Piecewise< Geom::SBasis > > const &p)
void cairo_d2_sb(cairo_t *cr, Geom::D2< Geom::SBasis > const &p)
two-dimensional geometric operators.
Polynomial in symmetric power basis (S-basis)
Piecewise< D2< SBasis > > linearizeCusps(D2< SBasis > f, double tol)
std::string exp_formatter(double x)
static double exp_rescale(double x)
void cairo_set_source_rgba(cairo_t *cr, colour c)
std::string default_formatter(double x)
void init(int argc, char **argv, Toy *t, int width=600, int height=600)