home *** CD-ROM | disk | FTP | other *** search
- /* CMD: Transform Points
- * Transform points algorithmically: Swirl,
- * By Arnie Cachelin © 1992, 1993 NewTek Inc.
- */
-
- libadd = addlib("LWModelerARexx.port",0)
- signal on error
- signal on syntax
- call addlib "rexxsupport.library", 0, -30, 0
- req=0
- xf=0
- coords.1='z,y,x'
- coords.2='x,z,y'
- coords.3='x,y,z'
- MATHLIB="rexxmathlib.library"
- IF POS(MATHLIB , SHOW('L')) = 0 THEN
- IF ~ADDLIB(MATHLIB , 0 , -30 , 0) THEN DO
- call notify(1,"!Can't find "MATHLIB)
- exit
- END
- ax=3
- rate=90
- cx=0
- cy=0
- cz=0
- rmax=1
- from=1
-
- version = 'XForm v1.0'
- filnam = 'ENV:XForm.state'
- if (exists(filnam)) then do
- if (~open(state, filnam, 'R')) then break
- if (readln(state) ~= version) then break
- parse value readln(state) with ax rate cx cy cz rmax from .
- call close state
- end
- call req_begin "Point Transformations"
- id_txt = req_addcontrol("Rotate points", 'T',"inside Effect Radius based on")
- id_txt = req_addcontrol("their radial", 'T',"positions")
- id_Axis = req_addcontrol("Axis", 'CH','X Y Z')
- id_cen = req_addcontrol("Center", 'v', 1)
- id_rate = req_addcontrol("Rotation Amount (°/m) ", 'n', 0)
- id_rad = req_addcontrol("Effect Radius", 'n', 0)
- id_from = req_addcontrol("Turn From", 'CH','Center Edge Middle')
- xform.1= 'a=a+(rmax-r)*rate' /* Swirl stronger at center */
- xform.2= 'a=a+r*rate' /* Swirl stronger at edge */
- xform.3= 'a=a+rmax-2*abs(rmax/2-r)*rate' /* Swirl strongest at rmax/2 */
-
- call req_setval id_Axis, ax
- call req_setval id_rate, rate
- call req_setval id_cen, cx cy cz, 0.0
- call req_setval id_from, from
- call req_setval id_rad, rmax, 1.0
-
- if (~req_post()) then do
- call req_end
- exit
- end
-
- ax= req_getval(id_Axis)
- rate=req_getval(id_rate)
- parse value req_getval(id_cen) with cx cy cz .
- rmax =req_getval(id_rad)
- from =req_getval(id_from)
-
- call req_end
-
- if (open(state, filnam, 'W')) then do
- call writeln state, version
- call writeln state, ax rate cx cy cz rmax from
- call close state
- end
-
- Pi=3.14159265358
- DegreesPerRadian= 180/pi
-
- /* Transform loop */
- t=time('e')
- n = xfrm_begin()
- call meter_begin n, 'Transforming 'n' Points'
- do i = 1 to n
- parse value xfrm_getpos(i) with dx dy dz .
- x = dx - cx
- y = dy - cy
- z = dz - cz
- interpret 'r=Cyl_R('coords.ax')'
- interpret 'a=Cyl_Theta('coords.ax')'
- interpret 'My_Z='translate(ax,"XYZ","123")
- /* say '#'i ax coords.ax x y z */
- /* say r*1 rmax a'°' My_Z */
- if r>rmax then iterate
- interpret xform.from
- x=Cyl_X(r,a,My_Z)+cx
- y=Cyl_Y(r,a,My_Z)+cy
- z=My_Z+cz
- pos=translate(coords.ax," ",",")
- /* say i '--->' x y z a'°' */
- cmd= 'call xfrm_setpos 'i','pos
- interpret cmd
- call meter_step
- end
- call meter_end
- call xfrm_end
- t=time('e')-t
- if n>100 then call notify(1,'!Whew, I just transformed 'n' points','!in only 't' seconds.')
- if (libadd) then call remlib("LWModelerARexx.port")
- exit
-
-
- syntax:
- error:
- call end_all
- t=Notify(1,'!Rexx Script Error','@'ErrorText(rc),'Line 'SIGL)
- if (libadd) then call remlib("LWModelerARexx.port")
- exit
-
- /*
- The following functions convert between 3D cartesian coordinates (X,Y,Z)
- and either cylindrical coordinates (R,Theta,Z) or Spherical
- coordinates (R,Theta,Phi). The Cylindrical coordinate conversions don't
- take Z inputs, since Z is the same in both cylindical and cartesian systems.
- To go between spherical and cylindrical, use cartesian... or write your own.
- p.s. I lied... see Cyl_Z(), z args are ok now too.
-
- */
-
-
- /* Return R in Cylindrical coordinate system */
- Cyl_R: PROCEDURE
- arg xf, yf, zf
- return sqrt(xf*xf+yf*yf)
-
- Cyl_Z: PROCEDURE
- arg xf, yf, zf
- return zf
-
- /* Return Theta in Cylindrical coordinate system */
- Cyl_Theta: PROCEDURE EXPOSE DegreesPerRadian Pi
- arg x, y, z
- if x=0 then t=sign(y)*90
- else t=DegreesPerRadian*atan(y/x)
- if x<0 then t=t + 180 /* atan() doesn't know which quadrant you're in */
- if t<0 then t=t + 360 /* atan() returns -180 to 180, I like 0 to 360 */
- return t
-
- /* Return Cartesian X from Cylindrical coordinate system */
- Cyl_X: PROCEDURE EXPOSE DegreesPerRadian
- arg R, Theta, Z
- return R*cos(Theta/DegreesPerRadian)
-
- /* Return Cartesian Y from Cylindrical coordinate system */
- Cyl_Y: PROCEDURE EXPOSE DegreesPerRadian
- arg R, Theta, Z
- return R*sin(Theta/DegreesPerRadian)
-
- /* Return R in Spherical coordinate system */
- Sphere_R: PROCEDURE
- arg x, y, z
- return sqrt(x*x+y*y+z*z)
-
- /* Return Theta in Spherical coordinate system */
- Sphere_Theta: PROCEDURE EXPOSE DegreesPerRadian Pi
- arg x, y, z
- if x=0 then t=sign(y)*90
- else t=DegreesPerRadian*atan(y/x)
- if x<0 then t=t + 180 /* atan() doesn't know which quadrant you're in */
- if t<0 then t=t + 360 /* atan() returns -180 to 180, I like 0 to 360 */
- return t
-
- /* Return Phi in Spherical coordinate system */
- Sphere_Phi: PROCEDURE EXPOSE DegreesPerRadian Pi
- arg x, y, z
- if z=0 then return 90
- else return DegreesPerRadian*atan(sqrt(x*x+y*y)/z)
-
- /* Return Cartesian X from Spherical coordinate system */
- Sphere_X: PROCEDURE EXPOSE DegreesPerRadian
- arg R, Theta, Phi
- return R*sin(abs(Phi)/DegreesPerRadian)*cos(Theta/DegreesPerRadian)
-
- /* Return Cartesian Y from Spherical coordinate system */
- Sphere_Y: PROCEDURE EXPOSE DegreesPerRadian
- arg R, Theta, Phi
- return R*sin(abs(Phi)/DegreesPerRadian)*sin(Theta/DegreesPerRadian)
-
- /* Return Cartesian Z from Spherical coordinate system */
- Sphere_Z: PROCEDURE EXPOSE DegreesPerRadian
- arg R, Theta, Phi
- return sign(Phi)*R*cos(Phi/DegreesPerRadian)