summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/2geom/src/toys/offset-toy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/2geom/src/toys/offset-toy.cpp')
-rw-r--r--src/3rdparty/2geom/src/toys/offset-toy.cpp156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/3rdparty/2geom/src/toys/offset-toy.cpp b/src/3rdparty/2geom/src/toys/offset-toy.cpp
new file mode 100644
index 0000000..4b3e617
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/offset-toy.cpp
@@ -0,0 +1,156 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/sbasis-math.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/path-intersection.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <sstream>
+
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+// TODO:
+// use path2
+// replace Ray stuff with path2 line segments.
+
+//-----------------------------------------------
+
+static void
+plot_offset(cairo_t* cr, D2<SBasis> const &M,
+ Coord offset = 10,
+ unsigned NbPts = 10){
+ D2<SBasis> dM = derivative(M);
+ for (unsigned i = 0;i < NbPts;i++){
+ double t = i*1./NbPts;
+ Point V = dM(t);
+ V = offset*rot90(unit_vector(V));
+ draw_handle(cr, M(t)+V);
+ }
+}
+
+static void plot(cairo_t* cr, Piecewise<SBasis> const &f,double vscale=1){
+ D2<Piecewise<SBasis> > plot;
+ plot[1]=-f*vscale;
+ plot[1]+=450;
+
+ plot[0].cuts.push_back(f.cuts.front());
+ plot[0].cuts.push_back(f.cuts.back());
+ plot[0].segs.emplace_back(Linear(150,450));
+
+ for (unsigned i=1; i<f.size(); i++){
+ double t=f.cuts[i],ft=f.segs[i].at0();
+ cairo_move_to(cr, Point(150+t*300, 450));
+ cairo_line_to(cr, Point(150+t*300, 450-ft*vscale));
+ }
+ cairo_d2_pw_sb(cr, plot);
+}
+
+
+
+class OffsetTester: public Toy {
+ PointSetHandle psh;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ D2<SBasis> B = psh.asBezier();
+ *notify << "Curve offset:" << endl;
+ *notify << " -blue: pointwise plotted offset," << endl;
+ *notify << " -red: rot90(unitVector(derivative(.)))+rays at cut" << endl;
+ *notify << " -gray: cos(atan2),sin(atan2)" << endl;
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ Coord offset = -100;
+ plot_offset(cr,B,offset,11);
+ cairo_set_source_rgba (cr, 0, 0, 1, 1);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba (cr, 0.5, 0.2, 0., 0.8);
+ Piecewise<D2<SBasis> > n = rot90(unitVector(derivative(B)));
+ Piecewise<D2<SBasis> > offset_curve = Piecewise<D2<SBasis> >(B)+n*offset;
+ PathVector offset_path = path_from_piecewise(offset_curve, 0.1);
+
+ cairo_path(cr, offset_path);
+ cairo_stroke(cr);
+ for(const auto & pi : offset_path) {
+ Crossings cs = self_crossings(pi);
+ for(auto & c : cs) {
+ draw_cross(cr, pi.pointAt(c.ta));
+ std::stringstream s;
+ Point Pa = pi.pointAt(c.ta);
+ Point Pb = pi.pointAt(c.tb);
+ s << L1(Pa - Pb) << std::endl;
+ std::string ss = s.str();
+ draw_text(cr, Pa+Point(3,3), ss.c_str(), false, "Serif 6");
+
+ }
+ }
+
+ for(unsigned i = 0; i < n.size()+1;i++){
+ Point ptA=B(n.cuts[i]), ptB;
+ if (i==n.size())
+ ptB=ptA+n.segs[i-1].at1()*offset;
+ else
+ ptB=ptA+n.segs[i].at0()*offset;
+ cairo_move_to(cr,ptA);
+ cairo_line_to(cr,ptB);
+ cairo_set_source_rgba (cr, 1, 0, 0, 1);
+ cairo_stroke(cr);
+ }
+
+ Piecewise<SBasis> alpha = atan2(derivative(B),1e-2,3);
+ plot(cr,alpha,75/M_PI);
+
+ Piecewise<D2<SBasis> >n2 = sectionize(D2<Piecewise<SBasis> >(sin(alpha),cos(alpha)));
+ cairo_pw_d2_sb(cr,Piecewise<D2<SBasis> >(B)+n2*offset*.9);
+ cairo_set_source_rgba (cr, 0.5, 0.2, 0.5, 0.8);
+ cairo_stroke(cr);
+
+ Piecewise<SBasis> k = curvature(B);
+ cairo_pw_d2_sb(cr,Piecewise<D2<SBasis> >(B)+k*n*100);
+ cairo_set_source_rgba (cr, 0.5, 0.2, 0.5, 0.8);
+ cairo_stroke(cr);
+
+ *notify << "Total length: " << length(B) << endl;
+ *notify << "(nb of cuts of unitVector: " << n.size()-1 << ")" << endl;
+ *notify << "(nb of cuts of cos,sin(atan2): " << n2.size()-1 << ")" << endl;
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ OffsetTester(int order) {
+ handles.push_back(&psh);
+ for(int i = 0; i < order; i++)
+ psh.push_back(200+50*i,300+70*uniform());
+ }
+};
+
+int main(int argc, char **argv) {
+ int A_bez_ord = 6;
+ if(argc > 1)
+ sscanf(argv[1], "%d", &A_bez_ord);
+ init(argc, argv, new OffsetTester(A_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:encoding = utf-8:textwidth = 99 :
+
+