subroutine aptplcy (ax, ay, az, bx, by, bz,
     &                    qc, qx, qy, qz, qxy, qyz, qzx,
     &                    qxx, qyy, qzz, tol,
     &                    rcyl, cx, cy, cz, dx, dy, dz,
     &                    ipar, daxis, dpax, dpay, dpaz, dsurf1, dsurf2,
     &                    dpcx, dpcy, dpcz, pcx, pcy, pcz,
     &                    ppx, ppy, ppz, pinx, piny, pinz, nerr)

ccbeg.
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c                             SUBROUTINE APTPLCY
c
c     call aptplcy (ax, ay, az, bx, by, bz,
c    &              qc, qx, qy, qz, qxy, qyz, qzx,
c    &              qxx, qyy, qzz, tol,
c    &              rcyl, cx, cy, cz, dx, dy, dz,
c    &              ipar, daxis, dpax, dpay, dpaz, dsurf1, dsurf2,
c    &              dpcx, dpcy, dpcz, pcx, pcy, pcz,
c    &              ppx, ppy, ppz, pinx, piny, pinz, nerr)
c
c     Version:  aptplcy  Updated    1995 January 13 14:20.
c               aptplcy  Originated 1995 January 10 13:50.
c
c     Author:   Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123.
c
c
c     Purpose:  For the plane through the point a = (ax, ay, az) with normal
c               vector b = (bx, by, bz), and the circular cylinder specified
c               by the implicit quadric equation coefficients qc, ..., qzz:
c
c               to find the radius rcyl of the cylinder,
c               a point c = (cx, cy, cz) on its axis, and
c               its axis vector d = (dx, dy, dz);
c
c               if the axis of the cylinder is parallel (ipar = 1) to the plane,
c               to find its distance from the plane da = abs (daxis);
c               to find the minimum and maximum distances dsurf1 = da - rcyl
c               and dsurf2 = da + rcyl from the plane to the surface of the
c               cylinder;
c               to find a point pp = (ppx, ppy, ppz) on the plane proximal to
c               the cylinder, and the vector dpa = (dpax, dpay, dpaz) from point
c               "pp" to point "c";
c               to find a point pc = (pcx, pcy, pcz) on the cylinder proximal to
c               the plane, and the vector dpc = (dpcx, dpcy, dpcz) from point
c               "pp" to point "pc";
c               if da does not exceed rcyl, to find the one (da = rcyl) or
c               two (da < rcyl) points pin(1) = (pinx(1), piny(1), pinz(1)) and
c               pin(2) = (pinx(2), piny(2), pinz(2)) on the line(s) of
c               intersection of the plane with the surface of the cylinder
c               (such lines will have the direction vector "d");
c
c               if the axis of the cylinder is not parallel to the plane
c               (ipar = 0), to find the point of intersection
c               pp = (ppx, ppy, ppz) of the axis with the plane, and the four
c               points pin(n) = (pinx(n), piny(n), pinz(n)), n = 1, 4, on the
c               major and minor axes of the elliptical intersection of the
c               plane with the circular cylinder.
c
c               If the plane is defined only by its implicit quadric equation,
c
c               f(x,y,z) = qc1 + qx1 * x + qy1 * y + qz1 * z = 0,
c
c               a point "a" and the normal vector "b" may be found from:
c
c               b = (bx, by, bz) = (qx1, qy1, qz1)
c               b**2 = qx1**2 + qy1**2 + qz1**2
c               a = (ax, ay, az) = -(qc1 / b**2) * (qx1, qy1, qz1)
c
c               The circular cylinder is defined by the implicit quadric
c               equation:
c
c               g(x,y,z) = qc +  qx  * x     + qy  * y     + qz  * z     +
c                                qxy * x * y + qyz * y * z + qzx * z * x +
c                                qxx * x**2  + qyy * y**2  + qzz * z**2 = 0,
c
c               which in standard form, with the axis through the origin and
c               in the direction of the z axis, is
c               g = -rcyl**2 + x**2 + y**2 = 0,
c               where rcyl is the radius.
c
c               If the circular cylinder is defined only by a point on the axis,
c               the axis vector, and the radius, use APT subroutine aptclis to
c               find the coefficients of the implicit quadric equation.
c
c               Flag nerr indicates any input error.
c
c     Input:    ax, ay, az, bx, by, bz, qc, qx, qy, qz, qxy, qyz, qzx,
c               qxx, qyy, qzz, tol.
c
c     Output:   rcyl, cx, cy, cz, dx, dy, dz, ipar, daxis, dpax, dpay, dpaz,
c               dsurf1, dsurf2, dpcx, dpcy, dpcz, pcx, pcy, pcz,
c               ppx, ppy, ppz, pinx, piny, pinz, nerr)
c
c     Calls: aptaxis, aptlnpl, aptptpl, aptvang, aptvxun 
c               
c
c     Glossary:
c
c     ax,ay,az  Input    The x, y, z coordinates of point "a" in the plane.
c
c     bx,by,bz  Input    The x, y, z components of the normal vector "b" of the
c                          plane.
c
c     cx,cy,cz  Output   The x, y, z coordinates of point "c" on the axis of
c                          the circular cylinder.
c
c     daxis     Output   Minimum distance between the plane and the axis of the
c                          cylinder.  Zero if they intersect (ipar = 0), or the
c                          axis of the cylinder is entirely within the plane
c                          (ipar = 1).  If positive, in the direction of the
c                          normal vector "b".  If negative, in the opposite
c                          direction.  The length of vector "dpa".
c
c     dpax,y,z  Output   The smallest vector from the plane to the axis of the
c                          cylinder.  If ipar = 0, a null vector.
c                          If ipar = 1, the vector from point "pp" on the plane
c                          to point "c" on the axis of the cylinder, with length
c                          daxis.
c                          Parallel (daxis > 0) or antiparallel (daxis < 0) to
c                          vector "b".
c
c     dpcx,y,z  Output   The smallest normal vector from the plane to the
c                          surface of the cylinder, with length dsurf1.
c                          If ipar = 0, a null vector.
c                          If ipar = 1, the vector from point "pp" on the plane
c                          to point "pc" on the surface of the cylinder.
c                          The largest normal vector from the plane to
c                          the surface of the cylinder is  2 * "dpa" - "dpc",
c                          with length dsurf2.
c
c     dsurf1    Output   If ipar = 0, dsurf1 = 0.
c                          If ipar = 1, the minimum distance from the plane
c                          to the surface of the cylinder,
c                          dsurf1 = abs (daxis) - rcyl, negative if
c                          the plane and the cylinder overlap, zero if they are
c                          tangent, positive if they do not overlap.
c                          The length of vector "dpa".
c                          Moving the plane and the cylinder toward each other
c                          in the direction of vector "b" by distance dsurf1
c                          would make them tangent.
c
c     dsurf2    Output   If ipar = 0, dsurf2 = 0.  If ipar = 1, the maximum
c                          distance from the plane to the surface of the
c                          cylinder, dsurf2 = abs (daxis) + rcyl.
c                          Moving the plane and the cylinder toward each other
c                          in the direction of vector "b" by distance dsurf2
c                          would make them tangent.  Zero if ipar = 0.
c
c     dx,dy,dz  Input    The x, y, z components of the unit axis vector "d" of
c                          the circular cylinder.  If ipar = 1, this is the
c                          direction vector of the lines through points "pp",
c                          "pc" and "pin(1)" through "pin(4)".
c
c     ipar      Output   Indicates that the axis of the circular cylinder is
c                          (ipar = 1) or is not (ipar = 0) parallel to the
c                          plane.  See daxis.
c
c     nerr      Output   Indicates an input error, if not zero.
c                          1 if vector "b" has zero length.
c                          2 if the implicit quadric equation coefficients do
c                          not define a circular cylinder.
c
c     pcx,y,z   Output   If ipar = 1, the x, y, z coordinates of point "pc" on
c                          the line on the cylindrical surface nearest point
c                          "pp" on the plane, at distance dsurf1 from point "pp"
c                          in direction "dpa".  The line has direction "d".
c                          The line on the cylindrical surface furthest from
c                          point "pp" is 2 * "c" - "pc", at distance dsurf2 from
c                          point "pp".
c
c     pinx(1),... Output   If ipar = 0, the points pin(1) through pin(4) are
c                          four points on the intersection of the plane with the
c                          surface of the circular cylinder.  The points are on
c                          the ends of the major and minor axes of the
c                          elliptical intersection curve.  Note that pinx, piny
c                          and pinz are arrays with a minimum size of 4.
c                          Point "pin(n)" has x, y, z coordinates pinx(n),
c                          piny(n), pinz(n), for n = 1, 4.
c
c     pinx(1),... Output   If ipar = 1, points pin(1) and pin(2) are points on
c                          any line(s) of intersection of the plane with the
c                          surface of the circular cylinder.  The direction of
c                          each line is vector "d".  There are no such lines if
c                          daxis > rcyl.  Note that pinx, piny and pinz are
c                          arrays with a minimum size of 4.
c                          Point "pin(n)" has x, y, z coordinates pinx(n),
c                          piny(n), pinz(n), for n = 1, 4.
c
c     ppx,y,z   Output   If ipar = 1, the x, y, z coordinates of the point "pp"
c                          on the plane nearest point "c" on the axis of the
c                          cylinder.  If ipar = 0, the x, y, z coordinates of
c                          point "pp", the intersection of the plane with the
c                          axis of the cylinder, which is also the center of the
c                          ellipse of intersection of the plane with the surface
c                          of the cylinder.
c
c     qc, ...   Input    Coefficients of the quadric equation for the cylinder:
c                          qc + qx  * x     + qy  * y     + qz  * z +
c                               qxy * x * y + qyz * y * z + qzx * z * x +
c                               qxx * x**2  + qyy * y**2  + qxx * z**2 = 0
c
c     rcyl      Output   The radius of the circular cylinder.
c
c     tol       Input    Numerical tolerance limit.  With 64-bit floating point
c                          numbers, 1.e-5 to 1.e-11 is recommended.
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
ccend.

c.... Dimensioned arguments.

      dimension pinx(4)               ! Coordinate x of a point.
      dimension piny(4)               ! Coordinate y of a point.
      dimension pinz(4)               ! Coordinate z of a point.

c.... Local variables.

      common /laptplcy/ rotq(3,3)     ! Rotation matrix to align cylinder.
cbugc***DEBUG begins.
cbug 9901 format (/ 'aptplcy finding distance between plane and',
cbug     &  ' cylinder.',
cbug     &  '  tol=',1pe13.5)
cbug 9902 format (
cbug     &  '  ax, ay, az= ',1p3e22.14 /
cbug     &  '  bx, by, bz= ',1p3e22.14 )
cbug 9903 format (
cbug     &  '  Cylinder qc=',1pe22.14 /
cbug     &  '  qx,qy,qz=   ',1p3e22.14 /
cbug     &  '  qxy,qyz,qzx=',1p3e22.14 /
cbug     &  '  qxx,qyy,qzz=',1p3e22.14)
cbug      write ( 3, 9901) tol
cbug      write ( 3, 9902) ax, ay, az, bx, by, bz
cbug      write ( 3, 9903) qc, qx, qy, qz, qxy, qyz, qzx, qxx, qyy, qzz
cbugc***DEBUG ends.

c.... Initialize.

      nerr  = 0

      rcyl   = -1.e99
      cx     = -1.e99
      cy     = -1.e99
      cz     = -1.e99
      dx     = -1.e99
      dy     = -1.e99
      dz     = -1.e99
      pcx    = -1.e99
      pcy    = -1.e99
      pcz    = -1.e99

      daxis  = -1.e99
      dsurf1 = -1.e99
      dsurf2 = -1.e99

      ppx    = -1.e99
      ppy    = -1.e99
      ppz    = -1.e99
      dpax   = -1.e99
      dpay   = -1.e99
      dpaz   = -1.e99
      dpcx   = -1.e99
      dpcy   = -1.e99
      dpcz   = -1.e99

      do 110 n = 1, 4
        pinx(n) = -1.e99
        piny(n) = -1.e99
        pinz(n) = -1.e99
  110 continue

c.... Test for input errors.

      call aptvunb (bx, by, bz, 1, tol, ubx, uby, ubz, blen, nerra)

      if (blen .eq. 0.0) then         ! Normal vector of plane is null.
        nerr = 1
cbugc***DEBUG begins.
cbug 9904 format (/ 'aptplcy ERROR.  Normal vector of plane is null.')
cbug      write ( 3, 9904)
cbugc***DEBUG ends.
        go to 710
      endif

c.... Find the radius and axis of the cylinder, and a second point on the axis.

      sc  = qc
      sx  = qx
      sy  = qy
      sz  = qz
      sxy = qxy
      syz = qyz
      szx = qzx
      sxx = qxx
      syy = qyy
      szz = qzz

      tolx = tol
      if (tolx .le. 0.0) tolx = 1.e-11

      call aptaxis (sc, sx, sy, sz, sxy, syz, szx, sxx, syy, szz, tolx,
     &              cx, cy, cz, rotq, ntype, nerraxis)

      if ((ntype .ne. 7)    .or.
     &    (nerraxis .ne. 0)) then
cbugc***DEBUG begins.
cbug 9905 format (/ 'aptplcy ERROR.  Z axis of cylinder is null.')
cbug      write ( 3, 9905)
cbugc***DEBUG ends.
        nerr = 2
        go to 710
      endif

      dx = rotq(3,1)
      dy = rotq(3,2)
      dz = rotq(3,3)

      cx2 = cx + dx
      cy2 = cy + dy
      cz2 = cz + dz

      rcyl = sqrt (-sc / sxx)

c.... Find a unit vector perpendicular to the normal and the cylinder axis.

      call aptvxun (bx, by, bz, dx, dy, dz, 1, tol,
     &              ux, uy, uz, vlen, nerra)

      if (vlen .eq. 0.0) then         ! Normal is parallel to cylinder axis.

        call aptvxun (bx, by, bz, 0.0, 0.0, 1.0, 1, tol,
     &                ux, uy, uz, vlen, nerra)

        if (vlen .eq. 0.0) then       ! Normal is parallel to z axis.

          call aptvxun (bx, by, bz, 1.0, 0.0, 0.0, 1, tol,
     &                  ux, uy, uz, vlen, nerra)

        endif

      endif

c.... Find any intersection of the axis of the cylinder with the plane.

      call aptlnpl (cx, cy, cz, cx2, cy2, cz2,
     &              ax, ay, az, bx, by, bz, 1, tol,
     &              daxis, dint, fracps, ppx, ppy, ppz, ipar, nerra)

      if (ipar .eq. 1) then           ! Plane is parallel to cylinder axis.
cbugc***DEBUG begins.
cbug      if (daxis .eq. 0.0) then
cbug 9906 format (/ 'aptplcy.  Plane contains axis of cylinder.')
cbug      write ( 3, 9906)
cbug      else
cbug 9907 format (/ 'aptplcy.  Plane is parallel to axis of cylinder.')
cbug      write ( 3, 9907)
cbug      endif
cbugc***DEBUG ends.

c....   Find the distances of minimum and maximum separation or overlap of the
c....     plane and the cylinder, when they are parallel.

        dsurf1  = abs (daxis) - rcyl
        dsurf2  = abs (daxis) + rcyl
        disterr = tol * dsurf2
        if (abs (dsurf1) .le. disterr) dsurf1 = 0.0
cbugc***DEBUG begins.
cbug      if (dsurf1 .lt. 0.0) then
cbug        if (daxis .ne. 0.0) then
cbug 9908 format (/ 'aptplcy.  Plane overlaps the cylinder.')
cbug      write ( 3, 9908)
cbug        endif
cbug      elseif (dsurf1 .eq. 0.0) then
cbug 9909 format (/ 'aptplcy.  Plane is tangent to the cylinder.')
cbug      write ( 3, 9909)
cbug      else
cbug 9910 format (/ 'aptplcy.  Plane does not contact the cylinder.')
cbug      write ( 3, 9910)
cbug      endif
cbugc***DEBUG ends.

c....   Find the point "pp" on the plane proximal to point "c" on the axis.

        call aptptpl (cx, cy, cz, ax, ay, az, bx, by, bz, 1, tol,
     &                dpmin, ppx, ppy, ppz, itrun, nerra)

        call aptvdis (ppx, ppy, ppz, cx, cy, cz, 1, tol,
     &                dpax, dpay, dpaz, dpa, nerra)

c....   Find the point "pc" on the cylinder proximal to point "a".

        if (dpa .eq. 0.0) then        ! The plane contains the axis.
          pcx = ppx + dsurf1 * bx / blen
          pcy = ppy + dsurf1 * by / blen
          pcz = ppz + dsurf1 * bz / blen
        else
          pcx = ppx + dsurf1 * dpax / dpa
          pcy = ppy + dsurf1 * dpay / dpa
          pcz = ppz + dsurf1 * dpaz / dpa
        endif

c....   Find the vector "dpc" from point "pp" to point "pc".

        call aptvdis (ppx, ppy, ppz, pcx, pcy, pcz, 1, tol,
     &                dpcx, dpcy, dpcz, dpc, nerra)

c....   Find the two points on the intersection lines on the plane.

        if (dsurf1 .le. 0.0) then     ! Plane and cylinder surface intersect.

          distpl  = sqrt (-dsurf1 * dsurf2)

          pinx(1) = ppx - distpl * ux
          piny(1) = ppy - distpl * uy
          pinz(1) = ppz - distpl * uz

          pinx(2) = ppx + distpl * ux
          piny(2) = ppy + distpl * uy
          pinz(2) = ppz + distpl * uz

        endif                         ! Plane and cylinder surface intersect.

        go to 710

      else                            ! Plane crosses axis of cylinder.
cbugc***DEBUG begins.
cbug 9911 format (/ 'aptplcy.  Plane not parallel to axis of cylinder.')
cbug      write ( 3, 9911)
cbugc***DEBUG ends.

        dsurf1  = 0.0
        dsurf2  = 0.0

        dpax    = 0.0
        dpay    = 0.0
        dpaz    = 0.0

        dpcx    = 0.0
        dpcy    = 0.0
        dpcz    = 0.0

c....   Find the two points on minor axis of elliptical curve of intersection.

        pinx(1) = ppx - rcyl * ux
        piny(1) = ppy - rcyl * uy
        pinz(1) = ppz - rcyl * uz

        pinx(2) = ppx + rcyl * ux
        piny(2) = ppy + rcyl * uy
        pinz(2) = ppz + rcyl * uz

c....   Find the two points on major axis of elliptical curve of intersection.

c....   Find the major axis of elliptical curve of intersection.

        call aptvxun (bx, by, bz, ux, uy, uz, 1, tol,
     &                umx, umy, umz, vlen, nerra)

        call aptvang (bx, by, bz, dx, dy, dz, 1, tol, costh, nerr)

        dmaj    = rcyl / abs (costh)

        pinx(3) = ppx - dmaj * umx
        piny(3) = ppy - dmaj * umy
        pinz(3) = ppz - dmaj * umz

        pinx(4) = ppx + dmaj * umx
        piny(4) = ppy + dmaj * umy
        pinz(4) = ppz + dmaj * umz

      endif                           ! Tested whether parallel or not.

  710 continue
cbugc***DEBUG begins.
cbug 9912 format (/ 'aptplcy results:  ipar=',i3,12x,'nerr=',i3 /
cbug     &  '  rcyl=       ',1pe22.14 /
cbug     &  '  cx,cy,cz=   ',1p3e22.14 /
cbug     &  '  dx,dy,dz=   ',1p3e22.14 /
cbug     &  '  daxis=      ',1pe22.14 /
cbug     &  '  dpax,y,z=   ',1p3e22.14 /
cbug     &  '  dsurf1,2=   ',1p2e22.14 /
cbug     &  '  dpcx,y,z=  =',1p3e22.14 /
cbug     &  '  pcx,pcy,pcz=',1p3e22.14 /
cbug     &  '  ppx,ppy,ppz=',1p3e22.14 /
cbug     &  '  pinx,y,z  1=',1p3e22.14 /
cbug     &  '  pinx,y,z  2=',1p3e22.14 /
cbug     &  '  pinx,y,z  3=',1p3e22.14 /
cbug     &  '  pinx,y,z  4=',1p3e22.14 )
cbug      write ( 3, 9912) ipar, nerr, rcyl, cx, cy, cz, dx, dy, dz,
cbug     &  daxis, dpax, dpay, dpaz, dsurf1, dsurf2, dpcx, dpcy, dpcz,
cbug     &  pcx, pcy, pcz, ppx, ppy, ppz,
cbug     &  (pinx(n), piny(n), pinz(n), n = 1, 4)
cbugc***DEBUG ends.
      return

c.... End of subroutine aptplcy.      (+1 line)
      end

UCRL-WEB-209832