program main !*****************************************************************************80 ! !! stripack_test3() looks at the Delaunay triangulation created by TRMESH. ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 29 April 2010 ! ! Author: ! ! John Burkardt ! implicit none integer, parameter :: rk = kind ( 1.0D+00 ) integer, parameter :: n = 10 integer, parameter :: nrow = 6 real ( kind = rk ), allocatable :: area ( : ) real ( kind = rk ) area_sum real ( kind = rk ) dist(n) integer i integer i1 integer i2 integer i3 integer ier integer lend(n) integer list(6*(n-2)) integer lnew integer lptr(6*(n-2)) integer ltri(nrow,2*(n-2)) integer near(n) integer next(n) integer nt real ( kind = rk ), parameter :: pi = 3.141592653589793D+00 real ( kind = rk ), parameter :: r = 1.0D+00 integer seed real ( kind = rk ) xyz(3,n) call timestamp ( ) write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'STRIPACK_PRB3' write ( *, '(a)' ) ' FORTRAN90 version' write ( *, '(a)' ) ' ' write ( *, '(a)' ) ' Have TRMESH create the Delaunay triangulation of' write ( *, '(a)' ) ' points on a sphere.' write ( *, '(a)' ) ' ' write ( *, '(a)' ) ' Have TRLIST return the triangle vertices,' write ( *, '(a)' ) ' and the triangle neighbors.' ! ! Choose a set of random values for X, Y, Z. ! seed = 123456789 call uniform_on_sphere01_map ( 3, n, seed, xyz ) call r8mat_transpose_print ( 3, n, xyz, ' Data points:' ) ! ! Compute the Delaunay triangulation. ! call trmesh ( n, xyz(1,:), xyz(2,:), xyz(3,:), list, lptr, lend, lnew, near, & next, dist, ier ) if ( ier /= 0 ) then write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'STRIPACK_PRB3 - Fatal error!' write ( *, '(a,i8)' ) ' TRMESH returns IER = ', ier stop 1 end if ! ! Create the triangle list. ! call trlist ( n, list, lptr, lend, nrow, nt, ltri, ier ) if ( ier /= 0 ) then write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'STRIPACK_PRB3 - Fatal error!' write ( *, '(a,i8)' ) ' TRLIST returns IER = ', ier stop 1 end if write ( *, '(a)' ) ' ' write ( *, '(a,i8)' ) ' Number of triangles = ', nt ! ! Euler's Formula. ! write ( *, '(a)' ) ' ' write ( *, '(a)' ) ' Check Euler''s formula:' write ( *, '(a)' ) ' ' write ( *, '(a,i8)' ) ' Faces = ', nt write ( *, '(a,i8)' ) ' Vertices = ', n write ( *, '(a,i8)' ) ' Edges = ', ( 3 * nt ) / 2 write ( *, '(a)' ) ' ' write ( *, '(a,i8)' ) ' F+V-E-2 = ', nt + n - ( ( 3 * nt ) / 2 ) - 2 ! ! Print the triangulation. ! call i4mat_transpose_print ( 3, nt, ltri(1:3,:), ' Delaunay triangles:' ) ! ! Print the triangle neighbors. ! call i4mat_transpose_print ( 3, nt, ltri(4:6,:), ' Triangle neighbors:' ) ! ! Compute areas. ! allocate ( area(1:nt) ) do i = 1, nt i1 = ltri(1,i) i2 = ltri(2,i) i3 = ltri(3,i) call stri_vertices_to_area ( r, xyz(1:3,i1), xyz(1:3,i2), xyz(1:3,i3), area(i) ) end do call r8vec_print ( nt, area, ' Spherical area of triangles:' ) area_sum = sum ( area (1:nt) ) write ( *, '(a)' ) ' ' write ( *, '(a,g14.6)' ) ' Area sum = ', area_sum write ( *, '(a,g14.6)' ) ' 4*PI = ', 4.0D+00 * pi deallocate ( area ) ! ! Terminate. ! write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'STRIPACK_PRB3:' write ( *, '(a)' ) ' Normal end of execution.' write ( *, '(a)' ) ' ' call timestamp ( ) stop end subroutine i4mat_transpose_print ( m, n, a, title ) !*****************************************************************************80 ! !! I4MAT_TRANSPOSE_PRINT prints an I4MAT, transposed. ! ! Discussion: ! ! An I4MAT is a rectangular array of I4 values. ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 28 December 2004 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input, integer M, N, the number of rows and columns. ! ! Input, integer A(M,N), an M by N matrix to be printed. ! ! Input, character ( len = * ) TITLE, a title. ! implicit none integer m integer n integer a(m,n) character ( len = * ) title call i4mat_transpose_print_some ( m, n, a, 1, 1, m, n, title ) return end subroutine i4mat_transpose_print_some ( m, n, a, ilo, jlo, ihi, jhi, title ) !*****************************************************************************80 !7 !! I4MAT_TRANSPOSE_PRINT_SOME prints some of the transpose of an I4MAT. ! ! Discussion: ! ! An I4MAT is a rectangular array of I4 values. ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 10 September 2009 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input, integer M, N, the number of rows and columns. ! ! Input, integer A(M,N), an M by N matrix to be printed. ! ! Input, integer ILO, JLO, the first row and column to print. ! ! Input, integer IHI, JHI, the last row and column to print. ! ! Input, character ( len = * ) TITLE, a title. ! implicit none integer, parameter :: incx = 10 integer m integer n integer a(m,n) character ( len = 8 ) ctemp(incx) integer i integer i2 integer i2hi integer i2lo integer ihi integer ilo integer inc integer j integer j2hi integer j2lo integer jhi integer jlo character ( len = * ) title write ( *, '(a)' ) ' ' write ( *, '(a)' ) trim ( title ) do i2lo = max ( ilo, 1 ), min ( ihi, m ), incx i2hi = i2lo + incx - 1 i2hi = min ( i2hi, m ) i2hi = min ( i2hi, ihi ) inc = i2hi + 1 - i2lo write ( *, '(a)' ) ' ' do i = i2lo, i2hi i2 = i + 1 - i2lo write ( ctemp(i2), '(i8)' ) i end do write ( *, '('' Row '',10a8)' ) ctemp(1:inc) write ( *, '(a)' ) ' Col' write ( *, '(a)' ) ' ' j2lo = max ( jlo, 1 ) j2hi = min ( jhi, n ) do j = j2lo, j2hi do i2 = 1, inc i = i2lo - 1 + i2 write ( ctemp(i2), '(i8)' ) a(i,j) end do write ( *, '(2x,i3,a,10a8)' ) j, ':', ( ctemp(i), i = 1, inc ) end do end do return end subroutine r8mat_transpose_print ( m, n, a, title ) !*****************************************************************************80 ! !! R8MAT_TRANSPOSE_PRINT prints an R8MAT, transposed. ! ! Discussion: ! ! An R8MAT is an array of R8 values. ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 14 June 2004 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input, integer M, N, the number of rows and columns. ! ! Input, real ( kind = rk ) A(M,N), an M by N matrix to be printed. ! ! Input, character ( len = * ) TITLE, a title. ! implicit none integer, parameter :: rk = kind ( 1.0D+00 ) integer m integer n real ( kind = rk ) a(m,n) character ( len = * ) title call r8mat_transpose_print_some ( m, n, a, 1, 1, m, n, title ) return end subroutine r8mat_transpose_print_some ( m, n, a, ilo, jlo, ihi, jhi, title ) !*****************************************************************************80 ! !! R8MAT_TRANSPOSE_PRINT_SOME prints some of an R8MAT, transposed. ! ! Discussion: ! ! An R8MAT is an array of R8 values. ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 10 September 2009 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input, integer M, N, the number of rows and columns. ! ! Input, real ( kind = rk ) A(M,N), an M by N matrix to be printed. ! ! Input, integer ILO, JLO, the first row and column to print. ! ! Input, integer IHI, JHI, the last row and column to print. ! ! Input, character ( len = * ) TITLE, a title. ! implicit none integer, parameter :: rk = kind ( 1.0D+00 ) integer, parameter :: incx = 5 integer m integer n real ( kind = rk ) a(m,n) character ( len = 14 ) ctemp(incx) integer i integer i2 integer i2hi integer i2lo integer ihi integer ilo integer inc integer j integer j2hi integer j2lo integer jhi integer jlo character ( len = * ) title write ( *, '(a)' ) ' ' write ( *, '(a)' ) trim ( title ) do i2lo = max ( ilo, 1 ), min ( ihi, m ), incx i2hi = i2lo + incx - 1 i2hi = min ( i2hi, m ) i2hi = min ( i2hi, ihi ) inc = i2hi + 1 - i2lo write ( *, '(a)' ) ' ' do i = i2lo, i2hi i2 = i + 1 - i2lo write ( ctemp(i2), '(i8,6x)' ) i end do write ( *, '('' Row '',5a14)' ) ctemp(1:inc) write ( *, '(a)' ) ' Col' write ( *, '(a)' ) ' ' j2lo = max ( jlo, 1 ) j2hi = min ( jhi, n ) do j = j2lo, j2hi do i2 = 1, inc i = i2lo - 1 + i2 write ( ctemp(i2), '(g14.6)' ) a(i,j) end do write ( *, '(2x,i3,a,5a14)' ) j, ':', ( ctemp(i), i = 1, inc ) end do end do return end subroutine r8vec_normal_01 ( n, seed, x ) !*****************************************************************************80 ! !! R8VEC_NORMAL_01 returns a unit pseudonormal R8VEC. ! ! Discussion: ! ! An R8VEC is an array of double precision real values. ! ! The standard normal probability distribution function (PDF) has ! mean 0 and standard deviation 1. ! ! This routine can generate a vector of values on one call. It ! has the feature that it should provide the same results ! in the same order no matter how we break up the task. ! ! Before calling this routine, the user may call RANDOM_SEED ! in order to set the seed of the random number generator. ! ! The Box-Muller method is used, which is efficient, but ! generates an even number of values each time. On any call ! to this routine, an even number of new values are generated. ! Depending on the situation, one value may be left over. ! In that case, it is saved for the next call. ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 31 May 2007 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input, integer N, the number of values desired. If N is ! negative, then the code will flush its internal memory; in particular, ! if there is a saved value to be used on the next call, it is ! instead discarded. This is useful if the user has reset the ! random number seed, for instance. ! ! Input/output, integer SEED, a seed for the random ! number generator. ! ! Output, real ( kind = rk ) X(N), a sample of the standard normal PDF. ! ! Local parameters: ! ! Local, integer MADE, records the number of values that have ! been computed. On input with negative N, this value overwrites ! the return value of N, so the user can get an accounting of ! how much work has been done. ! ! Local, real ( kind = rk ) R(N+1), is used to store some uniform ! random values. Its dimension is N+1, but really it is only needed ! to be the smallest even number greater than or equal to N. ! ! Local, integer SAVED, is 0 or 1 depending on whether there is a ! single saved value left over from the previous call. ! ! Local, integer X_LO_INDEX, X_HI_INDEX, records the range ! of entries of X that we need to compute. This starts off as 1:N, but ! is adjusted if we have a saved value that can be immediately stored ! in X(1), and so on. ! ! Local, real ( kind = rk ) Y, the value saved from the previous call, if ! SAVED is 1. ! implicit none integer, parameter :: rk = kind ( 1.0D+00 ) integer n integer m integer, save :: made = 0 real ( kind = rk ), parameter :: pi = 3.141592653589793D+00 real ( kind = rk ) r(n+1) integer, save :: saved = 0 integer seed integer, parameter :: two = 2 real ( kind = rk ) x(n) integer x_hi_index integer x_lo_index real ( kind = rk ), save :: y = 0.0D+00 ! ! I'd like to allow the user to reset the internal data. ! But this won't work properly if we have a saved value Y. ! I'm making a crock option that allows the user to signal ! explicitly that any internal memory should be flushed, ! by passing in a negative value for N. ! if ( n < 0 ) then n = made made = 0 saved = 0 y = 0.0D+00 return else if ( n == 0 ) then return end if ! ! Record the range of X we need to fill in. ! x_lo_index = 1 x_hi_index = n ! ! Use up the old value, if we have it. ! if ( saved == 1 ) then x(1) = y saved = 0 x_lo_index = 2 end if ! ! Maybe we don't need any more values. ! if ( x_hi_index - x_lo_index + 1 == 0 ) then ! ! If we need just one new value, do that here to avoid null arrays. ! else if ( x_hi_index - x_lo_index + 1 == 1 ) then call random_number ( harvest = r(1:2) ) x(x_hi_index) = & sqrt ( -2.0D+00 * log ( r(1) ) ) * cos ( 2.0D+00 * pi * r(2) ) y = sqrt ( -2.0D+00 * log ( r(1) ) ) * sin ( 2.0D+00 * pi * r(2) ) saved = 1 made = made + 2 ! ! If we require an even number of values, that's easy. ! else if ( mod ( x_hi_index - x_lo_index, two ) == 1 ) then m = ( x_hi_index - x_lo_index + 1 ) / 2 call random_number ( harvest = r(1:2*m) ) x(x_lo_index:x_hi_index-1:2) = & sqrt ( -2.0D+00 * log ( r(1:2*m-1:2) ) ) & * cos ( 2.0D+00 * pi * r(2:2*m:2) ) x(x_lo_index+1:x_hi_index:2) = & sqrt ( -2.0D+00 * log ( r(1:2*m-1:2) ) ) & * sin ( 2.0D+00 * pi * r(2:2*m:2) ) made = made + x_hi_index - x_lo_index + 1 ! ! If we require an odd number of values, we generate an even number, ! and handle the last pair specially, storing one in X(N), and ! saving the other for later. ! else x_hi_index = x_hi_index - 1 m = ( x_hi_index - x_lo_index + 1 ) / 2 + 1 call random_number ( harvest = r(1:2*m) ) x(x_lo_index:x_hi_index-1:2) = & sqrt ( -2.0D+00 * log ( r(1:2*m-3:2) ) ) & * cos ( 2.0D+00 * pi * r(2:2*m-2:2) ) x(x_lo_index+1:x_hi_index:2) = & sqrt ( -2.0D+00 * log ( r(1:2*m-3:2) ) ) & * sin ( 2.0D+00 * pi * r(2:2*m-2:2) ) x(n) = sqrt ( -2.0D+00 * log ( r(2*m-1) ) ) & * cos ( 2.0D+00 * pi * r(2*m) ) y = sqrt ( -2.0D+00 * log ( r(2*m-1) ) ) & * sin ( 2.0D+00 * pi * r(2*m) ) saved = 1 made = made + x_hi_index - x_lo_index + 2 end if return end subroutine r8vec_print ( n, a, title ) !*****************************************************************************80 ! !! R8VEC_PRINT prints an R8VEC. ! ! Discussion: ! ! An R8VEC is a vector of R8's. ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 22 August 2000 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input, integer N, the number of components of the vector. ! ! Input, real ( kind = rk ) A(N), the vector to be printed. ! ! Input, character ( len = * ) TITLE, a title. ! implicit none integer, parameter :: rk = kind ( 1.0D+00 ) integer n real ( kind = rk ) a(n) integer i character ( len = * ) title write ( *, '(a)' ) ' ' write ( *, '(a)' ) trim ( title ) write ( *, '(a)' ) ' ' do i = 1, n write ( *, '(2x,i3,a,g16.8)' ) i, ':', a(i) end do return end subroutine stri_angles_to_area_3d ( r, a, b, c, area ) !*****************************************************************************80 ! !! stri_angles_to_area_3d() computes the area of a spherical triangle. ! ! Discussion: ! ! A sphere centered at 0 in 3D satisfies the equation: ! ! X*X + Y*Y + Z*Z = R*R ! ! A spherical triangle is specified by three points on the surface ! of the sphere. ! ! The area formula is known as Girard's formula. ! ! The area of a spherical triangle is: ! ! AREA = ( A + B + C - PI ) * R*R ! ! where A, B and C are the (surface) angles of the triangle. ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 09 June 2002 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input, real ( kind = rk ) R, the radius of the sphere. ! ! Input, real ( kind = rk ) A, B, C, the angles of the triangle. ! ! Output, real ( kind = rk ) AREA, the area of the spherical triangle. ! implicit none integer, parameter :: rk = kind ( 1.0D+00 ) real ( kind = rk ) a real ( kind = rk ) area real ( kind = rk ) b real ( kind = rk ) c real ( kind = rk ), parameter :: pi = 3.141592653589793D+00 real ( kind = rk ) r ! ! Apply Girard's formula. ! area = r * r * ( a + b + c - pi ) return end subroutine stri_contains_point ( v1, v2, v3, p, contains ) !*****************************************************************************80 ! !! STRI_CONTAINS_POINT determines if a spherical triangle contains a point. ! ! Discussion: ! ! A sphere centered at 0 in 3D satisfies the equation: ! ! X*X + Y*Y + Z*Z = R*R ! ! A spherical triangle is specified by three points on the surface ! of the sphere. The inside of the triangle is defined by the fact ! that the three points are listed in counterclockwise order. ! Here "counterclockwise" is with reference to an observer standing ! outside the sphere. ! ! If P is a point on the sphere, we say that the spherical triangle ! "contains" P if P is in the interior of the spherical triangle. ! We do not actually require that P be a point on the sphere. Instead, ! we consider the ray defined from the origin through P, which intersects ! the sphere. It is essentially this point of intersection we are ! considering. ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 26 July 2007 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input, real ( kind = rk ) V1(3), V2(3), V3(3), the vertices of the triangle. ! ! Input, real ( kind = rk ) P(3), a point on the sphere, or the point on ! the sphere determined by the ray from the origin through P. P must ! not be zero. ! ! Output, real ( kind = rk ) CONTAINS, is positive if the spherical triangle ! contains P, zero if P is exactly on the boundary of the triangle, and ! negative if P is outside the triangle. ! implicit none integer, parameter :: rk = kind ( 1.0D+00 ) integer, parameter :: dim_num = 3 real ( kind = rk ) contains real ( kind = rk ) p(dim_num) real ( kind = rk ) p_direction(dim_num) real ( kind = rk ) p_norm real ( kind = rk ) normal_direction(dim_num) real ( kind = rk ) normal_norm real ( kind = rk ) v1(dim_num) real ( kind = rk ) v2(dim_num) real ( kind = rk ) v3(dim_num) ! ! Determine the normal vector to (V1,V2,V3), which is (V2-V1)x(V3-V13).. ! normal_direction(1) = ( v2(2) - v1(2) ) * ( v3(3) - v1(3) ) & - ( v2(3) - v1(3) ) * ( v3(2) - v1(2) ) normal_direction(2) = ( v2(3) - v1(3) ) * ( v3(1) - v1(1) ) & - ( v2(1) - v1(1) ) * ( v3(3) - v1(3) ) normal_direction(3) = ( v2(1) - v1(1) ) * ( v3(2) - v1(2) ) & - ( v2(2) - v1(2) ) * ( v3(1) - v1(1) ) normal_norm = sqrt ( sum ( normal_direction(1:dim_num)**2 ) ) if ( normal_norm == 0.0D+00 ) then contains = - huge ( contains ) return end if normal_direction(1:dim_num) = normal_direction(1:dim_num) / normal_norm ! ! Determine the length of P. ! p_norm = sqrt ( sum ( p(1:dim_num)**2 ) ) if ( p_norm == 0.0D+00 ) then contains = - huge ( contains ) return end if p_direction(1:dim_num) = p_direction(1:dim_num) / p_norm ! ! CONTAINS is the dot product of the normal vector to (V1,V2,V3) ! against the unit direction vector defined by P. ! contains = dot_product ( normal_direction, p_direction ) return end subroutine stri_sides_to_angles_3d ( r, as, bs, cs, a, b, c ) !*****************************************************************************80 ! !! STRI_SIDES_TO_ANGLES_3D computes spherical triangle angles in 3D. ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 09 June 2002 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input, real ( kind = rk ) R, the radius of the sphere. ! ! Input, real ( kind = rk ) AS, BS, CS, the (geodesic) length of the ! sides of the triangle. ! ! Output, real ( kind = rk ) A, B, C, the spherical angles of the triangle. ! Angle A is opposite the side of length AS, and so on. ! implicit none integer, parameter :: rk = kind ( 1.0D+00 ) real ( kind = rk ) a real ( kind = rk ) as real ( kind = rk ) asu real ( kind = rk ) b real ( kind = rk ) bs real ( kind = rk ) bsu real ( kind = rk ) c real ( kind = rk ) cs real ( kind = rk ) csu real ( kind = rk ) r real ( kind = rk ) ssu real ( kind = rk ) tan_a2 real ( kind = rk ) tan_b2 real ( kind = rk ) tan_c2 asu = as / r bsu = bs / r csu = cs / r ssu = ( asu + bsu + csu ) / 2.0D+00 tan_a2 = sqrt ( ( sin ( ssu - bsu ) * sin ( ssu - csu ) ) / & ( sin ( ssu ) * sin ( ssu - asu ) ) ) a = 2.0D+00 * atan ( tan_a2 ) tan_b2 = sqrt ( ( sin ( ssu - asu ) * sin ( ssu - csu ) ) / & ( sin ( ssu ) * sin ( ssu - bsu ) ) ) b = 2.0D+00 * atan ( tan_b2 ) tan_c2 = sqrt ( ( sin ( ssu - asu ) * sin ( ssu - bsu ) ) / & ( sin ( ssu ) * sin ( ssu - csu ) ) ) c = 2.0D+00 * atan ( tan_c2 ) return end subroutine stri_vertices_to_area ( r, v1, v2, v3, area ) !*****************************************************************************80 ! !! STRI_VERTICES_TO_AREA computes the area of a spherical triangle. ! ! Discussion: ! ! A sphere centered at 0 in 3D satisfies the equation: ! ! X*X + Y*Y + Z*Z = R*R ! ! A spherical triangle is specified by three points on the surface ! of the sphere. ! ! The area formula is known as Girard's formula. ! ! The area of a spherical triangle is: ! ! AREA = ( A + B + C - PI ) * R*R ! ! where A, B and C are the (surface) angles of the triangle. ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 09 June 2002 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input, real ( kind = rk ) R, the radius of the sphere. ! ! Input, real ( kind = rk ) V1(3), V2(3), V3(3), the vertices of the triangle. ! ! Output, real ( kind = rk ) AREA, the area of the spherical triangle. ! implicit none integer, parameter :: rk = kind ( 1.0D+00 ) integer, parameter :: dim_num = 3 real ( kind = rk ) a real ( kind = rk ) area real ( kind = rk ) as real ( kind = rk ) b real ( kind = rk ) bs real ( kind = rk ) c real ( kind = rk ) cs real ( kind = rk ) r real ( kind = rk ) v1(dim_num) real ( kind = rk ) v2(dim_num) real ( kind = rk ) v3(dim_num) ! ! Compute the lengths of the sides of the spherical triangle. ! call stri_vertices_to_sides ( r, v1, v2, v3, as, bs, cs ) ! ! Get the spherical angles. ! call stri_sides_to_angles_3d ( r, as, bs, cs, a, b, c ) ! ! Get the area ! call stri_angles_to_area_3d ( r, a, b, c, area ) return end subroutine stri_vertices_to_centroid_3d ( r, v1, v2, v3, vs ) !*****************************************************************************80 ! !! STRI_VERTICES_TO_CENTROID_3D gets a spherical triangle centroid in 3D. ! ! Discussion: ! ! A sphere centered at 0 in 3D satisfies the equation: ! ! X*X + Y*Y + Z*Z = R*R ! ! A spherical triangle is specified by three points on the sphere. ! ! The (true) centroid of a spherical triangle is the point ! ! VT = (XT,YT,ZT) = Integral ( X, Y, Z ) dArea / Integral 1 dArea ! ! Note that the true centroid does NOT, in general, lie on the sphere. ! ! The "flat" centroid VF is the centroid of the planar triangle defined by ! the vertices of the spherical triangle. ! ! The "spherical" centroid VS of a spherical triangle is computed by ! the intersection of the geodesic bisectors of the triangle angles. ! The spherical centroid lies on the sphere. ! ! VF, VT and VS lie on a line through the center of the sphere. We can ! easily calculate VF by averaging the vertices, and from this determine ! VS by normalizing. ! ! Of course, we still will not have actually computed VT, which lies ! somewhere between VF and VS! ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 18 June 2002 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input, real ( kind = rk ) R, the radius of the sphere. ! ! Input, real ( kind = rk ) V1(3), V2(3), V3(3), the vertices of the triangle. ! ! Output, real ( kind = rk ) VS(3), the coordinates of the "spherical ! centroid" of the spherical triangle. ! implicit none integer, parameter :: rk = kind ( 1.0D+00 ) integer, parameter :: dim_num = 3 real ( kind = rk ) norm real ( kind = rk ) r real ( kind = rk ) v1(dim_num) real ( kind = rk ) v2(dim_num) real ( kind = rk ) v3(dim_num) real ( kind = rk ) vs(dim_num) vs(1:dim_num) = ( v1(1:dim_num) + v2(1:dim_num) + v3(1:dim_num) ) / 3.0D+00 norm = sqrt ( sum ( vs(1:dim_num)**2 ) ) vs(1:dim_num) = r * vs(1:dim_num) / norm return end subroutine stri_vertices_to_sides ( r, v1, v2, v3, as, bs, cs ) !*****************************************************************************80 ! !! STRI_VERTICES_TO_SIDES_3D computes spherical triangle sides in 3D. ! ! Discussion: ! ! We can use the ACOS system call here, but the ARC_COSINE routine ! will automatically take care of cases where the input argument is ! (usually slightly) out of bounds. ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 21 June 2002 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input, real ( kind = rk ) R, the radius of the sphere. ! ! Input, real ( kind = rk ) V1(3), V2(3), V3(3), the vertices of the spherical ! triangle. ! ! Output, real ( kind = rk ) AS, BS, CS, the (geodesic) length of the sides ! of the triangle. ! implicit none integer, parameter :: rk = kind ( 1.0D+00 ) integer, parameter :: dim_num = 3 real ( kind = rk ) arc_cosine real ( kind = rk ) as real ( kind = rk ) bs real ( kind = rk ) cs real ( kind = rk ) r real ( kind = rk ) v1(dim_num) real ( kind = rk ) v2(dim_num) real ( kind = rk ) v3(dim_num) as = r * arc_cosine ( dot_product ( v2(1:dim_num), v3(1:dim_num) ) / r**2 ) bs = r * arc_cosine ( dot_product ( v3(1:dim_num), v1(1:dim_num) ) / r**2 ) cs = r * arc_cosine ( dot_product ( v1(1:dim_num), v2(1:dim_num) ) / r**2 ) return end subroutine uniform_on_sphere01_map ( dim_num, n, seed, x ) !*****************************************************************************80 ! !! UNIFORM_ON_SPHERE01_MAP maps uniform points onto the unit sphere. ! ! Discussion: ! ! The sphere has center 0 and radius 1. ! ! This procedure is valid for any spatial dimension DIM_NUM. ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 19 August 2004 ! ! Author: ! ! John Burkardt ! ! Reference: ! ! Russell Cheng, ! Random Variate Generation, ! in Handbook of Simulation, ! edited by Jerry Banks, ! Wiley, 1998, pages 168. ! ! Reuven Rubinstein, ! Monte Carlo Optimization, Simulation, and Sensitivity ! of Queueing Networks, ! Krieger, 1992, ! ISBN: 0894647644, ! LC: QA298.R79. ! ! Parameters: ! ! Input, integer DIM_NUM, the dimension of the space. ! ! Input, integer N, the number of points. ! ! Input/output, integer SEED, a seed for the random ! number generator. ! ! Output, real ( kind = rk ) X(DIM_NUM,N), the points. ! implicit none integer, parameter :: rk = kind ( 1.0D+00 ) integer dim_num integer n integer j real ( kind = rk ) norm integer seed real ( kind = rk ) x(dim_num,n) do j = 1, n ! ! Fill a vector with normally distributed values. ! call r8vec_normal_01 ( dim_num, seed, x(1:dim_num,j) ) ! ! Compute the length of the vector. ! norm = sqrt ( sum ( x(1:dim_num,j)**2 ) ) ! ! Normalize the vector. ! x(1:dim_num,j) = x(1:dim_num,j) / norm end do return end