Article View: comp.lang.postscript
Article #6263SOLUTION! to Spline data/Bezier Curve problem
From: cse0080
Date: Mon, 10 Jun 1991 21:23
Date: Mon, 10 Jun 1991 21:23
207 lines
6803 bytes
6803 bytes
In article <1991Jun3.095901.3793@desire.wright.edu>, I wrote:
> Help!
>
> I need to know how to generate spline curves in PostScript when
> all the data I have on hand is an array of data points that lie on
> the curve itself. (IE: no control points for the curveto operator)
>
> Anyone know a good way to do this?
>
> Thanks for your assistance.
>
> John Hansen
> cse0080@wsu.bitnet
> cse0080@desire.wright.edu
>
I received two C program fragments, and a copy of the posted PostScript
code that attempted to help me solve my problem. Unfortunately, none of
them seemed to do what I needed. The PostScript code didn't draw through
every point so it seemed pointless (pun intended) to use that. The other
two C programs produced weird results (and I'm no C expert so I didn't
try too hard to fix/modify them to my needs. So... I decided to attempt a
solution myself. Written in my native tongue: Fortran. (Sorry about that...)
I have included at the end a code fragment which should be easily translated
into C or Pascal for you CS types. My program appears to work for all the
test datasets which I tried. It works like this:
1. Calculate angle to horizontal of a line "tangent" to the desired curve
at each point. (tangle(i) in the code)
2. Calculate two control points in between each set of two data points
using the 1/4 (magic number 8-) the distance between the two data points.
formula: new_x = 0.25*len*sind(tangle(i)) + point(i).x, where len is dist.
between point_i & point_i+1.
I set the tangent angle of the first and last points to be equal to the
straight line angle between each of those points and the next/previous point.
Anyway, the code shouldn't be too obtuse (heh, heh, heh...) I have also
included a /SPline word in PostScript which I use to eat all the numbers I
write out. Hopefully this will save someone out there some time and effort.
It took me the better part of three days to get this to actually work in all
the cases that I threw at it.
Thanks for your help
John Hansen
cse0080@wsu.bitnet
cse0080@desire.wright.edu
hansen@mdss1.hq.aflc.af.mil (work)
--------------------------- cut here --------------------------------
C
C Sample do loop for processing my spline data.
C
do i=1,numsp
clr = splines(i).clr/10.0
wid = max(mod(splines(i).width,10)*1.0,0.5)
write(unit=pat,fmt='(I1)') mod(splines(i).style,10)
if (pat .eq. '0') pat = ' '
write(7,'(F5.2,A)') clr,' ['
do j=1,splines(i).points
pts(j).x = int(splines(i).x(j)*10)
pts(j).y = int(splines(i).y(j)*10)
end do
call dospline(splines(i).points)
write(7,'(3A,F5.2,A)') '] [',pat,'] 0',wid,' SPline'
end do
C
C The Fortran code which writes /SPline to my prolog file
C
write(7,'(A)') ' '
write(7,'(A)') '/SPline { setlinewidth setdash /polyarray exch def'
write(7,'(A)') '/pcount polyarray length 2 sub 6 idiv def'
write(7,'(A)') 'polyarray aload pop moveto pcount {curveto}'
write(7,'(A)') 'repeat setgray stroke} def'
write(7,'(A)') ' '
C
C The pts point array is COMMON but could be passed as a parameter
C to DOSPLINE. My splines will never be more than 30 points long
C so I hard-coded the array sizes.
C
subroutine dospline(npts)
structure /point/
real x,y
end structure
record /point/ pts(50), cp1(50), cp2(50)
real dx1,dx2,dy1,dy2,angle1(50),angle2(50),distp(50)
real jarct2d, tangle(50)
integer npts
common /ptdata/ pts
if (npts .lt. 3) goto 1000
do i=2,npts-1
dx1 = pts(i).x - pts(i-1).x
dy1 = pts(i).y - pts(i-1).y
dx2 = pts(i+1).x - pts(i).x
dy2 = pts(i+1).y - pts(i).y
distp(i) = sqrt(dx1*dx1+dy1*dy1)
angle1(i) = jarct2d(dy1,dx1)
angle2(i) = jarct2d(dy2,dx2)
tangle(i) = (angle2(i) + angle1(i))/2.0
end do
dx2 = pts(npts-1).x - pts(npts).x
dy2 = pts(npts-1).y - pts(npts).y
distp(npts) = sqrt(dx2*dx2+dy2*dy2)
angle1(npts) = jarct2d(dy2,dx2)
C
C The commented change slightly the look of the curve at start & end
C
C tangle(1) = angle1(2) + tangle(2) - angle2(2)
C tangle(npts)=angle1(npts)+(angle1(npts-1)-angle2(npt-1))/2.0
C
C Here they are set == to straight-line angle to next/previous points
C
tangle(1) = angle1(2)
tangle(npts)=angle1(npts)
do i=1,npts-1
call compcp(distp(i+1),tangle(i),i,1,cp1(i).x,cp1(i).y)
if (i .le. npts-2) then
call compcp(distp(i+1),tangle(i+1),i+1,2,cp2(i).x,cp2(i).y)
endif
end do
call compcp(distp(npts),tangle(npts),npts,2,
1 cp2(npts-1).x,cp2(npts-1).y)
do i=npts-1,1,-1
write(7,'(6F10.4)') cp1(i).x,cp1(i).y,
1 cp2(i).x,cp2(i).y,pts(i+1).x,pts(i+1).y
end do
write(7,'(2F10.4)') pts(1).x,pts(1).y
1000 return
end
real function compcp(len,ang,ptnum,cp,cpx,cpy)
structure /point/
real x, y
end structure
record /point/ pts(50)
real len, ang, tx, ty, dd, dx, dy, temp, cpx, cpy
real computecpx, computecpy
integer ptnum,cp
common /ptdata/ pts
tx = computecpx(len,ang,ptnum)
ty = computecpy(len,ang,ptnum)
if (cp .eq. 1) then
dx = pts(ptnum+1).x - tx
dy = pts(ptnum+1).y - ty
else
dx = pts(ptnum-1).x - tx
dy = pts(ptnum-1).y - ty
endif
dd = sqrt(dx*dx+dy*dy)
if (dd .gt. len) then
tx = computecpx(len,180+ang,ptnum)
ty = computecpy(len,180+ang,ptnum)
endif
cpx = tx
cpy = ty
return
end
real function computecpx(len,ang,ptnum)
structure /point/
real x, y
end structure
record /point/ pts(50)
real len, ang
integer ptnum
common /ptdata/ pts
C
C The number 0.25 could be used as a variable for "shaping"
C the curve between each data point.
C
temp = 0.25*len*cosd(ang) + pts(ptnum).x
computecpx = temp
return
end
real function computecpy(len,ang,ptnum)
structure /point/
real x, y
end structure
record /point/ pts(50)
real len, ang
integer ptnum
common /ptdata/ pts
temp = 0.25*len*sind(ang) + pts(ptnum).y
computecpy = temp
return
end
C
C The atan2d VMS fortran intrinsic funtion returns angles between
C -180 & 180. I remove the undefined case of dx=dy=0.
C
real function jarct2d(dumy,dumx)
real dumx,dumy
if (dumx .eq. 0 .and. dumy .eq. 0) then
jarct2d = 0
else
jarct2d = atan2d(dumy,dumx)
endif
return
end
Technical Details
Message-ID:
<1991Jun10.162302.3900@desire.wright.edu>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!dsac.dla.mil!dsacg3.dsac.dla.mil!desc.dla.mil!wright!desire.wright.edu!cse0080References:
<1991Jun3.095901.3793@desire.wright.edu>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!dsac.dla.mil!dsacg3.dsac.dla.mil!desc.dla.mil!wright!desire.wright.edu!cse0080 From: cse0080@desire.wright.edu Newsgroups: comp.lang.postscript Subject: SOLUTION! to Spline data/Bezier Curve problem Message-ID: <1991Jun10.162302.3900@desire.wright.edu> Date: 10 Jun 91 21:23:02 GMT References: <1991Jun3.095901.3793@desire.wright.edu> Organization: University Computing Services, Wright State University Lines: 207