aboutsummaryrefslogtreecommitdiff
path: root/pkg/proto/vol/src/vgetincr.x
blob: c96ff2bbb0c42f4c225f0e32b571889f0ebb0b30 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
include "pvol.h"


# VGETINCREM -- Get list of input voxel band & line indices that contribute to
# current ray, using simple incremental digital differential analyzer.

procedure vgetincrem (tx1,ty1, tx2,ty2, nx,ny, maxvox, nvox, xind, yind)
double	tx1,ty1		# (in)  starting coordinate of ray
double	tx2,ty2		# (in)  ending coordinate of ray
int	nx,ny		# (in)  dimensions of working plane (1:nx, 1:ny)
int	maxvox		# (in)  max dimension of output index arrays
int	nvox		# (out) count of indices for current ray
int	xind[ARB]	# (out) array of input voxel band indices
int	yind[ARB]	# (out) array of input voxel line indices

real	x1,y1, x2,y2, dy,dx, adx,ady, x,y, length
int	i, tvox, xi, yi

int	vsign()

begin
	# Going between integer and floating point grid representations
	# is tricky, especially for symmetrical rotation angles aligned with
	# the grid nodes.  Rounding from double to single precision here
	# is the only way I could get things to work for all possible angles
	# and grid dimensions.

	x1 = tx1
	y1 = ty1
	x2 = tx2
	y2 = ty2
	dx = x2 - x1
	dy = y2 - y1
	adx = abs (dx)
	ady = abs (dy)

	# Approximate the line length.
	if (adx >= ady)
	    length = adx
	else
	    length = ady
	tvox = int (length) + 1
	if (tvox > maxvox)
	    call error (0, "VGETINCREM:  nvox > maxvox")
	
	# Select the larger of dx or dy to be one raster unit.
	dx = dx / length
	dy = dy / length

	# Round values; using vsign function makes this work in all quadrants.
	x = x1 + 0.5 * vsign (dx)
	y = y1 + 0.5 * vsign (dy)

	# Boundary-extend if coming FROM +x or +y and if rounding would not
	# take us out of range.
	if (dx == -1.0 || dy == -1.0) {
	    if (!((int(x-dx) <= 0 || int(x-dx) > nx) ||
		(int(y-dy) <= 0 || int(y-dy) > ny))) {
		x = x - dx
		y = y - dy
	    }
	}

	# Fill in the integer grid coordinates.
	nvox = 0
	do i = 1, tvox {
	    xi = nx - int(x) + 1	# yes, we want to truncate here
	    yi = int (y)
	    if (1 <= xi && xi <= nx && 1 <= yi && yi <= ny) {
		nvox = nvox + 1
		xind[nvox] = xi
		yind[nvox] = yi
	    }
	    x = x + dx
	    y = y + dy
	}
end


# VSIGN -- Return -1, 0, +1 if val is <0, =0, >0.

int procedure vsign (val)
real	val

begin
	if (val < 0.0)
	    return (-1)
	else if (val == 0.0)
	    return (0)
	else
	    return (1)
end