FV3 Bundle
tools_stripack.F90
Go to the documentation of this file.
1 !----------------------------------------------------------------------
2 ! Module: tools_stripack
3 ! Purpose: STRIPACK routines
4 ! Source: https://people.sc.fsu.edu/~jburkardt/f_src/stripack/stripack.html
5 ! Author: Robert Renka
6 ! Original licensing: none
7 ! Modified by Benjamin Menetrier for BUMP
8 ! Licensing: this code is distributed under the CeCILL-C license
9 ! Copyright © 2015-... UCAR, CERFACS, METEO-FRANCE and IRIT
10 !----------------------------------------------------------------------
12 
13 use tools_kinds, only: kind_real
14 use tools_repro, only: eq,inf,sup,indist
15 use type_mpl, only: mpl_type
16 
17 implicit none
18 
19 private
21 
22 contains
23 
24 subroutine addnod ( mpl, nst, k, x, y, z, list, lptr, lend, lnew, ier )
25 
26 !*****************************************************************************80
27 !
28 ! Subroutine: addnod
29 ! Purpose: add a node to a triangulation
30 !
31 ! Discussion:
32 !
33 ! This subroutine adds node K to a triangulation of the
34 ! convex hull of nodes 1, ..., K-1, producing a triangulation
35 ! of the convex hull of nodes 1, ..., K.
36 !
37 ! The algorithm consists of the following steps: node K
38 ! is located relative to the triangulation (TRFIND), its
39 ! index is added to the data structure (INTADD or BDYADD),
40 ! and a sequence of swaps (SWPTST and SWAP) are applied to
41 ! the arcs opposite K so that all arcs incident on node K
42 ! and opposite node K are locally optimal (satisfy the circumcircle test).
43 !
44 ! Thus, if a Delaunay triangulation of nodes 1 through K-1 is input,
45 ! a Delaunay triangulation of nodes 1 through K will be output.
46 !
47 ! Modified:
48 !
49 ! 15 May 2007
50 !
51 ! Author:
52 !
53 ! Robert Renka
54 !
55 ! Reference:
56 !
57 ! Robert Renka,
58 ! Algorithm 772: STRIPACK,
59 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
60 ! ACM Transactions on Mathematical Software,
61 ! Volume 23, Number 3, September 1997, pages 416-434.
62 !
63 ! Parameters:
64 !
65 ! Input, integer NST, the index of a node at which TRFIND
66 ! begins its search. Search time depends on the proximity of this node to
67 ! K. If NST < 1, the search is begun at node K-1.
68 !
69 ! Input, integer K, the nodal index (index for X, Y, Z, and
70 ! LEND) of the new node to be added. 4 <= K.
71 !
72 ! Input, real ( kind_real ) X(K), Y(K), Z(K), the coordinates of the nodes.
73 !
74 ! Input/output, integer LIST(6*(N-2)), LPTR(6*(N-2)), LEND(K),
75 ! LNEW. On input, the data structure associated with the triangulation of
76 ! nodes 1 to K-1. On output, the data has been updated to include node
77 ! K. The array lengths are assumed to be large enough to add node K.
78 ! Refer to TRMESH.
79 !
80 ! Output, integer IER, error indicator:
81 ! 0 if no errors were encountered.
82 ! -1 if K is outside its valid range on input.
83 ! -2 if all nodes (including K) are collinear (lie on a common geodesic).
84 ! L if nodes L and K coincide for some L < K.
85 !
86 ! Local parameters:
87 !
88 ! B1,B2,B3 = Unnormalized barycentric coordinates returned by TRFIND.
89 ! I1,I2,I3 = Vertex indexes of a triangle containing K
90 ! IN1 = Vertex opposite K: first neighbor of IO2
91 ! that precedes IO1. IN1,IO1,IO2 are in
92 ! counterclockwise order.
93 ! IO1,IO2 = Adjacent neighbors of K defining an arc to
94 ! be tested for a swap
95 ! IST = Index of node at which TRFIND begins its search
96 ! KK = Local copy of K
97 ! KM1 = K-1
98 ! L = Vertex index (I1, I2, or I3) returned in IER
99 ! if node K coincides with a vertex
100 ! LP = LIST pointer
101 ! LPF = LIST pointer to the first neighbor of K
102 ! LPO1 = LIST pointer to IO1
103 ! LPO1S = Saved value of LPO1
104 ! P = Cartesian coordinates of node K
105 !
106  implicit none
107 
108  type(mpl_type),intent(in) :: mpl ! MPI data
109 
110  integer k
111 
112  real ( kind_real ) b1
113  real ( kind_real ) b2
114  real ( kind_real ) b3
115  integer i1
116  integer i2
117  integer i3
118  integer ier
119  integer in1
120  integer io1
121  integer io2
122  integer ist
123  integer kk
124  integer km1
125  integer l
126  integer lend(k)
127  integer list(*)
128  integer lnew
129  integer lp
130  integer lpf
131  integer lpo1
132  integer lpo1s
133  integer lptr(*)
134  integer nst
135  real ( kind_real ) p(3)
136  logical output
137  real ( kind_real ) x(k)
138  real ( kind_real ) y(k)
139  real ( kind_real ) z(k)
140 
141  kk = k
142 
143  if ( kk < 4 ) then
144  ier = -1
145  write ( *, '(a)' ) ' '
146  write ( *, '(a)' ) 'ADDNOD - Fatal error!'
147  write ( *, '(a)' ) ' K < 4.'
148  call mpl%abort('stop in stripack')
149  end if
150 !
151 ! Initialization:
152 !
153  km1 = kk - 1
154  ist = nst
155  if ( ist < 1 ) then
156  ist = km1
157  end if
158 
159  p(1) = x(kk)
160  p(2) = y(kk)
161  p(3) = z(kk)
162 !
163 ! Find a triangle (I1,I2,I3) containing K or the rightmost
164 ! (I1) and leftmost (I2) visible boundary nodes as viewed
165 ! from node K.
166 !
167 
168  call trfind ( ist, p, km1, x, y, z, list, lptr, lend, b1, b2, b3, &
169  i1, i2, i3 )
170 !
171 ! Test for collinear or duplicate nodes.
172 !
173  if ( i1 == 0 ) then
174  ier = -2
175  write ( *, '(a)' ) ' '
176  write ( *, '(a)' ) 'ADDNOD - Fatal error!'
177  write ( *, '(a)' ) ' The nodes are coplanar.'
178  call mpl%abort('stop in stripack')
179  end if
180 
181  if ( i3 /= 0 ) then
182 
183  l = i1
184 
185  if ( eq(p(1),x(l)) .and. eq(p(2),y(l)) .and. eq(p(3),z(l)) ) then
186  ier = l
187  write ( *, '(a)' ) ' '
188  write ( *, '(a)' ) 'ADDNOD - Fatal error!'
189  write ( *, '(a,i8,a,i8)' ) ' Node ', l, ' is equal to node ', k
190  call mpl%abort('stop in stripack')
191  end if
192 
193  l = i2
194 
195  if ( eq(p(1),x(l)) .and. eq(p(2),y(l)) .and. eq(p(3),z(l)) ) then
196  ier = l
197  write ( *, '(a)' ) ' '
198  write ( *, '(a)' ) 'ADDNOD - Fatal error!'
199  write ( *, '(a,i8,a,i8)' ) ' Node ', l, ' is equal to node ', k
200  call mpl%abort('stop in stripack')
201  end if
202 
203  l = i3
204  if ( eq(p(1),x(l)) .and. eq(p(2),y(l)) .and. eq(p(3),z(l)) ) then
205  ier = l
206  write ( *, '(a)' ) ' '
207  write ( *, '(a)' ) 'ADDNOD - Fatal error!'
208  write ( *, '(a,i8,a,i8)' ) ' Node ', l, ' is equal to node ', k
209  call mpl%abort('stop in stripack')
210  end if
211 
212  call intadd ( kk, i1, i2, i3, list, lptr, lend, lnew )
213 
214  else
215 
216  if ( i1 /= i2 ) then
217  call bdyadd ( kk, i1,i2, list, lptr, lend, lnew )
218  else
219  call covsph ( kk, i1, list, lptr, lend, lnew )
220  end if
221 
222  end if
223 
224  ier = 0
225 !
226 ! Initialize variables for optimization of the triangulation.
227 !
228  lp = lend(kk)
229  lpf = lptr(lp)
230  io2 = list(lpf)
231  lpo1 = lptr(lpf)
232  io1 = abs( list(lpo1) )
233 !
234 ! Begin loop: find the node opposite K.
235 !
236  do
237 
238  call lstptr ( lend(io1), io2, list, lptr, lp )
239 
240  if ( 0 <= list(lp) ) then
241 
242  lp = lptr(lp)
243  in1 = abs( list(lp) )
244 !
245 ! Swap test: if a swap occurs, two new arcs are
246 ! opposite K and must be tested.
247 !
248  lpo1s = lpo1
249 
250  call swptst ( in1, kk, io1, io2, x, y, z, output )
251  if ( .not. output ) then
252 
253  if ( lpo1 == lpf .or. list(lpo1) < 0 ) then
254  exit
255  end if
256 
257  io2 = io1
258  lpo1 = lptr(lpo1)
259  io1 = abs( list(lpo1) )
260  cycle
261 
262  end if
263 
264  call swap ( in1, kk, io1, io2, list, lptr, lend, lpo1 )
265 !
266 ! A swap is not possible because KK and IN1 are already
267 ! adjacent. This error in SWPTST only occurs in the
268 ! neutral case and when there are nearly duplicate nodes.
269 !
270  if ( lpo1 /= 0 ) then
271  io1 = in1
272  cycle
273  end if
274 
275  lpo1 = lpo1s
276 
277  end if
278 !
279 ! No swap occurred. Test for termination and reset IO2 and IO1.
280 !
281  if ( lpo1 == lpf .or. list(lpo1) < 0 ) then
282  exit
283  end if
284 
285  io2 = io1
286  lpo1 = lptr(lpo1)
287  io1 = abs( list(lpo1) )
288 
289  end do
290 
291  return
292 end subroutine addnod
293 function areas ( v1, v2, v3 )
295 !*****************************************************************************80
296 !
297 ! Function: areas
298 ! Purpose: compute the area of a spherical triangle on the unit sphere
299 !
300 ! Discussion:
301 !
302 ! This function returns the area of a spherical triangle
303 ! on the unit sphere.
304 !
305 ! Modified:
306 !
307 ! 16 June 2007
308 !
309 ! Author:
310 !
311 ! Robert Renka
312 !
313 ! Reference:
314 !
315 ! Robert Renka,
316 ! Algorithm 772: STRIPACK,
317 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
318 ! ACM Transactions on Mathematical Software,
319 ! Volume 23, Number 3, September 1997, pages 416-434.
320 !
321 ! Parameters:
322 !
323 ! Input, real ( kind_real ) V1(3), V2(3), V3(3), the Cartesian coordinates
324 ! of unit vectors (the three triangle vertices in any order). These
325 ! vectors, if nonzero, are implicitly scaled to have length 1.
326 !
327 ! Output, real ( kind_real ) AREAS, the area of the spherical triangle
328 ! defined by V1, V2, and V3, in the range 0 to 2*PI (the area of a
329 ! hemisphere). AREAS = 0 (or 2*PI) if and only if V1, V2, and V3 lie in (or
330 ! close to) a plane containing the origin.
331 !
332 ! Local parameters:
333 !
334 ! A1,A2,A3 = Interior angles of the spherical triangle.
335 !
336 ! CA1,CA2,CA3 = cos(A1), cos(A2), and cos(A3), respectively.
337 !
338 ! DV1,DV2,DV3 = copies of V1, V2, and V3.
339 !
340 ! I = DO-loop index and index for Uij.
341 !
342 ! S12,S23,S31 = Sum of squared components of U12, U23, U31.
343 !
344 ! U12,U23,U31 = Unit normal vectors to the planes defined by
345 ! pairs of triangle vertices.
346 !
347  implicit none
348 
349  real ( kind_real ) a1
350  real ( kind_real ) a2
351  real ( kind_real ) a3
352  real ( kind_real ) areas
353  real ( kind_real ) ca1
354  real ( kind_real ) ca2
355  real ( kind_real ) ca3
356  real ( kind_real ) dv1(3)
357  real ( kind_real ) dv2(3)
358  real ( kind_real ) dv3(3)
359  real ( kind_real ) s12
360  real ( kind_real ) s23
361  real ( kind_real ) s31
362  real ( kind_real ) u12(3)
363  real ( kind_real ) u23(3)
364  real ( kind_real ) u31(3)
365  real ( kind_real ) v1(3)
366  real ( kind_real ) v2(3)
367  real ( kind_real ) v3(3)
368 
369  dv1(1:3) = v1(1:3)
370  dv2(1:3) = v2(1:3)
371  dv3(1:3) = v3(1:3)
372 !
373 ! Compute cross products Uij = Vi X Vj.
374 !
375  u12(1) = dv1(2) * dv2(3) - dv1(3) * dv2(2)
376  u12(2) = dv1(3) * dv2(1) - dv1(1) * dv2(3)
377  u12(3) = dv1(1) * dv2(2) - dv1(2) * dv2(1)
378 
379  u23(1) = dv2(2) * dv3(3) - dv2(3) * dv3(2)
380  u23(2) = dv2(3) * dv3(1) - dv2(1) * dv3(3)
381  u23(3) = dv2(1) * dv3(2) - dv2(2) * dv3(1)
382 
383  u31(1) = dv3(2) * dv1(3) - dv3(3) * dv1(2)
384  u31(2) = dv3(3) * dv1(1) - dv3(1) * dv1(3)
385  u31(3) = dv3(1) * dv1(2) - dv3(2) * dv1(1)
386 !
387 ! Normalize Uij to unit vectors.
388 !
389  s12 = dot_product( u12(1:3), u12(1:3) )
390  s23 = dot_product( u23(1:3), u23(1:3) )
391  s31 = dot_product( u31(1:3), u31(1:3) )
392 !
393 ! Test for a degenerate triangle associated with collinear vertices.
394 !
395  if ( .not.(abs(s12)>0.0) .or. .not.(abs(s23)>0.0) .or. .not.(abs(s31)>0.0) ) then
396  areas = 0.0_kind_real
397  return
398  end if
399 
400  s12 = sqrt( s12 )
401  s23 = sqrt( s23 )
402  s31 = sqrt( s31 )
403 
404  u12(1:3) = u12(1:3) / s12
405  u23(1:3) = u23(1:3) / s23
406  u31(1:3) = u31(1:3) / s31
407 !
408 ! Compute interior angles Ai as the dihedral angles between planes:
409 ! CA1 = cos(A1) = -<U12,U31>
410 ! CA2 = cos(A2) = -<U23,U12>
411 ! CA3 = cos(A3) = -<U31,U23>
412 !
413  ca1 = - dot_product( u12(1:3), u31(1:3) )
414  ca2 = - dot_product( u23(1:3), u12(1:3) )
415  ca3 = - dot_product( u31(1:3), u23(1:3) )
416 
417  ca1 = max( ca1, -1.0_kind_real )
418  ca1 = min( ca1, +1.0_kind_real )
419  ca2 = max( ca2, -1.0_kind_real )
420  ca2 = min( ca2, +1.0_kind_real )
421  ca3 = max( ca3, -1.0_kind_real )
422  ca3 = min( ca3, +1.0_kind_real )
423 
424  a1 = acos( ca1 )
425  a2 = acos( ca2 )
426  a3 = acos( ca3 )
427 !
428 ! Compute AREAS = A1 + A2 + A3 - PI.
429 !
430  areas = a1 + a2 + a3 - acos( -1.0_kind_real )
431 
432  if ( areas < 0.0_kind_real ) then
433  areas = 0.0_kind_real
434  end if
435 
436  return
437 end function areas
438 subroutine bdyadd ( kk, i1, i2, list, lptr, lend, lnew )
440 !*****************************************************************************80
441 !
442 ! Subroutine: bdyadd
443 ! Purpose: add a boundary node to a triangulation
444 !
445 ! Discussion:
446 !
447 ! This subroutine adds a boundary node to a triangulation
448 ! of a set of KK-1 points on the unit sphere. The data
449 ! structure is updated with the insertion of node KK, but no
450 ! optimization is performed.
451 !
452 ! This routine is identical to the similarly named routine
453 ! in TRIPACK.
454 !
455 ! Modified:
456 !
457 ! 16 June 2007
458 !
459 ! Author:
460 !
461 ! Robert Renka
462 !
463 ! Reference:
464 !
465 ! Robert Renka,
466 ! Algorithm 772: STRIPACK,
467 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
468 ! ACM Transactions on Mathematical Software,
469 ! Volume 23, Number 3, September 1997, pages 416-434.
470 !
471 ! Parameters:
472 !
473 ! Input, integer KK, the index of a node to be connected to
474 ! the sequence of all visible boundary nodes. 1 <= KK and
475 ! KK must not be equal to I1 or I2.
476 !
477 ! Input, integer I1, the first (rightmost as viewed from KK)
478 ! boundary node in the triangulation that is visible from
479 ! node KK (the line segment KK-I1 intersects no arcs.
480 !
481 ! Input, integer I2, the last (leftmost) boundary node that
482 ! is visible from node KK. I1 and I2 may be determined by TRFIND.
483 !
484 ! Input/output, integer LIST(6*(N-2)), LPTR(6*(N-2)), LEND(N),
485 ! LNEW, the triangulation data structure created by TRMESH.
486 ! Nodes I1 and I2 must be included
487 ! in the triangulation. On output, the data structure is updated with
488 ! the addition of node KK. Node KK is connected to I1, I2, and
489 ! all boundary nodes in between.
490 !
491 ! Local parameters:
492 !
493 ! K = Local copy of KK
494 ! LP = LIST pointer
495 ! LSAV = LIST pointer
496 ! N1,N2 = Local copies of I1 and I2, respectively
497 ! NEXT = Boundary node visible from K
498 ! NSAV = Boundary node visible from K
499 !
500  implicit none
501 
502  integer i1
503  integer i2
504  integer k
505  integer kk
506  integer lend(*)
507  integer list(*)
508  integer lnew
509  integer lp
510  integer lptr(*)
511  integer lsav
512  integer n1
513  integer n2
514  integer next
515  integer nsav
516 
517  k = kk
518  n1 = i1
519  n2 = i2
520 !
521 ! Add K as the last neighbor of N1.
522 !
523  lp = lend(n1)
524  lsav = lptr(lp)
525  lptr(lp) = lnew
526  list(lnew) = -k
527  lptr(lnew) = lsav
528  lend(n1) = lnew
529  lnew = lnew + 1
530  next = -list(lp)
531  list(lp) = next
532  nsav = next
533 !
534 ! Loop on the remaining boundary nodes between N1 and N2,
535 ! adding K as the first neighbor.
536 !
537  do
538 
539  lp = lend(next)
540  call insert ( k, lp, list, lptr, lnew )
541 
542  if ( next == n2 ) then
543  exit
544  end if
545 
546  next = -list(lp)
547  list(lp) = next
548 
549  end do
550 !
551 ! Add the boundary nodes between N1 and N2 as neighbors of node K.
552 !
553  lsav = lnew
554  list(lnew) = n1
555  lptr(lnew) = lnew + 1
556  lnew = lnew + 1
557  next = nsav
558 
559  do
560 
561  if ( next == n2 ) then
562  exit
563  end if
564 
565  list(lnew) = next
566  lptr(lnew) = lnew + 1
567  lnew = lnew + 1
568  lp = lend(next)
569  next = list(lp)
570 
571  end do
572 
573  list(lnew) = -n2
574  lptr(lnew) = lsav
575  lend(k) = lnew
576  lnew = lnew + 1
577 
578  return
579 end subroutine bdyadd
580 subroutine bnodes ( n, list, lptr, lend, nodes, nb, na, nt )
582 !*****************************************************************************80
583 !
584 ! Subroutine: bnodes
585 ! Purpose: return the boundary nodes of a triangulation
586 !
587 ! Discussion:
588 !
589 ! Given a triangulation of N nodes on the unit sphere created by TRMESH,
590 ! this subroutine returns an array containing the indexes (if any) of
591 ! the counterclockwise sequence of boundary nodes, that is, the nodes on
592 ! the boundary of the convex hull of the set of nodes. The
593 ! boundary is empty if the nodes do not lie in a single
594 ! hemisphere. The numbers of boundary nodes, arcs, and
595 ! triangles are also returned.
596 !
597 ! Modified:
598 !
599 ! 16 June 2007
600 !
601 ! Author:
602 !
603 ! Robert Renka
604 !
605 ! Reference:
606 !
607 ! Robert Renka,
608 ! Algorithm 772: STRIPACK,
609 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
610 ! ACM Transactions on Mathematical Software,
611 ! Volume 23, Number 3, September 1997, pages 416-434.
612 !
613 ! Parameters:
614 !
615 ! Input, integer N, the number of nodes in the triangulation.
616 ! 3 <= N.
617 !
618 ! Input, integer LIST(6*(N-2)), LPTR(6*(N-2)), LEND(N), the
619 ! data structure defining the triangulation, created by TRMESH.
620 !
621 ! Output, integer NODES(*), the ordered sequence of NB boundary
622 ! node indexes in the range 1 to N. For safety, the dimension of NODES
623 ! should be N.
624 !
625 ! Output, integer NB, the number of boundary nodes.
626 !
627 ! Output, integer NA, NT, the number of arcs and triangles,
628 ! respectively, in the triangulation.
629 !
630 ! Local parameters:
631 !
632 ! K = NODES index
633 ! LP = LIST pointer
634 ! N0 = Boundary node to be added to NODES
635 ! NN = Local copy of N
636 ! NST = First element of nodes (arbitrarily chosen to be
637 ! the one with smallest index)
638 !
639  implicit none
640 
641  integer n
642 
643  integer i
644  integer k
645  integer lend(n)
646  integer list(6*(n-2))
647  integer lp
648  integer lptr(6*(n-2))
649  integer n0
650  integer na
651  integer nb
652  integer nn
653  integer nodes(*)
654  integer nst
655  integer nt
656 
657  nn = n
658 !
659 ! Search for a boundary node.
660 !
661  nst = 0
662 
663  do i = 1, nn
664 
665  lp = lend(i)
666 
667  if ( list(lp) < 0 ) then
668  nst = i
669  exit
670  end if
671 
672  end do
673 !
674 ! The triangulation contains no boundary nodes.
675 !
676  if ( nst == 0 ) then
677  nb = 0
678  na = 3 * ( nn - 2 )
679  nt = 2 * ( nn - 2 )
680  return
681  end if
682 !
683 ! NST is the first boundary node encountered.
684 !
685 ! Initialize for traversal of the boundary.
686 !
687  nodes(1) = nst
688  k = 1
689  n0 = nst
690 !
691 ! Traverse the boundary in counterclockwise order.
692 !
693  do
694 
695  lp = lend(n0)
696  lp = lptr(lp)
697  n0 = list(lp)
698 
699  if ( n0 == nst ) then
700  exit
701  end if
702 
703  k = k + 1
704  nodes(k) = n0
705 
706  end do
707 !
708 ! Store the counts.
709 !
710  nb = k
711  nt = 2 * n - nb - 2
712  na = nt + n - 1
713 
714  return
715 end subroutine bnodes
716 subroutine circum ( v1, v2, v3, c, ier )
718 !*****************************************************************************80
719 !
720 ! Subroutine: circum
721 ! Purpose: return the circumcenter of a spherical triangle
722 !
723 ! Discussion:
724 !
725 ! This subroutine returns the circumcenter of a spherical triangle on the
726 ! unit sphere: the point on the sphere surface that is equally distant
727 ! from the three triangle vertices and lies in the same hemisphere, where
728 ! distance is taken to be arc-length on the sphere surface.
729 !
730 ! Modified:
731 !
732 ! 16 June 2007
733 !
734 ! Author:
735 !
736 ! Robert Renka
737 !
738 ! Reference:
739 !
740 ! Robert Renka,
741 ! Algorithm 772: STRIPACK,
742 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
743 ! ACM Transactions on Mathematical Software,
744 ! Volume 23, Number 3, September 1997, pages 416-434.
745 !
746 ! Parameters:
747 !
748 ! Input, real V1(3), V2(3), V3(3), the coordinates of the
749 ! three triangle vertices (unit vectors) in counter clockwise order.
750 !
751 ! Output, real C(3), the coordinates of the circumcenter unless
752 ! 0 < IER, in which case C is not defined. C = (V2-V1) X (V3-V1)
753 ! normalized to a unit vector.
754 !
755 ! Output, integer IER = Error indicator:
756 ! 0, if no errors were encountered.
757 ! 1, if V1, V2, and V3 lie on a common line: (V2-V1) X (V3-V1) = 0.
758 !
759 ! Local parameters:
760 !
761 ! CNORM = Norm of CU: used to compute C
762 ! CU = Scalar multiple of C: E1 X E2
763 ! E1,E2 = Edges of the underlying planar triangle:
764 ! V2-V1 and V3-V1, respectively
765 ! I = DO-loop index
766 !
767  implicit none
768 
769  real (kind_real) c(3)
770  real (kind_real) cnorm
771  real (kind_real) cu(3)
772  real (kind_real) e1(3)
773  real (kind_real) e2(3)
774  integer ier
775  real (kind_real) v1(3)
776  real (kind_real) v2(3)
777  real (kind_real) v3(3)
778 
779  ier = 0
780 
781  e1(1:3) = v2(1:3) - v1(1:3)
782  e2(1:3) = v3(1:3) - v1(1:3)
783 !
784 ! Compute CU = E1 X E2 and CNORM**2.
785 !
786  cu(1) = e1(2) * e2(3) - e1(3) * e2(2)
787  cu(2) = e1(3) * e2(1) - e1(1) * e2(3)
788  cu(3) = e1(1) * e2(2) - e1(2) * e2(1)
789 
790  cnorm = sqrt( sum( cu(1:3)**2 ) )
791 !
792 ! The vertices lie on a common line if and only if CU is the zero vector.
793 !
794  if ( .not.(abs(cnorm)>0.0) ) then
795  ier = 1
796  return
797  end if
798 
799  c(1:3) = cu(1:3) / cnorm
800 
801  return
802 end subroutine circum
803 subroutine covsph ( kk, n0, list, lptr, lend, lnew )
805 !*****************************************************************************80
806 !
807 ! Subroutine: covsph
808 ! Purpose: connect an exterior node to boundary nodes, covering the sphere
809 !
810 ! Discussion:
811 !
812 ! This subroutine connects an exterior node KK to all
813 ! boundary nodes of a triangulation of KK-1 points on the
814 ! unit sphere, producing a triangulation that covers the
815 ! sphere. The data structure is updated with the addition
816 ! of node KK, but no optimization is performed. All
817 ! boundary nodes must be visible from node KK.
818 !
819 ! Modified:
820 !
821 ! 16 June 2007
822 !
823 ! Author:
824 !
825 ! Robert Renka
826 !
827 ! Reference:
828 !
829 ! Robert Renka,
830 ! Algorithm 772: STRIPACK,
831 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
832 ! ACM Transactions on Mathematical Software,
833 ! Volume 23, Number 3, September 1997, pages 416-434.
834 !
835 ! Parameters:
836 !
837 ! Input, integer KK = Index of the node to be connected to the
838 ! set of all boundary nodes. 4 <= KK.
839 !
840 ! Input, integer N0 = Index of a boundary node (in the range
841 ! 1 to KK-1). N0 may be determined by TRFIND.
842 !
843 ! Input/output, integer LIST(6*(N-2)), LPTR(6*(N-2)), LEND(N),
844 ! LNEW, the triangulation data structure created by TRMESH. Node N0 must
845 ! be included in the triangulation. On output, updated with the addition
846 ! of node KK as the last entry. The updated triangulation contains no
847 ! boundary nodes.
848 !
849 ! Local parameters:
850 !
851 ! K = Local copy of KK
852 ! LP = LIST pointer
853 ! LSAV = LIST pointer
854 ! NEXT = Boundary node visible from K
855 ! NST = Local copy of N0
856 !
857  implicit none
858 
859  integer k
860  integer kk
861  integer lend(*)
862  integer list(*)
863  integer lnew
864  integer lp
865  integer lptr(*)
866  integer lsav
867  integer n0
868  integer next
869  integer nst
870 
871  k = kk
872  nst = n0
873 !
874 ! Traverse the boundary in clockwise order, inserting K as
875 ! the first neighbor of each boundary node, and converting
876 ! the boundary node to an interior node.
877 !
878  next = nst
879 
880  do
881 
882  lp = lend(next)
883  call insert ( k, lp, list, lptr, lnew )
884  next = -list(lp)
885  list(lp) = next
886 
887  if ( next == nst ) then
888  exit
889  end if
890 
891  end do
892 !
893 ! Traverse the boundary again, adding each node to K's adjacency list.
894 !
895  lsav = lnew
896 
897  do
898 
899  lp = lend(next)
900  list(lnew) = next
901  lptr(lnew) = lnew + 1
902  lnew = lnew + 1
903  next = list(lp)
904 
905  if ( next == nst ) then
906  exit
907  end if
908 
909  end do
910 
911  lptr(lnew-1) = lsav
912  lend(k) = lnew - 1
913 
914  return
915 end subroutine covsph
916 subroutine det ( x1, y1, z1, x2, y2, z2, x0, y0, z0, output )
917 !*****************************************************************************80
918 !
919 ! Subroutine: det
920 ! Purpose: compute 3D determinant
921 !
922 ! DET(X1,...,Z0) >= 0 if and only if (X0,Y0,Z0) is in the
923 ! (closed) left hemisphere defined by the plane containing (0,0,0),
924 ! (X1,Y1,Z1), and (X2,Y2,Z2), where left is defined relative to an
925 ! observer at (X1,Y1,Z1) facing (X2,Y2,Z2).
926 !
927  implicit none
928 
929  real ( kind_real ) x1
930  real ( kind_real ) y1
931  real ( kind_real ) z1
932  real ( kind_real ) x2
933  real ( kind_real ) y2
934  real ( kind_real ) z2
935  real ( kind_real ) x0
936  real ( kind_real ) y0
937  real ( kind_real ) z0
938  real ( kind_real ) t1
939  real ( kind_real ) t2
940  real ( kind_real ) t3
941  real ( kind_real ) output
942 
943  t1 = x0*(y1*z2-y2*z1)
944  t2 = y0*(x1*z2-x2*z1)
945  t3 = z0*(x1*y2-x2*y1)
946  output = t1 - t2 + t3
947 
948  ! Indistinguishability threshold for cross-plateform reproducibility
949  if (indist(output,t1).or.indist(output,t2).or.indist(output,t3)) output = 0.0
950 end subroutine det
951 subroutine crlist ( n, ncol, x, y, z, list, lend, lptr, lnew, &
952  ltri, listc, nb, xc, yc, zc, rc, ier )
954 !*****************************************************************************80
955 !
956 ! Subroutine: crlist
957 ! Purpose: return triangle circumcenters and other information
958 !
959 ! Discussion:
960 !
961 ! Given a Delaunay triangulation of nodes on the surface
962 ! of the unit sphere, this subroutine returns the set of
963 ! triangle circumcenters corresponding to Voronoi vertices,
964 ! along with the circumradii and a list of triangle indexes
965 ! LISTC stored in one-to-one correspondence with LIST/LPTR
966 ! entries.
967 !
968 ! A triangle circumcenter is the point (unit vector) lying
969 ! at the same angular distance from the three vertices and
970 ! contained in the same hemisphere as the vertices. (Note
971 ! that the negative of a circumcenter is also equidistant
972 ! from the vertices.) If the triangulation covers the
973 ! surface, the Voronoi vertices are the circumcenters of the
974 ! triangles in the Delaunay triangulation. LPTR, LEND, and
975 ! LNEW are not altered in this case.
976 !
977 ! On the other hand, if the nodes are contained in a
978 ! single hemisphere, the triangulation is implicitly extended
979 ! to the entire surface by adding pseudo-arcs (of length
980 ! greater than 180 degrees) between boundary nodes forming
981 ! pseudo-triangles whose 'circumcenters' are included in the
982 ! list. This extension to the triangulation actually
983 ! consists of a triangulation of the set of boundary nodes in
984 ! which the swap test is reversed (a non-empty circumcircle
985 ! test). The negative circumcenters are stored as the
986 ! pseudo-triangle 'circumcenters'. LISTC, LPTR, LEND, and
987 ! LNEW contain a data structure corresponding to the
988 ! extended triangulation (Voronoi diagram), but LIST is not
989 ! altered in this case. Thus, if it is necessary to retain
990 ! the original (unextended) triangulation data structure,
991 ! copies of LPTR and LNEW must be saved before calling this
992 ! routine.
993 !
994 ! Modified:
995 !
996 ! 16 June 2007
997 !
998 ! Author:
999 !
1000 ! Robert Renka
1001 !
1002 ! Reference:
1003 !
1004 ! Robert Renka,
1005 ! Algorithm 772: STRIPACK,
1006 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
1007 ! ACM Transactions on Mathematical Software,
1008 ! Volume 23, Number 3, September 1997, pages 416-434.
1009 !
1010 ! Parameters:
1011 !
1012 ! Input, integer N, the number of nodes in the triangulation.
1013 ! 3 <= N. Note that, if N = 3, there are only two Voronoi vertices
1014 ! separated by 180 degrees, and the Voronoi regions are not well defined.
1015 !
1016 ! Input, integer NCOL, the number of columns reserved for LTRI.
1017 ! This must be at least NB-2, where NB is the number of boundary nodes.
1018 !
1019 ! Input, real X(N), Y(N), Z(N), the coordinates of the nodes
1020 ! (unit vectors).
1021 !
1022 ! Input, integer LIST(6*(N-2)), the set of adjacency lists.
1023 ! Refer to TRMESH.
1024 !
1025 ! Input, integer LEND(N), the set of pointers to ends of
1026 ! adjacency lists. Refer to TRMESH.
1027 !
1028 ! Input/output, integer LPTR(6*(N-2)), pointers associated
1029 ! with LIST. Refer to TRMESH. On output, pointers associated with LISTC.
1030 ! Updated for the addition of pseudo-triangles if the original triangulation
1031 ! contains boundary nodes (0 < NB).
1032 !
1033 ! Input/output, integer LNEW. On input, a pointer to the first
1034 ! empty location in LIST and LPTR (list length plus one). On output,
1035 ! pointer to the first empty location in LISTC and LPTR (list length plus
1036 ! one). LNEW is not altered if NB = 0.
1037 !
1038 ! Output, integer LTRI(6,NCOL). Triangle list whose first NB-2
1039 ! columns contain the indexes of a clockwise-ordered sequence of vertices
1040 ! (first three rows) followed by the LTRI column indexes of the triangles
1041 ! opposite the vertices (or 0 denoting the exterior region) in the last
1042 ! three rows. This array is not generally of any further use outside this
1043 ! routine.
1044 !
1045 ! Output, integer LISTC(3*NT), where NT = 2*N-4 is the number
1046 ! of triangles in the triangulation (after extending it to cover the entire
1047 ! surface if necessary). Contains the triangle indexes (indexes to XC, YC,
1048 ! ZC, and RC) stored in 1-1 correspondence with LIST/LPTR entries (or entries
1049 ! that would be stored in LIST for the extended triangulation): the index
1050 ! of triangle (N1,N2,N3) is stored in LISTC(K), LISTC(L), and LISTC(M),
1051 ! where LIST(K), LIST(L), and LIST(M) are the indexes of N2 as a neighbor
1052 ! of N1, N3 as a neighbor of N2, and N1 as a neighbor of N3. The Voronoi
1053 ! region associated with a node is defined by the CCW-ordered sequence of
1054 ! circumcenters in one-to-one correspondence with its adjacency
1055 ! list (in the extended triangulation).
1056 !
1057 ! Output, integer NB, the number of boundary nodes unless
1058 ! IER = 1.
1059 !
1060 ! Output, real XC(2*N-4), YC(2*N-4), ZC(2*N-4), the coordinates
1061 ! of the triangle circumcenters (Voronoi vertices). XC(I)**2 + YC(I)**2
1062 ! + ZC(I)**2 = 1. The first NB-2 entries correspond to pseudo-triangles
1063 ! if 0 < NB.
1064 !
1065 ! Output, real RC(2*N-4), the circumradii (the arc lengths or
1066 ! angles between the circumcenters and associated triangle vertices) in
1067 ! 1-1 correspondence with circumcenters.
1068 !
1069 ! Output, integer IER = Error indicator:
1070 ! 0, if no errors were encountered.
1071 ! 1, if N < 3.
1072 ! 2, if NCOL < NB-2.
1073 ! 3, if a triangle is degenerate (has vertices lying on a common geodesic).
1074 !
1075 ! Local parameters:
1076 !
1077 ! C = Circumcenter returned by Subroutine CIRCUM
1078 ! I1,I2,I3 = Permutation of (1,2,3): LTRI row indexes
1079 ! I4 = LTRI row index in the range 1 to 3
1080 ! IERR = Error flag for calls to CIRCUM
1081 ! KT = Triangle index
1082 ! KT1,KT2 = Indexes of a pair of adjacent pseudo-triangles
1083 ! KT11,KT12 = Indexes of the pseudo-triangles opposite N1
1084 ! and N2 as vertices of KT1
1085 ! KT21,KT22 = Indexes of the pseudo-triangles opposite N1
1086 ! and N2 as vertices of KT2
1087 ! LP,LPN = LIST pointers
1088 ! LPL = LIST pointer of the last neighbor of N1
1089 ! N0 = Index of the first boundary node (initial
1090 ! value of N1) in the loop on boundary nodes
1091 ! used to store the pseudo-triangle indexes
1092 ! in LISTC
1093 ! N1,N2,N3 = Nodal indexes defining a triangle (CCW order)
1094 ! or pseudo-triangle (clockwise order)
1095 ! N4 = Index of the node opposite N2 -> N1
1096 ! NM2 = N-2
1097 ! NN = Local copy of N
1098 ! NT = Number of pseudo-triangles: NB-2
1099 ! SWP = Logical variable set to TRUE in each optimization
1100 ! loop (loop on pseudo-arcs) iff a swap is performed.
1101 !
1102 ! V1,V2,V3 = Vertices of triangle KT = (N1,N2,N3) sent to subroutine
1103 ! CIRCUM
1104 !
1105  implicit none
1106 
1107  integer n
1108  integer ncol
1109 
1110  real (kind_real) c(3)
1111  integer i1
1112  integer i2
1113  integer i3
1114  integer i4
1115  integer ier
1116  integer ierr
1117  integer kt
1118  integer kt1
1119  integer kt11
1120  integer kt12
1121  integer kt2
1122  integer kt21
1123  integer kt22
1124  integer lend(n)
1125  integer list(6*(n-2))
1126  integer listc(6*(n-2))
1127  integer lnew
1128  integer lp
1129  integer lpl
1130  integer lpn
1131  integer lptr(6*(n-2))
1132  integer ltri(6,ncol)
1133  integer n0
1134  integer n1
1135  integer n2
1136  integer n3
1137  integer n4
1138  integer nb
1139  integer nm2
1140  integer nn
1141  integer nt
1142  real (kind_real) rc(2*n-4)
1143  logical swp
1144  real (kind_real) t
1145  real (kind_real) v1(3)
1146  real (kind_real) v2(3)
1147  real (kind_real) v3(3)
1148  real (kind_real) x(n)
1149  real (kind_real) xc(2*n-4)
1150  real (kind_real) y(n)
1151  real (kind_real) yc(2*n-4)
1152  real (kind_real) z(n)
1153  real (kind_real) zc(2*n-4)
1154  logical output
1155 
1156  nn = n
1157  nb = 0
1158  nt = 0
1159 
1160  if ( nn < 3 ) then
1161  ier = 1
1162  return
1163  end if
1164 !
1165 ! Search for a boundary node N1.
1166 !
1167  lp = 0
1168 
1169  do n1 = 1, nn
1170 
1171  if ( list(lend(n1)) < 0 ) then
1172  lp = lend(n1)
1173  exit
1174  end if
1175 
1176  end do
1177 !
1178 ! Does the triangulation already cover the sphere?
1179 !
1180  if ( lp /= 0 ) then
1181 !
1182 ! There are 3 <= NB boundary nodes. Add NB-2 pseudo-triangles (N1,N2,N3)
1183 ! by connecting N3 to the NB-3 boundary nodes to which it is not
1184 ! already adjacent.
1185 !
1186 ! Set N3 and N2 to the first and last neighbors,
1187 ! respectively, of N1.
1188 !
1189  n2 = -list(lp)
1190  lp = lptr(lp)
1191  n3 = list(lp)
1192 !
1193 ! Loop on boundary arcs N1 -> N2 in clockwise order,
1194 ! storing triangles (N1,N2,N3) in column NT of LTRI
1195 ! along with the indexes of the triangles opposite
1196 ! the vertices.
1197 !
1198  do
1199 
1200  nt = nt + 1
1201 
1202  if ( nt <= ncol ) then
1203  ltri(1,nt) = n1
1204  ltri(2,nt) = n2
1205  ltri(3,nt) = n3
1206  ltri(4,nt) = nt + 1
1207  ltri(5,nt) = nt - 1
1208  ltri(6,nt) = 0
1209  end if
1210 
1211  n1 = n2
1212  lp = lend(n1)
1213  n2 = -list(lp)
1214 
1215  if ( n2 == n3 ) then
1216  exit
1217  end if
1218 
1219  end do
1220 
1221  nb = nt + 2
1222 
1223  if ( ncol < nt ) then
1224  ier = 2
1225  return
1226  end if
1227 
1228  ltri(4,nt) = 0
1229 !
1230 ! Optimize the exterior triangulation (set of pseudo-
1231 ! triangles) by applying swaps to the pseudo-arcs N1-N2
1232 ! (pairs of adjacent pseudo-triangles KT1 and KT1 < KT2).
1233 ! The loop on pseudo-arcs is repeated until no swaps are
1234 ! performed.
1235 !
1236  if ( nt /= 1 ) then
1237 
1238  do
1239 
1240  swp = .false.
1241 
1242  do kt1 = 1, nt - 1
1243 
1244  do i3 = 1, 3
1245 
1246  kt2 = ltri(i3+3,kt1)
1247 
1248  if ( kt2 <= kt1 ) then
1249  cycle
1250  end if
1251 !
1252 ! The LTRI row indexes (I1,I2,I3) of triangle KT1 =
1253 ! (N1,N2,N3) are a cyclical permutation of (1,2,3).
1254 !
1255  if ( i3 == 1 ) then
1256  i1 = 2
1257  i2 = 3
1258  else if ( i3 == 2 ) then
1259  i1 = 3
1260  i2 = 1
1261  else
1262  i1 = 1
1263  i2 = 2
1264  end if
1265 
1266  n1 = ltri(i1,kt1)
1267  n2 = ltri(i2,kt1)
1268  n3 = ltri(i3,kt1)
1269 !
1270 ! KT2 = (N2,N1,N4) for N4 = LTRI(I,KT2), where LTRI(I+3,KT2) = KT1.
1271 !
1272  if ( ltri(4,kt2) == kt1 ) then
1273  i4 = 1
1274  else if ( ltri(5,kt2 ) == kt1 ) then
1275  i4 = 2
1276  else
1277  i4 = 3
1278  end if
1279 
1280  n4 = ltri(i4,kt2)
1281 !
1282 ! The empty circumcircle test is reversed for the pseudo-
1283 ! triangles. The reversal is implicit in the clockwise
1284 ! ordering of the vertices.
1285 !
1286  call swptst ( n1, n2, n3, n4, x, y, z, output )
1287  if ( .not. output ) then
1288  cycle
1289  end if
1290 !
1291 ! Swap arc N1-N2 for N3-N4. KTij is the triangle opposite
1292 ! Nj as a vertex of KTi.
1293 !
1294  swp = .true.
1295  kt11 = ltri(i1+3,kt1)
1296  kt12 = ltri(i2+3,kt1)
1297 
1298  if ( i4 == 1 ) then
1299  i2 = 2
1300  i1 = 3
1301  else if ( i4 == 2 ) then
1302  i2 = 3
1303  i1 = 1
1304  else
1305  i2 = 1
1306  i1 = 2
1307  end if
1308 
1309  kt21 = ltri(i1+3,kt2)
1310  kt22 = ltri(i2+3,kt2)
1311  ltri(1,kt1) = n4
1312  ltri(2,kt1) = n3
1313  ltri(3,kt1) = n1
1314  ltri(4,kt1) = kt12
1315  ltri(5,kt1) = kt22
1316  ltri(6,kt1) = kt2
1317  ltri(1,kt2) = n3
1318  ltri(2,kt2) = n4
1319  ltri(3,kt2) = n2
1320  ltri(4,kt2) = kt21
1321  ltri(5,kt2) = kt11
1322  ltri(6,kt2) = kt1
1323 !
1324 ! Correct the KT11 and KT22 entries that changed.
1325 !
1326  if ( kt11 /= 0 ) then
1327  i4 = 4
1328  if ( ltri(4,kt11) /= kt1 ) then
1329  i4 = 5
1330  if ( ltri(5,kt11) /= kt1 ) i4 = 6
1331  end if
1332  ltri(i4,kt11) = kt2
1333  end if
1334 
1335  if ( kt22 /= 0 ) then
1336  i4 = 4
1337  if ( ltri(4,kt22) /= kt2 ) then
1338  i4 = 5
1339  if ( ltri(5,kt22) /= kt2 ) then
1340  i4 = 6
1341  end if
1342  end if
1343  ltri(i4,kt22) = kt1
1344  end if
1345 
1346  end do
1347 
1348  end do
1349 
1350  if ( .not. swp ) then
1351  exit
1352  end if
1353 
1354  end do
1355 
1356  end if
1357 !
1358 ! Compute and store the negative circumcenters and radii of
1359 ! the pseudo-triangles in the first NT positions.
1360 !
1361  do kt = 1, nt
1362 
1363  n1 = ltri(1,kt)
1364  n2 = ltri(2,kt)
1365  n3 = ltri(3,kt)
1366  v1(1) = x(n1)
1367  v1(2) = y(n1)
1368  v1(3) = z(n1)
1369  v2(1) = x(n2)
1370  v2(2) = y(n2)
1371  v2(3) = z(n2)
1372  v3(1) = x(n3)
1373  v3(2) = y(n3)
1374  v3(3) = z(n3)
1375 
1376  call circum ( v1, v2, v3, c, ierr )
1377 
1378  if ( ierr /= 0 ) then
1379  ier = 3
1380  return
1381  end if
1382 !
1383 ! Store the negative circumcenter and radius (computed from <V1,C>).
1384 !
1385  xc(kt) = c(1)
1386  yc(kt) = c(2)
1387  zc(kt) = c(3)
1388 
1389  t = dot_product( v1(1:3), c(1:3) )
1390  t = max( t, -1.0_kind_real )
1391  t = min( t, +1.0_kind_real )
1392 
1393  rc(kt) = acos( t )
1394 
1395  end do
1396 
1397  end if
1398 !
1399 ! Compute and store the circumcenters and radii of the
1400 ! actual triangles in positions KT = NT+1, NT+2, ...
1401 !
1402 ! Also, store the triangle indexes KT in the appropriate LISTC positions.
1403 !
1404  kt = nt
1405 !
1406 ! Loop on nodes N1.
1407 !
1408  nm2 = nn - 2
1409 
1410  do n1 = 1, nm2
1411 
1412  lpl = lend(n1)
1413  lp = lpl
1414  n3 = list(lp)
1415 !
1416 ! Loop on adjacent neighbors N2,N3 of N1 for which N1 < N2 and N1 < N3.
1417 !
1418  do
1419 
1420  lp = lptr(lp)
1421  n2 = n3
1422  n3 = abs( list(lp) )
1423 
1424  if ( n1 < n2 .and. n1 < n3 ) then
1425 
1426  kt = kt + 1
1427 !
1428 ! Compute the circumcenter C of triangle KT = (N1,N2,N3).
1429 !
1430  v1(1) = x(n1)
1431  v1(2) = y(n1)
1432  v1(3) = z(n1)
1433  v2(1) = x(n2)
1434  v2(2) = y(n2)
1435  v2(3) = z(n2)
1436  v3(1) = x(n3)
1437  v3(2) = y(n3)
1438  v3(3) = z(n3)
1439 
1440  call circum ( v1, v2, v3, c, ierr )
1441 
1442  if ( ierr /= 0 ) then
1443  ier = 3
1444  return
1445  end if
1446 !
1447 ! Store the circumcenter, radius and triangle index.
1448 !
1449  xc(kt) = c(1)
1450  yc(kt) = c(2)
1451  zc(kt) = c(3)
1452 
1453  t = dot_product( v1(1:3), c(1:3) )
1454  t = max( t, -1.0_kind_real )
1455  t = min( t, +1.0_kind_real )
1456 
1457  rc(kt) = acos( t )
1458 !
1459 ! Store KT in LISTC(LPN), where abs ( LIST(LPN) ) is the
1460 ! index of N2 as a neighbor of N1, N3 as a neighbor
1461 ! of N2, and N1 as a neighbor of N3.
1462 !
1463  call lstptr ( lpl, n2, list, lptr, lpn )
1464  listc(lpn) = kt
1465  call lstptr ( lend(n2), n3, list, lptr, lpn )
1466  listc(lpn) = kt
1467  call lstptr ( lend(n3), n1, list, lptr, lpn )
1468  listc(lpn) = kt
1469 
1470  end if
1471 
1472  if ( lp == lpl ) then
1473  exit
1474  end if
1475 
1476  end do
1477 
1478  end do
1479 
1480  if ( nt == 0 ) then
1481  ier = 0
1482  return
1483  end if
1484 !
1485 ! Store the first NT triangle indexes in LISTC.
1486 !
1487 ! Find a boundary triangle KT1 = (N1,N2,N3) with a boundary arc opposite N3.
1488 !
1489  kt1 = 0
1490 
1491  do
1492 
1493  kt1 = kt1 + 1
1494 
1495  if ( ltri(4,kt1) == 0 ) then
1496  i1 = 2
1497  i2 = 3
1498  i3 = 1
1499  exit
1500  else if ( ltri(5,kt1) == 0 ) then
1501  i1 = 3
1502  i2 = 1
1503  i3 = 2
1504  exit
1505  else if ( ltri(6,kt1) == 0 ) then
1506  i1 = 1
1507  i2 = 2
1508  i3 = 3
1509  exit
1510  end if
1511 
1512  end do
1513 
1514  n1 = ltri(i1,kt1)
1515  n0 = n1
1516 !
1517 ! Loop on boundary nodes N1 in CCW order, storing the
1518 ! indexes of the clockwise-ordered sequence of triangles
1519 ! that contain N1. The first triangle overwrites the
1520 ! last neighbor position, and the remaining triangles,
1521 ! if any, are appended to N1's adjacency list.
1522 !
1523 ! A pointer to the first neighbor of N1 is saved in LPN.
1524 !
1525  do
1526 
1527  lp = lend(n1)
1528  lpn = lptr(lp)
1529  listc(lp) = kt1
1530 !
1531 ! Loop on triangles KT2 containing N1.
1532 !
1533  do
1534 
1535  kt2 = ltri(i2+3,kt1)
1536 
1537  if ( kt2 == 0 ) then
1538  exit
1539  end if
1540 !
1541 ! Append KT2 to N1's triangle list.
1542 !
1543  lptr(lp) = lnew
1544  lp = lnew
1545  listc(lp) = kt2
1546  lnew = lnew + 1
1547 !
1548 ! Set KT1 to KT2 and update (I1,I2,I3) such that LTRI(I1,KT1) = N1.
1549 !
1550  kt1 = kt2
1551 
1552  if ( ltri(1,kt1) == n1 ) then
1553  i1 = 1
1554  i2 = 2
1555  i3 = 3
1556  else if ( ltri(2,kt1) == n1 ) then
1557  i1 = 2
1558  i2 = 3
1559  i3 = 1
1560  else
1561  i1 = 3
1562  i2 = 1
1563  i3 = 2
1564  end if
1565 
1566  end do
1567 !
1568 ! Store the saved first-triangle pointer in LPTR(LP), set
1569 ! N1 to the next boundary node, test for termination,
1570 ! and permute the indexes: the last triangle containing
1571 ! a boundary node is the first triangle containing the
1572 ! next boundary node.
1573 !
1574  lptr(lp) = lpn
1575  n1 = ltri(i3,kt1)
1576 
1577  if ( n1 == n0 ) then
1578  exit
1579  end if
1580 
1581  i4 = i3
1582  i3 = i2
1583  i2 = i1
1584  i1 = i4
1585 
1586  end do
1587 
1588  ier = 0
1589 
1590  return
1591 end subroutine crlist
1592 subroutine insert ( k, lp, list, lptr, lnew )
1594 !*****************************************************************************80
1595 !
1596 ! Subroutine: insert
1597 ! Purpose: insert K as a neighbor of N1
1598 !
1599 ! Discussion:
1600 !
1601 ! This subroutine inserts K as a neighbor of N1 following
1602 ! N2, where LP is the LIST pointer of N2 as a neighbor of
1603 ! N1. Note that, if N2 is the last neighbor of N1, K will
1604 ! become the first neighbor (even if N1 is a boundary node).
1605 !
1606 ! This routine is identical to the similarly named routine in TRIPACK.
1607 !
1608 ! Modified:
1609 !
1610 ! 16 June 2007
1611 !
1612 ! Author:
1613 !
1614 ! Robert Renka
1615 !
1616 ! Reference:
1617 !
1618 ! Robert Renka,
1619 ! Algorithm 772: STRIPACK,
1620 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
1621 ! ACM Transactions on Mathematical Software,
1622 ! Volume 23, Number 3, September 1997, pages 416-434.
1623 !
1624 ! Parameters:
1625 !
1626 ! Input, integer K, the index of the node to be inserted.
1627 !
1628 ! Input, integer LP, the LIST pointer of N2 as a neighbor of N1.
1629 !
1630 ! Input/output, integer LIST(6*(N-2)), LPTR(6*(N-2)), LNEW,
1631 ! the data structure defining the triangulation, created by TRMESH.
1632 ! On output, updated with the addition of node K.
1633 !
1634  implicit none
1635 
1636  integer k
1637  integer list(*)
1638  integer lnew
1639  integer lp
1640  integer lptr(*)
1641  integer lsav
1642 
1643  lsav = lptr(lp)
1644  lptr(lp) = lnew
1645  list(lnew) = k
1646  lptr(lnew) = lsav
1647  lnew = lnew + 1
1648 
1649  return
1650 end subroutine insert
1651 function inside ( p, lv, xv, yv, zv, nv, listv, ier )
1653 !*****************************************************************************80
1654 !
1655 ! Function: inside
1656 ! Purpose: determine if a point is inside a polygonal region
1657 !
1658 ! Discussion:
1659 !
1660 ! This function locates a point P relative to a polygonal
1661 ! region R on the surface of the unit sphere, returning
1662 ! INSIDE = TRUE if and only if P is contained in R. R is
1663 ! defined by a cyclically ordered sequence of vertices which
1664 ! form a positively-oriented simple closed curve. Adjacent
1665 ! vertices need not be distinct but the curve must not be
1666 ! self-intersecting. Also, while polygon edges are by definition
1667 ! restricted to a single hemisphere, R is not so
1668 ! restricted. Its interior is the region to the left as the
1669 ! vertices are traversed in order.
1670 !
1671 ! The algorithm consists of selecting a point Q in R and
1672 ! then finding all points at which the great circle defined
1673 ! by P and Q intersects the boundary of R. P lies inside R
1674 ! if and only if there is an even number of intersection
1675 ! points between Q and P. Q is taken to be a point immediately
1676 ! to the left of a directed boundary edge -- the first
1677 ! one that results in no consistency-check failures.
1678 !
1679 ! If P is close to the polygon boundary, the problem is
1680 ! ill-conditioned and the decision may be incorrect. Also,
1681 ! an incorrect decision may result from a poor choice of Q
1682 ! (if, for example, a boundary edge lies on the great circle
1683 ! defined by P and Q). A more reliable result could be
1684 ! obtained by a sequence of calls to INSIDE with the vertices
1685 ! cyclically permuted before each call (to alter the
1686 ! choice of Q).
1687 !
1688 ! Modified:
1689 !
1690 ! 16 June 2007
1691 !
1692 ! Author:
1693 !
1694 ! Robert Renka
1695 !
1696 ! Reference:
1697 !
1698 ! Robert Renka,
1699 ! Algorithm 772: STRIPACK,
1700 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
1701 ! ACM Transactions on Mathematical Software,
1702 ! Volume 23, Number 3, September 1997, pages 416-434.
1703 !
1704 ! Parameters:
1705 !
1706 ! Input, real ( kind_real ) P(3), the coordinates of the point (unit vector)
1707 ! to be located.
1708 !
1709 ! Input, integer LV, the length of arrays XV, YV, and ZV.
1710 !
1711 ! Input, real ( kind_real ) XV(LV), YV(LV), ZV(LV), the coordinates of unit
1712 ! vectors (points on the unit sphere).
1713 !
1714 ! Input, integer NV, the number of vertices in the polygon.
1715 ! 3 <= NV <= LV.
1716 !
1717 ! Input, integer LISTV(NV), the indexes (for XV, YV, and ZV)
1718 ! of a cyclically-ordered (and CCW-ordered) sequence of vertices that
1719 ! define R. The last vertex (indexed by LISTV(NV)) is followed by the
1720 ! first (indexed by LISTV(1)). LISTV entries must be in the range 1 to LV.
1721 !
1722 ! Output, logical INSIDE, TRUE if and only if P lies inside R unless
1723 ! IER /= 0, in which case the value is not altered.
1724 !
1725 ! Output, integer IER, error indicator:
1726 ! 0, if no errors were encountered.
1727 ! 1, if LV or NV is outside its valid range.
1728 ! 2, if a LISTV entry is outside its valid range.
1729 ! 3, if the polygon boundary was found to be self-intersecting. This
1730 ! error will not necessarily be detected.
1731 ! 4, if every choice of Q (one for each boundary edge) led to failure of
1732 ! some internal consistency check. The most likely cause of this error
1733 ! is invalid input: P = (0,0,0), a null or self-intersecting polygon, etc.
1734 !
1735 ! Local parameters:
1736 !
1737 ! B = Intersection point between the boundary and
1738 ! the great circle defined by P and Q.
1739 !
1740 ! BP,BQ = <B,P> and <B,Q>, respectively, maximized over
1741 ! intersection points B that lie between P and
1742 ! Q (on the shorter arc) -- used to find the
1743 ! closest intersection points to P and Q
1744 ! CN = Q X P = normal to the plane of P and Q
1745 ! D = Dot product <B,P> or <B,Q>
1746 ! EPS = Parameter used to define Q as the point whose
1747 ! orthogonal distance to (the midpoint of)
1748 ! boundary edge V1->V2 is approximately EPS/
1749 ! (2*Cos(A/2)), where <V1,V2> = Cos(A).
1750 ! EVEN = TRUE iff an even number of intersection points
1751 ! lie between P and Q (on the shorter arc)
1752 ! I1,I2 = Indexes (LISTV elements) of a pair of adjacent
1753 ! boundary vertices (endpoints of a boundary
1754 ! edge)
1755 ! IERR = Error flag for calls to INTRSC (not tested)
1756 ! IMX = Local copy of LV and maximum value of I1 and I2
1757 ! K = DO-loop index and LISTV index
1758 ! K0 = LISTV index of the first endpoint of the
1759 ! boundary edge used to compute Q
1760 ! LFT1,LFT2 = Logical variables associated with I1 and I2 in
1761 ! the boundary traversal: TRUE iff the vertex
1762 ! is strictly to the left of Q->P (<V,CN> > 0)
1763 ! N = Local copy of NV
1764 ! NI = Number of intersections (between the boundary
1765 ! curve and the great circle P-Q) encountered
1766 ! PINR = TRUE iff P is to the left of the directed
1767 ! boundary edge associated with the closest
1768 ! intersection point to P that lies between P
1769 ! and Q (a left-to-right intersection as
1770 ! viewed from Q), or there is no intersection
1771 ! between P and Q (on the shorter arc)
1772 ! PN,QN = P X CN and CN X Q, respectively: used to
1773 ! locate intersections B relative to arc Q->P
1774 ! Q = (V1 + V2 + EPS*VN/VNRM)/QNRM, where V1->V2 is
1775 ! the boundary edge indexed by LISTV(K0) ->
1776 ! LISTV(K0+1)
1777 ! QINR = TRUE iff Q is to the left of the directed
1778 ! boundary edge associated with the closest
1779 ! intersection point to Q that lies between P
1780 ! and Q (a right-to-left intersection as
1781 ! viewed from Q), or there is no intersection
1782 ! between P and Q (on the shorter arc)
1783 ! QNRM = Euclidean norm of V1+V2+EPS*VN/VNRM used to
1784 ! compute (normalize) Q
1785 ! V1,V2 = Vertices indexed by I1 and I2 in the boundary
1786 ! traversal
1787 ! VN = V1 X V2, where V1->V2 is the boundary edge
1788 ! indexed by LISTV(K0) -> LISTV(K0+1)
1789 ! VNRM = Euclidean norm of VN
1790 !
1791  implicit none
1792 
1793  integer lv
1794  integer nv
1795 
1796  real ( kind_real ) b(3)
1797  real ( kind_real ) bp
1798  real ( kind_real ) bq
1799  real ( kind_real ) cn(3)
1800  real ( kind_real ) d
1801  real ( kind_real ), parameter :: eps = 0.001_kind_real
1802  logical even
1803  integer i1
1804  integer i2
1805  integer ier
1806  integer ierr
1807  integer imx
1808  logical inside
1809  integer k
1810  integer k0
1811  logical lft1
1812  logical lft2
1813  integer listv(nv)
1814  integer n
1815  integer ni
1816  real ( kind_real ) p(3)
1817  logical pinr
1818  real ( kind_real ) pn(3)
1819  real ( kind_real ) q(3)
1820  logical qinr
1821  real ( kind_real ) qn(3)
1822  real ( kind_real ) qnrm
1823  real ( kind_real ) v1(3)
1824  real ( kind_real ) v2(3)
1825  real ( kind_real ) vn(3)
1826  real ( kind_real ) vnrm
1827  real ( kind_real ) xv(lv)
1828  real ( kind_real ) yv(lv)
1829  real ( kind_real ) zv(lv)
1830 !
1831 ! Default value
1832 !
1833  inside = .false.
1834 !
1835 ! Store local parameters.
1836 !
1837  imx = lv
1838  n = nv
1839 !
1840 ! Test for error 1.
1841 !
1842  if ( n < 3 .or. imx < n ) then
1843  ier = 1
1844  return
1845  end if
1846 !
1847 ! Initialize K0.
1848 !
1849  k0 = 0
1850  i1 = listv(1)
1851 
1852  if ( i1 < 1 .or. imx < i1 ) then
1853  ier = 2
1854  return
1855  end if
1856 !
1857 ! Increment K0 and set Q to a point immediately to the left
1858 ! of the midpoint of edge V1->V2 = LISTV(K0)->LISTV(K0+1):
1859 ! Q = (V1 + V2 + EPS*VN/VNRM)/QNRM, where VN = V1 X V2.
1860 !
1861 1 continue
1862 
1863  k0 = k0 + 1
1864 
1865  if ( n < k0 ) then
1866  ier = 4
1867  return
1868  end if
1869 
1870  i1 = listv(k0)
1871 
1872  if ( k0 < n ) then
1873  i2 = listv(k0+1)
1874  else
1875  i2 = listv(1)
1876  end if
1877 
1878  if ( i2 < 1 .or. imx < i2 ) then
1879  ier = 2
1880  return
1881  end if
1882 
1883  vn(1) = yv(i1) * zv(i2) - zv(i1) * yv(i2)
1884  vn(2) = zv(i1) * xv(i2) - xv(i1) * zv(i2)
1885  vn(3) = xv(i1) * yv(i2) - yv(i1) * xv(i2)
1886  vnrm = sqrt( sum( vn(1:3)**2 ) )
1887 
1888  if ( .not.(abs(vnrm)>0.0) ) then
1889  go to 1
1890  end if
1891 
1892  q(1) = xv(i1) + xv(i2) + eps * vn(1) / vnrm
1893  q(2) = yv(i1) + yv(i2) + eps * vn(2) / vnrm
1894  q(3) = zv(i1) + zv(i2) + eps * vn(3) / vnrm
1895 
1896  qnrm = sqrt( sum( q(1:3)**2 ) )
1897 
1898  q(1) = q(1) / qnrm
1899  q(2) = q(2) / qnrm
1900  q(3) = q(3) / qnrm
1901 !
1902 ! Compute CN = Q X P, PN = P X CN, and QN = CN X Q.
1903 !
1904  cn(1) = q(2) * p(3) - q(3) * p(2)
1905  cn(2) = q(3) * p(1) - q(1) * p(3)
1906  cn(3) = q(1) * p(2) - q(2) * p(1)
1907 
1908  if ( .not.(abs(cn(1))>0.0) .and. .not.(abs(cn(2))>0.0) .and. .not.(abs(cn(2))>0.0) ) then
1909  go to 1
1910  end if
1911 
1912  pn(1) = p(2) * cn(3) - p(3) * cn(2)
1913  pn(2) = p(3) * cn(1) - p(1) * cn(3)
1914  pn(3) = p(1) * cn(2) - p(2) * cn(1)
1915  qn(1) = cn(2) * q(3) - cn(3) * q(2)
1916  qn(2) = cn(3) * q(1) - cn(1) * q(3)
1917  qn(3) = cn(1) * q(2) - cn(2) * q(1)
1918 !
1919 ! Initialize parameters for the boundary traversal.
1920 !
1921  ni = 0
1922  even = .true.
1923  bp = -2.0_kind_real
1924  bq = -2.0_kind_real
1925  pinr = .true.
1926  qinr = .true.
1927  i2 = listv(n)
1928 
1929  if ( i2 < 1 .or. imx < i2 ) then
1930  ier = 2
1931  return
1932  end if
1933 
1934  lft2 = 0.0_kind_real < cn(1) * xv(i2) + cn(2) * yv(i2) + cn(3) * zv(i2)
1935 !
1936 ! Loop on boundary arcs I1->I2.
1937 !
1938  do k = 1, n
1939 
1940  i1 = i2
1941  lft1 = lft2
1942  i2 = listv(k)
1943 
1944  if ( i2 < 1 .or. imx < i2 ) then
1945  ier = 2
1946  return
1947  end if
1948 
1949  lft2 = ( 0.0_kind_real < cn(1) * xv(i2) + cn(2) * yv(i2) + cn(3) * zv(i2) )
1950 
1951  if ( lft1 .eqv. lft2 ) then
1952  cycle
1953  end if
1954 !
1955 ! I1 and I2 are on opposite sides of Q->P. Compute the
1956 ! point of intersection B.
1957 !
1958  ni = ni + 1
1959  v1(1) = xv(i1)
1960  v1(2) = yv(i1)
1961  v1(3) = zv(i1)
1962  v2(1) = xv(i2)
1963  v2(2) = yv(i2)
1964  v2(3) = zv(i2)
1965 
1966  call intrsc ( v1, v2, cn, b, ierr )
1967 !
1968 ! B is between Q and P (on the shorter arc) iff
1969 ! B Forward Q->P and B Forward P->Q iff
1970 ! <B,QN> > 0 and 0 < <B,PN>.
1971 !
1972  if ( 0.0_kind_real < dot_product( b(1:3), qn(1:3) ) .and. &
1973  0.0_kind_real < dot_product( b(1:3), pn(1:3) ) ) then
1974 !
1975 ! Update EVEN, BQ, QINR, BP, and PINR.
1976 !
1977  even = .not. even
1978  d = dot_product( b(1:3), q(1:3) )
1979 
1980  if ( bq < d ) then
1981  bq = d
1982  qinr = lft2
1983  end if
1984 
1985  d = dot_product( b(1:3), p(1:3) )
1986 
1987  if ( bp < d ) then
1988  bp = d
1989  pinr = lft1
1990  end if
1991 
1992  end if
1993 
1994  end do
1995 !
1996 ! Test for consistency: NI must be even and QINR must be TRUE.
1997 !
1998  if ( ni /= 2 * ( ni / 2 ) .or. .not. qinr ) then
1999  go to 1
2000  end if
2001 !
2002 ! Test for error 3: different values of PINR and EVEN.
2003 !
2004  if ( pinr .neqv. even ) then
2005  ier = 3
2006  return
2007  end if
2008 
2009  ier = 0
2010  inside = even
2011 
2012  return
2013 end function inside
2014 subroutine intadd ( kk, i1, i2, i3, list, lptr, lend, lnew )
2016 !*****************************************************************************80
2017 !
2018 ! Subroutine: intadd
2019 ! Purpose: add an interior node to a triangulation
2020 !
2021 ! Discussion:
2022 !
2023 ! This subroutine adds an interior node to a triangulation
2024 ! of a set of points on the unit sphere. The data structure
2025 ! is updated with the insertion of node KK into the triangle
2026 ! whose vertices are I1, I2, and I3. No optimization of the
2027 ! triangulation is performed.
2028 !
2029 ! This routine is identical to the similarly named routine in TRIPACK.
2030 !
2031 ! Modified:
2032 !
2033 ! 16 June 2007
2034 !
2035 ! Author:
2036 !
2037 ! Robert Renka
2038 !
2039 ! Reference:
2040 !
2041 ! Robert Renka,
2042 ! Algorithm 772: STRIPACK,
2043 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
2044 ! ACM Transactions on Mathematical Software,
2045 ! Volume 23, Number 3, September 1997, pages 416-434.
2046 !
2047 ! Parameters:
2048 !
2049 ! Input, integer KK, the index of the node to be inserted.
2050 ! 1 <= KK and KK must not be equal to I1, I2, or I3.
2051 !
2052 ! Input, integer I1, I2, I3, indexes of the
2053 ! counterclockwise-ordered sequence of vertices of a triangle which contains
2054 ! node KK.
2055 !
2056 ! Input, integer LIST(6*(N-2)), LPTR(6*(N-2)), LEND(N), LNEW,
2057 ! the data structure defining the triangulation, created by TRMESH. Triangle
2058 ! (I1,I2,I3) must be included in the triangulation.
2059 ! On output, updated with the addition of node KK. KK
2060 ! will be connected to nodes I1, I2, and I3.
2061 !
2062 ! Local parameters:
2063 !
2064 ! K = Local copy of KK
2065 ! LP = LIST pointer
2066 ! N1,N2,N3 = Local copies of I1, I2, and I3
2067 !
2068  implicit none
2069 
2070  integer i1
2071  integer i2
2072  integer i3
2073  integer k
2074  integer kk
2075  integer lend(*)
2076  integer list(*)
2077  integer lnew
2078  integer lp
2079  integer lptr(*)
2080  integer n1
2081  integer n2
2082  integer n3
2083 
2084  k = kk
2085 !
2086 ! Initialization.
2087 !
2088  n1 = i1
2089  n2 = i2
2090  n3 = i3
2091 !
2092 ! Add K as a neighbor of I1, I2, and I3.
2093 !
2094  call lstptr ( lend(n1), n2, list, lptr, lp )
2095  call insert ( k, lp, list, lptr, lnew )
2096 
2097  call lstptr ( lend(n2), n3, list, lptr, lp )
2098  call insert ( k, lp, list, lptr, lnew )
2099 
2100  call lstptr ( lend(n3), n1, list, lptr, lp )
2101  call insert ( k, lp, list, lptr, lnew )
2102 !
2103 ! Add I1, I2, and I3 as neighbors of K.
2104 !
2105  list(lnew) = n1
2106  list(lnew+1) = n2
2107  list(lnew+2) = n3
2108  lptr(lnew) = lnew + 1
2109  lptr(lnew+1) = lnew + 2
2110  lptr(lnew+2) = lnew
2111  lend(k) = lnew + 2
2112  lnew = lnew + 3
2113 
2114  return
2115 end subroutine intadd
2116 subroutine intrsc ( p1, p2, cn, p, ier )
2118 !*****************************************************************************80
2119 !
2120 ! Subroutine: intrsc
2121 ! Purpose: find the intersection of two great circles
2122 !
2123 ! Discussion:
2124 !
2125 ! Given a great circle C and points P1 and P2 defining an
2126 ! arc A on the surface of the unit sphere, where A is the
2127 ! shorter of the two portions of the great circle C12
2128 ! associated with P1 and P2, this subroutine returns the point
2129 ! of intersection P between C and C12 that is closer to A.
2130 ! Thus, if P1 and P2 lie in opposite hemispheres defined by
2131 ! C, P is the point of intersection of C with A.
2132 !
2133 ! Modified:
2134 !
2135 ! 16 June 2007
2136 !
2137 ! Author:
2138 !
2139 ! Robert Renka
2140 !
2141 ! Reference:
2142 !
2143 ! Robert Renka,
2144 ! Algorithm 772: STRIPACK,
2145 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
2146 ! ACM Transactions on Mathematical Software,
2147 ! Volume 23, Number 3, September 1997, pages 416-434.
2148 !
2149 ! Parameters:
2150 !
2151 ! Input, real ( kind_real ) P1(3), P2(3), the coordinates of unit vectors.
2152 !
2153 ! Input, real ( kind_real ) CN(3), the coordinates of a nonzero vector
2154 ! which defines C as the intersection of the plane whose normal is CN
2155 ! with the unit sphere. Thus, if C is to be the great circle defined
2156 ! by P and Q, CN should be P X Q.
2157 !
2158 ! Output, real ( kind_real ) P(3), point of intersection defined above
2159 ! unless IER is not 0, in which case P is not altered.
2160 !
2161 ! Output, integer IER, error indicator.
2162 ! 0, if no errors were encountered.
2163 ! 1, if <CN,P1> = <CN,P2>. This occurs iff P1 = P2 or CN = 0 or there are
2164 ! two intersection points at the same distance from A.
2165 ! 2, if P2 = -P1 and the definition of A is therefore ambiguous.
2166 !
2167 ! Local parameters:
2168 !
2169 ! D1 = <CN,P1>
2170 ! D2 = <CN,P2>
2171 ! I = DO-loop index
2172 ! PP = P1 + T*(P2-P1) = Parametric representation of the
2173 ! line defined by P1 and P2
2174 ! PPN = Norm of PP
2175 ! T = D1/(D1-D2) = Parameter value chosen so that PP lies
2176 ! in the plane of C
2177 !
2178  implicit none
2179 
2180  real ( kind_real ) cn(3)
2181  real ( kind_real ) d1
2182  real ( kind_real ) d2
2183  integer ier
2184  real ( kind_real ) p(3)
2185  real ( kind_real ) p1(3)
2186  real ( kind_real ) p2(3)
2187  real ( kind_real ) pp(3)
2188  real ( kind_real ) ppn
2189  real ( kind_real ) t
2190 
2191  d1 = dot_product( cn(1:3), p1(1:3) )
2192  d2 = dot_product( cn(1:3), p2(1:3) )
2193 
2194  if ( .not.(abs(d1-d2)>0.0) ) then
2195  ier = 1
2196  return
2197  end if
2198 !
2199 ! Solve for T such that <PP,CN> = 0 and compute PP and PPN.
2200 !
2201  t = d1 / ( d1 - d2 )
2202 
2203  pp(1:3) = p1(1:3) + t * ( p2(1:3) - p1(1:3) )
2204 
2205  ppn = dot_product( pp(1:3), pp(1:3) )
2206 !
2207 ! PPN = 0 iff PP = 0 iff P2 = -P1 (and T = .5).
2208 !
2209  if ( .not.(abs(ppn)>0.0) ) then
2210  ier = 2
2211  return
2212  end if
2213 
2214  ppn = sqrt( ppn )
2215 !
2216 ! Compute P = PP/PPN.
2217 !
2218  p(1:3) = pp(1:3) / ppn
2219 
2220  ier = 0
2221 
2222  return
2223 end subroutine intrsc
2224 subroutine jrand ( n, ix, iy, iz, output )
2226 !*****************************************************************************80
2227 !
2228 ! Subroutine: jrand
2229 ! Purpose: return a random integer between 1 and N
2230 !
2231 ! Discussion:
2232 !
2233 ! This function returns a uniformly distributed pseudorandom integer
2234 ! in the range 1 to N.
2235 !
2236 ! Modified:
2237 !
2238 ! 16 June 2007
2239 !
2240 ! Author:
2241 !
2242 ! Robert Renka
2243 !
2244 ! Reference:
2245 !
2246 ! Brian Wichmann, David Hill,
2247 ! An Efficient and Portable Pseudo-random Number Generator,
2248 ! Applied Statistics,
2249 ! Volume 31, Number 2, 1982, pages 188-190.
2250 !
2251 ! Parameters:
2252 !
2253 ! Input, integer N, the maximum value to be returned.
2254 !
2255 ! Input/output, integer IX, IY, IZ = seeds initialized to
2256 ! values in the range 1 to 30,000 before the first call to JRAND, and
2257 ! not altered between subsequent calls (unless a sequence of random
2258 ! numbers is to be repeated by reinitializing the seeds).
2259 !
2260 ! Output, integer JRAND, a random integer in the range 1 to N.
2261 !
2262 ! Local parameters:
2263 !
2264 ! U = Pseudo-random number uniformly distributed in the interval (0,1).
2265 ! X = Pseudo-random number in the range 0 to 3 whose fractional part is U.
2266 !
2267  implicit none
2268 
2269  integer ix
2270  integer iy
2271  integer iz
2272  integer output
2273  integer n
2274  real ( kind_real ) u
2275  real ( kind_real ) x
2276 
2277  ix = mod( 171 * ix, 30269 )
2278  iy = mod( 172 * iy, 30307 )
2279  iz = mod( 170 * iz, 30323 )
2280 
2281  x = ( real ( ix, kind_real ) / 30269.0_kind_real ) &
2282  + ( real ( iy, kind_real ) / 30307.0_kind_real ) &
2283  + ( real ( iz, kind_real ) / 30323.0_kind_real )
2284 
2285  u = x - int( x )
2286  output = int( real ( n, kind_real ) * u ) + 1
2287 
2288  return
2289 end subroutine jrand
2290 subroutine left ( x1, y1, z1, x2, y2, z2, x0, y0, z0, output )
2292 !*****************************************************************************80
2293 !
2294 ! Subroutine: left
2295 ! Purpose: determin whether a node is to the left of a plane through the origin
2296 !
2297 ! Discussion:
2298 !
2299 ! This function determines whether node N0 is in the
2300 ! (closed) left hemisphere defined by the plane containing
2301 ! N1, N2, and the origin, where left is defined relative to
2302 ! an observer at N1 facing N2.
2303 !
2304 ! Modified:
2305 !
2306 ! 16 June 2007
2307 !
2308 ! Author:
2309 !
2310 ! Robert Renka
2311 !
2312 ! Reference:
2313 !
2314 ! Robert Renka,
2315 ! Algorithm 772: STRIPACK,
2316 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
2317 ! ACM Transactions on Mathematical Software,
2318 ! Volume 23, Number 3, September 1997, pages 416-434.
2319 !
2320 ! Parameters:
2321 !
2322 ! Input, real ( kind_real ) X1, Y1, Z1 = Coordinates of N1.
2323 !
2324 ! Input, real ( kind_real ) X2, Y2, Z2 = Coordinates of N2.
2325 !
2326 ! Input, real ( kind_real ) X0, Y0, Z0 = Coordinates of N0.
2327 !
2328 ! Output, logical LEFT = TRUE if and only if N0 is in the closed
2329 ! left hemisphere.
2330 !
2331  implicit none
2332 
2333  logical output
2334  real ( kind_real ) x0
2335  real ( kind_real ) x1
2336  real ( kind_real ) x2
2337  real ( kind_real ) y0
2338  real ( kind_real ) y1
2339  real ( kind_real ) y2
2340  real ( kind_real ) z0
2341  real ( kind_real ) z1
2342  real ( kind_real ) z2
2343  real ( kind_real ) zz
2344 !
2345 ! LEFT = TRUE iff <N0,N1 X N2> = det(N0,N1,N2) >= 0.
2346 !
2347 
2348  call det ( x1, y1, z1, x2, y2, z2, x0, y0, z0, zz )
2349  output = zz > 0.0_kind_real
2350 
2351  return
2352 end subroutine left
2353 subroutine lstptr ( lpl, nb, list, lptr, output )
2355 !*****************************************************************************80
2356 !
2357 ! Subroutine: lstptr
2358 ! Purpose: return the index of NB in the adjacency list
2359 !
2360 ! Discussion:
2361 !
2362 ! This function returns the index (LIST pointer) of NB in
2363 ! the adjacency list for N0, where LPL = LEND(N0).
2364 !
2365 ! This function is identical to the similarly named function in TRIPACK.
2366 !
2367 ! Modified:
2368 !
2369 ! 16 June 2007
2370 !
2371 ! Author:
2372 !
2373 ! Robert Renka
2374 !
2375 ! Reference:
2376 !
2377 ! Robert Renka,
2378 ! Algorithm 772: STRIPACK,
2379 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
2380 ! ACM Transactions on Mathematical Software,
2381 ! Volume 23, Number 3, September 1997, pages 416-434.
2382 !
2383 ! Parameters:
2384 !
2385 ! Input, integer LPL, is LEND(N0).
2386 !
2387 ! Input, integer NB, index of the node whose pointer is to
2388 ! be returned. NB must be connected to N0.
2389 !
2390 ! Input, integer LIST(6*(N-2)), LPTR(6*(N-2)), the data
2391 ! structure defining the triangulation, created by TRMESH.
2392 !
2393 ! Output, integer LSTPTR, pointer such that LIST(LSTPTR) = NB or
2394 ! LIST(LSTPTR) = -NB, unless NB is not a neighbor of N0, in which
2395 ! case LSTPTR = LPL.
2396 !
2397 ! Local parameters:
2398 !
2399 ! LP = LIST pointer
2400 ! ND = Nodal index
2401 !
2402  implicit none
2403 
2404  integer list(*)
2405  integer lp
2406  integer lpl
2407  integer lptr(*)
2408  integer output
2409  integer nb
2410  integer nd
2411 
2412  lp = lptr(lpl)
2413 
2414  do
2415 
2416  nd = list(lp)
2417 
2418  if ( nd == nb ) then
2419  exit
2420  end if
2421 
2422  lp = lptr(lp)
2423 
2424  if ( lp == lpl ) then
2425  exit
2426  end if
2427 
2428  end do
2429 
2430  output = lp
2431 
2432  return
2433 end subroutine lstptr
2434 function nbcnt ( lpl, lptr )
2436 !*****************************************************************************80
2437 !
2438 ! Function: nbcnt
2439 ! Purpose: return the number of neighbors of a node
2440 !
2441 ! Discussion:
2442 !
2443 ! This function returns the number of neighbors of a node
2444 ! N0 in a triangulation created by TRMESH.
2445 !
2446 ! The number of neighbors also gives the order of the Voronoi
2447 ! polygon containing the point. Thus, a neighbor count of 6
2448 ! means the node is contained in a 6-sided Voronoi region.
2449 !
2450 ! This function is identical to the similarly named function in TRIPACK.
2451 !
2452 ! Modified:
2453 !
2454 ! 16 June 2007
2455 !
2456 ! Author:
2457 !
2458 ! Robert Renka
2459 !
2460 ! Reference:
2461 !
2462 ! Robert Renka,
2463 ! Algorithm 772: STRIPACK,
2464 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
2465 ! ACM Transactions on Mathematical Software,
2466 ! Volume 23, Number 3, September 1997, pages 416-434.
2467 !
2468 ! Parameters:
2469 !
2470 ! Input, integer LPL = LIST pointer to the last neighbor of N0;
2471 ! LPL = LEND(N0).
2472 !
2473 ! Input, integer LPTR(6*(N-2)), pointers associated with LIST.
2474 !
2475 ! Output, integer NBCNT, the number of neighbors of N0.
2476 !
2477 ! Local parameters:
2478 !
2479 ! K = Counter for computing the number of neighbors.
2480 !
2481 ! LP = LIST pointer
2482 !
2483  implicit none
2484 
2485  integer k
2486  integer lp
2487  integer lpl
2488  integer lptr(*)
2489  integer nbcnt
2490 
2491  lp = lpl
2492  k = 1
2493 
2494  do
2495 
2496  lp = lptr(lp)
2497 
2498  if ( lp == lpl ) then
2499  exit
2500  end if
2501 
2502  k = k + 1
2503 
2504  end do
2505 
2506  nbcnt = k
2507 
2508  return
2509 end function nbcnt
2510 function nearnd ( p, ist, n, x, y, z, list, lptr, lend, al )
2512 !*****************************************************************************80
2513 !
2514 ! Function: nearnd
2515 ! Purpose: return the nearest node to a given point
2516 !
2517 ! Discussion:
2518 !
2519 ! Given a point P on the surface of the unit sphere and a
2520 ! Delaunay triangulation created by TRMESH, this
2521 ! function returns the index of the nearest triangulation
2522 ! node to P.
2523 !
2524 ! The algorithm consists of implicitly adding P to the
2525 ! triangulation, finding the nearest neighbor to P, and
2526 ! implicitly deleting P from the triangulation. Thus, it
2527 ! is based on the fact that, if P is a node in a Delaunay
2528 ! triangulation, the nearest node to P is a neighbor of P.
2529 !
2530 ! For large values of N, this procedure will be faster than
2531 ! the naive approach of computing the distance from P to every node.
2532 !
2533 ! Note that the number of candidates for NEARND (neighbors of P)
2534 ! is limited to LMAX defined in the PARAMETER statement below.
2535 !
2536 ! Modified:
2537 !
2538 ! 16 June 2007
2539 !
2540 ! Author:
2541 !
2542 ! Robert Renka
2543 !
2544 ! Reference:
2545 !
2546 ! Robert Renka,
2547 ! Algorithm 772: STRIPACK,
2548 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
2549 ! ACM Transactions on Mathematical Software,
2550 ! Volume 23, Number 3, September 1997, pages 416-434.
2551 !
2552 ! Parameters:
2553 !
2554 ! Input, real ( kind_real ) P(3), the Cartesian coordinates of the point P to
2555 ! be located relative to the triangulation. It is assumed
2556 ! that P(1)**2 + P(2)**2 + P(3)**2 = 1, that is, that the
2557 ! point lies on the unit sphere.
2558 !
2559 ! Input, integer IST, the index of the node at which the search
2560 ! is to begin. The search time depends on the proximity of this
2561 ! node to P. If no good candidate is known, any value between
2562 ! 1 and N will do.
2563 !
2564 ! Input, integer N, the number of nodes in the triangulation.
2565 ! N must be at least 3.
2566 !
2567 ! Input, real ( kind_real ) X(N), Y(N), Z(N), the Cartesian coordinates of
2568 ! the nodes.
2569 !
2570 ! Input, integer LIST(6*(N-2)), LPTR(6*(N-2)), LEND(N),
2571 ! the data structure defining the triangulation, created by TRMESH.
2572 !
2573 ! Output, real ( kind_real ) AL, the arc length between P and node NEARND.
2574 ! Because both points are on the unit sphere, this is also
2575 ! the angular separation in radians.
2576 !
2577 ! Output, integer NEARND, the index of the nearest node to P.
2578 ! NEARND will be 0 if N < 3 or the triangulation data structure
2579 ! is invalid.
2580 !
2581 ! Local parameters:
2582 !
2583 ! B1,B2,B3 = Unnormalized barycentric coordinates returned by TRFIND
2584 ! DS1 = (Negative cosine of the) distance from P to N1
2585 ! DSR = (Negative cosine of the) distance from P to NR
2586 ! DX1,..DZ3 = Components of vectors used by the swap test
2587 ! I1,I2,I3 = Nodal indexes of a triangle containing P, or
2588 ! the rightmost (I1) and leftmost (I2) visible
2589 ! boundary nodes as viewed from P
2590 ! L = Length of LISTP/LPTRP and number of neighbors of P
2591 ! LMAX = Maximum value of L
2592 ! LISTP = Indexes of the neighbors of P
2593 ! LPTRP = Array of pointers in 1-1 correspondence with LISTP elements
2594 ! LP = LIST pointer to a neighbor of N1 and LISTP pointer
2595 ! LP1,LP2 = LISTP indexes (pointers)
2596 ! LPL = Pointer to the last neighbor of N1
2597 ! N1 = Index of a node visible from P
2598 ! N2 = Index of an endpoint of an arc opposite P
2599 ! N3 = Index of the node opposite N1->N2
2600 ! NN = Local copy of N
2601 ! NR = Index of a candidate for the nearest node to P
2602 ! NST = Index of the node at which TRFIND begins the search
2603 !
2604  implicit none
2605 
2606  integer ( kind = 4 ), parameter :: lmax = 25
2607  integer n
2608 
2609  real ( kind_real ) al
2610  real ( kind_real ) b1
2611  real ( kind_real ) b2
2612  real ( kind_real ) b3
2613  real ( kind_real ) ds1
2614  real ( kind_real ) dsr
2615  real ( kind_real ) dx1
2616  real ( kind_real ) dx2
2617  real ( kind_real ) dx3
2618  real ( kind_real ) dy1
2619  real ( kind_real ) dy2
2620  real ( kind_real ) dy3
2621  real ( kind_real ) dz1
2622  real ( kind_real ) dz2
2623  real ( kind_real ) dz3
2624  integer i1
2625  integer i2
2626  integer i3
2627  integer ist
2628  integer l
2629  integer lend(n)
2630  integer list(6*(n-2))
2631  integer listp(lmax)
2632  integer lp
2633  integer lp1
2634  integer lp2
2635  integer lpl
2636  integer lptr(6*(n-2))
2637  integer lptrp(lmax)
2638  integer nearnd
2639  integer n1
2640  integer n2
2641  integer n3
2642  integer nn
2643  integer nr
2644  integer nst
2645  real ( kind_real ) p(3)
2646  real ( kind_real ) x(n)
2647  real ( kind_real ) y(n)
2648  real ( kind_real ) z(n)
2649 
2650  nearnd = 0
2651  al = 0.0_kind_real
2652 !
2653 ! Store local parameters and test for N invalid.
2654 !
2655  nn = n
2656 
2657  if ( nn < 3 ) then
2658  return
2659  end if
2660 
2661  nst = ist
2662 
2663  if ( nst < 1 .or. nn < nst ) then
2664  nst = 1
2665  end if
2666 !
2667 ! Find a triangle (I1,I2,I3) containing P, or the rightmost
2668 ! (I1) and leftmost (I2) visible boundary nodes as viewed from P.
2669 !
2670  call trfind ( nst, p, n, x, y, z, list, lptr, lend, b1, b2, b3, i1, i2, i3 )
2671 !
2672 ! Test for collinear nodes.
2673 !
2674  if ( i1 == 0 ) then
2675  return
2676  end if
2677 !
2678 ! Store the linked list of 'neighbors' of P in LISTP and
2679 ! LPTRP. I1 is the first neighbor, and 0 is stored as
2680 ! the last neighbor if P is not contained in a triangle.
2681 ! L is the length of LISTP and LPTRP, and is limited to
2682 ! LMAX.
2683 !
2684  if ( i3 /= 0 ) then
2685 
2686  listp(1) = i1
2687  lptrp(1) = 2
2688  listp(2) = i2
2689  lptrp(2) = 3
2690  listp(3) = i3
2691  lptrp(3) = 1
2692  l = 3
2693 
2694  else
2695 
2696  n1 = i1
2697  l = 1
2698  lp1 = 2
2699  listp(l) = n1
2700  lptrp(l) = lp1
2701 !
2702 ! Loop on the ordered sequence of visible boundary nodes
2703 ! N1 from I1 to I2.
2704 !
2705  do
2706 
2707  lpl = lend(n1)
2708  n1 = -list(lpl)
2709  l = lp1
2710  lp1 = l+1
2711  listp(l) = n1
2712  lptrp(l) = lp1
2713 
2714  if ( n1 == i2 .or. lmax <= lp1 ) then
2715  exit
2716  end if
2717 
2718  end do
2719 
2720  l = lp1
2721  listp(l) = 0
2722  lptrp(l) = 1
2723 
2724  end if
2725 !
2726 ! Initialize variables for a loop on arcs N1-N2 opposite P
2727 ! in which new 'neighbors' are 'swapped' in. N1 follows
2728 ! N2 as a neighbor of P, and LP1 and LP2 are the LISTP
2729 ! indexes of N1 and N2.
2730 !
2731  lp2 = 1
2732  n2 = i1
2733  lp1 = lptrp(1)
2734  n1 = listp(lp1)
2735 !
2736 ! Begin loop: find the node N3 opposite N1->N2.
2737 !
2738  do
2739 
2740  call lstptr ( lend(n1), n2, list, lptr, lp )
2741 
2742  if ( 0 <= list(lp) ) then
2743 
2744  lp = lptr(lp)
2745  n3 = abs( list(lp) )
2746 !
2747 ! Swap test: Exit the loop if L = LMAX.
2748 !
2749  if ( l == lmax ) then
2750  exit
2751  end if
2752 
2753  dx1 = x(n1) - p(1)
2754  dy1 = y(n1) - p(2)
2755  dz1 = z(n1) - p(3)
2756 
2757  dx2 = x(n2) - p(1)
2758  dy2 = y(n2) - p(2)
2759  dz2 = z(n2) - p(3)
2760 
2761  dx3 = x(n3) - p(1)
2762  dy3 = y(n3) - p(2)
2763  dz3 = z(n3) - p(3)
2764 !
2765 ! Swap: Insert N3 following N2 in the adjacency list for P.
2766 ! The two new arcs opposite P must be tested.
2767 !
2768  if ( dx3 * ( dy2 * dz1 - dy1 * dz2 ) - &
2769  dy3 * ( dx2 * dz1 - dx1 * dz2 ) + &
2770  dz3 * ( dx2 * dy1 - dx1 * dy2 ) > 0.0_kind_real ) then
2771 
2772  l = l+1
2773  lptrp(lp2) = l
2774  listp(l) = n3
2775  lptrp(l) = lp1
2776  lp1 = l
2777  n1 = n3
2778  cycle
2779 
2780  end if
2781 
2782  end if
2783 !
2784 ! No swap: Advance to the next arc and test for termination
2785 ! on N1 = I1 (LP1 = 1) or N1 followed by 0.
2786 !
2787  if ( lp1 == 1 ) then
2788  exit
2789  end if
2790 
2791  lp2 = lp1
2792  n2 = n1
2793  lp1 = lptrp(lp1)
2794  n1 = listp(lp1)
2795 
2796  if ( n1 == 0 ) then
2797  exit
2798  end if
2799 
2800  end do
2801 !
2802 ! Set NR and DSR to the index of the nearest node to P and
2803 ! an increasing function (negative cosine) of its distance
2804 ! from P, respectively.
2805 !
2806  nr = i1
2807  dsr = -( x(nr) * p(1) + y(nr) * p(2) + z(nr) * p(3) )
2808 
2809  do lp = 2, l
2810 
2811  n1 = listp(lp)
2812 
2813  if ( n1 == 0 ) then
2814  cycle
2815  end if
2816 
2817  ds1 = -( x(n1) * p(1) + y(n1) * p(2) + z(n1) * p(3) )
2818 
2819  if ( ds1 < dsr ) then
2820  nr = n1
2821  dsr = ds1
2822  end if
2823 
2824  end do
2825 
2826  dsr = -dsr
2827  dsr = min( dsr, 1.0_kind_real )
2828 
2829  al = acos( dsr )
2830  nearnd = nr
2831 
2832  return
2833 end function nearnd
2834 subroutine scoord ( px, py, pz, plat, plon, pnrm )
2836 !*****************************************************************************80
2837 !
2838 ! Subroutine: scoord
2839 ! Purpose: convert from Cartesian to spherical coordinates
2840 !
2841 ! Discussion:
2842 !
2843 ! This subroutine converts a point P from Cartesian (X,Y,Z) coordinates
2844 ! to spherical ( LATITUDE, LONGITUDE, RADIUS ) coordinates.
2845 !
2846 ! Modified:
2847 !
2848 ! 16 June 2007
2849 !
2850 ! Author:
2851 !
2852 ! Robert Renka
2853 !
2854 ! Reference:
2855 !
2856 ! Robert Renka,
2857 ! Algorithm 772: STRIPACK,
2858 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
2859 ! ACM Transactions on Mathematical Software,
2860 ! Volume 23, Number 3, September 1997, pages 416-434.
2861 !
2862 ! Parameters:
2863 !
2864 ! Input, real PX, PY, PZ, the coordinates of P.
2865 !
2866 ! Output, real PLAT, the latitude of P in the range -PI/2
2867 ! to PI/2, or 0 if PNRM = 0.
2868 !
2869 ! Output, real PLON, the longitude of P in the range -PI to PI,
2870 ! or 0 if P lies on the Z-axis.
2871 !
2872 ! Output, real PNRM, the magnitude (Euclidean norm) of P.
2873 !
2874  implicit none
2875 
2876  real(kind_real) plat
2877  real(kind_real) plon
2878  real(kind_real) pnrm
2879  real(kind_real) px
2880  real(kind_real) py
2881  real(kind_real) pz
2882 
2883  pnrm = sqrt( px * px + py * py + pz * pz )
2884 
2885  if ( abs(px)>0.0 .or. abs(py)>0.0 ) then
2886  plon = atan2( py, px )
2887  else
2888  plon = 0.0
2889  end if
2890 
2891  if ( abs(pnrm)>0.0 ) then
2892  plat = asin( pz / pnrm )
2893  else
2894  plat = 0.0
2895  end if
2896 
2897  return
2898 end subroutine scoord
2899 subroutine swap ( in1, in2, io1, io2, list, lptr, lend, lp21 )
2901 !*****************************************************************************80
2902 !
2903 ! Subroutine: swap
2904 ! Purpose: replace the diagonal arc of a quadrilateral with the other diagonal
2905 !
2906 ! Discussion:
2907 !
2908 ! Given a triangulation of a set of points on the unit
2909 ! sphere, this subroutine replaces a diagonal arc in a
2910 ! strictly convex quadrilateral (defined by a pair of adja-
2911 ! cent triangles) with the other diagonal. Equivalently, a
2912 ! pair of adjacent triangles is replaced by another pair
2913 ! having the same union.
2914 !
2915 ! Modified:
2916 !
2917 ! 16 June 2007
2918 !
2919 ! Author:
2920 !
2921 ! Robert Renka
2922 !
2923 ! Reference:
2924 !
2925 ! Robert Renka,
2926 ! Algorithm 772: STRIPACK,
2927 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
2928 ! ACM Transactions on Mathematical Software,
2929 ! Volume 23, Number 3, September 1997, pages 416-434.
2930 !
2931 ! Parameters:
2932 !
2933 ! Input, integer IN1, IN2, IO1, IO2, nodal indexes of the
2934 ! vertices of the quadrilateral. IO1-IO2 is replaced by IN1-IN2.
2935 ! (IO1,IO2,IN1) and (IO2,IO1,IN2) must be triangles on input.
2936 !
2937 ! Input/output, integer LIST(6*(N-2)), LPTR(6*(N-2)), LEND(N),
2938 ! the data structure defining the triangulation, created by TRMESH.
2939 ! On output, updated with the swap; triangles (IO1,IO2,IN1) an (IO2,IO1,IN2)
2940 ! are replaced by (IN1,IN2,IO2) and (IN2,IN1,IO1) unless LP21 = 0.
2941 !
2942 ! Output, integer LP21, index of IN1 as a neighbor of IN2 after
2943 ! the swap is performed unless IN1 and IN2 are adjacent on input, in which
2944 ! case LP21 = 0.
2945 !
2946 ! Local parameters:
2947 !
2948 ! LP, LPH, LPSAV = LIST pointers
2949 !
2950  implicit none
2951 
2952  integer in1
2953  integer in2
2954  integer io1
2955  integer io2
2956  integer lend(*)
2957  integer list(*)
2958  integer lp
2959  integer lp21
2960  integer lph
2961  integer lpsav
2962  integer lptr(*)
2963 !
2964 ! Test for IN1 and IN2 adjacent.
2965 !
2966  call lstptr ( lend(in1), in2, list, lptr, lp )
2967 
2968  if ( abs( list(lp) ) == in2 ) then
2969  lp21 = 0
2970  return
2971  end if
2972 !
2973 ! Delete IO2 as a neighbor of IO1.
2974 !
2975  call lstptr ( lend(io1), in2, list, lptr, lp )
2976  lph = lptr(lp)
2977  lptr(lp) = lptr(lph)
2978 !
2979 ! If IO2 is the last neighbor of IO1, make IN2 the last neighbor.
2980 !
2981  if ( lend(io1) == lph ) then
2982  lend(io1) = lp
2983  end if
2984 !
2985 ! Insert IN2 as a neighbor of IN1 following IO1 using the hole created above.
2986 !
2987  call lstptr ( lend(in1), io1, list, lptr, lp )
2988  lpsav = lptr(lp)
2989  lptr(lp) = lph
2990  list(lph) = in2
2991  lptr(lph) = lpsav
2992 !
2993 ! Delete IO1 as a neighbor of IO2.
2994 !
2995  call lstptr ( lend(io2), in1, list, lptr, lp )
2996  lph = lptr(lp)
2997  lptr(lp) = lptr(lph)
2998 !
2999 ! If IO1 is the last neighbor of IO2, make IN1 the last neighbor.
3000 !
3001  if ( lend(io2) == lph ) then
3002  lend(io2) = lp
3003  end if
3004 !
3005 ! Insert IN1 as a neighbor of IN2 following IO2.
3006 !
3007  call lstptr ( lend(in2), io2, list, lptr, lp )
3008  lpsav = lptr(lp)
3009  lptr(lp) = lph
3010  list(lph) = in1
3011  lptr(lph) = lpsav
3012  lp21 = lph
3013 
3014  return
3015 end subroutine swap
3016 subroutine swptst ( n1, n2, n3, n4, x, y, z, output )
3018 !*****************************************************************************80
3019 !
3020 ! Subroutine: swptst
3021 ! Purpose: decide whether to replace a diagonal arc by the other
3022 !
3023 ! Discussion:
3024 !
3025 ! This function decides whether or not to replace a
3026 ! diagonal arc in a quadrilateral with the other diagonal.
3027 ! The decision will be to swap (SWPTST = TRUE) if and only
3028 ! if N4 lies above the plane (in the half-space not contain-
3029 ! ing the origin) defined by (N1,N2,N3), or equivalently, if
3030 ! the projection of N4 onto this plane is interior to the
3031 ! circumcircle of (N1,N2,N3). The decision will be for no
3032 ! swap if the quadrilateral is not strictly convex.
3033 !
3034 ! Modified:
3035 !
3036 ! 16 June 2007
3037 !
3038 ! Author:
3039 !
3040 ! Robert Renka
3041 !
3042 ! Reference:
3043 !
3044 ! Robert Renka,
3045 ! Algorithm 772: STRIPACK,
3046 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
3047 ! ACM Transactions on Mathematical Software,
3048 ! Volume 23, Number 3, September 1997, pages 416-434.
3049 !
3050 ! Parameters:
3051 !
3052 ! Input, integer N1, N2, N3, N4, indexes of the four nodes
3053 ! defining the quadrilateral with N1 adjacent to N2, and (N1,N2,N3) in
3054 ! counterclockwise order. The arc connecting N1 to N2 should be replaced
3055 ! by an arc connecting N3 to N4 if SWPTST = TRUE. Refer to subroutine SWAP.
3056 !
3057 ! Input, real ( kind_real ) X(N), Y(N), Z(N), the coordinates of the nodes.
3058 !
3059 ! Output, logical SWPTST, TRUE if and only if the arc connecting N1
3060 ! and N2 should be swapped for an arc connecting N3 and N4.
3061 !
3062 ! Local parameters:
3063 !
3064 ! DX1,DY1,DZ1 = Coordinates of N4->N1
3065 ! DX2,DY2,DZ2 = Coordinates of N4->N2
3066 ! DX3,DY3,DZ3 = Coordinates of N4->N3
3067 ! X4,Y4,Z4 = Coordinates of N4
3068 !
3069  implicit none
3070 
3071  real ( kind_real ) dx1
3072  real ( kind_real ) dx2
3073  real ( kind_real ) dx3
3074  real ( kind_real ) dy1
3075  real ( kind_real ) dy2
3076  real ( kind_real ) dy3
3077  real ( kind_real ) dz1
3078  real ( kind_real ) dz2
3079  real ( kind_real ) dz3
3080  integer n1
3081  integer n2
3082  integer n3
3083  integer n4
3084  logical output
3085  real ( kind_real ) x(*)
3086  real ( kind_real ) x4
3087  real ( kind_real ) y(*)
3088  real ( kind_real ) y4
3089  real ( kind_real ) z(*)
3090  real ( kind_real ) z4
3091  real ( kind_real ) zz
3092 
3093  x4 = x(n4)
3094  y4 = y(n4)
3095  z4 = z(n4)
3096  dx1 = x(n1) - x4
3097  dx2 = x(n2) - x4
3098  dx3 = x(n3) - x4
3099  dy1 = y(n1) - y4
3100  dy2 = y(n2) - y4
3101  dy3 = y(n3) - y4
3102  dz1 = z(n1) - z4
3103  dz2 = z(n2) - z4
3104  dz3 = z(n3) - z4
3105 !
3106 ! N4 lies above the plane of (N1,N2,N3) iff N3 lies above
3107 ! the plane of (N2,N1,N4) iff Det(N3-N4,N2-N4,N1-N4) =
3108 ! (N3-N4,N2-N4 X N1-N4) > 0.
3109 !
3110 
3111  call det ( dx2, dy2, dz2, dx1, dy1, dz1, dx3, dy3, dz3, zz )
3112  output = zz > 0.0_kind_real
3113 
3114  return
3115 end subroutine swptst
3116 subroutine trans ( n, rlat, rlon, x, y, z )
3118 !*****************************************************************************80
3119 !
3120 ! Subroutine: trans
3121 ! Purpose: transform spherical coordinates to Cartesian coordinates
3122 !
3123 ! Discussion:
3124 !
3125 ! This subroutine transforms spherical coordinates into
3126 ! Cartesian coordinates on the unit sphere for input to
3127 ! TRMESH. Storage for X and Y may coincide with
3128 ! storage for RLAT and RLON if the latter need not be saved.
3129 !
3130 ! Modified:
3131 !
3132 ! 16 June 2007
3133 !
3134 ! Author:
3135 !
3136 ! Robert Renka
3137 !
3138 ! Reference:
3139 !
3140 ! Robert Renka,
3141 ! Algorithm 772: STRIPACK,
3142 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
3143 ! ACM Transactions on Mathematical Software,
3144 ! Volume 23, Number 3, September 1997, pages 416-434.
3145 !
3146 ! Parameters:
3147 !
3148 ! Input, integer N, the number of nodes (points on the unit
3149 ! sphere) whose coordinates are to be transformed.
3150 !
3151 ! Input, real ( kind_real ) RLAT(N), latitudes of the nodes in radians.
3152 !
3153 ! Input, real ( kind_real ) RLON(N), longitudes of the nodes in radians.
3154 !
3155 ! Output, real ( kind_real ) X(N), Y(N), Z(N), the coordinates in the
3156 ! range -1 to 1. X(I)**2 + Y(I)**2 + Z(I)**2 = 1 for I = 1 to N.
3157 !
3158 ! Local parameters:
3159 !
3160 ! COSPHI = cos(PHI)
3161 ! I = DO-loop index
3162 ! NN = Local copy of N
3163 ! PHI = Latitude
3164 ! THETA = Longitude
3165 !
3166  implicit none
3167 
3168  integer n
3169 
3170  real ( kind_real ) cosphi
3171  integer i
3172  integer nn
3173  real ( kind_real ) phi
3174  real ( kind_real ) rlat(n)
3175  real ( kind_real ) rlon(n)
3176  real ( kind_real ) theta
3177  real ( kind_real ) x(n)
3178  real ( kind_real ) y(n)
3179  real ( kind_real ) z(n)
3180 
3181  nn = n
3182 
3183  do i = 1, nn
3184  phi = rlat(i)
3185  theta = rlon(i)
3186  cosphi = cos( phi )
3187  x(i) = cosphi * cos( theta )
3188  y(i) = cosphi * sin( theta )
3189  z(i) = sin( phi )
3190  end do
3191 
3192  return
3193 end subroutine trans
3194 subroutine trfind ( nst, p, n, x, y, z, list, lptr, lend, b1, b2, b3, i1, &
3195  i2, i3 )
3197 !*****************************************************************************80
3198 !
3199 ! Subroutine: trfind
3200 ! Purpose: locate a point relative to a triangulation
3201 !
3202 ! Discussion:
3203 !
3204 ! This subroutine locates a point P relative to a triangulation
3205 ! created by TRMESH. If P is contained in
3206 ! a triangle, the three vertex indexes and barycentric
3207 ! coordinates are returned. Otherwise, the indexes of the
3208 ! visible boundary nodes are returned.
3209 !
3210 ! Modified:
3211 !
3212 ! 16 June 2007
3213 !
3214 ! Author:
3215 !
3216 ! Robert Renka
3217 !
3218 ! Reference:
3219 !
3220 ! Robert Renka,
3221 ! Algorithm 772: STRIPACK,
3222 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
3223 ! ACM Transactions on Mathematical Software,
3224 ! Volume 23, Number 3, September 1997, pages 416-434.
3225 !
3226 ! Parameters:
3227 !
3228 ! Input, integer NST, index of a node at which TRFIND begins
3229 ! its search. Search time depends on the proximity of this node to P.
3230 !
3231 ! Input, real ( kind_real ) P(3), the x, y, and z coordinates (in that order)
3232 ! of the point P to be located.
3233 !
3234 ! Input, integer N, the number of nodes in the triangulation.
3235 ! 3 <= N.
3236 !
3237 ! Input, real ( kind_real ) X(N), Y(N), Z(N), the coordinates of the
3238 ! triangulation nodes (unit vectors).
3239 !
3240 ! Input, integer LIST(6*(N-2)), LPTR(6*(N-2)), LEND(N), the
3241 ! data structure defining the triangulation, created by TRMESH.
3242 !
3243 ! Output, real ( kind_real ) B1, B2, B3, the unnormalized barycentric
3244 ! coordinates of the central projection of P onto the underlying planar
3245 ! triangle if P is in the convex hull of the nodes. These parameters
3246 ! are not altered if I1 = 0.
3247 !
3248 ! Output, integer I1, I2, I3, the counterclockwise-ordered
3249 ! vertex indexes of a triangle containing P if P is contained in a triangle.
3250 ! If P is not in the convex hull of the nodes, I1 and I2 are the rightmost
3251 ! and leftmost (boundary) nodes that are visible from P, and I3 = 0. (If
3252 ! all boundary nodes are visible from P, then I1 and I2 coincide.)
3253 ! I1 = I2 = I3 = 0 if P and all of the nodes are coplanar (lie on a
3254 ! common great circle.
3255 !
3256 ! Local parameters:
3257 !
3258 ! EPS = Machine precision
3259 ! IX,IY,IZ = Integer seeds for JRAND
3260 ! LP = LIST pointer
3261 ! N0,N1,N2 = Nodes in counterclockwise order defining a
3262 ! cone (with vertex N0) containing P, or end-
3263 ! points of a boundary edge such that P Right
3264 ! N1->N2
3265 ! N1S,N2S = Initially-determined values of N1 and N2
3266 ! N3,N4 = Nodes opposite N1->N2 and N2->N1, respectively
3267 ! NEXT = Candidate for I1 or I2 when P is exterior
3268 ! NF,NL = First and last neighbors of N0, or first
3269 ! (rightmost) and last (leftmost) nodes
3270 ! visible from P when P is exterior to the
3271 ! triangulation
3272 ! PTN1 = Scalar product <P,N1>
3273 ! PTN2 = Scalar product <P,N2>
3274 ! Q = (N2 X N1) X N2 or N1 X (N2 X N1) -- used in
3275 ! the boundary traversal when P is exterior
3276 ! S12 = Scalar product <N1,N2>
3277 ! TOL = Tolerance (multiple of EPS) defining an upper
3278 ! bound on the magnitude of a negative bary-
3279 ! centric coordinate (B1 or B2) for P in a
3280 ! triangle -- used to avoid an infinite number
3281 ! of restarts with 0 <= B3 < EPS and B1 < 0 or
3282 ! B2 < 0 but small in magnitude
3283 ! XP,YP,ZP = Local variables containing P(1), P(2), and P(3)
3284 ! X0,Y0,Z0 = Dummy arguments for DET
3285 ! X1,Y1,Z1 = Dummy arguments for DET
3286 ! X2,Y2,Z2 = Dummy arguments for DET
3287 !
3288  implicit none
3289 
3290  integer n
3291 
3292  real ( kind_real ) b1
3293  real ( kind_real ) b2
3294  real ( kind_real ) b3
3295  real ( kind_real ) output
3296  real ( kind_real ) eps
3297  integer i1
3298  integer i2
3299  integer i3
3300  integer ( kind = 4 ), save :: ix = 1
3301  integer ( kind = 4 ), save :: iy = 2
3302  integer ( kind = 4 ), save :: iz = 3
3303  integer lend(n)
3304  integer list(6*(n-2))
3305  integer lp
3306  integer lptr(6*(n-2))
3307  integer n0
3308  integer n1
3309  integer n1s
3310  integer n2
3311  integer n2s
3312  integer n3
3313  integer n4
3314  integer next
3315  integer nf
3316  integer nl
3317  integer nst
3318  real ( kind_real ) p(3)
3319  real ( kind_real ) ptn1
3320  real ( kind_real ) ptn2
3321  real ( kind_real ) q(3)
3322  real ( kind_real ) s12
3323  real ( kind_real ) tol
3324  real ( kind_real ) x(n)
3325  real ( kind_real ) xp
3326  real ( kind_real ) y(n)
3327  real ( kind_real ) yp
3328  real ( kind_real ) z(n)
3329  real ( kind_real ) zp
3330 !
3331 ! Initialize variables.
3332 !
3333  xp = p(1)
3334  yp = p(2)
3335  zp = p(3)
3336  n0 = nst
3337 
3338  if ( n0 < 1 .or. n < n0 ) then
3339  call jrand ( n, ix, iy, iz, n0 )
3340  end if
3341 !
3342 ! Compute the relative machine precision EPS and TOL.
3343 !
3344  eps = epsilon( eps )
3345  tol = 100.0_kind_real * eps
3346 !
3347 ! Set NF and NL to the first and last neighbors of N0, and initialize N1 = NF.
3348 !
3349 2 continue
3350 
3351  lp = lend(n0)
3352  nl = list(lp)
3353  lp = lptr(lp)
3354  nf = list(lp)
3355  n1 = nf
3356 !
3357 ! Find a pair of adjacent neighbors N1,N2 of N0 that define
3358 ! a wedge containing P: P LEFT N0->N1 and P RIGHT N0->N2.
3359 !
3360  if ( 0 < nl ) then
3361 !
3362 ! N0 is an interior node. Find N1.
3363 !
3364 3 continue
3365 
3366  call det(x(n0),y(n0),z(n0),x(n1),y(n1),z(n1),xp,yp,zp,output)
3367  if ( output < 0.0_kind_real ) then
3368  lp = lptr(lp)
3369  n1 = list(lp)
3370  if ( n1 == nl ) then
3371  go to 6
3372  end if
3373  go to 3
3374  end if
3375  else
3376 !
3377 ! N0 is a boundary node. Test for P exterior.
3378 !
3379  nl = -nl
3380 !
3381 ! Is P to the right of the boundary edge N0->NF?
3382 !
3383  call det(x(n0),y(n0),z(n0),x(nf),y(nf),z(nf), xp,yp,zp,output)
3384  if ( output < 0.0_kind_real ) then
3385  n1 = n0
3386  n2 = nf
3387  go to 9
3388  end if
3389 !
3390 ! Is P to the right of the boundary edge NL->N0?
3391 !
3392  call det(x(nl),y(nl),z(nl),x(n0),y(n0),z(n0),xp,yp,zp,output)
3393  if ( output < 0.0_kind_real ) then
3394  n1 = nl
3395  n2 = n0
3396  go to 9
3397  end if
3398 
3399  end if
3400 !
3401 ! P is to the left of arcs N0->N1 and NL->N0. Set N2 to the
3402 ! next neighbor of N0 (following N1).
3403 !
3404 4 continue
3405 
3406  lp = lptr(lp)
3407  n2 = abs( list(lp) )
3408 
3409  call det(x(n0),y(n0),z(n0),x(n2),y(n2),z(n2),xp,yp,zp,output)
3410  if ( output < 0.0_kind_real ) then
3411  go to 7
3412  end if
3413 
3414  n1 = n2
3415 
3416  if ( n1 /= nl ) then
3417  go to 4
3418  end if
3419 
3420  call det ( x(n0), y(n0), z(n0), x(nf), y(nf), z(nf), xp, yp, zp, output )
3421  if ( output < 0.0_kind_real ) then
3422  go to 6
3423  end if
3424 !
3425 ! P is left of or on arcs N0->NB for all neighbors NB
3426 ! of N0. Test for P = +/-N0.
3427 !
3428  if ( abs( x(n0 ) * xp + y(n0) * yp + z(n0) * zp) < 1.0_kind_real - 4.0_kind_real * eps ) then
3429 !
3430 ! All points are collinear iff P Left NB->N0 for all
3431 ! neighbors NB of N0. Search the neighbors of N0.
3432 ! Note: N1 = NL and LP points to NL.
3433 !
3434  do
3435 
3436  call det(x(n1),y(n1),z(n1),x(n0),y(n0),z(n0),xp,yp,zp,output)
3437  if ( output < 0.0_kind_real ) then
3438  exit
3439  end if
3440 
3441  lp = lptr(lp)
3442  n1 = abs( list(lp) )
3443 
3444  if ( n1 == nl ) then
3445  i1 = 0
3446  i2 = 0
3447  i3 = 0
3448  return
3449  end if
3450 
3451  end do
3452 
3453  end if
3454 !
3455 ! P is to the right of N1->N0, or P = +/-N0. Set N0 to N1 and start over.
3456 !
3457  n0 = n1
3458  go to 2
3459 !
3460 ! P is between arcs N0->N1 and N0->NF.
3461 !
3462 6 continue
3463 
3464  n2 = nf
3465 !
3466 ! P is contained in a wedge defined by geodesics N0-N1 and
3467 ! N0-N2, where N1 is adjacent to N2. Save N1 and N2 to
3468 ! test for cycling.
3469 !
3470 7 continue
3471 
3472  n3 = n0
3473  n1s = n1
3474  n2s = n2
3475 !
3476 ! Top of edge-hopping loop:
3477 !
3478 8 continue
3479 
3480  call det ( x(n1),y(n1),z(n1),x(n2),y(n2),z(n2),xp,yp,zp,b3 )
3481 
3482  if ( b3 < 0.0_kind_real ) then
3483 !
3484 ! Set N4 to the first neighbor of N2 following N1 (the
3485 ! node opposite N2->N1) unless N1->N2 is a boundary arc.
3486 !
3487  call lstptr ( lend(n2), n1, list, lptr, lp )
3488 
3489  if ( list(lp) < 0 ) then
3490  go to 9
3491  end if
3492 
3493  lp = lptr(lp)
3494  n4 = abs( list(lp) )
3495 !
3496 ! Define a new arc N1->N2 which intersects the geodesic N0-P.
3497 !
3498  call det ( x(n0),y(n0),z(n0),x(n4),y(n4),z(n4),xp,yp,zp,output )
3499  if ( output < 0.0_kind_real ) then
3500  n3 = n2
3501  n2 = n4
3502  n1s = n1
3503  if ( n2 /= n2s .and. n2 /= n0 ) then
3504  go to 8
3505  end if
3506  else
3507  n3 = n1
3508  n1 = n4
3509  n2s = n2
3510  if ( n1 /= n1s .and. n1 /= n0 ) then
3511  go to 8
3512  end if
3513  end if
3514 !
3515 ! The starting node N0 or edge N1-N2 was encountered
3516 ! again, implying a cycle (infinite loop). Restart
3517 ! with N0 randomly selected.
3518 !
3519  call jrand ( n, ix, iy, iz, n0 )
3520  go to 2
3521 
3522  end if
3523 !
3524 ! P is in (N1,N2,N3) unless N0, N1, N2, and P are collinear
3525 ! or P is close to -N0.
3526 !
3527  if ( .not.(b3 < eps) ) then
3528 !
3529 ! B3 /= 0.
3530 !
3531  call det(x(n2),y(n2),z(n2),x(n3),y(n3),z(n3),xp,yp,zp,b1)
3532  call det(x(n3),y(n3),z(n3),x(n1),y(n1),z(n1),xp,yp,zp,b2)
3533 !
3534 ! Restart with N0 randomly selected.
3535 !
3536  if ( b1 < -tol .or. b2 < -tol ) then
3537  call jrand ( n, ix, iy, iz, n0 )
3538  go to 2
3539  end if
3540 
3541  else
3542 !
3543 ! B3 = 0 and thus P lies on N1->N2. Compute
3544 ! B1 = Det(P,N2 X N1,N2) and B2 = Det(P,N1,N2 X N1).
3545 !
3546  b3 = 0.0_kind_real
3547  s12 = x(n1) * x(n2) + y(n1) * y(n2) + z(n1) * z(n2)
3548  ptn1 = xp * x(n1) + yp * y(n1) + zp * z(n1)
3549  ptn2 = xp * x(n2) + yp * y(n2) + zp * z(n2)
3550  b1 = ptn1 - s12 * ptn2
3551  b2 = ptn2 - s12 * ptn1
3552 !
3553 ! Restart with N0 randomly selected.
3554 !
3555  if ( b1 < -tol .or. b2 < -tol ) then
3556  call jrand ( n, ix, iy, iz, n0 )
3557  go to 2
3558  end if
3559 
3560  end if
3561 !
3562 ! P is in (N1,N2,N3).
3563 !
3564  i1 = n1
3565  i2 = n2
3566  i3 = n3
3567  b1 = max( b1, 0.0_kind_real )
3568  b2 = max( b2, 0.0_kind_real )
3569  return
3570 !
3571 ! P Right N1->N2, where N1->N2 is a boundary edge.
3572 ! Save N1 and N2, and set NL = 0 to indicate that
3573 ! NL has not yet been found.
3574 !
3575 9 continue
3576 
3577  n1s = n1
3578  n2s = n2
3579  nl = 0
3580 !
3581 ! Counterclockwise Boundary Traversal:
3582 !
3583 10 continue
3584 
3585  lp = lend(n2)
3586  lp = lptr(lp)
3587  next = list(lp)
3588 
3589  call det(x(n2),y(n2),z(n2),x(next),y(next),z(next),xp,yp,zp,output)
3590  if ( .not.(output < 0.0_kind_real) ) then
3591 !
3592 ! N2 is the rightmost visible node if P Forward N2->N1
3593 ! or NEXT Forward N2->N1. Set Q to (N2 X N1) X N2.
3594 !
3595  s12 = x(n1) * x(n2) + y(n1) * y(n2) + z(n1) * z(n2)
3596 
3597  q(1) = x(n1) - s12 * x(n2)
3598  q(2) = y(n1) - s12 * y(n2)
3599  q(3) = z(n1) - s12 * z(n2)
3600 
3601  if ( .not.(xp * q(1) + yp * q(2) + zp * q(3) < 0.0_kind_real) ) then
3602  go to 11
3603  end if
3604 
3605  if ( .not.(x(next) * q(1) + y(next) * q(2) + z(next) * q(3) < 0.0_kind_real) ) then
3606  go to 11
3607  end if
3608 !
3609 ! N1, N2, NEXT, and P are nearly collinear, and N2 is
3610 ! the leftmost visible node.
3611 !
3612  nl = n2
3613  end if
3614 !
3615 ! Bottom of counterclockwise loop:
3616 !
3617  n1 = n2
3618  n2 = next
3619 
3620  if ( n2 /= n1s ) then
3621  go to 10
3622  end if
3623 !
3624 ! All boundary nodes are visible from P.
3625 !
3626  i1 = n1s
3627  i2 = n1s
3628  i3 = 0
3629  return
3630 !
3631 ! N2 is the rightmost visible node.
3632 !
3633 11 continue
3634 
3635  nf = n2
3636 
3637  if ( nl == 0 ) then
3638 !
3639 ! Restore initial values of N1 and N2, and begin the search
3640 ! for the leftmost visible node.
3641 !
3642  n2 = n2s
3643  n1 = n1s
3644 !
3645 ! Clockwise Boundary Traversal:
3646 !
3647 12 continue
3648 
3649  lp = lend(n1)
3650  next = -list(lp)
3651 
3652  call det ( x(next), y(next), z(next), x(n1), y(n1), z(n1), xp, yp, zp, output )
3653  if ( .not.(output < 0.0_kind_real) ) then
3654 !
3655 ! N1 is the leftmost visible node if P or NEXT is
3656 ! forward of N1->N2. Compute Q = N1 X (N2 X N1).
3657 !
3658  s12 = x(n1) * x(n2) + y(n1) * y(n2) + z(n1) * z(n2)
3659  q(1) = x(n2) - s12 * x(n1)
3660  q(2) = y(n2) - s12 * y(n1)
3661  q(3) = z(n2) - s12 * z(n1)
3662 
3663  if ( .not.(xp * q(1) + yp * q(2) + zp * q(3) < 0.0_kind_real) ) then
3664  go to 13
3665  end if
3666 
3667  if ( .not.(x(next) * q(1) + y(next) * q(2) + z(next) * q(3) < 0.0_kind_real) ) then
3668  go to 13
3669  end if
3670 !
3671 ! P, NEXT, N1, and N2 are nearly collinear and N1 is the rightmost
3672 ! visible node.
3673 !
3674  nf = n1
3675  end if
3676 !
3677 ! Bottom of clockwise loop:
3678 !
3679  n2 = n1
3680  n1 = next
3681 
3682  if ( n1 /= n1s ) then
3683  go to 12
3684  end if
3685 !
3686 ! All boundary nodes are visible from P.
3687 !
3688  i1 = n1
3689  i2 = n1
3690  i3 = 0
3691  return
3692 !
3693 ! N1 is the leftmost visible node.
3694 !
3695 13 continue
3696 
3697  nl = n1
3698 
3699  end if
3700 !
3701 ! NF and NL have been found.
3702 !
3703  i1 = nf
3704  i2 = nl
3705  i3 = 0
3706 
3707  return
3708 end subroutine trfind
3709 subroutine trlist ( n, list, lptr, lend, nrow, nt, ltri, ier )
3711 !*****************************************************************************80
3712 !
3713 ! Subroutine: trlist
3714 ! Purpose: convert a triangulation data structure to a triangle list
3715 !
3716 ! Discussion:
3717 !
3718 ! This subroutine converts a triangulation data structure
3719 ! from the linked list created by TRMESH to a triangle list.
3720 !
3721 ! Modified:
3722 !
3723 ! 16 June 2007
3724 !
3725 ! Author:
3726 !
3727 ! Robert Renka
3728 !
3729 ! Reference:
3730 !
3731 ! Robert Renka,
3732 ! Algorithm 772: STRIPACK,
3733 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
3734 ! ACM Transactions on Mathematical Software,
3735 ! Volume 23, Number 3, September 1997, pages 416-434.
3736 !
3737 ! Parameters:
3738 !
3739 ! Input, integer N, the number of nodes in the triangulation.
3740 ! 3 <= N.
3741 !
3742 ! Input, integer LIST(6*(N-2)), LPTR(6*(N-2)), LEND(N), linked
3743 ! list data structure defining the triangulation. Refer to TRMESH.
3744 !
3745 ! Input, integer NROW, the number of rows (entries per triangle)
3746 ! reserved for the triangle list LTRI. The value must be 6 if only the
3747 ! vertex indexes and neighboring triangle indexes are to be stored, or 9
3748 ! if arc indexes are also to be assigned and stored. Refer to LTRI.
3749 !
3750 ! Output, integer NT, the number of triangles in the
3751 ! triangulation unless IER /=0, in which case NT = 0. NT = 2N-NB-2 if
3752 ! NB >= 3 or 2N-4 if NB = 0, where NB is the number of boundary nodes.
3753 !
3754 ! Output, integer LTRI(NROW,*). The second dimension of LTRI
3755 ! must be at least NT, where NT will be at most 2*N-4. The J-th column
3756 ! contains the vertex nodal indexes (first three rows), neighboring triangle
3757 ! indexes (second three rows), and, if NROW = 9, arc indexes (last three
3758 ! rows) associated with triangle J for J = 1,...,NT. The vertices are
3759 ! ordered counterclockwise with the first vertex taken to be the one
3760 ! with smallest index. Thus, LTRI(2,J) and LTRI(3,J) are larger than
3761 ! LTRI(1,J) and index adjacent neighbors of node LTRI(1,J). For
3762 ! I = 1,2,3, LTRI(I+3,J) and LTRI(I+6,J) index the triangle and arc,
3763 ! respectively, which are opposite (not shared by) node LTRI(I,J), with
3764 ! LTRI(I+3,J) = 0 if LTRI(I+6,J) indexes a boundary arc. Vertex indexes
3765 ! range from 1 to N, triangle indexes from 0 to NT, and, if included,
3766 ! arc indexes from 1 to NA, where NA = 3N-NB-3 if NB >= 3 or 3N-6 if
3767 ! NB = 0. The triangles are ordered on first (smallest) vertex indexes.
3768 !
3769 ! Output, integer IER, error indicator.
3770 ! 0, if no errors were encountered.
3771 ! 1, if N or NROW is outside its valid range on input.
3772 ! 2, if the triangulation data structure (LIST,LPTR,LEND) is invalid.
3773 ! Note, however, that these arrays are not completely tested for validity.
3774 !
3775 ! Local parameters:
3776 !
3777 ! ARCS = Logical variable with value TRUE iff are
3778 ! indexes are to be stored
3779 ! I,J = LTRI row indexes (1 to 3) associated with
3780 ! triangles KT and KN, respectively
3781 ! I1,I2,I3 = Nodal indexes of triangle KN
3782 ! ISV = Variable used to permute indexes I1,I2,I3
3783 ! KA = Arc index and number of currently stored arcs
3784 ! KN = Index of the triangle that shares arc I1-I2 with KT
3785 ! KT = Triangle index and number of currently stored triangles
3786 ! LP = LIST pointer
3787 ! LP2 = Pointer to N2 as a neighbor of N1
3788 ! LPL = Pointer to the last neighbor of I1
3789 ! LPLN1 = Pointer to the last neighbor of N1
3790 ! N1,N2,N3 = Nodal indexes of triangle KT
3791 ! NM2 = N-2
3792 !
3793  implicit none
3794 
3795  integer n
3796  integer nrow
3797 
3798  logical arcs
3799  integer i
3800  integer i1
3801  integer i2
3802  integer i3
3803  integer ier
3804  integer isv
3805  integer j
3806  integer ka
3807  integer kn
3808  integer kt
3809  integer lend(n)
3810  integer list(6*(n-2))
3811  integer lp
3812  integer lp2
3813  integer lpl
3814  integer lpln1
3815  integer lptr(6*(n-2))
3816  integer ltri(nrow,*)
3817  integer n1
3818  integer n2
3819  integer n3
3820  integer nm2
3821  integer nt
3822 !
3823 ! Test for invalid input parameters.
3824 !
3825  if ( n < 3 .or. ( nrow /= 6 .and. nrow /= 9 ) ) then
3826  nt = 0
3827  ier = 1
3828  return
3829  end if
3830 !
3831 ! Initialize parameters for loop on triangles KT = (N1,N2,
3832 ! N3), where N1 < N2 and N1 < N3.
3833 !
3834 ! ARCS = TRUE iff arc indexes are to be stored.
3835 ! KA,KT = Numbers of currently stored arcs and triangles.
3836 ! NM2 = Upper bound on candidates for N1.
3837 !
3838  arcs = nrow == 9
3839  ka = 0
3840  kt = 0
3841  nm2 = n-2
3842 !
3843 ! Loop on nodes N1.
3844 !
3845  do n1 = 1, nm2
3846 !
3847 ! Loop on pairs of adjacent neighbors (N2,N3). LPLN1 points
3848 ! to the last neighbor of N1, and LP2 points to N2.
3849 !
3850  lpln1 = lend(n1)
3851  lp2 = lpln1
3852 
3853 1 continue
3854 
3855  lp2 = lptr(lp2)
3856  n2 = list(lp2)
3857  lp = lptr(lp2)
3858  n3 = abs( list(lp) )
3859 
3860  if ( n2 < n1 .or. n3 < n1 ) then
3861  go to 8
3862  end if
3863 !
3864 ! Add a new triangle KT = (N1,N2,N3).
3865 !
3866  kt = kt + 1
3867  ltri(1,kt) = n1
3868  ltri(2,kt) = n2
3869  ltri(3,kt) = n3
3870 !
3871 ! Loop on triangle sides (I2,I1) with neighboring triangles
3872 ! KN = (I1,I2,I3).
3873 !
3874  do i = 1, 3
3875 
3876  if ( i == 1 ) then
3877  i1 = n3
3878  i2 = n2
3879  else if ( i == 2 ) then
3880  i1 = n1
3881  i2 = n3
3882  else
3883  i1 = n2
3884  i2 = n1
3885  end if
3886  j = 0
3887 !
3888 ! Set I3 to the neighbor of I1 that follows I2 unless
3889 ! I2->I1 is a boundary arc.
3890 !
3891  lpl = lend(i1)
3892  lp = lptr(lpl)
3893 
3894  do
3895 
3896  if ( list(lp) == i2 ) then
3897  go to 3
3898  end if
3899 
3900  lp = lptr(lp)
3901 
3902  if ( lp == lpl ) then
3903  exit
3904  end if
3905 
3906  end do
3907 !
3908 ! Invalid triangulation data structure: I1 is a neighbor of
3909 ! I2, but I2 is not a neighbor of I1.
3910 !
3911  if ( abs( list(lp) ) /= i2 ) then
3912  nt = 0
3913  ier = 2
3914  return
3915  end if
3916 !
3917 ! I2 is the last neighbor of I1. Bypass the search for a neighboring
3918 ! triangle if I2->I1 is a boundary arc.
3919 !
3920  kn = 0
3921 
3922  if ( list(lp) < 0 ) then
3923  go to 6
3924  end if
3925 !
3926 ! I2->I1 is not a boundary arc, and LP points to I2 as
3927 ! a neighbor of I1.
3928 !
3929 3 continue
3930 
3931  lp = lptr(lp)
3932  i3 = abs( list(lp) )
3933 !
3934 ! Find J such that LTRI(J,KN) = I3 (not used if KT < KN),
3935 ! and permute the vertex indexes of KN so that I1 is smallest.
3936 !
3937  if ( i1 < i2 .and. i1 < i3 ) then
3938  j = 3
3939  else if ( i2 < i3 ) then
3940  j = 2
3941  isv = i1
3942  i1 = i2
3943  i2 = i3
3944  i3 = isv
3945  else
3946  j = 1
3947  isv = i1
3948  i1 = i3
3949  i3 = i2
3950  i2 = isv
3951  end if
3952 !
3953 ! Test for KT < KN (triangle index not yet assigned).
3954 !
3955  if ( n1 < i1 ) then
3956  cycle
3957  end if
3958 !
3959 ! Find KN, if it exists, by searching the triangle list in
3960 ! reverse order.
3961 !
3962  do kn = kt-1, 1, -1
3963  if ( ltri(1,kn) == i1 .and. &
3964  ltri(2,kn) == i2 .and. &
3965  ltri(3,kn) == i3 ) then
3966  go to 5
3967  end if
3968  end do
3969 
3970  cycle
3971 !
3972 ! Store KT as a neighbor of KN.
3973 !
3974 5 continue
3975 
3976  ltri(j+3,kn) = kt
3977 !
3978 ! Store KN as a neighbor of KT, and add a new arc KA.
3979 !
3980 6 continue
3981 
3982  ltri(i+3,kt) = kn
3983 
3984  if ( arcs ) then
3985  ka = ka + 1
3986  ltri(i+6,kt) = ka
3987  if ( kn /= 0 ) then
3988  ltri(j+6,kn) = ka
3989  end if
3990  end if
3991 
3992  end do
3993 !
3994 ! Bottom of loop on triangles.
3995 !
3996 8 continue
3997 
3998  if ( lp2 /= lpln1 ) then
3999  go to 1
4000  end if
4001 
4002  end do
4003 
4004  nt = kt
4005  ier = 0
4006 
4007  return
4008 end subroutine trlist
4009 subroutine trmesh ( mpl, n, x, y, z, list, lptr, lend, lnew, near, next, dist, ier )
4011 !*****************************************************************************80
4012 !
4013 ! Subroutine: trmesh
4014 ! Purpose: create a Delaunay triangulation on the unit sphere
4015 !
4016 ! Discussion:
4017 !
4018 ! This subroutine creates a Delaunay triangulation of a
4019 ! set of N arbitrarily distributed points, referred to as
4020 ! nodes, on the surface of the unit sphere. The Delaunay
4021 ! triangulation is defined as a set of (spherical) triangles
4022 ! with the following five properties:
4023 !
4024 ! 1) The triangle vertices are nodes.
4025 ! 2) No triangle contains a node other than its vertices.
4026 ! 3) The interiors of the triangles are pairwise disjoint.
4027 ! 4) The union of triangles is the convex hull of the set
4028 ! of nodes (the smallest convex set that contains
4029 ! the nodes). If the nodes are not contained in a
4030 ! single hemisphere, their convex hull is the
4031 ! entire sphere and there are no boundary nodes.
4032 ! Otherwise, there are at least three boundary nodes.
4033 ! 5) The interior of the circumcircle of each triangle
4034 ! contains no node.
4035 !
4036 ! The first four properties define a triangulation, and the
4037 ! last property results in a triangulation which is as close
4038 ! as possible to equiangular in a certain sense and which is
4039 ! uniquely defined unless four or more nodes lie in a common
4040 ! plane. This property makes the triangulation well-suited
4041 ! for solving closest-point problems and for triangle-based
4042 ! interpolation.
4043 !
4044 ! Provided the nodes are randomly ordered, the algorithm
4045 ! has expected time complexity O(N*log(N)) for most nodal
4046 ! distributions. Note, however, that the complexity may be
4047 ! as high as O(N**2) if, for example, the nodes are ordered
4048 ! on increasing latitude.
4049 !
4050 ! Spherical coordinates (latitude and longitude) may be
4051 ! converted to Cartesian coordinates by Subroutine TRANS.
4052 !
4053 ! The following is a list of the software package modules
4054 ! which a user may wish to call directly:
4055 !
4056 ! ADDNOD - Updates the triangulation by appending a new node.
4057 !
4058 ! AREAS - Returns the area of a spherical triangle.
4059 !
4060 ! BNODES - Returns an array containing the indexes of the
4061 ! boundary nodes (if any) in counterclockwise
4062 ! order. Counts of boundary nodes, triangles,
4063 ! and arcs are also returned.
4064 !
4065 ! CIRCUM - Returns the circumcenter of a spherical triangle.
4066 !
4067 ! CRLIST - Returns the set of triangle circumcenters
4068 ! (Voronoi vertices) and circumradii associated
4069 ! with a triangulation.
4070 !
4071 ! DELARC - Deletes a boundary arc from a triangulation.
4072 !
4073 ! DELNOD - Updates the triangulation with a nodal deletion.
4074 !
4075 ! EDGE - Forces an arbitrary pair of nodes to be connected
4076 ! by an arc in the triangulation.
4077 !
4078 ! GETNP - Determines the ordered sequence of L closest nodes
4079 ! to a given node, along with the associated distances.
4080 !
4081 ! INSIDE - Locates a point relative to a polygon on the
4082 ! surface of the sphere.
4083 !
4084 ! INTRSC - Returns the point of intersection between a
4085 ! pair of great circle arcs.
4086 !
4087 ! JRAND - Generates a uniformly distributed pseudo-random integer.
4088 !
4089 ! LEFT - Locates a point relative to a great circle.
4090 !
4091 ! NEARND - Returns the index of the nearest node to an
4092 ! arbitrary point, along with its squared
4093 ! distance.
4094 !
4095 ! SCOORD - Converts a point from Cartesian coordinates to
4096 ! spherical coordinates.
4097 !
4098 ! TRANS - Transforms spherical coordinates into Cartesian
4099 ! coordinates on the unit sphere for input to
4100 ! Subroutine TRMESH.
4101 !
4102 ! TRLIST - Converts the triangulation data structure to a
4103 ! triangle list more suitable for use in a finite
4104 ! element code.
4105 !
4106 ! TRMESH - Creates a Delaunay triangulation of a set of
4107 ! nodes.
4108 !
4109 ! Modified:
4110 !
4111 ! 16 June 2007
4112 !
4113 ! Author:
4114 !
4115 ! Robert Renka
4116 !
4117 ! Reference:
4118 !
4119 ! Robert Renka,
4120 ! Algorithm 772: STRIPACK,
4121 ! Delaunay Triangulation and Voronoi Diagram on the Surface of a Sphere,
4122 ! ACM Transactions on Mathematical Software,
4123 ! Volume 23, Number 3, September 1997, pages 416-434.
4124 !
4125 ! Parameters:
4126 !
4127 ! Input, integer N, the number of nodes in the triangulation.
4128 ! 3 <= N.
4129 !
4130 ! Input, real ( kind_real ) X(N), Y(N), Z(N), the coordinates of distinct
4131 ! nodes. (X(K),Y(K), Z(K)) is referred to as node K, and K is referred
4132 ! to as a nodal index. It is required that X(K)**2 + Y(K)**2 + Z(K)**2 = 1
4133 ! for all K. The first three nodes must not be collinear (lie on a
4134 ! common great circle).
4135 !
4136 ! Output, integer LIST(6*(N-2)), nodal indexes which, along
4137 ! with LPTR, LEND, and LNEW, define the triangulation as a set of N
4138 ! adjacency lists; counterclockwise-ordered sequences of neighboring nodes
4139 ! such that the first and last neighbors of a boundary node are boundary
4140 ! nodes (the first neighbor of an interior node is arbitrary). In order to
4141 ! distinguish between interior and boundary nodes, the last neighbor of
4142 ! each boundary node is represented by the negative of its index.
4143 !
4144 ! Output, integer LPTR(6*(N-2)), = Set of pointers (LIST
4145 ! indexes) in one-to-one correspondence with the elements of LIST.
4146 ! LIST(LPTR(I)) indexes the node which follows LIST(I) in cyclical
4147 ! counterclockwise order (the first neighbor follows the last neighbor).
4148 !
4149 ! Output, integer LEND(N), pointers to adjacency lists.
4150 ! LEND(K) points to the last neighbor of node K. LIST(LEND(K)) < 0 if and
4151 ! only if K is a boundary node.
4152 !
4153 ! Output, integer LNEW, pointer to the first empty location
4154 ! in LIST and LPTR (list length plus one). LIST, LPTR, LEND, and LNEW are
4155 ! not altered if IER < 0, and are incomplete if 0 < IER.
4156 !
4157 ! Workspace, integer NEAR(N),
4158 ! used to efficiently determine the nearest triangulation node to each
4159 ! unprocessed node for use by ADDNOD.
4160 !
4161 ! Workspace, integer NEXT(N),
4162 ! used to efficiently determine the nearest triangulation node to each
4163 ! unprocessed node for use by ADDNOD.
4164 !
4165 ! Workspace, real ( kind_real ) DIST(N),
4166 ! used to efficiently determine the nearest triangulation node to each
4167 ! unprocessed node for use by ADDNOD.
4168 !
4169 ! Output, integer IER, error indicator:
4170 ! 0, if no errors were encountered.
4171 ! -1, if N < 3 on input.
4172 ! -2, if the first three nodes are collinear.
4173 ! L, if nodes L and M coincide for some L < M. The data structure
4174 ! represents a triangulation of nodes 1 to M-1 in this case.
4175 !
4176 ! Local parameters:
4177 !
4178 ! D = (Negative cosine of) distance from node K to node I
4179 ! D1,D2,D3 = Distances from node K to nodes 1, 2, and 3, respectively
4180 ! I,J = Nodal indexes
4181 ! I0 = Index of the node preceding I in a sequence of
4182 ! unprocessed nodes: I = NEXT(I0)
4183 ! K = Index of node to be added and DO-loop index: 3 < K
4184 ! LP = LIST index (pointer) of a neighbor of K
4185 ! LPL = Pointer to the last neighbor of K
4186 ! NEXTI = NEXT(I)
4187 ! NN = Local copy of N
4188 !
4189  implicit none
4190 
4191  type(mpl_type),intent(in) :: mpl ! MPI data
4192 
4193  integer n
4194 
4195  real ( kind_real ) d
4196  real ( kind_real ) d1
4197  real ( kind_real ) d2
4198  real ( kind_real ) d3
4199  real ( kind_real ) dist(n)
4200  integer i
4201  integer i0
4202  integer ier
4203  integer j
4204  integer k
4205  logical output_1, output_2
4206  integer lend(n)
4207  integer list(6*(n-2))
4208  integer lnew
4209  integer lp
4210  integer lpl
4211  integer lptr(6*(n-2))
4212  integer near(n)
4213  integer next(n)
4214  integer nexti
4215  integer nn
4216  real ( kind_real ) x(n)
4217  real ( kind_real ) y(n)
4218  real ( kind_real ) z(n)
4219 
4220  nn = n
4221 
4222  if ( nn < 3 ) then
4223  ier = -1
4224  write ( *, '(a)' ) ' '
4225  write ( *, '(a)' ) 'TRMESH - Fatal error!'
4226  write ( *, '(a)' ) ' N < 3.'
4227  call mpl%abort('stop in stripack')
4228  end if
4229 !
4230 ! Initialize
4231 !
4232  list = 0
4233  lptr = 0
4234  lend = 0
4235 !
4236 ! Store the first triangle in the linked list.
4237 !
4238  call left (x(1),y(1),z(1),x(2),y(2),z(2),x(3),y(3),z(3),output_1)
4239  call left (x(2),y(2),z(2),x(1),y(1),z(1),x(3),y(3),z(3),output_2)
4240 
4241  if ( .not. output_1 ) then
4242 !
4243 ! The first triangle is (3,2,1) = (2,1,3) = (1,3,2).
4244 !
4245  list(1) = 3
4246  lptr(1) = 2
4247  list(2) = -2
4248  lptr(2) = 1
4249  lend(1) = 2
4250 
4251  list(3) = 1
4252  lptr(3) = 4
4253  list(4) = -3
4254  lptr(4) = 3
4255  lend(2) = 4
4256 
4257  list(5) = 2
4258  lptr(5) = 6
4259  list(6) = -1
4260  lptr(6) = 5
4261  lend(3) = 6
4262 
4263  else if ( .not. output_2 ) then
4264 !
4265 ! The first triangle is (1,2,3): 3 Strictly Left 1->2,
4266 ! i.e., node 3 lies in the left hemisphere defined by arc 1->2.
4267 !
4268  list(1) = 2
4269  lptr(1) = 2
4270  list(2) = -3
4271  lptr(2) = 1
4272  lend(1) = 2
4273 
4274  list(3) = 3
4275  lptr(3) = 4
4276  list(4) = -1
4277  lptr(4) = 3
4278  lend(2) = 4
4279 
4280  list(5) = 1
4281  lptr(5) = 6
4282  list(6) = -2
4283  lptr(6) = 5
4284  lend(3) = 6
4285 !
4286 ! The first three nodes are collinear.
4287 !
4288  else
4289 
4290  ier = -2
4291  write ( *, '(a)' ) ' '
4292  write ( *, '(a)' ) 'TRMESH - Fatal error!'
4293  write ( *, '(a)' ) ' The first 3 nodes are collinear.'
4294  write ( *, '(a)' ) ' Try reordering the data.'
4295  call mpl%abort('stop in stripack')
4296 
4297  end if
4298 !
4299 ! Initialize LNEW and test for N = 3.
4300 !
4301  lnew = 7
4302 
4303  if ( nn == 3 ) then
4304  ier = 0
4305  return
4306  end if
4307 !
4308 ! A nearest-node data structure (NEAR, NEXT, and DIST) is
4309 ! used to obtain an expected-time (N*log(N)) incremental
4310 ! algorithm by enabling constant search time for locating
4311 ! each new node in the triangulation.
4312 !
4313 ! For each unprocessed node K, NEAR(K) is the index of the
4314 ! triangulation node closest to K (used as the starting
4315 ! point for the search in Subroutine TRFIND) and DIST(K)
4316 ! is an increasing function of the arc length (angular
4317 ! distance) between nodes K and NEAR(K): -Cos(a) for arc
4318 ! length a.
4319 !
4320 ! Since it is necessary to efficiently find the subset of
4321 ! unprocessed nodes associated with each triangulation
4322 ! node J (those that have J as their NEAR entries), the
4323 ! subsets are stored in NEAR and NEXT as follows: for
4324 ! each node J in the triangulation, I = NEAR(J) is the
4325 ! first unprocessed node in J's set (with I = 0 if the
4326 ! set is empty), L = NEXT(I) (if 0 < I) is the second,
4327 ! NEXT(L) (if 0 < L) is the third, etc. The nodes in each
4328 ! set are initially ordered by increasing indexes (which
4329 ! maximizes efficiency) but that ordering is not main-
4330 ! tained as the data structure is updated.
4331 !
4332 ! Initialize the data structure for the single triangle.
4333 !
4334  near(1) = 0
4335  near(2) = 0
4336  near(3) = 0
4337 
4338  do k = nn, 4, -1
4339 
4340  d1 = -( x(k) * x(1) + y(k) * y(1) + z(k) * z(1) )
4341  d2 = -( x(k) * x(2) + y(k) * y(2) + z(k) * z(2) )
4342  d3 = -( x(k) * x(3) + y(k) * y(3) + z(k) * z(3) )
4343 
4344  if ( inf(d1,d2) .and. inf(d1,d3) ) then
4345  near(k) = 1
4346  dist(k) = d1
4347  next(k) = near(1)
4348  near(1) = k
4349  else if ( inf(d2,d1) .and. inf(d2,d3) ) then
4350  near(k) = 2
4351  dist(k) = d2
4352  next(k) = near(2)
4353  near(2) = k
4354  else
4355  near(k) = 3
4356  dist(k) = d3
4357  next(k) = near(3)
4358  near(3) = k
4359  end if
4360  end do
4361 !
4362 ! Add the remaining nodes.
4363 !
4364  do k = 4, nn
4365 
4366  call addnod ( mpl, near(k), k, x, y, z, list, lptr, lend, lnew, ier )
4367 
4368  if ( ier /= 0 ) then
4369  write ( *, '(a)' ) ' '
4370  write ( *, '(a)' ) 'TRMESH - Fatal error!'
4371  write ( *, '(a,i8)' ) ' ADDNOD returned error code IER = ', ier
4372  call mpl%abort('stop in stripack')
4373  end if
4374 !
4375 ! Remove K from the set of unprocessed nodes associated with NEAR(K).
4376 !
4377  i = near(k)
4378  i0 = i
4379 
4380  if ( near(i) == k ) then
4381 
4382  near(i) = next(k)
4383 
4384  else
4385 
4386  i = near(i)
4387 
4388  do
4389 
4390  i0 = i
4391  i = next(i0)
4392 
4393  if ( i == k ) then
4394  exit
4395  end if
4396 
4397  end do
4398 
4399  next(i0) = next(k)
4400 
4401  end if
4402 
4403  near(k) = 0
4404 !
4405 ! Loop on neighbors J of node K.
4406 !
4407  lpl = lend(k)
4408  lp = lpl
4409 
4410 3 continue
4411 
4412  lp = lptr(lp)
4413  j = abs( list(lp) )
4414 !
4415 ! Loop on elements I in the sequence of unprocessed nodes
4416 ! associated with J: K is a candidate for replacing J
4417 ! as the nearest triangulation node to I. The next value
4418 ! of I in the sequence, NEXT(I), must be saved before I
4419 ! is moved because it is altered by adding I to K's set.
4420 !
4421  i = near(j)
4422 
4423  do
4424 
4425  if ( i == 0 ) then
4426  exit
4427  end if
4428 
4429  nexti = next(i)
4430 !
4431 ! Test for the distance from I to K less than the distance
4432 ! from I to J. Indistinguishability threshold for cross-plateform reproducibility
4433 !
4434  d = - ( x(i) * x(k) + y(i) * y(k) + z(i) * z(k) )
4435  if ( inf(d,dist(i)) ) then
4436 !
4437 ! Replace J by K as the nearest triangulation node to I:
4438 ! update NEAR(I) and DIST(I), and remove I from J's set
4439 ! of unprocessed nodes and add it to K's set.
4440 !
4441  near(i) = k
4442  dist(i) = d
4443 
4444  if ( i == near(j) ) then
4445  near(j) = nexti
4446  else
4447  next(i0) = nexti
4448  end if
4449 
4450  next(i) = near(k)
4451  near(k) = i
4452  else
4453  i0 = i
4454  end if
4455 
4456  i = nexti
4457 
4458  end do
4459 !
4460 ! Bottom of loop on neighbors J.
4461 !
4462  if ( lp /= lpl ) then
4463  go to 3
4464  end if
4465 
4466  end do
4467 
4468  return
4469 end subroutine trmesh
4470 
4471 end module tools_stripack
logical function, public sup(x, y)
Definition: tools_repro.F90:85
subroutine left(x1, y1, z1, x2, y2, z2, x0, y0, z0, output)
subroutine jrand(n, ix, iy, iz, output)
subroutine swptst(n1, n2, n3, n4, x, y, z, output)
integer function nbcnt(lpl, lptr)
subroutine, public trmesh(mpl, n, x, y, z, list, lptr, lend, lnew, near, next, dist, ier)
subroutine, public trans(n, rlat, rlon, x, y, z)
subroutine det(x1, y1, z1, x2, y2, z2, x0, y0, z0, output)
subroutine, public addnod(mpl, nst, k, x, y, z, list, lptr, lend, lnew, ier)
subroutine swap(in1, in2, io1, io2, list, lptr, lend, lp21)
subroutine, public trfind(nst, p, n, x, y, z, list, lptr, lend, b1, b2, b3, i1, i2, i3)
subroutine bdyadd(kk, i1, i2, list, lptr, lend, lnew)
subroutine intrsc(p1, p2, cn, p, ier)
subroutine lstptr(lpl, nb, list, lptr, output)
integer function nearnd(p, ist, n, x, y, z, list, lptr, lend, al)
subroutine covsph(kk, n0, list, lptr, lend, lnew)
#define max(a, b)
Definition: mosaic_util.h:33
real(kind_real) function, public areas(v1, v2, v3)
subroutine, public crlist(n, ncol, x, y, z, list, lend, lptr, lnew, ltri, listc, nb, xc, yc, zc, rc, ier)
subroutine circum(v1, v2, v3, c, ier)
subroutine, public scoord(px, py, pz, plat, plon, pnrm)
subroutine, public trlist(n, list, lptr, lend, nrow, nt, ltri, ier)
subroutine, public bnodes(n, list, lptr, lend, nodes, nb, na, nt)
integer, parameter, public kind_real
logical function, public inf(x, y)
Definition: tools_repro.F90:47
#define min(a, b)
Definition: mosaic_util.h:32
subroutine insert(k, lp, list, lptr, lnew)
logical function, public inside(p, lv, xv, yv, zv, nv, listv, ier)
subroutine intadd(kk, i1, i2, i3, list, lptr, lend, lnew)
logical function, public eq(x, y)
Definition: tools_repro.F90:28
logical function, public indist(x, y)