subroutine conloc (ndp,xd,yd,ntr,ipt,nli,ipl,xii,yii,iti,iwk,wk)
  use gcont_contour
  !---------------------------------------------------------------------
  ! @ public
  !	This subroutine locates a point, i.e., determines to what
  !	triangle a given point (xii,yii) belongs.  When the given
  !	point does not lie inside the data area, this subroutine
  !	determines the border line segment when the point lies in
  !	an outside rectangular area, and two border line segments
  !	when the point lies in an outside triangular area.
  ! Arguments :
  !	NDP	I	number of data points			Input
  !	XD	R*4 (*)	Arrays of dimension NDP containing the
  !			X coordinates of the data points	Input
  !	YD	R*4 (*) Array of Y coordinates			Input
  !	NTR	I	Number of triangles			Input
  !	IPT	I (*)	Array of dimension 3*NTR containing the
  !			point numbers of the vertexes of the
  !			triangles				Input
  !	NLI	I	Number of border line segments		Input
  !	IPL	I (*)	Array of dimension 3*NLI containing the
  !			point numbers of the end points of the
  !			border line segments and their respective
  !			triangle numbers			Input
  !	XII	R*4	X coordinate of point to locate		Input
  !	YII 	R*4	Y coordinate of point to locate		Input
  !	ITI 	I	Triangle number, when the point is
  !			inside the data area, or two border
  !			line segment numbers, IL1 and IL2,
  !			coded to IL1*(NTR+NLI)+IL2, when the
  !			point is outside the data area.		Output
  !	IWK 	I (*)	Array of dimension 18*NDP used
  !			internally as a work area
  !	WK  	R*4 (*)	Array of dimension 8*NDP used internally
  !			as a work area.
  !---------------------------------------------------------------------
  integer :: ndp                    !
  real :: xd(*)                     !
  real :: yd(*)                     !
  integer :: ntr                    !
  integer :: ipt(*)                 !
  integer :: nli                    !
  integer :: ipl(*)                 !
  real :: xii                       !
  real :: yii                       !
  integer :: iti                    !
  integer :: iwk(*)                 !
  real :: wk(*)                     !
  ! Local
  integer :: ntsc(9), idsc(9)
  !      REAL SIDE,U1,U2,V1,V2,U3,V3,SPDT
  integer :: nt0, nl0, idp, isc, it0t3, it0, i1, i2, i3
  integer :: jiwk, ip1, ip2, ip3, il1, il2, il1t3
  integer :: ntsci, itsc, ntl, jwk
  real :: x0, y0, xmn, xmx, ymn, ymx
  real :: xi, yi, xs1, ys1, xs2, ys2
  real :: x1, y1, x2, y2, x3, y3
  !
  ! Needed for at least NTSC, XS1, XS2, YS1, YS2
  save ntsc, xi, yi, xs1, ys1, xs2, ys2
  !
  ! Statement functions
  !
  !      SIDE(U1,V1,U2,V2,U3,V3) = (U1-U3)*(V2-V3)-(V1-V3)*(U2-U3)
  !      SPDT(U1,V1,U2,V2,U3,V3) = (U1-U2)*(U3-U2)+(V1-V2)*(V3-V2)
  !
  ! Preliminary processing
  !
  nt0 = ntr
  nl0 = nli
  ntl = nt0+nl0
  x0 = xii
  y0 = yii
  !
  ! Processing for a new set of data points
  !
  if (nit .ne. 0) go to  170
  nit = 1
  !
  ! Divides the X-Y plane into nine rectangular sections.
  !
  xmn = xd(1)
  xmx = xmn
  ymn = yd(1)
  ymx = ymn
  do idp=2,ndp
    xi = xd(idp)
    yi = yd(idp)
    xmn = amin1(xi,xmn)
    xmx = amax1(xi,xmx)
    ymn = amin1(yi,ymn)
    ymx = amax1(yi,ymx)
  enddo
  xs1 = (xmn+xmn+xmx)/3.0
  xs2 = (xmn+xmx+xmx)/3.0
  ys1 = (ymn+ymn+ymx)/3.0
  ys2 = (ymn+ymx+ymx)/3.0
  !
  ! Determines and stores in the IWK array triangle numbers of
  ! the triangles associated with each of the nine sections.
  !
  do isc=1,9
    ntsc(isc) = 0
    idsc(isc) = 0
  enddo
  it0t3 = 0
  jwk = 0
  do it0=1,nt0
    it0t3 = it0t3+3
    i1 = ipt(it0t3-2)
    i2 = ipt(it0t3-1)
    i3 = ipt(it0t3)
    xmn = amin1(xd(i1),xd(i2),xd(i3))
    xmx = amax1(xd(i1),xd(i2),xd(i3))
    ymn = amin1(yd(i1),yd(i2),yd(i3))
    ymx = amax1(yd(i1),yd(i2),yd(i3))
    if (ymn .gt. ys1) go to  120
    if (xmn .le. xs1) idsc(1) = 1
    if (xmx.ge.xs1 .and. xmn.le.xs2) idsc(2) = 1
    if (xmx .ge. xs2) idsc(3) = 1
120 if (ymx.lt.ys1 .or. ymn.gt.ys2) go to  130
    if (xmn .le. xs1) idsc(4) = 1
    if (xmx.ge.xs1 .and. xmn.le.xs2) idsc(5) = 1
    if (xmx .ge. xs2) idsc(6) = 1
130 if (ymx .lt. ys2) go to  140
    if (xmn .le. xs1) idsc(7) = 1
    if (xmx.ge.xs1 .and. xmn.le.xs2) idsc(8) = 1
    if (xmx .ge. xs2) idsc(9) = 1
140 do isc=1,9
      if (idsc(isc).eq.0) cycle    ! ISC
      jiwk = 9*ntsc(isc)+isc
      iwk(jiwk) = it0
      ntsc(isc) = ntsc(isc)+1
      idsc(isc) = 0
    enddo                      ! ISC
    !
    ! Stores in the WK array the minimum and maximum of the X and
    ! Y coordinate values for each of the triangle.
    !
    jwk = jwk+4
    wk(jwk-3) = xmn
    wk(jwk-2) = xmx
    wk(jwk-1) = ymn
    wk(jwk) = ymx
  enddo                        ! IT0
  go to  200
  !
  ! Checks if in the same triangle as previous.
  !
170 it0 = itipv
  if (it0 .gt. nt0) go to  180
  it0t3 = it0*3
  ip1 = ipt(it0t3-2)
  x1 = xd(ip1)
  y1 = yd(ip1)
  ip2 = ipt(it0t3-1)
  x2 = xd(ip2)
  y2 = yd(ip2)
  if (side(x1,y1,x2,y2,x0,y0) .lt. 0.0) go to  200
  ip3 = ipt(it0t3)
  x3 = xd(ip3)
  y3 = yd(ip3)
  if (side(x2,y2,x3,y3,x0,y0) .lt. 0.0) go to  200
  if (side(x3,y3,x1,y1,x0,y0) .lt. 0.0) go to  200
  go to  260
  !
  ! Checks if on the same border line segment.
  !
180 il1 = it0/ntl
  il2 = it0-il1*ntl
  il1t3 = il1*3
  ip1 = ipl(il1t3-2)
  x1 = xd(ip1)
  y1 = yd(ip1)
  ip2 = ipl(il1t3-1)
  x2 = xd(ip2)
  y2 = yd(ip2)
  if (il2 .ne. il1) go to  190
  if (spdt(x1,y1,x2,y2,x0,y0) .lt. 0.0) go to  200
  if (spdt(x2,y2,x1,y1,x0,y0) .lt. 0.0) go to  200
  if (side(x1,y1,x2,y2,x0,y0) .gt. 0.0) go to  200
  go to  260
  !
  ! Checks if between the same two border line segments.
  !
190 if (spdt(x1,y1,x2,y2,x0,y0) .gt. 0.0) go to  200
  ip3 = ipl(3*il2-1)
  x3 = xd(ip3)
  y3 = yd(ip3)
  if (spdt(x3,y3,x2,y2,x0,y0) .le. 0.0) go to  260
  !
  ! Locates inside the data area.
  ! Determines the section in which the point in question lies.
  !
200 isc = 1
  if (x0 .ge. xs1) isc = isc+1
  if (x0 .ge. xs2) isc = isc+1
  if (y0 .ge. ys1) isc = isc+3
  if (y0 .ge. ys2) isc = isc+3
  !
  ! Searches through the triangles associated with the section.
  !
  ntsci = ntsc(isc)
  if (ntsci .le. 0) go to  220
  jiwk = -9+isc
  do itsc=1,ntsci
    jiwk = jiwk+9
    it0 = iwk(jiwk)
    jwk = it0*4
    if (x0 .lt. wk(jwk-3)) cycle
    if (x0 .gt. wk(jwk-2)) cycle
    if (y0 .lt. wk(jwk-1)) cycle
    if (y0 .gt. wk(jwk))   cycle
    it0t3 = it0*3
    ip1 = ipt(it0t3-2)
    x1 = xd(ip1)
    y1 = yd(ip1)
    ip2 = ipt(it0t3-1)
    x2 = xd(ip2)
    y2 = yd(ip2)
    if (side(x1,y1,x2,y2,x0,y0) .lt. 0.0) cycle
    ip3 = ipt(it0t3)
    x3 = xd(ip3)
    y3 = yd(ip3)
    if (side(x2,y2,x3,y3,x0,y0) .lt. 0.0) cycle
    if (side(x3,y3,x1,y1,x0,y0) .lt. 0.0) cycle
    go to  260
  enddo                        ! ITSC
  !
  ! Locates outside the data area.
  !
220 do il1=1,nl0
    il1t3 = il1*3
    ip1 = ipl(il1t3-2)
    x1 = xd(ip1)
    y1 = yd(ip1)
    ip2 = ipl(il1t3-1)
    x2 = xd(ip2)
    y2 = yd(ip2)
    if (spdt(x2,y2,x1,y1,x0,y0) .lt. 0.0) cycle
    if (spdt(x1,y1,x2,y2,x0,y0) .lt. 0.0) go to  230
    if (side(x1,y1,x2,y2,x0,y0) .gt. 0.0) cycle
    il2 = il1
    go to  250
230 il2 = mod(il1,nl0)+1
    ip3 = ipl(3*il2-1)
    x3 = xd(ip3)
    y3 = yd(ip3)
    if (spdt(x3,y3,x2,y2,x0,y0) .le. 0.0) go to  250
  enddo                        ! IL1
  it0 = 1
  go to  260
250 it0 = il1*ntl+il2
  !
  ! Normal exit
  !
260 iti = it0
  itipv = it0
  return
  !
contains
  !
  ! Statement functions
  real function side(u1,v1,u2,v2,u3,v3)
    real :: u1                      !
    real :: v1                      !
    real :: u2                      !
    real :: v2                      !
    real :: u3                      !
    real :: v3                      !
    side = (u1-u3)*(v2-v3)-(v1-v3)*(u2-u3)
  end function side
  !
  real function spdt(u1,v1,u2,v2,u3,v3)
    real :: u1                      !
    real :: v1                      !
    real :: u2                      !
    real :: v2                      !
    real :: u3                      !
    real :: v3                      !
    spdt = (u1-u2)*(u3-u2)+(v1-v2)*(v3-v2)
  end function spdt
  !
end subroutine conloc
