Drawing pen-data


#1

I’m trying to draw data from a Wacom pen.

If I make each Datapoint a circle (radius proportional to pressure), it looks okay if I write slowly, but if I write at normal speed it starts to look like a bunch of circles rather than a smooth line.

What I’ve done is consider the set of points as the backbone, and between points k and k+1 I first get the midpoint, then I extend a positive and negative perpendicular (the length depending on the pressure). And construct a path from these points.

It is really ugly, but it kind of works:

    float x(int i) { return getWidth() * inkling.penData[i].x / 1920.f; };
    float y(int i) { return getHeight() * inkling.penData[i].y / 1920.f; };

    void drawStroke(Graphics& g, int start, int end) {
        if (end-start < 5)
            return;
        
        using PointF = Point<float>;
        
        std::vector<PointF> pts;
        for(int i=start; i<=end; ++i)
            pts.push_back(PointF(x(i),y(i)));
        
        // smooth data
        for(int i=1;            i < pts.size(); ++i) pts[i] = 0.5f * pts[i-1] + .5f * pts[i];
        for(int i=pts.size()-2; i >= 0;         --i) pts[i] = 0.5f * pts[i+1] + .5f * pts[i];

        std::vector<float> widths;
        for(int i=start; i<=end; ++i)
            widths.push_back(inkling.penData[i].pressure / 1023.f);
        
        // smooth data
        for(int i=1;            i < widths.size(); ++i) widths[i] = 0.5f * widths[i-1] + .5f * widths[i];
        for(int i=widths.size()-2; i >= 0;         --i) widths[i] = 0.5f * widths[i+1] + .5f * widths[i];
        
        
        std::vector<PointF> A, B;
        
        for(int i=0; i < pts.size()-1; ++i) {
            auto seg = pts[i+1] - pts[i];
            auto normal = PointF(seg.y, -seg.x);
            auto unitNormal = normal / normal.getDistanceFromOrigin();

            auto center = pts[i] + .5f * seg;
            
            float thickness = (widths[i] + widths[i+1]) / 2.f;
            thickness *= 1.f;
            
            A.push_back( center + thickness * unitNormal );
            B.push_back( center - thickness * unitNormal );
        }
        
        Path path;
        
        path.startNewSubPath(A[0]);
        for(int i=1; i<A.size(); ++i)
            path.lineTo(A[i]);
        for(int i=B.size()-1; i>=0; --i)
            path.lineTo(B[i]);
        path.closeSubPath();
                
        g.setColour(Colours::blue);
        g.fillPath(path);
    }
    
    void paint (Graphics& g) override
    {
        g.setColour(Colour(255, 245, 200));
        g.fillAll (Colour(255, 245, 200));

        
        auto& D = inkling.penData;
        
        int strokeStart = 0;
        while(true) {
            while(strokeStart < D.size() && D[strokeStart].pressure == 0.f)
                ++strokeStart;
            
            if(strokeStart == D.size())
                break;
            
            int strokeEnd = strokeStart;
            while(strokeEnd < D.size() && D[strokeEnd].pressure > 0.f)
                ++strokeEnd;
            --strokeEnd;
            
            drawStroke(g, strokeStart, strokeEnd);
            
            strokeStart = strokeEnd+1;
        };

…produces…

Can anyone see a better way of doing it?

My thinking is that it must be really inefficient, I bet it would be much more efficient to generate a triangle strip. But that could end up being pages of GL code.

I like the idea of drawing to an embedded HTML 5 canvas, then I can leverage D3 and friends, and get GL at a fraction of the code complexity. The main problem is: how to communicate between JavaScript and C++. Can anyone see a way through?

π


#2

I find the subject of html5 integration very interesting !

I also have few javascript code i’d like to make communicate with my C source :
D3.js is really nice to draw interactive data graphics,
SlickGrid is a nice fast editable gridview,
and drawing Gantt Charts with JqGantt is really cool.

maybe trough *.json serialization lib or just some *.json data files you could accomplish some communication?

But Function Calling from JS code to C seems difficult to me (mean call a C function in JS).
I also wonder about JS code execution speed compared to C code

Keep Me tuned with your work on HTML5 canvas!
Regards,
Jerome


#3

I’d take a look at V8 or SpiderMonkey for JavaScript integration.