#include <2geom/basic-intersection.h> #include <2geom/d2.h> #include <2geom/sbasis.h> #include <2geom/bezier-to-sbasis.h> #include <2geom/path-intersection.h> #include #include using std::vector; using namespace Geom; class PairIntersect: public Toy { PointSetHandle A_handles; PointSetHandle B_handles; std::vector toggles; void mouse_pressed(GdkEventButton* e) override { toggle_events(toggles, e); Toy::mouse_pressed(e); } void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override { draw_toggles(cr, toggles); cairo_save(cr); cairo_set_source_rgba(cr, 0, 0, 0, 1.0); cairo_set_line_width (cr, 0.5); D2 A = A_handles.asBezier(); cairo_d2_sb(cr, A); cairo_stroke(cr); cairo_set_source_rgba(cr, 0.0, 0, 0.8, 1.0); cairo_set_line_width (cr, 0.5); D2 B = B_handles.asBezier(); cairo_d2_sb(cr, B); cairo_stroke(cr); cairo_save(cr); cairo_set_source_rgba(cr, 0, 0, 0, 1.0); cairo_set_line_width (cr, 0.5); SBasis crs (cross(A - A(0), derivative(A))); crs = shift(crs*Linear(-1, 0)*Linear(-1, 0), -2); crs = crs * (300/(*bounds_exact(crs)).extent()); vector rts = roots(crs); for(double t : rts) { cairo_move_to(cr, A(0)); cairo_line_to(cr, A(t)); cairo_stroke(cr); } cairo_restore(cr); cairo_move_to(cr, 0, 300); cairo_line_to(cr, width, 300); crs += 300; D2 are_graph(SBasis(Linear(0, width)), crs ); cairo_save(cr); cairo_d2_sb(cr, are_graph); cairo_set_line_width (cr, .5); cairo_set_source_rgba (cr, 0., 0., 0., 1); cairo_stroke(cr); cairo_restore(cr); Path PB; PB.append(B); Path PA; PA.append(A); if (toggles[0].on) { PathVector ps; ps.push_back(PA); ps.push_back(PB); CrossingSet cs = crossings_among(ps); *notify << "total intersections: " << cs.size() << '\n'; cairo_stroke(cr); cairo_set_source_rgba (cr, 1., 0., 0, 0.8); for(unsigned i = 0; i < cs.size(); i++) { Crossings section = cs[i]; *notify << "section " << i << ": " << section.size() << '\n'; for(auto & j : section) { draw_handle(cr, A(j.ta)); *notify << Geom::distance(A(j.ta), B(j.tb)) << std::endl; } } cairo_stroke(cr); } else { vector Ab = A_handles.pts, Bb = B_handles.pts; std::vector > section; find_intersections( section, A, B); std::vector > polished_section = section; *notify << "total intersections: " << section.size(); polish_intersections( polished_section, A, B); cairo_stroke(cr); cairo_set_source_rgba (cr, 1., 0., 0, 0.8); for(unsigned i = 0; i < section.size(); i++) { draw_handle(cr, A(section[i].first)); *notify << Geom::distance(A(section[i].first), B(section[i].second)) << " polished " << Geom::distance(A(polished_section[i].first), B(polished_section[i].second)) << std::endl; } cairo_stroke(cr); } cairo_restore(cr); Toy::draw(cr, notify, width, height, save,timer_stream); } public: PairIntersect (unsigned A_bez_ord, unsigned B_bez_ord) { toggles.emplace_back("Path", true); toggles[0].bounds = Rect(Point(10,100), Point(100, 130)); //toggles.push_back(Toggle("Curve", true)); //toggles[1].bounds = Rect(Point(10,130), Point(100, 160)); handles.push_back(&A_handles); handles.push_back(&B_handles); A_handles.name = "A"; B_handles.name = "B"; for(unsigned i = 0; i < A_bez_ord; i++) A_handles.push_back(uniform()*400, uniform()*400); for(unsigned i = 0; i < B_bez_ord; i++) B_handles.push_back(uniform()*400, uniform()*400); } }; int main(int argc, char **argv) { unsigned A_bez_ord=10; unsigned B_bez_ord=3; if(argc > 2) sscanf(argv[2], "%d", &B_bez_ord); if(argc > 1) sscanf(argv[1], "%d", &A_bez_ord); init(argc, argv, new PairIntersect(A_bez_ord, B_bez_ord)); return 0; } /* Local Variables: mode:c++ c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :