Blob Blame Raw

#include <GL/gl.h>

#include "raster.h"


void Raster::touch(const Painter &painter, const Vector2 &position, int index, TouchPointList &points) {
    Vector2 rxy = painter.get_radius_xy();
    rxy.x = fabs(rxy.x) + 0.52;
    rxy.y = fabs(rxy.y) + 0.52;
    
    int x0, x1, y0, y1;
    if (rxy.x < width) { // to handle values greater than INT_MAX
        x0 = std::max(0     , (int)ceil(position.x - rxy.x));
        x1 = std::min(width , (int)ceil(position.x + rxy.x));
    } else {
        x0 = 0; x1 = width;
    }
    if (rxy.y < height) {
        y0 = std::max(0     , (int)ceil(position.y - rxy.y));
        y1 = std::min(height, (int)ceil(position.y + rxy.y));
    } else {
        y0 = 0; y1 = height;
    }
    
    for(int iy = y0; iy < y1; ++iy) {
        for(int ix = x0; ix < x1; ++ix) {
            Vector2 v(
                std::max(0.0, fabs(ix - position.x) - 0.51),
                std::max(0.0, fabs(iy - position.y) - 0.51) );
            Real h = painter.get_height_xy(v);
            Real &pixel = (*this)[iy][ix];
            if (pixel > h) {
                points.push_back( TouchPoint(index, iy, ix, pixel, h) );
                pixel = h;
            }
        }
    }
}


Vector4 FlatRaster::color_by_distance(Real d) const {
    Real dv = max_value - min_value;
    Real k = fabs(dv) < 1e-5 ? 0 : (d - min_value)/dv;
    return Vector4(
        1 - k,
        1 - 2*fabs(0.5 - k),
        k,
        0.5 );
}

void FlatRaster::draw() const
{
    int w = raster.get_width();
    int h = raster.get_height();
    if (w < 2 || h < 2) return;

    Vector3 v, v0, v1;
    
    Real kx = (x1 - x0)/w;
    Real ky = (y1 - y0)/h;

    glEnable(GL_LIGHTING);
    
    glBegin(GL_TRIANGLE_STRIP);
    for(int r = 1; r < h; ++r) {
        v0.y = y0 + (r - 1)*ky;
        v1.y = y0 + r*ky;
        for(int c = 0; c < w; ++c) {
            v0.x = v1.x = x0 + c*kx;
            v0.z = raster[r-1][c];
            v1.z = raster[r][c];
            
            if (r == 1 && c == 0) v = v0;
            
            Vector3 dv0(v0.x - v.x, v0.y - v.y, v0.z - v.z);
            Vector3 dv1(v1.x - v.x, v1.y - v.y, v1.z - v.z);
            Vector3 norm(
                dv0.y*dv1.z - dv0.z*dv1.y,
                dv0.z*dv1.x - dv0.x*dv1.z,
                dv0.x*dv1.y - dv0.y*dv1.x );
            Real l = sqrt(norm.x*norm.x + norm.y*norm.y + norm.z*norm.z);
            l = l > 1e-5 ? 1/l : 0;
            glNormal3d(norm.x*l, norm.y*l, norm.z*l);

            if (!c) glVertex3dv(v0.c);
            glColor4dv(color_by_distance(v0.z).c);
            glVertex3dv(v0.c);
            glColor4dv(color_by_distance(v1.z).c);
            glVertex3dv(v1.c);
            v = v1;
        }
        glVertex3dv(v.c);
    }
    glEnd();
    
    glDisable(GL_LIGHTING);
}


Vector4 PolarRaster::color_by_distance(Real d) const {
    Real dv = max_value - min_value;
    Real k = fabs(dv) < 1e-5 ? 0 : (d - min_value)/dv;
    return Vector4(
        1 - k,
        1 - 2*fabs(0.5 - k),
        k,
        0.5 );
}

void PolarRaster::draw() const
{
    int w = raster.get_width();
    int h = raster.get_height();
    if (w < 2 || h < 2) return;

    Vector3 v, v0, v1;
    
    Real kx = (x1 - x0)/w;
    Real ka = 2*M_PI/h;

    glEnable(GL_LIGHTING);
    
    glBegin(GL_TRIANGLE_STRIP);
    for(int r = 0; r < h; ++r) {
        int rr = r ? r-1 : h-1;
        Real a0 = rr*ka;
        Real a1 = r*ka;
        Real s0 = sin(a0), s1 = sin(a1);
        Real c0 = cos(a0), c1 = cos(a1);
        for(int c = 0; c < w; ++c) {
            v0.x = v1.x = x0 + c*kx;
            Real r0 = raster[rr][c];
            Real r1 = raster[r][c];
            v0.y = -s0*r0, v0.z = c0*r0;
            v1.y = -s1*r1, v1.z = c1*r1;
            
            Vector3 dv0(v0.x - v.x, v0.y - v.y, v0.z - v.z);
            Vector3 dv1(v1.x - v.x, v1.y - v.y, v1.z - v.z);
            Vector3 norm(
                dv0.y*dv1.z - dv0.z*dv1.y,
                dv0.z*dv1.x - dv0.x*dv1.z,
                dv0.x*dv1.y - dv0.y*dv1.x );
            Real l = sqrt(norm.x*norm.x + norm.y*norm.y + norm.z*norm.z);
            l = l > 1e-5 ? 1/l : 0;
            glNormal3d(norm.x*l, norm.y*l, norm.z*l);

            if (!c) glVertex3dv(v0.c);
            glColor4dv(color_by_distance(r0).c);
            glVertex3dv(v0.c);
            glColor4dv(color_by_distance(r0).c);
            glVertex3dv(v1.c);
            v = v1;
        }
        glVertex3dv(v.c);
    }
    glEnd();
    
    glDisable(GL_LIGHTING);
}