subroutine aptlnln (ax, ay, az, bx, by, bz, cx, cy, cz, & dx, dy, dz, np, tol, dpmin, fracab, fraccd, & ex, ey, ez, fx, fy, fz, itrun, ipar, nerr) ccbeg. cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c SUBROUTINE APTLNLN c c call aptlnln (ax, ay, az, bx, by, bz, cx, cy, cz, c & dx, dy, dz, np, tol, dpmin, fracab, fraccd, c & ex, ey, ez, fx, fy, fz, itrun, ipar, nerr) c c Version: aptlnln Updated 1994 January 5 17:30. c aptlnln Originated 1989 November 2 14:10. c c Author: Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123. c c c Purpose: To find, for each of np sets of input data, the minimum c distance dpmin between the line through the points c a = (ax, ay, az) and b = (bx, by, bz), and the line through c the points c = (cx, cy, cz) and d = (dx, dy, dz), and the c point e = (ex, ey, ez) on line "ab", and the point c f = (fx, fy, fz) on line "cd", at which the minimum distance c dpmin occurs. If dpmin is smaller than the estimated error in c its calculation, it will be truncated to zero, and itrun = 1 c will be returned. c The fractional distance fracab of point "e" along line "ab", c and the fractional distance fraccd of point "f" along line c "cd", are also returned. c If the lines are parallel, ipar = 1 will be returned. c If a line segment is too short, ipar = 2, 3 or 4 will be c returned. c c History: 1990 March 14. Changed tol to 0.0 in call to unit vector c subroutine. Allows small magnitudes. c 1994 January 5. Added truncation of coordinates of points e c and f. c c Input: ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, np, tol. c c Output: dpmin, fracab, fraccd, ex, ey, ez, fx, fy, fz, c itrun, ipar, nerr. c c Calls: aptvdis, aptvdot, aptvuna c c c Glossary: c c ax,ay,az Input The first point on line segment "ab". Size np. c c bx,by,bz Input The second point on line segment "ab". Size np. c c cx,cy,cz Input The first point on line segment "cd". Size np. c c dpmin Output Minimum distance from line "ab" to line "cd". c Distance from e = (ex, ey, ez) to f = (fx, fy, fz). c Truncated to zero if less than the estimated error c in its calculation. See tol. Size np. c c dx,dy,dz Input The second point on line segment "cd". Size np. c c ex,ey,ez Output The x, y, z coordinates of the point on line "ab" c nearest line "cd". Size np. c c fracab Output Fractional distance of "e" along line "ab". Size np. c Meaningless if ipar = 2 or 4. c c fraccd Output Fractional distance of "f" along line "cd". Size np. c Meaningless if ipar = 3 or 4. c c fx,fy,fz Output The x, y, z coordinates of the point on line "cd" c nearest line "ab". Size np. c c ipar Output 0 if lines are not parallel. 1 if they are, and c points "e" and "f" can be moved arbitrarily by c equal distances along the lines. Size np. c 2 if line segment "ab" is too short. c 3 if line segment "cd" is too short. c 4 if "ab" and "cd" are both too short. c c itrun Output 0 if dpmin not truncated to zero, based on tol. c 1 if dpmin is truncated to zero, based on tol. c Size np. c c nerr Output Indicates an input error, if not 0. c 1 if np is not positive. c c np Input Size of arrays. c c tol Input Numerical tolerance limit. c On Cray computers, recommend 1.e-5 to 1.e-11. c cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccend. c.... Dimensioned arguments. c---- Coordinate x of point "a". dimension ax (1) c---- Coordinate y of point "a". dimension ay (1) c---- Coordinate z of point "a". dimension az (1) c---- Coordinate x of point "b". dimension bx (1) c---- Coordinate y of point "b". dimension by (1) c---- Coordinate z of point "b". dimension bz (1) c---- Coordinate x of point "c". dimension cx (1) c---- Coordinate y of point "c". dimension cy (1) c---- Coordinate z of point "c". dimension cz (1) c---- Distance from line "ab" to line "cd". dimension dpmin (1) c---- Coordinate x of point "d". dimension dx (1) c---- Coordinate y of point "d". dimension dy (1) c---- Coordinate z of point "d". dimension dz (1) c---- Coordinate x of point "e". dimension ex (1) c---- Coordinate y of point "e". dimension ey (1) c---- Coordinate z of point "e". dimension ez (1) c---- Fractional distance of "e" on "ab". dimension fracab (1) c---- Fractional distance of "f" on "cd". dimension fraccd (1) c---- Coordinate x of point "f". dimension fx (1) c---- Coordinate y of point "f". dimension fy (1) c---- Coordinate z of point "f". dimension fz (1) c---- 1 if lines parallel, 2 if bad. dimension ipar (1) c---- 1 if dpmin truncated to zero. dimension itrun (1) c.... Local variables. c---- Component of "ac" in direction "ab". common /laptlnln/ acdotab (64) c---- Component of "ac" in direction "cd". common /laptlnln/ acdotcd (64) c---- Component x of vector "ac". common /laptlnln/ acx (64) c---- Component y of vector "ac". common /laptlnln/ acy (64) c---- Component z of vector "ac". common /laptlnln/ acz (64) c---- Cosine of angle between "ab" and "cd". common /laptlnln/ costh (64) c---- Distance from "a" to "b". common /laptlnln/ distab (64) c---- Distance from "a" to "e". common /laptlnln/ distae c---- Distance from "c" to "d". common /laptlnln/ distcd (64) c---- Distance from "c" to "f". common /laptlnln/ distcf c---- Value of dpmin before truncating. common /laptlnln/ dpmins (64) c---- Component x of vector "ef". common /laptlnln/ efx (64) c---- Component y of vector "ef". common /laptlnln/ efy (64) c---- Component z of vector "ef". common /laptlnln/ efz (64) c---- Estimated error in sinth2. common /laptlnln/ errs c---- Estimated error in ex or fx. common /laptlnln/ errx c---- Estimated error in ey or fy. common /laptlnln/ erry c---- Estimated error in ez or fz. common /laptlnln/ errz c---- A very small number. common /laptlnln/ fuz c---- Index in arrays. common /laptlnln/ n c---- First index of subset of data. common /laptlnln/ n1 c---- Last index of subset of data. common /laptlnln/ n2 c---- Index in external array. common /laptlnln/ nn c---- Size of current subset of data. common /laptlnln/ ns c---- Sine**2 of angle between "ab" and "cd" common /laptlnln/ sinth2 c---- Component x of unit vector along "ab". common /laptlnln/ uabx (64) c---- Component y of unit vector along "ab". common /laptlnln/ uaby (64) c---- Component z of unit vector along "ab". common /laptlnln/ uabz (64) c---- Component x of unit vector along "cd". common /laptlnln/ ucdx (64) c---- Component y of unit vector along "cd". common /laptlnln/ ucdy (64) c---- Component z of unit vector along "cd". common /laptlnln/ ucdz (64) c---- Magnitude of a vector. common /laptlnln/ vlen (64) c---- Maqnitude of a vector. common /laptlnln/ vlene c---- Maqnitude of a vector. common /laptlnln/ vlenf cbugc***DEBUG begins. cbug 9901 format (/ 'aptlnln finding distance from the line through:') cbug 9902 format (i3,' ax,ay,az=',1p3e22.14 / cbug & ' bx,by,bz=',1p3e22.14 / cbug & ' to the line through:' / cbug & ' cx,cy,cz=',1p3e22.14 / cbug & ' dx,dy,dz=',1p3e22.14) cbug write ( 3, 9901) cbug write ( 3, 9902) (n, ax(n), ay(n), az(n), bx(n), by(n), bz(n), cbug & cx(n), cy(n), cz(n), dx(n), dy(n), dz(n), n = 1, np) cbugc***DEBUG ends. c.... Initialize. c---- A very small number. fuz = 1.e-99 nerr = 0 c.... Test for input errors. if (np .le. 0) then nerr = 1 go to 210 endif c.... Set up the indices of the first subset of data. n1 = 1 n2 = min (np, 64) c.... Loop over subsets of data. 110 ns = n2 - n1 + 1 c.... Find the unit vector "uab" along line "ab". call aptvdis (ax(n1), ay(n1), az(n1), bx(n1), by(n1), bz(n1), ns, & tol, uabx, uaby, uabz, distab, nerr) call aptvuna (uabx, uaby, uabz, ns, 0., vlen, nerr) c.... Find the unit vector "ucd" along line "cd". call aptvdis (cx(n1), cy(n1), cz(n1), dx(n1), dy(n1), dz(n1), ns, & tol, ucdx, ucdy, ucdz, distcd, nerr) call aptvuna (ucdx, ucdy, ucdz, ns, 0., vlen, nerr) c.... Find the vector ac from point "a" to point "c". call aptvdis (ax(n1), ay(n1), az(n1), cx(n1), cy(n1), cz(n1), ns, & tol, acx, acy, acz, vlen, nerr) c.... Find the components of vector "ac" in the directions of the lines c.... (the scalar products of "ac" with "uab" and "ucd"). call aptvdot (acx, acy, acz, uabx, uaby, uabz, ns, tol, & acdotab, nerr) call aptvdot (acx, acy, acz, ucdx, ucdy, ucdz, ns, tol, & acdotcd, nerr) c.... Find the scalar (dot) product of the two unit direction vectors. call aptvdot (uabx, uaby, uabz, ucdx, ucdy, ucdz, ns, tol, & costh, nerr) c.... Find the points of nearest approach on each line, "e" and "f", c.... and their fractional distances along lines "ab" and "cd". c---- Loop over subset of data. do 120 n = 1, ns nn = n + n1 - 1 sinth2 = (1.0 - costh(n)) * (1.0 + costh(n)) if ((distab(n) * distcd(n)) .eq. 0.0) then sinth2 = 0.0 endif errs = tol * (1.0 + costh(n)**2) if (abs (sinth2) .ge. errs) then ipar(nn) = 0 else ipar(nn) = 1 endif if (distab(n) .eq. 0.0) then ipar(nn) = 2 endif if (distcd(n) .eq. 0.0) then ipar(nn) = ipar(nn) + 2 endif distae = (acdotab(n) - acdotcd(n) * costh(n)) / & (sinth2 + fuz) distcf = (acdotab(n) * costh(n) - acdotcd(n)) / & (sinth2 + fuz) if (abs (sinth2) .le. errs) then distae = 0.5 * acdotab(n) distcf = -0.5 * acdotcd(n) endif ex(nn) = ax(nn) + distae * uabx(n) ey(nn) = ay(nn) + distae * uaby(n) ez(nn) = az(nn) + distae * uabz(n) errx = tol * (abs (ax(nn)) + abs (bx(nn))) erry = tol * (abs (ay(nn)) + abs (by(nn))) errz = tol * (abs (az(nn)) + abs (bz(nn))) if (abs (ex(nn)) .le. errx) ex(nn) = 0.0 if (abs (ey(nn)) .le. erry) ey(nn) = 0.0 if (abs (ez(nn)) .le. errz) ez(nn) = 0.0 fx(nn) = cx(nn) + distcf * ucdx(n) fy(nn) = cy(nn) + distcf * ucdy(n) fz(nn) = cz(nn) + distcf * ucdz(n) errx = tol * (abs (cx(nn)) + abs (dx(nn))) erry = tol * (abs (cy(nn)) + abs (dy(nn))) errz = tol * (abs (cz(nn)) + abs (dz(nn))) if (abs (fx(nn)) .le. errx) fx(nn) = 0.0 if (abs (fy(nn)) .le. erry) fy(nn) = 0.0 if (abs (fz(nn)) .le. errz) fz(nn) = 0.0 fracab(nn) = distae / (distab(n) + fuz) fraccd(nn) = distcf / (distcd(n) + fuz) c---- End of loop over subset of data. 120 continue c.... Find the minimum distance between the lines. call aptvdis (ex(n1), ey(n1), ez(n1), fx(n1), fy(n1), fz(n1), ns, & 0.0, efx, efy, efz, dpmin(n1), nerr) c.... See if truncation to zero is allowed. c---- Truncation is allowed. if (tol .gt. 0.0) then c---- Loop over subset of data. do 130 n = 1, ns nn = n + n1 - 1 dpmins(n) = dpmin(nn) c---- End of loop over subset of data. 130 continue call aptvdis (ex(n1), ey(n1), ez(n1), fx(n1), fy(n1), fz(n1), & ns, tol, efx, efy, efz, dpmin(n1), nerr) c---- Loop over subset of data. do 140 n = 1, ns nn = n + n1 - 1 if (dpmin(nn) .eq. dpmins(n)) then itrun(nn) = 0 else itrun(nn) = 1 endif c---- End of loop over subset of data. 140 continue c---- Tested tol. endif c.... See if all data subsets are done. c---- Do another subset of data. if (n2 .lt. np) then n1 = n2 + 1 n2 = min (np, n1 + 63) go to 110 endif cbugc***DEBUG begins. cbug 9903 format (/ 'aptlnln results:' / cbug & (i3,' dpmin= ',1pe22.14 / cbug & ' fracab= ',1pe22.14,' fraccd=',1pe22.14 / cbug & ' itrun=',i2,' ipar=',i2 / cbug & ' ex,ey,ez=',1p3e22.14 / cbug & ' fx,fy,fz=',1p3e22.14)) cbug write ( 3, 9903) (n, dpmin(n), fracab(n), fraccd(n), itrun(n), cbug & ipar(n), ex(n), ey(n), ez(n), fx(n), fy(n), fz(n), n = 1, np) cbugc***DEBUG ends. 210 return c.... End of subroutine aptlnln. (+1 line.) end UCRL-WEB-209832