#define PERL_NO_GET_CONTEXT #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #define XX 0 #define YY 1 MODULE = Algorithm::Line::Lerp PACKAGE = Algorithm::Line::Lerp SV * bline(SV* sp1, SV* sp2) PROTOTYPE: $$ PREINIT: AV* ap1; AV* ap2; AV* theline; AV* point; long x0, y0, x1, y1, dx, dy, sx, sy, err, e2; CODE: if (!(SvROK(sp1) && SvTYPE(SvRV(sp1)) == SVt_PVAV)) croak("p1 must be array reference"); ap1 = (AV*)SvRV(sp1); if (av_count(ap1) != 2) croak("p1 must only have two elements"); if (!(SvROK(sp2) && SvTYPE(SvRV(sp2)) == SVt_PVAV)) croak("p2 must be array reference"); ap2 = (AV*)SvRV(sp2); if (av_count(ap2) != 2) croak("p2 must only have two elements"); x0 = SvIV(*av_fetch(ap1, XX, 0)); y0 = SvIV(*av_fetch(ap1, YY, 0)); x1 = SvIV(*av_fetch(ap2, XX, 0)); y1 = SvIV(*av_fetch(ap2, YY, 0)); dx = labs(x1 - x0); dy = labs(y1 - y0); sx = x0 < x1 ? 1 : -1; sy = y0 < y1 ? 1 : -1; err = (dx > dy ? dx : -dy) / 2; theline = newAV(); while (1) { point = newAV_alloc_x(2); av_push(point, newSViv(x0)); av_push(point, newSViv(y0)); av_push(theline, newRV_noinc((SV*)point)); if (x0 == x1 && y0 == y1) break; e2 = err; if (e2 > -dx) { err -= dy; x0 += sx; } if (e2 < dy) { err += dx; y0 += sy; } } RETVAL = newRV_noinc((SV*)theline); OUTPUT: RETVAL SV * line(SV* sp1, SV* sp2) PROTOTYPE: $$ PREINIT: AV* ap1; AV* ap2; AV* theline; AV* point; long dx, dy, ix, iy, n, m, step; double divn, xstep, ystep, x, y; CODE: if (!(SvROK(sp1) && SvTYPE(SvRV(sp1)) == SVt_PVAV)) croak("p1 must be array reference"); ap1 = (AV*)SvRV(sp1); if (av_count(ap1) != 2) croak("p1 must only have two elements"); if (!(SvROK(sp2) && SvTYPE(SvRV(sp2)) == SVt_PVAV)) croak("p2 must be array reference"); ap2 = (AV*)SvRV(sp2); if (av_count(ap2) != 2) croak("p2 must only have two elements"); ix = SvIV(*av_fetch(ap1, XX, 0)); iy = SvIV(*av_fetch(ap1, YY, 0)); dx = SvIV(*av_fetch(ap2, XX, 0)) - ix; dy = SvIV(*av_fetch(ap2, YY, 0)) - iy; n = labs(dx); /* distance */ m = labs(dy); if (m > n) n = m; if (!n) { theline = newAV_alloc_x(1); point = newAV_alloc_x(2); av_store(point, XX, newSViv(ix)); av_store(point, YY, newSViv(iy)); av_store(theline, 0, newRV_noinc((SV*)point)); } else { theline = newAV_alloc_x(n); divn = 1.0 / n; xstep = dx * divn; ystep = dy * divn; x = ix; y = iy; for (step = 0; step <= n; ++step, x += xstep, y += ystep) { point = newAV_alloc_x(2); av_push(point, newSViv(lround(x))); av_push(point, newSViv(lround(y))); av_push(theline, newRV_noinc((SV*)point)); } } RETVAL = newRV_noinc((SV*)theline); OUTPUT: RETVAL