Algorithm-Line-Bresenham-C

 view release on metacpan or  search on metacpan

Line/Bresenham/C/C.xs  view on Meta::CPAN

/* 
   it is a C version Algorithm::Line::Bresenham to speed up a bit. 
   LiloHuang @ 2008, kenwu@cpan.org
 */

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

MODULE = Algorithm::Line::Bresenham::C		PACKAGE = Algorithm::Line::Bresenham::C		

void circle(int y, int x, int radius)
PPCODE:
	AV * point;
	int curr_x = 0;
	int curr_y = radius;
	int d = 3 - (radius << 1);
	
	while(1) {
		EXTEND(SP, 8);

		point = (AV *)sv_2mortal((SV *)newAV());	
		av_push(point, newSViv(y + curr_y));
		av_push(point, newSViv(x + curr_x));	
		PUSHs(sv_2mortal(newRV((SV *)point)));	

		point = (AV *)sv_2mortal((SV *)newAV());	
		av_push(point, newSViv(y + curr_y));
		av_push(point, newSViv(x - curr_x));	
		PUSHs(sv_2mortal(newRV((SV *)point)));	

		point = (AV *)sv_2mortal((SV *)newAV());	
		av_push(point, newSViv(y - curr_y));
		av_push(point, newSViv(x + curr_x));	
		PUSHs(sv_2mortal(newRV((SV *)point)));	

		point = (AV *)sv_2mortal((SV *)newAV());	
		av_push(point, newSViv(y - curr_y));
		av_push(point, newSViv(x - curr_x));	
		PUSHs(sv_2mortal(newRV((SV *)point)));	

		point = (AV *)sv_2mortal((SV *)newAV());	
		av_push(point, newSViv(y + curr_x));
		av_push(point, newSViv(x + curr_y));	
		PUSHs(sv_2mortal(newRV((SV *)point)));	

		point = (AV *)sv_2mortal((SV *)newAV());	
		av_push(point, newSViv(y + curr_x));
		av_push(point, newSViv(x - curr_y));	
		PUSHs(sv_2mortal(newRV((SV *)point)));	

		point = (AV *)sv_2mortal((SV *)newAV());	
		av_push(point, newSViv(y - curr_x));
		av_push(point, newSViv(x + curr_y));	
		PUSHs(sv_2mortal(newRV((SV *)point)));			

		point = (AV *)sv_2mortal((SV *)newAV());	
		av_push(point, newSViv(y - curr_x));
		av_push(point, newSViv(x - curr_y));
		PUSHs(sv_2mortal(newRV((SV *)point)));	                

		if(curr_x >= curr_y) break;
		if (d < 0) {
			d += (curr_x << 2) + 6;
		}else{
			d += ((curr_x - curr_y) << 2) + 10;
			curr_y -= 1;
		}
		curr_x++;
	}

void line(int from_y, int from_x, int to_y, int to_x)
PPCODE:
	AV * point;
	int curr_maj, curr_min, to_maj, to_min, delta_maj, delta_min;
	int delta_y = to_y - from_y;
	int delta_x = to_x - from_x;
	int dir = 0;
	if(abs(delta_y) > abs(delta_x)) dir = 1;
	
	if(dir) {
		curr_maj = from_y;
		curr_min = from_x;
		to_maj = to_y;
		to_min = to_x;
		delta_maj = delta_y;
		delta_min = delta_x;
	}else{
		curr_maj = from_x;
		curr_min = from_y;
		to_maj = to_x;
		to_min = to_y;
		delta_maj = delta_x;
		delta_min = delta_y;	
	}
	int inc_maj, inc_min;
	if(!delta_maj) inc_maj = 0;
	else inc_maj = (abs(delta_maj)==delta_maj ? 1 : -1);
	
	if(!delta_min) inc_min = 0;
	else inc_min = (abs(delta_min)==delta_min ? 1 : -1);
	
	delta_maj = abs(delta_maj)+0;
	delta_min = abs(delta_min)+0;
	
	int d = (delta_min << 1) - delta_maj;
	int d_inc1 = (delta_min << 1);
	int d_inc2 = ((delta_min - delta_maj) << 1);	
	
	while(1) {     
		EXTEND(SP, 1);
		point = (AV *)sv_2mortal((SV *)newAV());	
		if(dir) {
			av_push(point, newSViv(curr_maj));
			av_push(point, newSViv(curr_min));	
		}else{
			av_push(point, newSViv(curr_min));	
			av_push(point, newSViv(curr_maj));
		}
		PUSHs(sv_2mortal(newRV((SV *)point)));	

		if(curr_maj == to_maj) break;
        curr_maj += inc_maj;
		if (d < 0) {
				d += d_inc1;
		}else{
				d += d_inc2;
				curr_min += inc_min;
		}
	}



( run in 0.687 second using v1.01-cache-2.11-cpan-71847e10f99 )