fplot 1.7.1
A Fortran library providing a convenient interface for plotting with Gnuplot.
Loading...
Searching...
No Matches
fplot_delaunay_tri_surface.f90
1! fplot_delaunay_tri_surface.f90
2
3submodule(fplot_core) fplot_delaunay_tri_surface
4 use ieee_arithmetic
5contains
6! ------------------------------------------------------------------------------
7 module subroutine dts_define_fcn(this, z, err)
8 ! Arguments
9 class(delaunay_tri_surface), intent(inout) :: this
10 real(real64), intent(in), dimension(:) :: z
11 class(errors), intent(inout), optional, target :: err
12
13 ! Local Variables
14 integer(int32) :: n, flag
15 class(errors), pointer :: errmgr
16 type(errors), target :: deferr
17 character(len = 256) :: errmsg
18
19 ! Initialization
20 if (present(err)) then
21 errmgr => err
22 else
23 errmgr => deferr
24 end if
25 n = this%get_point_count()
26
27 ! Input Check
28 if (n == 0) then
29 call errmgr%report_error("dts_define_fcn", &
30 "No x-y coordinates have been defined.", &
31 plot_invalid_operation_error)
32 return
33 end if
34 if (size(z) /= n) then
35 write (errmsg, 100) "The number of function values " // &
36 "does not match the number of x-y points. Expected to find ", &
37 n, " function values, but found ", size(z), " instead."
38 call errmgr%report_error("dts_define_fcn", trim(errmsg), &
39 plot_array_size_mismatch_error)
40 return
41 end if
42
43 ! Store the data
44 if (allocated(this%m_z)) deallocate(this%m_z)
45 allocate(this%m_z(n), stat = flag)
46 if (flag /= 0) then
47 call errmgr%report_error("dts_define_fcn", &
48 "Insufficient memory available.", &
49 plot_out_of_memory_error)
50 return
51 end if
52 this%m_z = z
53
54100 format(a, i0, a, i0, a)
55 end subroutine
56
57! ------------------------------------------------------------------------------
58 pure module function dts_get_z(this) result(rst)
59 class(delaunay_tri_surface), intent(in) :: this
60 real(real64), allocatable, dimension(:) :: rst
61 if (allocated(this%m_z)) then
62 rst = this%m_z
63 else
64 allocate(rst(0))
65 end if
66 end function
67
68! ------------------------------------------------------------------------------
69 ! Interpolation Routine - Barycentric Coordinate Approach
70 ! https://www.iue.tuwien.ac.at/phd/nentchev/node25.html
71 ! https://academic.csuohio.edu/duffy_s/CVE_512_11.pdf
72 pure module function dts_interp_1(this, x, y) result(z)
73 ! Arguments
74 class(delaunay_tri_surface), intent(in) :: this
75 real(real64), intent(in) :: x, y
76 real(real64) :: z
77
78 ! Local Variables
79 integer(int32) :: i, n1, n2, n3
80 real(real64) :: x1, x2, x3, y1, y2, y3, z1, z2, z3
81 integer(int32), allocatable, dimension(:,:) :: indices
82 real(real64), allocatable, dimension(:) :: xc, yc, zc
83
84 ! Initialization
85 z = ieee_value(z, ieee_quiet_nan)
86 indices = this%get_indices()
87 xc = this%get_points_x()
88 yc = this%get_points_y()
89 zc = this%get_points_z()
90
91 ! Quick Return
92 if (this%get_triangle_count() == 0 .or. &
93 this%get_point_count() == 0 .or. &
94 size(zc) == 0) return
95
96 ! Locate the triangle to which the point (x, y) belongs. If no triangle
97 ! is found, simply return NaN
98 i = this%find_triangle(x, y)
99 if (i == -1) return
100
101 ! Get the triangle vertices
102 n1 = indices(i, 1)
103 n2 = indices(i, 2)
104 n3 = indices(i, 3)
105
106 x1 = xc(n1)
107 y1 = yc(n1)
108 z1 = zc(n1)
109
110 x2 = xc(n2)
111 y2 = yc(n2)
112 z2 = zc(n2)
113
114 x3 = xc(n3)
115 y3 = yc(n3)
116 z3 = zc(n3)
117
118 ! Perform the interpolation
119 z = linear_interp(x1, y1, z1, x2, y2, z2, x3, y3, z3, x, y)
120 end function
121
122! --------------------
123 pure module function dts_interp_2(this, x, y) result(z)
124 ! Arguments
125 class(delaunay_tri_surface), intent(in) :: this
126 real(real64), intent(in), dimension(:) :: x, y
127 real(real64), allocatable, dimension(:) :: z
128
129 ! Local Variables
130 integer(int32) :: i, j, n1, n2, n3, nxy
131 real(real64) :: x1, x2, x3, y1, y2, y3, z1, z2, z3, nan
132 integer(int32), allocatable, dimension(:,:) :: indices
133 real(real64), allocatable, dimension(:) :: xc, yc, zc
134
135 ! Initialization
136 nxy = min(size(x), size(y))
137 nan = ieee_value(nan, ieee_quiet_nan)
138 allocate(z(nxy))
139 z = nan
140 indices = this%get_indices()
141 xc = this%get_points_x()
142 yc = this%get_points_y()
143 zc = this%get_points_z()
144
145 ! Quick Return
146 if (this%get_triangle_count() == 0 .or. &
147 this%get_point_count() == 0 .or. &
148 size(zc) == 0) return
149
150 ! Locate the triangle to which the point (x, y) belongs. If no triangle
151 ! is found, simply return NaN
152 do i = 1, nxy
153 ! Find the index of the triangle
154 j = this%find_triangle(x(i), y(i))
155
156 if (j == -1) cycle ! Skip if we couldn't find a triangle
157
158 ! Get the vertices
159 n1 = indices(j, 1)
160 n2 = indices(j, 2)
161 n3 = indices(j, 3)
162
163 x1 = xc(n1)
164 y1 = yc(n1)
165 z1 = zc(n1)
166
167 x2 = xc(n2)
168 y2 = yc(n2)
169 z2 = zc(n2)
170
171 x3 = xc(n3)
172 y3 = yc(n3)
173 z3 = zc(n3)
174
175 ! Perform the interpolation
176 z(i) = linear_interp(x1, y1, z1, x2, y2, z2, x3, y3, z3, x(i), y(i))
177 end do
178 end function
179
180! ------------------------------------------------------------------------------
181 ! Utilizes linear shape functions to interpolate on a triangle given its
182 ! vertex locations, and the desired interpolation location. Notice, the
183 ! interpolation location is expected to lie within the triangle. This is
184 ! not checked.
185 pure elemental function linear_interp(x1, y1, z1, x2, y2, z2, x3, &
186 y3, z3, x, y) result(z)
187 real(real64), intent(in) :: x1, y1, z1, x2, y2, z2, x3, y3, z3, x, y
188 real(real64) :: a1, a2, a3, j, z
189
190 j = (x2 - x1) * y3 + (x1 - x3) * y2 + (x3 - x2) * y1
191 a1 = (x2 * y3 - x3 * y2 + (y2 - y3) * x + (x3 - x2) * y)
192 a2 = (x3 * y1 - x1 * y3 + (y3 - y1) * x + (x1 - x3) * y)
193 a3 = (x1 * y2 - x2 * y1 + (y1 - y2) * x + (x2 - x1) * y)
194 z = (a1 * z1 + a2 * z2 + a3 * z3) / j
195 end function
196
197! ------------------------------------------------------------------------------
198end submodule
fplot_core